event-target.ts 4.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  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 {globalSources, patchEventPrototype, patchEventTarget, zoneSymbolEventNames} from '../common/events';
  9. import {FALSE_STR, isIEOrEdge, TRUE_STR, ZONE_SYMBOL_PREFIX} from '../common/utils';
  10. import {eventNames} from './property-descriptor';
  11. export function eventTargetPatch(_global: any, api: _ZonePrivate) {
  12. const WTF_ISSUE_555 =
  13. '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';
  14. const NO_EVENT_TARGET =
  15. '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'
  16. .split(',');
  17. const EVENT_TARGET = 'EventTarget';
  18. let apis = [];
  19. const isWtf = _global['wtf'];
  20. const WTF_ISSUE_555_ARRAY = WTF_ISSUE_555.split(',');
  21. if (isWtf) {
  22. // Workaround for: https://github.com/google/tracing-framework/issues/555
  23. apis = WTF_ISSUE_555_ARRAY.map((v) => 'HTML' + v + 'Element').concat(NO_EVENT_TARGET);
  24. } else if (_global[EVENT_TARGET]) {
  25. apis.push(EVENT_TARGET);
  26. } else {
  27. // Note: EventTarget is not available in all browsers,
  28. // if it's not available, we instead patch the APIs in the IDL that inherit from EventTarget
  29. apis = NO_EVENT_TARGET;
  30. }
  31. const isDisableIECheck = _global['__Zone_disable_IE_check'] || false;
  32. const isEnableCrossContextCheck = _global['__Zone_enable_cross_context_check'] || false;
  33. const ieOrEdge = isIEOrEdge();
  34. const ADD_EVENT_LISTENER_SOURCE = '.addEventListener:';
  35. const FUNCTION_WRAPPER = '[object FunctionWrapper]';
  36. const BROWSER_TOOLS = 'function __BROWSERTOOLS_CONSOLE_SAFEFUNC() { [native code] }';
  37. // predefine all __zone_symbol__ + eventName + true/false string
  38. for (let i = 0; i < eventNames.length; i++) {
  39. const eventName = eventNames[i];
  40. const falseEventName = eventName + FALSE_STR;
  41. const trueEventName = eventName + TRUE_STR;
  42. const symbol = ZONE_SYMBOL_PREFIX + falseEventName;
  43. const symbolCapture = ZONE_SYMBOL_PREFIX + trueEventName;
  44. zoneSymbolEventNames[eventName] = {};
  45. zoneSymbolEventNames[eventName][FALSE_STR] = symbol;
  46. zoneSymbolEventNames[eventName][TRUE_STR] = symbolCapture;
  47. }
  48. // predefine all task.source string
  49. for (let i = 0; i < WTF_ISSUE_555.length; i++) {
  50. const target: any = WTF_ISSUE_555_ARRAY[i];
  51. const targets: any = globalSources[target] = {};
  52. for (let j = 0; j < eventNames.length; j++) {
  53. const eventName = eventNames[j];
  54. targets[eventName] = target + ADD_EVENT_LISTENER_SOURCE + eventName;
  55. }
  56. }
  57. const checkIEAndCrossContext = function(
  58. nativeDelegate: any, delegate: any, target: any, args: any) {
  59. if (!isDisableIECheck && ieOrEdge) {
  60. if (isEnableCrossContextCheck) {
  61. try {
  62. const testString = delegate.toString();
  63. if ((testString === FUNCTION_WRAPPER || testString == BROWSER_TOOLS)) {
  64. nativeDelegate.apply(target, args);
  65. return false;
  66. }
  67. } catch (error) {
  68. nativeDelegate.apply(target, args);
  69. return false;
  70. }
  71. } else {
  72. const testString = delegate.toString();
  73. if ((testString === FUNCTION_WRAPPER || testString == BROWSER_TOOLS)) {
  74. nativeDelegate.apply(target, args);
  75. return false;
  76. }
  77. }
  78. } else if (isEnableCrossContextCheck) {
  79. try {
  80. delegate.toString();
  81. } catch (error) {
  82. nativeDelegate.apply(target, args);
  83. return false;
  84. }
  85. }
  86. return true;
  87. };
  88. const apiTypes: any[] = [];
  89. for (let i = 0; i < apis.length; i++) {
  90. const type = _global[apis[i]];
  91. apiTypes.push(type && type.prototype);
  92. }
  93. // vh is validateHandler to check event handler
  94. // is valid or not(for security check)
  95. patchEventTarget(_global, apiTypes, {vh: checkIEAndCrossContext});
  96. api.patchEventTarget = patchEventTarget;
  97. return true;
  98. }
  99. export function patchEvent(global: any, api: _ZonePrivate) {
  100. patchEventPrototype(global, api);
  101. }