zone-legacy.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702
  1. 'use strict';
  2. /**
  3. * @license Angular v<unknown>
  4. * (c) 2010-2025 Google LLC. https://angular.io/
  5. * License: MIT
  6. */
  7. /*
  8. * This is necessary for Chrome and Chrome mobile, to enable
  9. * things like redefining `createdCallback` on an element.
  10. */
  11. let zoneSymbol;
  12. let _defineProperty;
  13. let _getOwnPropertyDescriptor;
  14. let _create;
  15. let unconfigurablesKey;
  16. function propertyPatch() {
  17. zoneSymbol = Zone.__symbol__;
  18. _defineProperty = Object[zoneSymbol('defineProperty')] = Object.defineProperty;
  19. _getOwnPropertyDescriptor = Object[zoneSymbol('getOwnPropertyDescriptor')] =
  20. Object.getOwnPropertyDescriptor;
  21. _create = Object.create;
  22. unconfigurablesKey = zoneSymbol('unconfigurables');
  23. Object.defineProperty = function (obj, prop, desc) {
  24. if (isUnconfigurable(obj, prop)) {
  25. throw new TypeError("Cannot assign to read only property '" + prop + "' of " + obj);
  26. }
  27. const originalConfigurableFlag = desc.configurable;
  28. if (prop !== 'prototype') {
  29. desc = rewriteDescriptor(obj, prop, desc);
  30. }
  31. return _tryDefineProperty(obj, prop, desc, originalConfigurableFlag);
  32. };
  33. Object.defineProperties = function (obj, props) {
  34. Object.keys(props).forEach(function (prop) {
  35. Object.defineProperty(obj, prop, props[prop]);
  36. });
  37. for (const sym of Object.getOwnPropertySymbols(props)) {
  38. const desc = Object.getOwnPropertyDescriptor(props, sym);
  39. // Since `Object.getOwnPropertySymbols` returns *all* symbols,
  40. // including non-enumerable ones, retrieve property descriptor and check
  41. // enumerability there. Proceed with the rewrite only when a property is
  42. // enumerable to make the logic consistent with the way regular
  43. // properties are retrieved (via `Object.keys`, which respects
  44. // `enumerable: false` flag). More information:
  45. // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Enumerability_and_ownership_of_properties#retrieval
  46. if (desc?.enumerable) {
  47. Object.defineProperty(obj, sym, props[sym]);
  48. }
  49. }
  50. return obj;
  51. };
  52. Object.create = function (proto, propertiesObject) {
  53. if (typeof propertiesObject === 'object' && !Object.isFrozen(propertiesObject)) {
  54. Object.keys(propertiesObject).forEach(function (prop) {
  55. propertiesObject[prop] = rewriteDescriptor(proto, prop, propertiesObject[prop]);
  56. });
  57. }
  58. return _create(proto, propertiesObject);
  59. };
  60. Object.getOwnPropertyDescriptor = function (obj, prop) {
  61. const desc = _getOwnPropertyDescriptor(obj, prop);
  62. if (desc && isUnconfigurable(obj, prop)) {
  63. desc.configurable = false;
  64. }
  65. return desc;
  66. };
  67. }
  68. function _redefineProperty(obj, prop, desc) {
  69. const originalConfigurableFlag = desc.configurable;
  70. desc = rewriteDescriptor(obj, prop, desc);
  71. return _tryDefineProperty(obj, prop, desc, originalConfigurableFlag);
  72. }
  73. function isUnconfigurable(obj, prop) {
  74. return obj && obj[unconfigurablesKey] && obj[unconfigurablesKey][prop];
  75. }
  76. function rewriteDescriptor(obj, prop, desc) {
  77. // issue-927, if the desc is frozen, don't try to change the desc
  78. if (!Object.isFrozen(desc)) {
  79. desc.configurable = true;
  80. }
  81. if (!desc.configurable) {
  82. // issue-927, if the obj is frozen, don't try to set the desc to obj
  83. if (!obj[unconfigurablesKey] && !Object.isFrozen(obj)) {
  84. _defineProperty(obj, unconfigurablesKey, { writable: true, value: {} });
  85. }
  86. if (obj[unconfigurablesKey]) {
  87. obj[unconfigurablesKey][prop] = true;
  88. }
  89. }
  90. return desc;
  91. }
  92. function _tryDefineProperty(obj, prop, desc, originalConfigurableFlag) {
  93. try {
  94. return _defineProperty(obj, prop, desc);
  95. }
  96. catch (error) {
  97. if (desc.configurable) {
  98. // In case of errors, when the configurable flag was likely set by rewriteDescriptor(),
  99. // let's retry with the original flag value
  100. if (typeof originalConfigurableFlag == 'undefined') {
  101. delete desc.configurable;
  102. }
  103. else {
  104. desc.configurable = originalConfigurableFlag;
  105. }
  106. try {
  107. return _defineProperty(obj, prop, desc);
  108. }
  109. catch (error) {
  110. let swallowError = false;
  111. if (prop === 'createdCallback' ||
  112. prop === 'attachedCallback' ||
  113. prop === 'detachedCallback' ||
  114. prop === 'attributeChangedCallback') {
  115. // We only swallow the error in registerElement patch
  116. // this is the work around since some applications
  117. // fail if we throw the error
  118. swallowError = true;
  119. }
  120. if (!swallowError) {
  121. throw error;
  122. }
  123. // TODO: @JiaLiPassion, Some application such as `registerElement` patch
  124. // still need to swallow the error, in the future after these applications
  125. // are updated, the following logic can be removed.
  126. let descJson = null;
  127. try {
  128. descJson = JSON.stringify(desc);
  129. }
  130. catch (error) {
  131. descJson = desc.toString();
  132. }
  133. console.log(`Attempting to configure '${prop}' with descriptor '${descJson}' on object '${obj}' and got error, giving up: ${error}`);
  134. }
  135. }
  136. else {
  137. throw error;
  138. }
  139. }
  140. }
  141. function eventTargetLegacyPatch(_global, api) {
  142. const { eventNames, globalSources, zoneSymbolEventNames, TRUE_STR, FALSE_STR, ZONE_SYMBOL_PREFIX } = api.getGlobalObjects();
  143. const 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';
  144. const 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'.split(',');
  145. const EVENT_TARGET = 'EventTarget';
  146. let apis = [];
  147. const isWtf = _global['wtf'];
  148. const WTF_ISSUE_555_ARRAY = WTF_ISSUE_555.split(',');
  149. if (isWtf) {
  150. // Workaround for: https://github.com/google/tracing-framework/issues/555
  151. apis = WTF_ISSUE_555_ARRAY.map((v) => 'HTML' + v + 'Element').concat(NO_EVENT_TARGET);
  152. }
  153. else if (_global[EVENT_TARGET]) {
  154. apis.push(EVENT_TARGET);
  155. }
  156. else {
  157. // Note: EventTarget is not available in all browsers,
  158. // if it's not available, we instead patch the APIs in the IDL that inherit from EventTarget
  159. apis = NO_EVENT_TARGET;
  160. }
  161. const isDisableIECheck = _global['__Zone_disable_IE_check'] || false;
  162. const isEnableCrossContextCheck = _global['__Zone_enable_cross_context_check'] || false;
  163. const ieOrEdge = api.isIEOrEdge();
  164. const ADD_EVENT_LISTENER_SOURCE = '.addEventListener:';
  165. const FUNCTION_WRAPPER = '[object FunctionWrapper]';
  166. const BROWSER_TOOLS = 'function __BROWSERTOOLS_CONSOLE_SAFEFUNC() { [native code] }';
  167. const pointerEventsMap = {
  168. 'MSPointerCancel': 'pointercancel',
  169. 'MSPointerDown': 'pointerdown',
  170. 'MSPointerEnter': 'pointerenter',
  171. 'MSPointerHover': 'pointerhover',
  172. 'MSPointerLeave': 'pointerleave',
  173. 'MSPointerMove': 'pointermove',
  174. 'MSPointerOut': 'pointerout',
  175. 'MSPointerOver': 'pointerover',
  176. 'MSPointerUp': 'pointerup',
  177. };
  178. // predefine all __zone_symbol__ + eventName + true/false string
  179. for (let i = 0; i < eventNames.length; i++) {
  180. const eventName = eventNames[i];
  181. const falseEventName = eventName + FALSE_STR;
  182. const trueEventName = eventName + TRUE_STR;
  183. const symbol = ZONE_SYMBOL_PREFIX + falseEventName;
  184. const symbolCapture = ZONE_SYMBOL_PREFIX + trueEventName;
  185. zoneSymbolEventNames[eventName] = {};
  186. zoneSymbolEventNames[eventName][FALSE_STR] = symbol;
  187. zoneSymbolEventNames[eventName][TRUE_STR] = symbolCapture;
  188. }
  189. // predefine all task.source string
  190. for (let i = 0; i < WTF_ISSUE_555_ARRAY.length; i++) {
  191. const target = WTF_ISSUE_555_ARRAY[i];
  192. const targets = (globalSources[target] = {});
  193. for (let j = 0; j < eventNames.length; j++) {
  194. const eventName = eventNames[j];
  195. targets[eventName] = target + ADD_EVENT_LISTENER_SOURCE + eventName;
  196. }
  197. }
  198. const checkIEAndCrossContext = function (nativeDelegate, delegate, target, args) {
  199. if (!isDisableIECheck && ieOrEdge) {
  200. if (isEnableCrossContextCheck) {
  201. try {
  202. const testString = delegate.toString();
  203. if (testString === FUNCTION_WRAPPER || testString == BROWSER_TOOLS) {
  204. nativeDelegate.apply(target, args);
  205. return false;
  206. }
  207. }
  208. catch (error) {
  209. nativeDelegate.apply(target, args);
  210. return false;
  211. }
  212. }
  213. else {
  214. const testString = delegate.toString();
  215. if (testString === FUNCTION_WRAPPER || testString == BROWSER_TOOLS) {
  216. nativeDelegate.apply(target, args);
  217. return false;
  218. }
  219. }
  220. }
  221. else if (isEnableCrossContextCheck) {
  222. try {
  223. delegate.toString();
  224. }
  225. catch (error) {
  226. nativeDelegate.apply(target, args);
  227. return false;
  228. }
  229. }
  230. return true;
  231. };
  232. const apiTypes = [];
  233. for (let i = 0; i < apis.length; i++) {
  234. const type = _global[apis[i]];
  235. apiTypes.push(type && type.prototype);
  236. }
  237. // vh is validateHandler to check event handler
  238. // is valid or not(for security check)
  239. api.patchEventTarget(_global, api, apiTypes, {
  240. vh: checkIEAndCrossContext,
  241. transferEventName: (eventName) => {
  242. const pointerEventName = pointerEventsMap[eventName];
  243. return pointerEventName || eventName;
  244. },
  245. });
  246. Zone[api.symbol('patchEventTarget')] = !!_global[EVENT_TARGET];
  247. return true;
  248. }
  249. // we have to patch the instance since the proto is non-configurable
  250. function apply(api, _global) {
  251. const { ADD_EVENT_LISTENER_STR, REMOVE_EVENT_LISTENER_STR } = api.getGlobalObjects();
  252. const WS = _global.WebSocket;
  253. // On Safari window.EventTarget doesn't exist so need to patch WS add/removeEventListener
  254. // On older Chrome, no need since EventTarget was already patched
  255. if (!_global.EventTarget) {
  256. api.patchEventTarget(_global, api, [WS.prototype]);
  257. }
  258. _global.WebSocket = function (x, y) {
  259. const socket = arguments.length > 1 ? new WS(x, y) : new WS(x);
  260. let proxySocket;
  261. let proxySocketProto;
  262. // Safari 7.0 has non-configurable own 'onmessage' and friends properties on the socket instance
  263. const onmessageDesc = api.ObjectGetOwnPropertyDescriptor(socket, 'onmessage');
  264. if (onmessageDesc && onmessageDesc.configurable === false) {
  265. proxySocket = api.ObjectCreate(socket);
  266. // socket have own property descriptor 'onopen', 'onmessage', 'onclose', 'onerror'
  267. // but proxySocket not, so we will keep socket as prototype and pass it to
  268. // patchOnProperties method
  269. proxySocketProto = socket;
  270. [ADD_EVENT_LISTENER_STR, REMOVE_EVENT_LISTENER_STR, 'send', 'close'].forEach(function (propName) {
  271. proxySocket[propName] = function () {
  272. const args = api.ArraySlice.call(arguments);
  273. if (propName === ADD_EVENT_LISTENER_STR || propName === REMOVE_EVENT_LISTENER_STR) {
  274. const eventName = args.length > 0 ? args[0] : undefined;
  275. if (eventName) {
  276. const propertySymbol = Zone.__symbol__('ON_PROPERTY' + eventName);
  277. socket[propertySymbol] = proxySocket[propertySymbol];
  278. }
  279. }
  280. return socket[propName].apply(socket, args);
  281. };
  282. });
  283. }
  284. else {
  285. // we can patch the real socket
  286. proxySocket = socket;
  287. }
  288. api.patchOnProperties(proxySocket, ['close', 'error', 'message', 'open'], proxySocketProto);
  289. return proxySocket;
  290. };
  291. const globalWebSocket = _global['WebSocket'];
  292. for (const prop in WS) {
  293. globalWebSocket[prop] = WS[prop];
  294. }
  295. }
  296. /**
  297. * @fileoverview
  298. * @suppress {globalThis}
  299. */
  300. function propertyDescriptorLegacyPatch(api, _global) {
  301. const { isNode, isMix } = api.getGlobalObjects();
  302. if (isNode && !isMix) {
  303. return;
  304. }
  305. if (!canPatchViaPropertyDescriptor(api, _global)) {
  306. const supportsWebSocket = typeof WebSocket !== 'undefined';
  307. // Safari, Android browsers (Jelly Bean)
  308. patchViaCapturingAllTheEvents(api);
  309. api.patchClass('XMLHttpRequest');
  310. if (supportsWebSocket) {
  311. apply(api, _global);
  312. }
  313. Zone[api.symbol('patchEvents')] = true;
  314. }
  315. }
  316. function canPatchViaPropertyDescriptor(api, _global) {
  317. const { isBrowser, isMix } = api.getGlobalObjects();
  318. if ((isBrowser || isMix) &&
  319. !api.ObjectGetOwnPropertyDescriptor(HTMLElement.prototype, 'onclick') &&
  320. typeof Element !== 'undefined') {
  321. // WebKit https://bugs.webkit.org/show_bug.cgi?id=134364
  322. // IDL interface attributes are not configurable
  323. const desc = api.ObjectGetOwnPropertyDescriptor(Element.prototype, 'onclick');
  324. if (desc && !desc.configurable)
  325. return false;
  326. // try to use onclick to detect whether we can patch via propertyDescriptor
  327. // because XMLHttpRequest is not available in service worker
  328. if (desc) {
  329. api.ObjectDefineProperty(Element.prototype, 'onclick', {
  330. enumerable: true,
  331. configurable: true,
  332. get: function () {
  333. return true;
  334. },
  335. });
  336. const div = document.createElement('div');
  337. const result = !!div.onclick;
  338. api.ObjectDefineProperty(Element.prototype, 'onclick', desc);
  339. return result;
  340. }
  341. }
  342. const XMLHttpRequest = _global['XMLHttpRequest'];
  343. if (!XMLHttpRequest) {
  344. // XMLHttpRequest is not available in service worker
  345. return false;
  346. }
  347. const ON_READY_STATE_CHANGE = 'onreadystatechange';
  348. const XMLHttpRequestPrototype = XMLHttpRequest.prototype;
  349. const xhrDesc = api.ObjectGetOwnPropertyDescriptor(XMLHttpRequestPrototype, ON_READY_STATE_CHANGE);
  350. // add enumerable and configurable here because in opera
  351. // by default XMLHttpRequest.prototype.onreadystatechange is undefined
  352. // without adding enumerable and configurable will cause onreadystatechange
  353. // non-configurable
  354. // and if XMLHttpRequest.prototype.onreadystatechange is undefined,
  355. // we should set a real desc instead a fake one
  356. if (xhrDesc) {
  357. api.ObjectDefineProperty(XMLHttpRequestPrototype, ON_READY_STATE_CHANGE, {
  358. enumerable: true,
  359. configurable: true,
  360. get: function () {
  361. return true;
  362. },
  363. });
  364. const req = new XMLHttpRequest();
  365. const result = !!req.onreadystatechange;
  366. // restore original desc
  367. api.ObjectDefineProperty(XMLHttpRequestPrototype, ON_READY_STATE_CHANGE, xhrDesc || {});
  368. return result;
  369. }
  370. else {
  371. const SYMBOL_FAKE_ONREADYSTATECHANGE = api.symbol('fake');
  372. api.ObjectDefineProperty(XMLHttpRequestPrototype, ON_READY_STATE_CHANGE, {
  373. enumerable: true,
  374. configurable: true,
  375. get: function () {
  376. return this[SYMBOL_FAKE_ONREADYSTATECHANGE];
  377. },
  378. set: function (value) {
  379. this[SYMBOL_FAKE_ONREADYSTATECHANGE] = value;
  380. },
  381. });
  382. const req = new XMLHttpRequest();
  383. const detectFunc = () => { };
  384. req.onreadystatechange = detectFunc;
  385. const result = req[SYMBOL_FAKE_ONREADYSTATECHANGE] === detectFunc;
  386. req.onreadystatechange = null;
  387. return result;
  388. }
  389. }
  390. const globalEventHandlersEventNames = [
  391. 'abort',
  392. 'animationcancel',
  393. 'animationend',
  394. 'animationiteration',
  395. 'auxclick',
  396. 'beforeinput',
  397. 'blur',
  398. 'cancel',
  399. 'canplay',
  400. 'canplaythrough',
  401. 'change',
  402. 'compositionstart',
  403. 'compositionupdate',
  404. 'compositionend',
  405. 'cuechange',
  406. 'click',
  407. 'close',
  408. 'contextmenu',
  409. 'curechange',
  410. 'dblclick',
  411. 'drag',
  412. 'dragend',
  413. 'dragenter',
  414. 'dragexit',
  415. 'dragleave',
  416. 'dragover',
  417. 'drop',
  418. 'durationchange',
  419. 'emptied',
  420. 'ended',
  421. 'error',
  422. 'focus',
  423. 'focusin',
  424. 'focusout',
  425. 'gotpointercapture',
  426. 'input',
  427. 'invalid',
  428. 'keydown',
  429. 'keypress',
  430. 'keyup',
  431. 'load',
  432. 'loadstart',
  433. 'loadeddata',
  434. 'loadedmetadata',
  435. 'lostpointercapture',
  436. 'mousedown',
  437. 'mouseenter',
  438. 'mouseleave',
  439. 'mousemove',
  440. 'mouseout',
  441. 'mouseover',
  442. 'mouseup',
  443. 'mousewheel',
  444. 'orientationchange',
  445. 'pause',
  446. 'play',
  447. 'playing',
  448. 'pointercancel',
  449. 'pointerdown',
  450. 'pointerenter',
  451. 'pointerleave',
  452. 'pointerlockchange',
  453. 'mozpointerlockchange',
  454. 'webkitpointerlockerchange',
  455. 'pointerlockerror',
  456. 'mozpointerlockerror',
  457. 'webkitpointerlockerror',
  458. 'pointermove',
  459. 'pointout',
  460. 'pointerover',
  461. 'pointerup',
  462. 'progress',
  463. 'ratechange',
  464. 'reset',
  465. 'resize',
  466. 'scroll',
  467. 'seeked',
  468. 'seeking',
  469. 'select',
  470. 'selectionchange',
  471. 'selectstart',
  472. 'show',
  473. 'sort',
  474. 'stalled',
  475. 'submit',
  476. 'suspend',
  477. 'timeupdate',
  478. 'volumechange',
  479. 'touchcancel',
  480. 'touchmove',
  481. 'touchstart',
  482. 'touchend',
  483. 'transitioncancel',
  484. 'transitionend',
  485. 'waiting',
  486. 'wheel',
  487. ];
  488. const documentEventNames = [
  489. 'afterscriptexecute',
  490. 'beforescriptexecute',
  491. 'DOMContentLoaded',
  492. 'freeze',
  493. 'fullscreenchange',
  494. 'mozfullscreenchange',
  495. 'webkitfullscreenchange',
  496. 'msfullscreenchange',
  497. 'fullscreenerror',
  498. 'mozfullscreenerror',
  499. 'webkitfullscreenerror',
  500. 'msfullscreenerror',
  501. 'readystatechange',
  502. 'visibilitychange',
  503. 'resume',
  504. ];
  505. const windowEventNames = [
  506. 'absolutedeviceorientation',
  507. 'afterinput',
  508. 'afterprint',
  509. 'appinstalled',
  510. 'beforeinstallprompt',
  511. 'beforeprint',
  512. 'beforeunload',
  513. 'devicelight',
  514. 'devicemotion',
  515. 'deviceorientation',
  516. 'deviceorientationabsolute',
  517. 'deviceproximity',
  518. 'hashchange',
  519. 'languagechange',
  520. 'message',
  521. 'mozbeforepaint',
  522. 'offline',
  523. 'online',
  524. 'paint',
  525. 'pageshow',
  526. 'pagehide',
  527. 'popstate',
  528. 'rejectionhandled',
  529. 'storage',
  530. 'unhandledrejection',
  531. 'unload',
  532. 'userproximity',
  533. 'vrdisplayconnected',
  534. 'vrdisplaydisconnected',
  535. 'vrdisplaypresentchange',
  536. ];
  537. const htmlElementEventNames = [
  538. 'beforecopy',
  539. 'beforecut',
  540. 'beforepaste',
  541. 'copy',
  542. 'cut',
  543. 'paste',
  544. 'dragstart',
  545. 'loadend',
  546. 'animationstart',
  547. 'search',
  548. 'transitionrun',
  549. 'transitionstart',
  550. 'webkitanimationend',
  551. 'webkitanimationiteration',
  552. 'webkitanimationstart',
  553. 'webkittransitionend',
  554. ];
  555. const ieElementEventNames = [
  556. 'activate',
  557. 'afterupdate',
  558. 'ariarequest',
  559. 'beforeactivate',
  560. 'beforedeactivate',
  561. 'beforeeditfocus',
  562. 'beforeupdate',
  563. 'cellchange',
  564. 'controlselect',
  565. 'dataavailable',
  566. 'datasetchanged',
  567. 'datasetcomplete',
  568. 'errorupdate',
  569. 'filterchange',
  570. 'layoutcomplete',
  571. 'losecapture',
  572. 'move',
  573. 'moveend',
  574. 'movestart',
  575. 'propertychange',
  576. 'resizeend',
  577. 'resizestart',
  578. 'rowenter',
  579. 'rowexit',
  580. 'rowsdelete',
  581. 'rowsinserted',
  582. 'command',
  583. 'compassneedscalibration',
  584. 'deactivate',
  585. 'help',
  586. 'mscontentzoom',
  587. 'msmanipulationstatechanged',
  588. 'msgesturechange',
  589. 'msgesturedoubletap',
  590. 'msgestureend',
  591. 'msgesturehold',
  592. 'msgesturestart',
  593. 'msgesturetap',
  594. 'msgotpointercapture',
  595. 'msinertiastart',
  596. 'mslostpointercapture',
  597. 'mspointercancel',
  598. 'mspointerdown',
  599. 'mspointerenter',
  600. 'mspointerhover',
  601. 'mspointerleave',
  602. 'mspointermove',
  603. 'mspointerout',
  604. 'mspointerover',
  605. 'mspointerup',
  606. 'pointerout',
  607. 'mssitemodejumplistitemremoved',
  608. 'msthumbnailclick',
  609. 'stop',
  610. 'storagecommit',
  611. ];
  612. const webglEventNames = ['webglcontextrestored', 'webglcontextlost', 'webglcontextcreationerror'];
  613. const formEventNames = ['autocomplete', 'autocompleteerror'];
  614. const detailEventNames = ['toggle'];
  615. const eventNames = [
  616. ...globalEventHandlersEventNames,
  617. ...webglEventNames,
  618. ...formEventNames,
  619. ...detailEventNames,
  620. ...documentEventNames,
  621. ...windowEventNames,
  622. ...htmlElementEventNames,
  623. ...ieElementEventNames,
  624. ];
  625. // Whenever any eventListener fires, we check the eventListener target and all parents
  626. // for `onwhatever` properties and replace them with zone-bound functions
  627. // - Chrome (for now)
  628. function patchViaCapturingAllTheEvents(api) {
  629. const unboundKey = api.symbol('unbound');
  630. for (let i = 0; i < eventNames.length; i++) {
  631. const property = eventNames[i];
  632. const onproperty = 'on' + property;
  633. self.addEventListener(property, function (event) {
  634. let elt = event.target, bound, source;
  635. if (elt) {
  636. source = elt.constructor['name'] + '.' + onproperty;
  637. }
  638. else {
  639. source = 'unknown.' + onproperty;
  640. }
  641. while (elt) {
  642. if (elt[onproperty] && !elt[onproperty][unboundKey]) {
  643. bound = api.wrapWithCurrentZone(elt[onproperty], source);
  644. bound[unboundKey] = elt[onproperty];
  645. elt[onproperty] = bound;
  646. }
  647. elt = elt.parentElement;
  648. }
  649. }, true);
  650. }
  651. }
  652. function registerElementPatch(_global, api) {
  653. const { isBrowser, isMix } = api.getGlobalObjects();
  654. if ((!isBrowser && !isMix) || !('registerElement' in _global.document)) {
  655. return;
  656. }
  657. const callbacks = [
  658. 'createdCallback',
  659. 'attachedCallback',
  660. 'detachedCallback',
  661. 'attributeChangedCallback',
  662. ];
  663. api.patchCallbacks(api, document, 'Document', 'registerElement', callbacks);
  664. }
  665. /**
  666. * @fileoverview
  667. * @suppress {missingRequire}
  668. */
  669. function patchBrowserLegacy() {
  670. const _global = typeof window !== 'undefined'
  671. ? window
  672. : typeof global !== 'undefined'
  673. ? global
  674. : typeof self !== 'undefined'
  675. ? self
  676. : {};
  677. const symbolPrefix = _global['__Zone_symbol_prefix'] || '__zone_symbol__';
  678. function __symbol__(name) {
  679. return symbolPrefix + name;
  680. }
  681. _global[__symbol__('legacyPatch')] = function () {
  682. const Zone = _global['Zone'];
  683. Zone.__load_patch('defineProperty', (global, Zone, api) => {
  684. api._redefineProperty = _redefineProperty;
  685. propertyPatch();
  686. });
  687. Zone.__load_patch('registerElement', (global, Zone, api) => {
  688. registerElementPatch(global, api);
  689. });
  690. Zone.__load_patch('EventTargetLegacy', (global, Zone, api) => {
  691. eventTargetLegacyPatch(global, api);
  692. propertyDescriptorLegacyPatch(api, global);
  693. });
  694. };
  695. }
  696. patchBrowserLegacy();