dcp-client 4.1.13 → 4.1.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"browser":["deny-node","kvin/kvin.js","script-load-wrapper","primitive-timers","event-loop-virtualization","access-lists","bravojs-init","bravojs/bravo.js","bravojs-env","calculate-capabilities","bootstrap"],"node":["kvin/kvin.js","sa-ww-simulation","script-load-wrapper","primitive-timers","event-loop-virtualization","access-lists","bravojs-init","bravojs/bravo.js","bravojs-env","calculate-capabilities","bootstrap"],"native":["deny-node","kvin/kvin.js","sa-ww-simulation","script-load-wrapper","event-loop-virtualization","access-lists","bravojs-init","bravojs/bravo.js","bravojs-env","calculate-capabilities","bootstrap"],"webGpuNative":["deny-node","kvin/kvin.js","sa-ww-simulation","script-load-wrapper","event-loop-virtualization","access-lists","bravojs-init","bravojs/bravo.js","bravojs-env","calculate-capabilities","webgpu-worker-environment.js","bootstrap"],"nodeTesting":["kvin/kvin.js","sa-ww-simulation","script-load-wrapper","primitive-timers","event-loop-virtualization","access-lists","bravojs-init","bravojs/bravo.js","bravojs-env","calculate-capabilities","bootstrap","testing.js"],"testing":["deny-node","kvin/kvin.js","sa-ww-simulation","script-load-wrapper","event-loop-virtualization","access-lists","bravojs-init","bravojs/bravo.js","bravojs-env","calculate-capabilities","bootstrap","testing.js"]}
1
+ {"browser":["deny-node","kvin/kvin.js","script-load-wrapper","wrap-event-listeners","event-loop-virtualization","access-lists","bravojs-init","bravojs/bravo.js","bravojs-env","calculate-capabilities","bootstrap"],"node":["kvin/kvin.js","sa-ww-simulation","script-load-wrapper","wrap-event-listeners","event-loop-virtualization","access-lists","bravojs-init","bravojs/bravo.js","bravojs-env","calculate-capabilities","bootstrap"],"native":["deny-node","kvin/kvin.js","sa-ww-simulation","script-load-wrapper","native-event-loop","wrap-event-listeners","event-loop-virtualization","access-lists","bravojs-init","bravojs/bravo.js","bravojs-env","calculate-capabilities","bootstrap"],"webGpuNative":["deny-node","kvin/kvin.js","sa-ww-simulation","script-load-wrapper","native-event-loop","wrap-event-listeners","event-loop-virtualization","access-lists","bravojs-init","bravojs/bravo.js","bravojs-env","calculate-capabilities","webgpu-worker-environment.js","bootstrap"],"nodeTesting":["kvin/kvin.js","sa-ww-simulation","script-load-wrapper","wrap-event-listeners","event-loop-virtualization","access-lists","bravojs-init","bravojs/bravo.js","bravojs-env","calculate-capabilities","bootstrap","testing.js"],"testing":["deny-node","kvin/kvin.js","sa-ww-simulation","script-load-wrapper","native-event-loop","wrap-event-listeners","event-loop-virtualization","access-lists","bravojs-init","bravojs/bravo.js","bravojs-env","calculate-capabilities","bootstrap","testing.js"]}
package/index.js CHANGED
@@ -29,6 +29,7 @@ const os = require('os');
29
29
  const fs = require('fs')
30
30
  const path = require('path');
31
31
  const process = require('process');
32
+ const kvin = require('kvin');
32
33
  const moduleSystem = require('module');
33
34
  const { spawnSync } = require('child_process');
34
35
  const { createContext, runInContext } = require('vm');
@@ -690,7 +691,6 @@ exports.initSync = function dcpClient$$initSync() {
690
691
  finalBundleCode = exports.fetchSync(finalBundleURL);
691
692
  } catch(e) {
692
693
  console.error('Error downloading autoUpdate bundle from ' + finalBundleURL);
693
- console.log(require('dcp/utils').justFetchPrettyError(e));
694
694
  throw e;
695
695
  }
696
696
  }
@@ -810,7 +810,7 @@ exports.createAggregateConfig = async function dcpClient$$createAggregateConfig(
810
810
  if (!aggrConfig.scheduler.configLocation &&
811
811
  aggrConfig.scheduler.configLocation !== false) {
812
812
  addConfigs(aggrConfig.scheduler, localConfig.scheduler, {
813
- configLocation: new URL(`${aggrConfig.scheduler.location}etc/dcp-config.js`)
813
+ configLocation: new URL(`${aggrConfig.scheduler.location}etc/dcp-config.kvin`)
814
814
  });
815
815
  }
816
816
 
@@ -822,9 +822,9 @@ exports.createAggregateConfig = async function dcpClient$$createAggregateConfig(
822
822
  try {
823
823
  debugging() && console.debug(` * Loading configuration from ${aggrConfig.scheduler.configLocation.href}`);
824
824
  remoteConfigCode = await require('dcp/protocol').fetchSchedulerConfig(aggrConfig.scheduler.configLocation);
825
+ remoteConfigCode = kvin.deserialize(remoteConfigCode);
825
826
  } catch(e) {
826
827
  console.error('Error: dcp-client::init could not fetch scheduler configuration at', '' + aggrConfig.scheduler.configLocation);
827
- console.log(require('dcp/utils').justFetchPrettyError(e));
828
828
  throw e;
829
829
  }
830
830
  if (remoteConfigCode.length === 0)
@@ -93,6 +93,10 @@ function StandaloneWorker(options = {}) {
93
93
  socket.setNoDelay(dcpConfig.worker ? dcpConfig.worker.nagle : true);
94
94
  socket.connect(port, hostname);
95
95
  socket.on('connect', beginSession.bind(this));
96
+ socket.on('end', () => {
97
+ connected = false;
98
+ ee.emit('end')
99
+ })
96
100
  socket.on('error', function saWorker$$socket$errorHandler(e) {
97
101
  connecting = false;
98
102
  if (!dcpConfig.standaloneWorker.quiet)
@@ -279,7 +283,7 @@ function StandaloneWorker(options = {}) {
279
283
  /* Shutdown the stream(s) which are connected to the evaluator */
280
284
  shutdown = (e) => {
281
285
  if (connectTimer) {
282
- clearTimeout(connectTimer);
286
+ clearBackoffInterval(connectTimer);
283
287
  connectTimer = true;
284
288
  }
285
289
 
@@ -309,6 +313,7 @@ function StandaloneWorker(options = {}) {
309
313
  * type DIE:, which in turn eventuallys triggers shutdown.
310
314
  */
311
315
  this.terminate = function standaloneWorker$$Worker$terminate () {
316
+ debugging() && console.log(`312: saw.terminate on Evaluator ${this.serial}`);
312
317
  var wrappedMessage = this.serialize({ type: 'die' }) + '\n'
313
318
 
314
319
  try {
@@ -317,6 +322,11 @@ function StandaloneWorker(options = {}) {
317
322
  // Socket may have already been destroyed
318
323
  }
319
324
 
325
+ if (connectTimer) {
326
+ clearBackoffInterval(connectTimer);
327
+ connectTimer = true;
328
+ }
329
+
320
330
  /* If DIE: response doesn't arrive in a reasonable time -- clean up */
321
331
  dieTimer = setTimeout(shutdown, 7000);
322
332
  }
@@ -84,29 +84,34 @@ exports.Evaluator = function Evaluator(inputStream, outputStream, files) {
84
84
  codeGeneration: { strings: true, wasm: true },
85
85
  });
86
86
 
87
- for(const file of files) {
88
- fd = fs.openSync(file, 'r');
89
- if (mmap) {
90
- fs.flockSync(fd, 'sh');
91
- bootstrapCode = mmap.map(fs.fstatSync(fd).size, mmap.PROT_READ, mmap.MAP_SHARED, fd, 0, mmap.MADV_SEQUENTIAL).toString('utf8');
92
- } else {
93
- bootstrapCode = fs.readFileSync(fd, 'utf-8');
87
+ if(files) {
88
+ for(const file of files) {
89
+ fd = fs.openSync(file, 'r');
90
+ if (mmap) {
91
+ fs.flockSync(fd, 'sh');
92
+ bootstrapCode = mmap.map(fs.fstatSync(fd).size, mmap.PROT_READ, mmap.MAP_SHARED, fd, 0, mmap.MADV_SEQUENTIAL).toString('utf8');
93
+ } else {
94
+ bootstrapCode = fs.readFileSync(fd, 'utf-8');
95
+ }
96
+ fs.closeSync(fd);
97
+
98
+ vm.runInContext(bootstrapCode, this.sandboxGlobal, {
99
+ filename: path.basename(file),
100
+ lineOffset: 0,
101
+ columnOffset: 0,
102
+ contextName: 'Evaluator #' + this.id,
103
+ contextCodeGeneration: {
104
+ wasm: true,
105
+ strings: true
106
+ },
107
+ displayErrors: true,
108
+ timeout: 3600 * 1000, /* gives us our own event loop; this is max time for one pass run-to-completion */
109
+ breakOnSigInt: true /* also gives us our own event loop */
110
+ });
94
111
  }
95
- fs.closeSync(fd);
96
-
97
- vm.runInContext(bootstrapCode, this.sandboxGlobal, {
98
- filename: path.basename(file),
99
- lineOffset: 0,
100
- columnOffset: 0,
101
- contextName: 'Evaluator #' + this.id,
102
- contextCodeGeneration: {
103
- wasm: true,
104
- strings: true
105
- },
106
- displayErrors: true,
107
- timeout: 3600 * 1000, /* gives us our own event loop; this is max time for one pass run-to-completion */
108
- breakOnSigInt: true /* also gives us our own event loop */
109
- });
112
+ } else {
113
+ console.error('There are no files to run in the node evaluator -- this is ok in the presence of other errors.');
114
+ process.exit(1);
110
115
  }
111
116
 
112
117
  /* Pass any new data on the input stream to the onreadln()
@@ -84,6 +84,7 @@ self.wrapScriptLoading({ scriptName: 'access-lists', ringTransition: true }, (ri
84
84
  'Set',
85
85
  'setInterval',
86
86
  'setTimeout',
87
+ 'setImmediate',
87
88
  'sleep',
88
89
  'String',
89
90
  'Symbol',
@@ -560,11 +561,11 @@ self.wrapScriptLoading({ scriptName: 'access-lists', ringTransition: true }, (ri
560
561
 
561
562
  addEventListener('message', async (event) => {
562
563
  try {
563
- if (event.data.request === 'applyRequirements') {
564
+ if (event.request === 'applyRequirements') {
564
565
  // This event is fired when the worker is initialized with job requirements,
565
566
  // apply restrictions to the environment based on the requirements.
566
567
  // Assume the scheduler gave us a nicely-shaped req object.
567
- const requirements = event.data.requirements;
568
+ const requirements = event.requirements;
568
569
  blockList.OffscreenCanvas = !requirements.environment.offscreenCanvas;
569
570
  applyAllAccessLists();
570
571
 
@@ -22,11 +22,11 @@ self.wrapScriptLoading({ scriptName: 'bootstrap', finalScript: true }, (ring2Pos
22
22
  addEventListener('message', async (event) => {
23
23
  try {
24
24
  var indirectEval = eval // eslint-disable-line
25
- if (event.data.request === 'eval') {
25
+ if (event.request === 'eval') {
26
26
  try {
27
- let result = await indirectEval(event.data.data, event.data.filename)
27
+ let result = await indirectEval(event.data, event.filename)
28
28
  ring2PostMessage({
29
- request: `evalResult::${event.data.msgId}`,
29
+ request: `evalResult::${event.msgId}`,
30
30
  data: result
31
31
  })
32
32
  } catch (error) {
@@ -42,7 +42,7 @@ self.wrapScriptLoading({ scriptName: 'bootstrap', finalScript: true }, (ring2Pos
42
42
  }
43
43
  })
44
44
  }
45
- } else if (event.data.request === 'resetState') {
45
+ } else if (event.request === 'resetState') {
46
46
  // This event is fired when the web worker is about to be reused with another slice
47
47
  lastProgress = 0;
48
48
  postMessageSentTime = 0;
@@ -23,7 +23,7 @@ self.wrapScriptLoading({ scriptName: 'bravojs-env', ringTransition: true }, (rin
23
23
  }
24
24
  //Listens for postMessage from the sandbox
25
25
  addEventListener('message', async (event) => {
26
- let message = event.data
26
+ let message = event
27
27
  let indirectEval = eval // eslint-disable-line
28
28
  switch (message.request) {
29
29
  case 'moduleGroup': /* Outside environment is sending us a module group */
@@ -173,7 +173,7 @@ self.wrapScriptLoading(
173
173
 
174
174
  addEventListener('message', async (event) => {
175
175
  try {
176
- if (event.data.request === 'describe') {
176
+ if (event.request === 'describe') {
177
177
  const capabilities = await getCapabilities();
178
178
  ring2PostMessage({
179
179
  capabilities,
@@ -5,87 +5,71 @@
5
5
  * This gives DCP introspection capability to see how long a job
6
6
  * should take, and how we can pay DCCs accordingly.
7
7
  *
8
- * The node, v8, and web worker evaluators have been modified to
9
- * provide the following primitive functions onto the global object
10
- * when this program is evaluated:
11
- * - ontimer will be invoked by the reactor when there are timers that
12
- * should need servicing based on the information provided to nextTimer().
13
- * - nextTimer() sets when the next timer will be fired (in ms)
14
- * - evalTimer evaluates using either the actual setImmediate/setTimeout or uses
15
- * Promise.resolve.then as a fallback
16
- *
17
- * Once this file has run, the following methods will be
18
- * available on the global object for every evaluator:
19
- * - setTimeout() execute callback after minimum timeout time in ms
20
- * - clearTimeout() clear the timeout created by setTimeout
21
- * - setInterval() recurringly execute callback after minimum timeout time in ms
22
- * - clearInterval() clear the interval created by setInterval
23
- * - queueMicrotask() add a microtask to the microtask queue, bypassing 4ms timeout clamping
8
+ * All evaluators have their own implementation of the event loop at this
9
+ * point, with corresponding timeout functions for their loop. This file will
10
+ * create a wrapper for each of the timeouts, with a virtual event loop
11
+ * to control code execution.
24
12
  *
25
- * @author Parker Rowe, parker@kingsds.network
26
- * @date August 2020
13
+ * Ryan Saweczko, ryansaweczko@kingsds.network
14
+ * @date January 2022
27
15
  *
28
- * @note Unusual function scoping is done to eliminate spurious symbols
29
- * from being accessible from the global object, to mitigate
30
- * certain classes of security risks. The global object here is
31
- * the top of the scope chain (ie global object) for all code run
32
- * by hosts in this environment.
33
16
  */
34
- /* globals self, ontimer, nextTimer, evalTimer */
17
+ /* globals self */
18
+
35
19
 
36
20
  self.wrapScriptLoading({ scriptName: 'event-loop-virtualization' }, (ring0PostMessage) => {
37
- let lastTimeStamp;
38
-
39
- if (typeof self.evalTimer === 'undefined'){
40
- self.evalTimer = (func) => Promise.resolve().then(func);
41
- }
42
-
43
- (function privateScope(ontimer, nextTimer, evalTimer) {
44
- const timers = [];
45
- timers.serial = 0; /* If this isn't set, it becomes NaN */
46
-
47
- function sortTimers() {
48
- timers.sort(function (a, b) { return a.when - b.when; });
21
+
22
+ (function privateScope(realSetTimeout, realSetInterval, realSetImmediate, realClearTimeout, realClearInterval, realClearImmediate) {
23
+ let totalCPUTime = 0;
24
+ const events = [];
25
+ events.serial = 0;
26
+
27
+ function sortEvents() {
28
+ events.sort(function (a, b) { return a.when - b.when; });
49
29
  }
50
30
 
51
- /* Fire any timers which are ready to run, being careful not to
52
- * get into a recurring timer death loop without reactor mediation.
53
- */
54
- ontimer(function fireTimerCallbacks() {
55
- let now = Date.now();
31
+ function serviceEvents()
32
+ {
33
+ serviceEvents.timeout = null;
34
+ serviceEvents.nextTimeout = null;
35
+ serviceEvents.servicing = true;
56
36
 
57
- sortTimers();
58
- for (let i = 0; i < timers.length; ++i) {
59
- let timer = timers[i];
60
- if (timer.when > now) {
61
- break;
62
- }
37
+ const startTime = performance.now();
38
+ let now = Date.now();
63
39
 
64
- let measurementWrapper = async () => {
65
- if (lastTimeStamp) {
66
- ring0PostMessage({
67
- request: 'measurement',
68
- idle: performance.now() - lastTimeStamp
69
- });
40
+ sortEvents();
41
+ if (events[0].when <= now)
42
+ {
43
+ const event = events.shift();
44
+ if (event.eventType === 'timer')
45
+ {
46
+ serviceEvents.executingTimeout = realSetTimeout(event.fn, 0, event.args);
47
+ if (event.recur)
48
+ {
49
+ event.when = Date.now() + event.recur;
50
+ events.push(event);
51
+ sortEvents();
70
52
  }
71
-
72
- lastTimeStamp = performance.now();
73
- await timer.fn();
74
- lastTimeStamp = performance.now();
75
53
  }
76
- Promise.resolve().then(measurementWrapper);
54
+ // Can add handles for events to the event loop as needed (ie messages)
55
+ }
77
56
 
78
- if (timer.recur) {
79
- timer.when = Date.now() + timer.recur;
80
- } else {
81
- timers.splice(i--, 1);
57
+ // Measure the time on the event loop after everything has executed
58
+ serviceEvents.measurerTimeout = realSetTimeout(endOfRealEventCycle,1);
59
+ function endOfRealEventCycle()
60
+ {
61
+ serviceEvents.servicing = false;
62
+ const endTime = performance.now();
63
+ totalCPUTime += endTime - startTime;
64
+
65
+ // Set timeout to rerun this function if there are events remaining that just can't be used yet
66
+ if (events.length > 0)
67
+ {
68
+ serviceEvents.nextTimeout = events[0].when
69
+ serviceEvents.timeout = realSetTimeout(serviceEvents, events[0].when - Date.now());
82
70
  }
83
71
  }
84
- if (timers.length) {
85
- sortTimers();
86
- nextTimer(timers[0].when);
87
- }
88
- });
72
+ }
89
73
 
90
74
  /** Execute callback after at least timeout ms.
91
75
  *
@@ -94,7 +78,8 @@ self.wrapScriptLoading({ scriptName: 'event-loop-virtualization' }, (ring0PostMe
94
78
  * @param arg array of arguments to be applied to the callback function
95
79
  * @returns {object} A value which may be used as the timeoutId parameter of clearTimeout()
96
80
  */
97
- self.setTimeout = function eventLoop$$Worker$setTimeout(callback, timeout, arg) {
81
+ setTimeout = function eventLoop$$Worker$setTimeout(callback, timeout, arg) {
82
+ timeout = timeout || 0;
98
83
  let timer, args;
99
84
  if (typeof callback === 'string') {
100
85
  let code = callback;
@@ -112,18 +97,30 @@ self.wrapScriptLoading({ scriptName: 'event-loop-virtualization' }, (ring0PostMe
112
97
  callback = () => fn.apply(fn, args); // apply the arguments to the callback function
113
98
  }
114
99
 
115
- timers.serial = +timers.serial + 1;
100
+ events.serial = +events.serial + 1;
116
101
  timer = {
102
+ eventType: 'timer',
117
103
  fn: callback,
118
104
  when: Date.now() + (+timeout || 0),
119
- serial: timers.serial,
105
+ serial: events.serial,
120
106
  valueOf: function () { return this.serial; }
121
107
  }
122
- timers.push(timer);
123
- lastTimeStamp = performance.now();
124
- if (timer.when <= timers[0].when) {
125
- sortTimers();
126
- nextTimer(timers[0].when);
108
+ events.push(timer);
109
+ sortEvents();
110
+ if (!serviceEvents.servicing)
111
+ {
112
+ if (!serviceEvents.nextTimeout)
113
+ {
114
+ realSetTimeout(serviceEvents, events[0].when - Date.now());
115
+ }
116
+ else
117
+ {
118
+ if (serviceEvents.nextTimeout > events[0].when)
119
+ {
120
+ realClearTimeout(serviceEvents.timeout);
121
+ realSetTimeout(serviceEvents, events[0].when - Date.now())
122
+ }
123
+ }
127
124
  }
128
125
  return timer;
129
126
  }
@@ -133,42 +130,38 @@ self.wrapScriptLoading({ scriptName: 'event-loop-virtualization' }, (ring0PostMe
133
130
  *
134
131
  * @param timeoutId {object} The value, returned from setTimeout(), identifying the timer.
135
132
  */
136
- self.clearTimeout = function eventLoop$$Worker$clearTimeout(timeoutId) {
137
- if (typeof timeoutId === "object") {
138
- let i = timers.indexOf(timeoutId);
139
- if (i != -1) {
140
- timers.splice(i, 1);
141
-
142
- /* if there is a timer at the top of the timers list, set that to be the nextTimer to fire
143
- * otherwise, tell the event loop that there are no more timers to fire, and end the loop accordingly.
144
- * this fixes a bug where you clear a timeout, but the program still waits that time before ending,
145
- * despite never calling the callback function
146
- *
147
- * for example:
148
- * const timeout = setTimeout(() => console.log("hi"), 10000);
149
- * clearTimeout(timeout);
150
- *
151
- * used to still wait 10 seconds before closing the program, despite never printing hi to the console
152
- */
153
- if (timers.length) {
154
- nextTimer(timers[0].when);
155
- }
156
- else {
157
- nextTimer(0);
133
+ clearTimeout = function eventLoop$$Worker$clearTimeout(timeoutId)
134
+ {
135
+ function checkService()
136
+ {
137
+ if (!serviceEvents.servicing)
138
+ {
139
+ if (events.length)
140
+ {
141
+ realClearTimeout(serviceEvents.timeout);
142
+ realSetTimeout(serviceEvents, events[0].when - Date.now())
158
143
  }
144
+ else
145
+ realClearTimeout(serviceEvents.timeout);
159
146
  }
160
- } else if (typeof timeoutId === "number") { /* slow path - object has been reinterpreted in terms of valueOf() */
161
- for (let i = 0; i < timers.length; i++) {
162
- if (timers[i].serial === timeoutId) {
163
- timers.splice(i, 1);
164
-
165
- if (timers.length) {
166
- nextTimer(timers[0].when);
167
- }
168
- else {
169
- nextTimer(0);
170
- }
171
-
147
+ }
148
+ if (typeof timeoutId === "object")
149
+ {
150
+ let i = events.indexOf(timeoutId);
151
+ if (i !== -1)
152
+ events.splice(i, 1);
153
+ if (i === 0)
154
+ checkService()
155
+ }
156
+ else if (typeof timeoutId === "number")
157
+ { /* slow path - object has been reinterpreted in terms of valueOf() */
158
+ for (let i = 0; i < events.length; i++)
159
+ {
160
+ if (events[i].serial === timeoutId)
161
+ {
162
+ events.splice(i, 1);
163
+ if (i === 0)
164
+ checkService()
172
165
  break;
173
166
  }
174
167
  }
@@ -182,41 +175,63 @@ self.wrapScriptLoading({ scriptName: 'event-loop-virtualization' }, (ring0PostMe
182
175
  * @param arg array of arguments to be applied to the callback function
183
176
  * @returns {object} A value which may be used as the intervalId paramter of clearInterval()
184
177
  */
185
- self.setInterval = function eventLoop$$Worker$setInterval(callback, interval, arg) {
186
- let timer = self.setTimeout(callback, +interval || 0, arg);
178
+ setInterval = function eventLoop$$Worker$setInterval(callback, interval, arg)
179
+ {
180
+ let timer = setTimeout(callback, +interval || 0, arg);
187
181
  timer.recur = interval;
188
182
  return timer;
189
183
  }
184
+ /** Execute callback after 0 ms, immediately when the event loop allows.
185
+ *
186
+ * @param callback {function} Callback function to fire after a minimum callback time
187
+ * @param arg array of arguments to be applied to the callback function
188
+ * @returns {object} A value which may be used as the intervalId paramter of clearImmediate()
189
+ */
190
+ setImmediate = function eventLoop$$Worker$setImmediate(callback, arg) {
191
+ let timer = setTimeout(callback, 0, arg);
192
+ return timer;
193
+ }
190
194
 
191
195
  /** Remove an interval timer from the list of pending interval timers, regardless of its current
192
196
  * status. (Same as clearTimeout)
193
197
  *
194
198
  * @param intervalId {object} The value, returned from setInterval(), identifying the timer.
195
199
  */
196
- self.clearInterval = self.clearTimeout;
200
+ clearInterval = clearTimeout;
201
+ clearImmediate = clearTimeout
197
202
 
198
203
  /** queues a microtask to be executed at a safe time prior to control returning to the event loop
199
204
  *
200
205
  * @param callback {function} Callback function to fire
201
206
  */
202
- self.queueMicrotask = function eventLoop$$Worker$queueMicrotask(callback) {
207
+ queueMicrotask = function eventLoop$$Worker$queueMicrotask(callback) {
203
208
  Promise.resolve().then(callback);
204
209
  }
205
210
 
206
211
  function clearAllTimers() {
207
- timers.length = 0;
208
- nextTimer(0);
209
- lastTimeStamp = null;
212
+ events.length = 0;
213
+ realClearTimeout(serviceEvents.timeout);
214
+ realClearTimeout(serviceEvents.measurerTimeout);
215
+ realClearTimeout(serviceEvents.executingTimeout);
210
216
  }
211
217
 
212
218
  addEventListener('message', async (event) => {
213
219
  try {
214
- if (event.data.request === 'clearTimers') {
220
+ if (event.request === 'clearTimers') {
215
221
  clearAllTimers();
216
222
  ring0PostMessage({
217
223
  request: 'clearTimersDone',
218
224
  });
219
225
  }
226
+ else if (event.request === 'resetAndGetCPUTime')
227
+ {
228
+ const cpuTime = totalCPUTime;
229
+ totalCPUTime = 0;
230
+ ring0PostMessage({
231
+ request: 'totalCPUTime',
232
+ CPU: cpuTime
233
+ })
234
+ }
220
235
  } catch (error) {
221
236
  ring0PostMessage({
222
237
  request: 'error',
@@ -228,10 +243,12 @@ self.wrapScriptLoading({ scriptName: 'event-loop-virtualization' }, (ring0PostMe
228
243
  });
229
244
  }
230
245
  });
231
- })(self.ontimer, self.nextTimer, self.evalTimer);
232
-
233
- ontimer = nextTimer = evalTimer = undefined;
234
- delete self.ontimer;
235
- delete self.nextTimer;
236
- delete self.evalTimer;
246
+ })(self.setTimeout, self.setInterval, self.setImmediate, self.clearTimeout, self.clearInterval, self.clearImmediate);
247
+
248
+ self.setTimeout = setTimeout;
249
+ self.setInterval = setInterval;
250
+ self.setImmediate = setImmediate;
251
+ self.clearTimeout = clearTimeout;
252
+ self.clearInterval = clearInterval;
253
+ self.clearImmediate = clearImmediate;
237
254
  });