UI for Zipcoin Blue

timers.ts 4.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  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. /**
  9. * @fileoverview
  10. * @suppress {missingRequire}
  11. */
  12. import {patchMethod, scheduleMacroTaskWithCurrentZone, zoneSymbol} from './utils';
  13. const taskSymbol = zoneSymbol('zoneTask');
  14. interface TimerOptions extends TaskData {
  15. handleId: number;
  16. args: any[];
  17. }
  18. export function patchTimer(window: any, setName: string, cancelName: string, nameSuffix: string) {
  19. let setNative: Function = null;
  20. let clearNative: Function = null;
  21. setName += nameSuffix;
  22. cancelName += nameSuffix;
  23. const tasksByHandleId: {[id: number]: Task} = {};
  24. function scheduleTask(task: Task) {
  25. const data = <TimerOptions>task.data;
  26. function timer() {
  27. try {
  28. task.invoke.apply(this, arguments);
  29. } finally {
  30. // issue-934, task will be cancelled
  31. // even it is a periodic task such as
  32. // setInterval
  33. if (!(task.data && task.data.isPeriodic)) {
  34. if (typeof data.handleId === 'number') {
  35. // in non-nodejs env, we remove timerId
  36. // from local cache
  37. delete tasksByHandleId[data.handleId];
  38. } else if (data.handleId) {
  39. // Node returns complex objects as handleIds
  40. // we remove task reference from timer object
  41. (data.handleId as any)[taskSymbol] = null;
  42. }
  43. }
  44. }
  45. }
  46. data.args[0] = timer;
  47. data.handleId = setNative.apply(window, data.args);
  48. return task;
  49. }
  50. function clearTask(task: Task) {
  51. return clearNative((<TimerOptions>task.data).handleId);
  52. }
  53. setNative =
  54. patchMethod(window, setName, (delegate: Function) => function(self: any, args: any[]) {
  55. if (typeof args[0] === 'function') {
  56. const options: TimerOptions = {
  57. handleId: null,
  58. isPeriodic: nameSuffix === 'Interval',
  59. delay: (nameSuffix === 'Timeout' || nameSuffix === 'Interval') ? args[1] || 0 : null,
  60. args: args
  61. };
  62. const task =
  63. scheduleMacroTaskWithCurrentZone(setName, args[0], options, scheduleTask, clearTask);
  64. if (!task) {
  65. return task;
  66. }
  67. // Node.js must additionally support the ref and unref functions.
  68. const handle: any = (<TimerOptions>task.data).handleId;
  69. if (typeof handle === 'number') {
  70. // for non nodejs env, we save handleId: task
  71. // mapping in local cache for clearTimeout
  72. tasksByHandleId[handle] = task;
  73. } else if (handle) {
  74. // for nodejs env, we save task
  75. // reference in timerId Object for clearTimeout
  76. handle[taskSymbol] = task;
  77. }
  78. // check whether handle is null, because some polyfill or browser
  79. // may return undefined from setTimeout/setInterval/setImmediate/requestAnimationFrame
  80. if (handle && handle.ref && handle.unref && typeof handle.ref === 'function' &&
  81. typeof handle.unref === 'function') {
  82. (<any>task).ref = (<any>handle).ref.bind(handle);
  83. (<any>task).unref = (<any>handle).unref.bind(handle);
  84. }
  85. if (typeof handle === 'number' || handle) {
  86. return handle;
  87. }
  88. return task;
  89. } else {
  90. // cause an error by calling it directly.
  91. return delegate.apply(window, args);
  92. }
  93. });
  94. clearNative =
  95. patchMethod(window, cancelName, (delegate: Function) => function(self: any, args: any[]) {
  96. const id = args[0];
  97. let task: Task;
  98. if (typeof id === 'number') {
  99. // non nodejs env.
  100. task = tasksByHandleId[id];
  101. } else {
  102. // nodejs env.
  103. task = id && id[taskSymbol];
  104. // other environments.
  105. if (!task) {
  106. task = id;
  107. }
  108. }
  109. if (task && typeof task.type === 'string') {
  110. if (task.state !== 'notScheduled' &&
  111. (task.cancelFn && task.data.isPeriodic || task.runCount === 0)) {
  112. if (typeof id === 'number') {
  113. delete tasksByHandleId[id];
  114. } else if (id) {
  115. id[taskSymbol] = null;
  116. }
  117. // Do not cancel already canceled functions
  118. task.zone.cancelTask(task);
  119. }
  120. } else {
  121. // cause an error by calling it directly.
  122. delegate.apply(window, args);
  123. }
  124. });
  125. }