@jsenv/test 1.2.4 → 1.3.0

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.
@@ -4,48 +4,56 @@ import { PerformanceObserver, performance } from "node:perf_hooks";
4
4
 
5
5
  // https://developer.mozilla.org/en-US/docs/Glossary/Primitive
6
6
 
7
- const isComposite = value => {
7
+ const isComposite = (value) => {
8
8
  if (value === null) {
9
- return false;
9
+ return false
10
10
  }
11
+
11
12
  const type = typeof value;
12
13
  if (type === "object") {
13
- return true;
14
+ return true
14
15
  }
16
+
15
17
  if (type === "function") {
16
- return true;
18
+ return true
17
19
  }
18
- return false;
20
+
21
+ return false
19
22
  };
20
23
 
21
24
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap
22
25
  const compositeWellKnownMap = new WeakMap();
23
26
  const primitiveWellKnownMap = new Map();
24
- const getCompositeGlobalPath = value => compositeWellKnownMap.get(value);
25
- const getPrimitiveGlobalPath = value => primitiveWellKnownMap.get(value);
26
- const visitGlobalObject = value => {
27
+
28
+ const getCompositeGlobalPath = (value) => compositeWellKnownMap.get(value);
29
+
30
+ const getPrimitiveGlobalPath = (value) => primitiveWellKnownMap.get(value);
31
+
32
+ const visitGlobalObject = (value) => {
27
33
  const visitValue = (value, path) => {
28
34
  if (isComposite(value)) {
29
35
  // prevent infinite recursion
30
36
  if (compositeWellKnownMap.has(value)) {
31
- return;
37
+ return
32
38
  }
33
39
  compositeWellKnownMap.set(value, path);
34
- const visitProperty = property => {
40
+
41
+ const visitProperty = (property) => {
35
42
  let descriptor;
36
43
  try {
37
44
  descriptor = Object.getOwnPropertyDescriptor(value, property);
38
45
  } catch (e) {
39
46
  if (e.name === "SecurityError") {
40
- return;
47
+ return
41
48
  }
42
- throw e;
49
+ throw e
43
50
  }
51
+
44
52
  if (!descriptor) {
45
53
  // it's apparently possible to have getOwnPropertyNames returning
46
54
  // a property that later returns a null descriptor
47
55
  // for instance window.showModalDialog in webkit 13.0
48
- return;
56
+ return
49
57
  }
50
58
 
51
59
  // do not trigger getter/setter
@@ -54,15 +62,20 @@ const visitGlobalObject = value => {
54
62
  visitValue(propertyValue, [...path, property]);
55
63
  }
56
64
  };
57
- Object.getOwnPropertyNames(value).forEach(name => visitProperty(name));
58
- Object.getOwnPropertySymbols(value).forEach(symbol => visitProperty(symbol));
65
+
66
+ Object.getOwnPropertyNames(value).forEach((name) => visitProperty(name));
67
+ Object.getOwnPropertySymbols(value).forEach((symbol) => visitProperty(symbol));
59
68
  }
69
+
60
70
  primitiveWellKnownMap.set(value, path);
61
- return;
71
+ return
62
72
  };
73
+
63
74
  visitValue(value, []);
64
75
  };
76
+
65
77
  if (typeof window === "object") visitGlobalObject(window);
78
+
66
79
  if (typeof global === "object") visitGlobalObject(global);
67
80
 
68
81
  /**
@@ -70,172 +83,196 @@ if (typeof global === "object") visitGlobalObject(global);
70
83
  *
71
84
  */
72
85
 
73
- const decompose = (mainValue, {
74
- functionAllowed,
75
- prototypeStrict,
76
- ignoreSymbols
77
- }) => {
86
+
87
+ const decompose = (mainValue, { functionAllowed, prototypeStrict, ignoreSymbols }) => {
78
88
  const valueMap = {};
79
89
  const recipeArray = [];
90
+
80
91
  const valueToIdentifier = (value, path = []) => {
81
92
  if (!isComposite(value)) {
82
93
  const existingIdentifier = identifierForPrimitive(value);
83
94
  if (existingIdentifier !== undefined) {
84
- return existingIdentifier;
95
+ return existingIdentifier
85
96
  }
86
97
  const identifier = identifierForNewValue(value);
87
98
  recipeArray[identifier] = primitiveToRecipe(value);
88
- return identifier;
99
+ return identifier
89
100
  }
101
+
90
102
  if (typeof Promise === "function" && value instanceof Promise) {
91
- throw new Error(createPromiseAreNotSupportedMessage({
92
- path
93
- }));
103
+ throw new Error(createPromiseAreNotSupportedMessage({ path }))
94
104
  }
95
105
  if (typeof WeakSet === "function" && value instanceof WeakSet) {
96
- throw new Error(createWeakSetAreNotSupportedMessage({
97
- path
98
- }));
106
+ throw new Error(createWeakSetAreNotSupportedMessage({ path }))
99
107
  }
100
108
  if (typeof WeakMap === "function" && value instanceof WeakMap) {
101
- throw new Error(createWeakMapAreNotSupportedMessage({
102
- path
103
- }));
109
+ throw new Error(createWeakMapAreNotSupportedMessage({ path }))
104
110
  }
105
111
  if (typeof value === "function" && !functionAllowed) {
106
- throw new Error(createForbiddenFunctionMessage({
107
- path
108
- }));
112
+ throw new Error(createForbiddenFunctionMessage({ path }))
109
113
  }
114
+
110
115
  const existingIdentifier = identifierForComposite(value);
111
116
  if (existingIdentifier !== undefined) {
112
- return existingIdentifier;
117
+ return existingIdentifier
113
118
  }
114
119
  const identifier = identifierForNewValue(value);
120
+
115
121
  const compositeGlobalPath = getCompositeGlobalPath(value);
116
122
  if (compositeGlobalPath) {
117
123
  recipeArray[identifier] = createGlobalReferenceRecipe(compositeGlobalPath);
118
- return identifier;
124
+ return identifier
119
125
  }
126
+
120
127
  const propertyDescriptionArray = [];
121
- Object.getOwnPropertyNames(value).forEach(propertyName => {
128
+ Object.getOwnPropertyNames(value).forEach((propertyName) => {
122
129
  const propertyDescriptor = Object.getOwnPropertyDescriptor(value, propertyName);
123
130
  const propertyNameIdentifier = valueToIdentifier(propertyName, [...path, propertyName]);
124
131
  const propertyDescription = computePropertyDescription(propertyDescriptor, propertyName, path);
125
- propertyDescriptionArray.push({
126
- propertyNameIdentifier,
127
- propertyDescription
128
- });
132
+ propertyDescriptionArray.push({ propertyNameIdentifier, propertyDescription });
129
133
  });
134
+
130
135
  const symbolDescriptionArray = [];
131
136
  if (!ignoreSymbols) {
132
- Object.getOwnPropertySymbols(value).forEach(symbol => {
137
+ Object.getOwnPropertySymbols(value).forEach((symbol) => {
133
138
  const propertyDescriptor = Object.getOwnPropertyDescriptor(value, symbol);
134
139
  const symbolIdentifier = valueToIdentifier(symbol, [...path, `[${symbol.toString()}]`]);
135
140
  const propertyDescription = computePropertyDescription(propertyDescriptor, symbol, path);
136
- symbolDescriptionArray.push({
137
- symbolIdentifier,
138
- propertyDescription
139
- });
141
+ symbolDescriptionArray.push({ symbolIdentifier, propertyDescription });
140
142
  });
141
143
  }
144
+
142
145
  const methodDescriptionArray = computeMethodDescriptionArray(value, path);
146
+
143
147
  const extensible = Object.isExtensible(value);
148
+
144
149
  recipeArray[identifier] = createCompositeRecipe({
145
150
  propertyDescriptionArray,
146
151
  symbolDescriptionArray,
147
152
  methodDescriptionArray,
148
- extensible
153
+ extensible,
149
154
  });
150
- return identifier;
155
+ return identifier
151
156
  };
157
+
152
158
  const computePropertyDescription = (propertyDescriptor, propertyNameOrSymbol, path) => {
153
159
  if (propertyDescriptor.set && !functionAllowed) {
154
- throw new Error(createForbiddenPropertySetterMessage({
155
- path,
156
- propertyNameOrSymbol
157
- }));
160
+ throw new Error(createForbiddenPropertySetterMessage({ path, propertyNameOrSymbol }))
158
161
  }
159
162
  if (propertyDescriptor.get && !functionAllowed) {
160
- throw new Error(createForbiddenPropertyGetterMessage({
161
- path,
162
- propertyNameOrSymbol
163
- }));
163
+ throw new Error(createForbiddenPropertyGetterMessage({ path, propertyNameOrSymbol }))
164
164
  }
165
+
165
166
  return {
166
167
  configurable: propertyDescriptor.configurable,
167
168
  writable: propertyDescriptor.writable,
168
169
  enumerable: propertyDescriptor.enumerable,
169
- getIdentifier: "get" in propertyDescriptor ? valueToIdentifier(propertyDescriptor.get, [...path, String(propertyNameOrSymbol), "[[descriptor:get]]"]) : undefined,
170
- setIdentifier: "set" in propertyDescriptor ? valueToIdentifier(propertyDescriptor.set, [...path, String(propertyNameOrSymbol), "[[descriptor:set]]"]) : undefined,
171
- valueIdentifier: "value" in propertyDescriptor ? valueToIdentifier(propertyDescriptor.value, [...path, String(propertyNameOrSymbol), "[[descriptor:value]]"]) : undefined
172
- };
170
+ getIdentifier:
171
+ "get" in propertyDescriptor
172
+ ? valueToIdentifier(propertyDescriptor.get, [
173
+ ...path,
174
+ String(propertyNameOrSymbol),
175
+ "[[descriptor:get]]",
176
+ ])
177
+ : undefined,
178
+ setIdentifier:
179
+ "set" in propertyDescriptor
180
+ ? valueToIdentifier(propertyDescriptor.set, [
181
+ ...path,
182
+ String(propertyNameOrSymbol),
183
+ "[[descriptor:set]]",
184
+ ])
185
+ : undefined,
186
+ valueIdentifier:
187
+ "value" in propertyDescriptor
188
+ ? valueToIdentifier(propertyDescriptor.value, [
189
+ ...path,
190
+ String(propertyNameOrSymbol),
191
+ "[[descriptor:value]]",
192
+ ])
193
+ : undefined,
194
+ }
173
195
  };
196
+
174
197
  const computeMethodDescriptionArray = (value, path) => {
175
198
  const methodDescriptionArray = [];
199
+
176
200
  if (typeof Set === "function" && value instanceof Set) {
177
201
  const callArray = [];
178
202
  value.forEach((entryValue, index) => {
179
- const entryValueIdentifier = valueToIdentifier(entryValue, [...path, `[[SetEntryValue]]`, index]);
203
+ const entryValueIdentifier = valueToIdentifier(entryValue, [
204
+ ...path,
205
+ `[[SetEntryValue]]`,
206
+ index,
207
+ ]);
180
208
  callArray.push([entryValueIdentifier]);
181
209
  });
182
- methodDescriptionArray.push({
183
- methodNameIdentifier: valueToIdentifier("add"),
184
- callArray
185
- });
210
+ methodDescriptionArray.push({ methodNameIdentifier: valueToIdentifier("add"), callArray });
186
211
  }
212
+
187
213
  if (typeof Map === "function" && value instanceof Map) {
188
214
  const callArray = [];
189
215
  value.forEach((entryValue, entryKey) => {
190
- const entryKeyIdentifier = valueToIdentifier(entryKey, [...path, "[[MapEntryKey]]", entryKey]);
191
- const entryValueIdentifier = valueToIdentifier(entryValue, [...path, "[[MapEntryValue]]", entryValue]);
216
+ const entryKeyIdentifier = valueToIdentifier(entryKey, [
217
+ ...path,
218
+ "[[MapEntryKey]]",
219
+ entryKey,
220
+ ]);
221
+ const entryValueIdentifier = valueToIdentifier(entryValue, [
222
+ ...path,
223
+ "[[MapEntryValue]]",
224
+ entryValue,
225
+ ]);
192
226
  callArray.push([entryKeyIdentifier, entryValueIdentifier]);
193
227
  });
194
- methodDescriptionArray.push({
195
- methodNameIdentifier: valueToIdentifier("set"),
196
- callArray
197
- });
228
+ methodDescriptionArray.push({ methodNameIdentifier: valueToIdentifier("set"), callArray });
198
229
  }
199
- return methodDescriptionArray;
230
+
231
+ return methodDescriptionArray
200
232
  };
201
- const identifierForPrimitive = value => {
202
- return Object.keys(valueMap).find(existingIdentifier => {
233
+
234
+ const identifierForPrimitive = (value) => {
235
+ return Object.keys(valueMap).find((existingIdentifier) => {
203
236
  const existingValue = valueMap[existingIdentifier];
204
- if (Object.is(value, existingValue)) return true;
205
- return value === existingValue;
206
- });
237
+ if (Object.is(value, existingValue)) return true
238
+ return value === existingValue
239
+ })
207
240
  };
208
- const identifierForComposite = value => {
209
- return Object.keys(valueMap).find(existingIdentifier => {
241
+
242
+ const identifierForComposite = (value) => {
243
+ return Object.keys(valueMap).find((existingIdentifier) => {
210
244
  const existingValue = valueMap[existingIdentifier];
211
- return value === existingValue;
212
- });
245
+ return value === existingValue
246
+ })
213
247
  };
214
- const identifierForNewValue = value => {
248
+
249
+ const identifierForNewValue = (value) => {
215
250
  const identifier = nextIdentifier();
216
251
  valueMap[identifier] = value;
217
- return identifier;
252
+ return identifier
218
253
  };
254
+
219
255
  let currentIdentifier = -1;
220
256
  const nextIdentifier = () => {
221
257
  const identifier = String(parseInt(currentIdentifier) + 1);
222
258
  currentIdentifier = identifier;
223
- return identifier;
259
+ return identifier
224
260
  };
261
+
225
262
  const mainIdentifier = valueToIdentifier(mainValue);
226
263
 
227
264
  // prototype, important to keep after the whole structure was visited
228
265
  // so that we discover if any prototype is part of the value
229
- const prototypeValueToIdentifier = prototypeValue => {
266
+ const prototypeValueToIdentifier = (prototypeValue) => {
230
267
  // prototype is null
231
268
  if (prototypeValue === null) {
232
- return valueToIdentifier(prototypeValue);
269
+ return valueToIdentifier(prototypeValue)
233
270
  }
234
271
 
235
272
  // prototype found somewhere already
236
273
  const prototypeExistingIdentifier = identifierForComposite(prototypeValue);
237
274
  if (prototypeExistingIdentifier !== undefined) {
238
- return prototypeExistingIdentifier;
275
+ return prototypeExistingIdentifier
239
276
  }
240
277
 
241
278
  // mark prototype as visited
@@ -245,56 +282,63 @@ const decompose = (mainValue, {
245
282
  const prototypeGlobalPath = getCompositeGlobalPath(prototypeValue);
246
283
  if (prototypeGlobalPath) {
247
284
  recipeArray[prototypeIdentifier] = createGlobalReferenceRecipe(prototypeGlobalPath);
248
- return prototypeIdentifier;
285
+ return prototypeIdentifier
249
286
  }
250
287
 
251
288
  // otherwise prototype is unknown
252
289
  if (prototypeStrict) {
253
- throw new Error(createUnknownPrototypeMessage({
254
- prototypeValue
255
- }));
290
+ throw new Error(createUnknownPrototypeMessage({ prototypeValue }))
256
291
  }
257
- return prototypeValueToIdentifier(Object.getPrototypeOf(prototypeValue));
292
+
293
+ return prototypeValueToIdentifier(Object.getPrototypeOf(prototypeValue))
258
294
  };
259
295
  const identifierForValueOf = (value, path = []) => {
260
296
  if (value instanceof Array) {
261
- return valueToIdentifier(value.length, [...path, "length"]);
297
+ return valueToIdentifier(value.length, [...path, "length"])
262
298
  }
299
+
263
300
  if ("valueOf" in value === false) {
264
- return undefined;
301
+ return undefined
265
302
  }
303
+
266
304
  if (typeof value.valueOf !== "function") {
267
- return undefined;
305
+ return undefined
268
306
  }
307
+
269
308
  const valueOfReturnValue = value.valueOf();
270
309
  if (!isComposite(valueOfReturnValue)) {
271
- return valueToIdentifier(valueOfReturnValue, [...path, "valueOf()"]);
310
+ return valueToIdentifier(valueOfReturnValue, [...path, "valueOf()"])
272
311
  }
312
+
273
313
  if (valueOfReturnValue === value) {
274
- return undefined;
314
+ return undefined
275
315
  }
276
- throw new Error(createUnexpectedValueOfReturnValueMessage());
316
+
317
+ throw new Error(createUnexpectedValueOfReturnValueMessage())
277
318
  };
319
+
278
320
  recipeArray.slice().forEach((recipe, index) => {
279
321
  if (recipe.type === "composite") {
280
322
  const value = valueMap[index];
323
+
281
324
  if (typeof value === "function") {
282
325
  const valueOfIdentifier = nextIdentifier();
283
326
  recipeArray[valueOfIdentifier] = {
284
327
  type: "primitive",
285
- value
328
+ value,
286
329
  };
287
330
  recipe.valueOfIdentifier = valueOfIdentifier;
288
- return;
331
+ return
289
332
  }
333
+
290
334
  if (value instanceof RegExp) {
291
335
  const valueOfIdentifier = nextIdentifier();
292
336
  recipeArray[valueOfIdentifier] = {
293
337
  type: "primitive",
294
- value
338
+ value,
295
339
  };
296
340
  recipe.valueOfIdentifier = valueOfIdentifier;
297
- return;
341
+ return
298
342
  }
299
343
 
300
344
  // valueOf, mandatory to uneval new Date(10) for instance.
@@ -303,57 +347,65 @@ const decompose = (mainValue, {
303
347
  recipe.prototypeIdentifier = prototypeValueToIdentifier(prototypeValue);
304
348
  }
305
349
  });
350
+
306
351
  return {
307
352
  recipeArray,
308
353
  mainIdentifier,
309
- valueMap
310
- };
354
+ valueMap,
355
+ }
311
356
  };
312
- const primitiveToRecipe = value => {
357
+
358
+ const primitiveToRecipe = (value) => {
313
359
  if (typeof value === "symbol") {
314
- return symbolToRecipe(value);
360
+ return symbolToRecipe(value)
315
361
  }
316
- return createPimitiveRecipe(value);
362
+
363
+ return createPimitiveRecipe(value)
317
364
  };
318
- const symbolToRecipe = symbol => {
365
+
366
+ const symbolToRecipe = (symbol) => {
319
367
  const globalSymbolKey = Symbol.keyFor(symbol);
320
368
  if (globalSymbolKey !== undefined) {
321
- return createGlobalSymbolRecipe(globalSymbolKey);
369
+ return createGlobalSymbolRecipe(globalSymbolKey)
322
370
  }
371
+
323
372
  const symbolGlobalPath = getPrimitiveGlobalPath(symbol);
324
373
  if (!symbolGlobalPath) {
325
- throw new Error(createUnknownSymbolMessage({
326
- symbol
327
- }));
374
+ throw new Error(createUnknownSymbolMessage({ symbol }))
328
375
  }
329
- return createGlobalReferenceRecipe(symbolGlobalPath);
376
+
377
+ return createGlobalReferenceRecipe(symbolGlobalPath)
330
378
  };
331
- const createPimitiveRecipe = value => {
379
+
380
+ const createPimitiveRecipe = (value) => {
332
381
  return {
333
382
  type: "primitive",
334
- value
335
- };
383
+ value,
384
+ }
336
385
  };
337
- const createGlobalReferenceRecipe = path => {
386
+
387
+ const createGlobalReferenceRecipe = (path) => {
338
388
  const recipe = {
339
389
  type: "global-reference",
340
- path
390
+ path,
341
391
  };
342
- return recipe;
392
+ return recipe
343
393
  };
344
- const createGlobalSymbolRecipe = key => {
394
+
395
+ const createGlobalSymbolRecipe = (key) => {
345
396
  return {
346
397
  type: "global-symbol",
347
- key
348
- };
398
+ key,
399
+ }
349
400
  };
401
+
350
402
  const createCompositeRecipe = ({
351
403
  prototypeIdentifier,
352
404
  valueOfIdentifier,
353
405
  propertyDescriptionArray,
354
406
  symbolDescriptionArray,
355
407
  methodDescriptionArray,
356
- extensible
408
+ extensible,
357
409
  }) => {
358
410
  return {
359
411
  type: "composite",
@@ -362,132 +414,152 @@ const createCompositeRecipe = ({
362
414
  propertyDescriptionArray,
363
415
  symbolDescriptionArray,
364
416
  methodDescriptionArray,
365
- extensible
366
- };
417
+ extensible,
418
+ }
367
419
  };
368
- const createPromiseAreNotSupportedMessage = ({
369
- path
370
- }) => {
420
+
421
+ const createPromiseAreNotSupportedMessage = ({ path }) => {
371
422
  if (path.length === 0) {
372
- return `promise are not supported.`;
423
+ return `promise are not supported.`
373
424
  }
425
+
374
426
  return `promise are not supported.
375
- promise found at: ${path.join("")}`;
427
+ promise found at: ${path.join("")}`
376
428
  };
377
- const createWeakSetAreNotSupportedMessage = ({
378
- path
379
- }) => {
429
+
430
+ const createWeakSetAreNotSupportedMessage = ({ path }) => {
380
431
  if (path.length === 0) {
381
- return `weakSet are not supported.`;
432
+ return `weakSet are not supported.`
382
433
  }
434
+
383
435
  return `weakSet are not supported.
384
- weakSet found at: ${path.join("")}`;
436
+ weakSet found at: ${path.join("")}`
385
437
  };
386
- const createWeakMapAreNotSupportedMessage = ({
387
- path
388
- }) => {
438
+
439
+ const createWeakMapAreNotSupportedMessage = ({ path }) => {
389
440
  if (path.length === 0) {
390
- return `weakMap are not supported.`;
441
+ return `weakMap are not supported.`
391
442
  }
443
+
392
444
  return `weakMap are not supported.
393
- weakMap found at: ${path.join("")}`;
445
+ weakMap found at: ${path.join("")}`
394
446
  };
395
- const createForbiddenFunctionMessage = ({
396
- path
397
- }) => {
447
+
448
+ const createForbiddenFunctionMessage = ({ path }) => {
398
449
  if (path.length === 0) {
399
- return `function are not allowed.`;
450
+ return `function are not allowed.`
400
451
  }
452
+
401
453
  return `function are not allowed.
402
- function found at: ${path.join("")}`;
454
+ function found at: ${path.join("")}`
403
455
  };
456
+
404
457
  const createForbiddenPropertyGetterMessage = ({
405
458
  path,
406
- propertyNameOrSymbol
459
+ propertyNameOrSymbol,
407
460
  }) => `property getter are not allowed.
408
461
  getter found on property: ${String(propertyNameOrSymbol)}
409
462
  at: ${path.join("")}`;
463
+
410
464
  const createForbiddenPropertySetterMessage = ({
411
465
  path,
412
- propertyNameOrSymbol
466
+ propertyNameOrSymbol,
413
467
  }) => `property setter are not allowed.
414
468
  setter found on property: ${String(propertyNameOrSymbol)}
415
469
  at: ${path.join("")}`;
416
- const createUnexpectedValueOfReturnValueMessage = () => `valueOf() must return a primitive of the object itself.`;
470
+
471
+ const createUnexpectedValueOfReturnValueMessage = () =>
472
+ `valueOf() must return a primitive of the object itself.`;
473
+
417
474
  const createUnknownSymbolMessage = ({
418
- symbol
475
+ symbol,
419
476
  }) => `symbol must be global, like Symbol.iterator, or created using Symbol.for().
420
477
  symbol: ${symbol.toString()}`;
421
- const createUnknownPrototypeMessage = ({
422
- prototypeValue
423
- }) => `prototype must be global, like Object.prototype, or somewhere in the value.
478
+
479
+ const createUnknownPrototypeMessage = ({ prototypeValue }) =>
480
+ `prototype must be global, like Object.prototype, or somewhere in the value.
424
481
  prototype constructor name: ${prototypeValue.constructor.name}`;
425
482
 
426
483
  // be carefull because this function is mutating recipe objects inside the recipeArray.
427
484
  // this is not an issue because each recipe object is not accessible from the outside
428
485
  // when used internally by uneval
429
- const sortRecipe = recipeArray => {
486
+ const sortRecipe = (recipeArray) => {
430
487
  const findInRecipePrototypeChain = (recipe, callback) => {
431
488
  let currentRecipe = recipe;
432
489
  // eslint-disable-next-line no-constant-condition
433
490
  while (true) {
434
491
  if (currentRecipe.type !== "composite") {
435
- break;
492
+ break
436
493
  }
494
+
437
495
  const prototypeIdentifier = currentRecipe.prototypeIdentifier;
438
496
  if (prototypeIdentifier === undefined) {
439
- break;
497
+ break
440
498
  }
499
+
441
500
  currentRecipe = recipeArray[prototypeIdentifier];
501
+
442
502
  if (callback(currentRecipe, prototypeIdentifier)) {
443
- return prototypeIdentifier;
503
+ return prototypeIdentifier
444
504
  }
445
505
  }
446
- return undefined;
506
+ return undefined
447
507
  };
508
+
448
509
  const recipeArrayOrdered = recipeArray.slice();
449
510
  recipeArrayOrdered.sort((leftRecipe, rightRecipe) => {
450
511
  const leftType = leftRecipe.type;
451
512
  const rightType = rightRecipe.type;
513
+
452
514
  if (leftType === "composite" && rightType === "composite") {
453
- const rightRecipeIsInLeftRecipePrototypeChain = findInRecipePrototypeChain(leftRecipe, recipeCandidate => recipeCandidate === rightRecipe);
515
+ const rightRecipeIsInLeftRecipePrototypeChain = findInRecipePrototypeChain(
516
+ leftRecipe,
517
+ (recipeCandidate) => recipeCandidate === rightRecipe,
518
+ );
454
519
  // if left recipe requires right recipe, left must be after right
455
520
  if (rightRecipeIsInLeftRecipePrototypeChain) {
456
- return 1;
521
+ return 1
457
522
  }
458
- const leftRecipeIsInRightRecipePrototypeChain = findInRecipePrototypeChain(rightRecipe, recipeCandidate => recipeCandidate === leftRecipe);
523
+
524
+ const leftRecipeIsInRightRecipePrototypeChain = findInRecipePrototypeChain(
525
+ rightRecipe,
526
+ (recipeCandidate) => recipeCandidate === leftRecipe,
527
+ );
459
528
  // if right recipe requires left recipe, right must be after left
460
529
  if (leftRecipeIsInRightRecipePrototypeChain) {
461
- return -1;
530
+ return -1
462
531
  }
463
532
  }
533
+
464
534
  if (leftType !== rightType) {
465
535
  // if left is a composite, left must be after right
466
536
  if (leftType === "composite") {
467
- return 1;
537
+ return 1
468
538
  }
469
539
 
470
540
  // if right is a composite, right must be after left
471
541
  if (rightType === "composite") {
472
- return -1;
542
+ return -1
473
543
  }
474
544
  }
545
+
475
546
  const leftIndex = recipeArray.indexOf(leftRecipe);
476
547
  const rightIndex = recipeArray.indexOf(rightRecipe);
477
548
  // left was before right, don't change that
478
549
  if (leftIndex < rightIndex) {
479
- return -1;
550
+ return -1
480
551
  }
481
552
 
482
553
  // right was after left, don't change that
483
- return 1;
554
+ return 1
484
555
  });
485
- return recipeArrayOrdered;
556
+
557
+ return recipeArrayOrdered
486
558
  };
487
559
 
488
560
  // https://github.com/joliss/js-string-escape/blob/master/index.js
489
561
  // http://javascript.crockford.com/remedial.html
490
- const escapeString = value => {
562
+ const escapeString = (value) => {
491
563
  const string = String(value);
492
564
  let i = 0;
493
565
  const j = string.length;
@@ -511,24 +583,20 @@ const escapeString = value => {
511
583
  escapedString += escapedChar;
512
584
  i++;
513
585
  }
514
- return escapedString;
586
+ return escapedString
515
587
  };
516
588
 
517
- const uneval = (value, {
518
- functionAllowed = false,
519
- prototypeStrict = false,
520
- ignoreSymbols = false
521
- } = {}) => {
522
- const {
523
- recipeArray,
524
- mainIdentifier,
525
- valueMap
526
- } = decompose(value, {
589
+ const uneval = (
590
+ value,
591
+ { functionAllowed = false, prototypeStrict = false, ignoreSymbols = false } = {},
592
+ ) => {
593
+ const { recipeArray, mainIdentifier, valueMap } = decompose(value, {
527
594
  functionAllowed,
528
595
  prototypeStrict,
529
- ignoreSymbols
596
+ ignoreSymbols,
530
597
  });
531
598
  const recipeArraySorted = sortRecipe(recipeArray);
599
+
532
600
  let source = `(function () {
533
601
  var globalObject
534
602
  try {
@@ -543,116 +611,139 @@ function safeDefineProperty(object, propertyNameOrSymbol, descriptor) {
543
611
  Object.defineProperty(object, propertyNameOrSymbol, descriptor)
544
612
  };
545
613
  `;
614
+
546
615
  const variableNameMap = {};
547
616
  recipeArray.forEach((recipe, index) => {
548
617
  const indexSorted = recipeArraySorted.indexOf(recipe);
549
618
  variableNameMap[index] = `_${indexSorted}`;
550
619
  });
551
- const identifierToVariableName = identifier => variableNameMap[identifier];
552
- const recipeToSetupSource = recipe => {
553
- if (recipe.type === "primitive") return primitiveRecipeToSetupSource(recipe);
554
- if (recipe.type === "global-symbol") return globalSymbolRecipeToSetupSource(recipe);
555
- if (recipe.type === "global-reference") return globalReferenceRecipeToSetupSource(recipe);
556
- return compositeRecipeToSetupSource(recipe);
620
+
621
+ const identifierToVariableName = (identifier) => variableNameMap[identifier];
622
+
623
+ const recipeToSetupSource = (recipe) => {
624
+ if (recipe.type === "primitive") return primitiveRecipeToSetupSource(recipe)
625
+ if (recipe.type === "global-symbol") return globalSymbolRecipeToSetupSource(recipe)
626
+ if (recipe.type === "global-reference") return globalReferenceRecipeToSetupSource(recipe)
627
+ return compositeRecipeToSetupSource(recipe)
557
628
  };
558
- const primitiveRecipeToSetupSource = ({
559
- value
560
- }) => {
629
+
630
+ const primitiveRecipeToSetupSource = ({ value }) => {
561
631
  const type = typeof value;
632
+
562
633
  if (type === "string") {
563
- return `"${escapeString(value)}";`;
634
+ return `"${escapeString(value)}";`
564
635
  }
636
+
565
637
  if (type === "bigint") {
566
- return `${value.toString()}n`;
638
+ return `${value.toString()}n`
567
639
  }
640
+
568
641
  if (Object.is(value, -0)) {
569
- return "-0;";
642
+ return "-0;"
570
643
  }
571
- return `${String(value)};`;
644
+
645
+ return `${String(value)};`
572
646
  };
573
- const globalSymbolRecipeToSetupSource = recipe => {
574
- return `Symbol.for("${escapeString(recipe.key)}");`;
647
+
648
+ const globalSymbolRecipeToSetupSource = (recipe) => {
649
+ return `Symbol.for("${escapeString(recipe.key)}");`
575
650
  };
576
- const globalReferenceRecipeToSetupSource = recipe => {
577
- const pathSource = recipe.path.map(part => `["${escapeString(part)}"]`).join("");
578
- return `globalObject${pathSource};`;
651
+
652
+ const globalReferenceRecipeToSetupSource = (recipe) => {
653
+ const pathSource = recipe.path.map((part) => `["${escapeString(part)}"]`).join("");
654
+ return `globalObject${pathSource};`
579
655
  };
580
- const compositeRecipeToSetupSource = ({
581
- prototypeIdentifier,
582
- valueOfIdentifier
583
- }) => {
656
+
657
+ const compositeRecipeToSetupSource = ({ prototypeIdentifier, valueOfIdentifier }) => {
584
658
  if (prototypeIdentifier === undefined) {
585
- return identifierToVariableName(valueOfIdentifier);
659
+ return identifierToVariableName(valueOfIdentifier)
586
660
  }
661
+
587
662
  const prototypeValue = valueMap[prototypeIdentifier];
588
663
  if (prototypeValue === null) {
589
- return `Object.create(null);`;
664
+ return `Object.create(null);`
590
665
  }
666
+
591
667
  const prototypeConstructor = prototypeValue.constructor;
592
668
  if (prototypeConstructor === Object) {
593
- return `Object.create(${identifierToVariableName(prototypeIdentifier)});`;
669
+ return `Object.create(${identifierToVariableName(prototypeIdentifier)});`
594
670
  }
671
+
595
672
  if (valueOfIdentifier === undefined) {
596
- return `new ${prototypeConstructor.name}();`;
673
+ return `new ${prototypeConstructor.name}();`
597
674
  }
675
+
598
676
  if (prototypeConstructor.name === "BigInt") {
599
- return `Object(${identifierToVariableName(valueOfIdentifier)})`;
677
+ return `Object(${identifierToVariableName(valueOfIdentifier)})`
600
678
  }
601
- return `new ${prototypeConstructor.name}(${identifierToVariableName(valueOfIdentifier)});`;
679
+
680
+ return `new ${prototypeConstructor.name}(${identifierToVariableName(valueOfIdentifier)});`
602
681
  };
603
- recipeArraySorted.forEach(recipe => {
682
+
683
+ recipeArraySorted.forEach((recipe) => {
604
684
  const recipeVariableName = identifierToVariableName(recipeArray.indexOf(recipe));
605
685
  source += `var ${recipeVariableName} = ${recipeToSetupSource(recipe)}
606
686
  `;
607
687
  });
688
+
608
689
  const recipeToMutateSource = (recipe, recipeVariableName) => {
609
690
  if (recipe.type === "composite") {
610
- return compositeRecipeToMutateSource(recipe, recipeVariableName);
691
+ return compositeRecipeToMutateSource(recipe, recipeVariableName)
611
692
  }
612
- return ``;
693
+ return ``
613
694
  };
614
- const compositeRecipeToMutateSource = ({
615
- propertyDescriptionArray,
616
- symbolDescriptionArray,
617
- methodDescriptionArray,
618
- extensible
619
- }, recipeVariableName) => {
695
+
696
+ const compositeRecipeToMutateSource = (
697
+ { propertyDescriptionArray, symbolDescriptionArray, methodDescriptionArray, extensible },
698
+ recipeVariableName,
699
+ ) => {
620
700
  let mutateSource = ``;
621
- propertyDescriptionArray.forEach(({
622
- propertyNameIdentifier,
623
- propertyDescription
624
- }) => {
625
- mutateSource += generateDefinePropertySource(recipeVariableName, propertyNameIdentifier, propertyDescription);
701
+
702
+ propertyDescriptionArray.forEach(({ propertyNameIdentifier, propertyDescription }) => {
703
+ mutateSource += generateDefinePropertySource(
704
+ recipeVariableName,
705
+ propertyNameIdentifier,
706
+ propertyDescription,
707
+ );
626
708
  });
627
- symbolDescriptionArray.forEach(({
628
- symbolIdentifier,
629
- propertyDescription
630
- }) => {
631
- mutateSource += generateDefinePropertySource(recipeVariableName, symbolIdentifier, propertyDescription);
709
+
710
+ symbolDescriptionArray.forEach(({ symbolIdentifier, propertyDescription }) => {
711
+ mutateSource += generateDefinePropertySource(
712
+ recipeVariableName,
713
+ symbolIdentifier,
714
+ propertyDescription,
715
+ );
632
716
  });
633
- methodDescriptionArray.forEach(({
634
- methodNameIdentifier,
635
- callArray
636
- }) => {
717
+
718
+ methodDescriptionArray.forEach(({ methodNameIdentifier, callArray }) => {
637
719
  mutateSource += generateMethodCallSource(recipeVariableName, methodNameIdentifier, callArray);
638
720
  });
721
+
639
722
  if (!extensible) {
640
723
  mutateSource += generatePreventExtensionSource(recipeVariableName);
641
724
  }
642
- return mutateSource;
725
+
726
+ return mutateSource
643
727
  };
644
- const generateDefinePropertySource = (recipeVariableName, propertyNameOrSymbolIdentifier, propertyDescription) => {
728
+
729
+ const generateDefinePropertySource = (
730
+ recipeVariableName,
731
+ propertyNameOrSymbolIdentifier,
732
+ propertyDescription,
733
+ ) => {
645
734
  const propertyOrSymbolVariableName = identifierToVariableName(propertyNameOrSymbolIdentifier);
735
+
646
736
  const propertyDescriptorSource = generatePropertyDescriptorSource(propertyDescription);
647
- return `safeDefineProperty(${recipeVariableName}, ${propertyOrSymbolVariableName}, ${propertyDescriptorSource});`;
737
+ return `safeDefineProperty(${recipeVariableName}, ${propertyOrSymbolVariableName}, ${propertyDescriptorSource});`
648
738
  };
739
+
649
740
  const generatePropertyDescriptorSource = ({
650
741
  configurable,
651
742
  writable,
652
743
  enumerable,
653
744
  getIdentifier,
654
745
  setIdentifier,
655
- valueIdentifier
746
+ valueIdentifier,
656
747
  }) => {
657
748
  if (valueIdentifier === undefined) {
658
749
  return `{
@@ -660,33 +751,46 @@ function safeDefineProperty(object, propertyNameOrSymbol, descriptor) {
660
751
  enumerable: ${enumerable},
661
752
  get: ${getIdentifier === undefined ? undefined : identifierToVariableName(getIdentifier)},
662
753
  set: ${setIdentifier === undefined ? undefined : identifierToVariableName(setIdentifier)},
663
- }`;
754
+ }`
664
755
  }
756
+
665
757
  return `{
666
758
  configurable: ${configurable},
667
759
  writable: ${writable},
668
760
  enumerable: ${enumerable},
669
761
  value: ${valueIdentifier === undefined ? undefined : identifierToVariableName(valueIdentifier)}
670
- }`;
762
+ }`
671
763
  };
764
+
672
765
  const generateMethodCallSource = (recipeVariableName, methodNameIdentifier, callArray) => {
673
766
  let methodCallSource = ``;
767
+
674
768
  const methodVariableName = identifierToVariableName(methodNameIdentifier);
675
- callArray.forEach(argumentIdentifiers => {
676
- const argumentVariableNames = argumentIdentifiers.map(argumentIdentifier => identifierToVariableName(argumentIdentifier));
677
- methodCallSource += `${recipeVariableName}[${methodVariableName}](${argumentVariableNames.join(",")});`;
769
+ callArray.forEach((argumentIdentifiers) => {
770
+ const argumentVariableNames = argumentIdentifiers.map((argumentIdentifier) =>
771
+ identifierToVariableName(argumentIdentifier),
772
+ );
773
+
774
+ methodCallSource += `${recipeVariableName}[${methodVariableName}](${argumentVariableNames.join(
775
+ ",",
776
+ )});`;
678
777
  });
679
- return methodCallSource;
778
+
779
+ return methodCallSource
680
780
  };
681
- const generatePreventExtensionSource = recipeVariableName => {
682
- return `Object.preventExtensions(${recipeVariableName});`;
781
+
782
+ const generatePreventExtensionSource = (recipeVariableName) => {
783
+ return `Object.preventExtensions(${recipeVariableName});`
683
784
  };
684
- recipeArraySorted.forEach(recipe => {
785
+
786
+ recipeArraySorted.forEach((recipe) => {
685
787
  const recipeVariableName = identifierToVariableName(recipeArray.indexOf(recipe));
686
788
  source += `${recipeToMutateSource(recipe, recipeVariableName)}`;
687
789
  });
790
+
688
791
  source += `return ${identifierToVariableName(mainIdentifier)}; })()`;
689
- return source;
792
+
793
+ return source
690
794
  };
691
795
 
692
796
  /*
@@ -704,9 +808,10 @@ function safeDefineProperty(object, propertyNameOrSymbol, descriptor) {
704
808
  * - https://vanilla.aslushnikov.com/?Profiler.startPreciseCoverage
705
809
  */
706
810
 
811
+
707
812
  const startJsCoverage = async ({
708
813
  callCount = true,
709
- detailed = true
814
+ detailed = true,
710
815
  } = {}) => {
711
816
  const session = new Session();
712
817
  session.connect();
@@ -722,70 +827,76 @@ const startJsCoverage = async ({
722
827
  });
723
828
  return promise;
724
829
  };
830
+
725
831
  await postSession("Profiler.enable");
726
- await postSession("Profiler.startPreciseCoverage", {
727
- callCount,
728
- detailed
729
- });
832
+ await postSession("Profiler.startPreciseCoverage", { callCount, detailed });
833
+
730
834
  const takeJsCoverage = async () => {
731
835
  const coverage = await postSession("Profiler.takePreciseCoverage");
732
836
  return coverage;
733
837
  };
838
+
734
839
  const stopJsCoverage = async () => {
735
840
  const coverage = await takeJsCoverage();
736
841
  await postSession("Profiler.stopPreciseCoverage");
737
842
  await postSession("Profiler.disable");
738
843
  return coverage;
739
844
  };
845
+
740
846
  return {
741
847
  takeJsCoverage,
742
- stopJsCoverage
848
+ stopJsCoverage,
743
849
  };
744
850
  };
745
851
 
746
852
  const startObservingPerformances = () => {
747
853
  const measureEntries = [];
748
854
  // https://nodejs.org/dist/latest-v16.x/docs/api/perf_hooks.html
749
- const perfObserver = new PerformanceObserver((
750
- // https://nodejs.org/dist/latest-v16.x/docs/api/perf_hooks.html#perf_hooks_class_performanceobserverentrylist
751
- list) => {
752
- const perfMeasureEntries = list.getEntriesByType("measure");
753
- measureEntries.push(...perfMeasureEntries);
754
- });
855
+ const perfObserver = new PerformanceObserver(
856
+ (
857
+ // https://nodejs.org/dist/latest-v16.x/docs/api/perf_hooks.html#perf_hooks_class_performanceobserverentrylist
858
+ list,
859
+ ) => {
860
+ const perfMeasureEntries = list.getEntriesByType("measure");
861
+ measureEntries.push(...perfMeasureEntries);
862
+ },
863
+ );
755
864
  perfObserver.observe({
756
- entryTypes: ["measure"]
865
+ entryTypes: ["measure"],
757
866
  });
758
867
  return async () => {
759
868
  // wait for node to call the performance observer
760
- await new Promise(resolve => {
869
+ await new Promise((resolve) => {
761
870
  setTimeout(resolve);
762
871
  });
763
872
  performance.clearMarks();
764
873
  perfObserver.disconnect();
765
874
  return {
766
875
  ...readNodePerformance(),
767
- measures: measuresFromMeasureEntries(measureEntries)
876
+ measures: measuresFromMeasureEntries(measureEntries),
768
877
  };
769
878
  };
770
879
  };
880
+
771
881
  const readNodePerformance = () => {
772
882
  const nodePerformance = {
773
883
  nodeTiming: asPlainObject(performance.nodeTiming),
774
884
  timeOrigin: performance.timeOrigin,
775
- eventLoopUtilization: performance.eventLoopUtilization()
885
+ eventLoopUtilization: performance.eventLoopUtilization(),
776
886
  };
777
887
  return nodePerformance;
778
888
  };
779
889
 
780
890
  // remove getters that cannot be stringified
781
- const asPlainObject = objectWithGetters => {
891
+ const asPlainObject = (objectWithGetters) => {
782
892
  const objectWithoutGetters = {};
783
- Object.keys(objectWithGetters).forEach(key => {
893
+ Object.keys(objectWithGetters).forEach((key) => {
784
894
  objectWithoutGetters[key] = objectWithGetters[key];
785
895
  });
786
896
  return objectWithoutGetters;
787
897
  };
788
- const measuresFromMeasureEntries = measureEntries => {
898
+
899
+ const measuresFromMeasureEntries = (measureEntries) => {
789
900
  const measures = {};
790
901
  // Sort to ensure measures order is predictable
791
902
  // It seems to be already predictable on Node 16+ but
@@ -793,11 +904,14 @@ const measuresFromMeasureEntries = measureEntries => {
793
904
  measureEntries.sort((a, b) => {
794
905
  return a.startTime - b.startTime;
795
906
  });
796
- measureEntries.forEach((
797
- // https://nodejs.org/dist/latest-v16.x/docs/api/perf_hooks.html#perf_hooks_class_performanceentry
798
- perfMeasureEntry) => {
799
- measures[perfMeasureEntry.name] = perfMeasureEntry.duration;
800
- });
907
+ measureEntries.forEach(
908
+ (
909
+ // https://nodejs.org/dist/latest-v16.x/docs/api/perf_hooks.html#perf_hooks_class_performanceentry
910
+ perfMeasureEntry,
911
+ ) => {
912
+ measures[perfMeasureEntry.name] = perfMeasureEntry.duration;
913
+ },
914
+ );
801
915
  return measures;
802
916
  };
803
917
 
@@ -808,24 +922,23 @@ const executeUsingDynamicImport = async ({
808
922
  coverageEnabled,
809
923
  coverageConfig,
810
924
  coverageMethodForNodeJs,
811
- coverageFileUrl
925
+ coverageFileUrl,
812
926
  }) => {
813
927
  const result = {};
814
928
  const afterImportCallbacks = [];
815
929
  if (coverageEnabled && coverageMethodForNodeJs === "Profiler") {
816
- const {
817
- filterV8Coverage
818
- } = await import("./v8_coverage.js").then(n => n.v8_coverage);
819
- const {
820
- stopJsCoverage
821
- } = await startJsCoverage();
930
+ const { filterV8Coverage } = await import("./v8_coverage.js").then(n => n.v8_coverage);
931
+ const { stopJsCoverage } = await startJsCoverage();
822
932
  afterImportCallbacks.push(async () => {
823
933
  const coverage = await stopJsCoverage();
824
934
  const coverageLight = await filterV8Coverage(coverage, {
825
935
  rootDirectoryUrl,
826
- coverageConfig
936
+ coverageConfig,
827
937
  });
828
- writeFileSync(new URL(coverageFileUrl), JSON.stringify(coverageLight, null, " "));
938
+ writeFileSync(
939
+ new URL(coverageFileUrl),
940
+ JSON.stringify(coverageLight, null, " "),
941
+ );
829
942
  });
830
943
  }
831
944
  if (collectPerformance) {
@@ -837,10 +950,12 @@ const executeUsingDynamicImport = async ({
837
950
  }
838
951
  const namespace = await import(fileUrl);
839
952
  const namespaceResolved = {};
840
- await Promise.all(Object.keys(namespace).map(async key => {
841
- const value = await namespace[key];
842
- namespaceResolved[key] = value;
843
- }));
953
+ await Promise.all(
954
+ Object.keys(namespace).map(async (key) => {
955
+ const value = await namespace[key];
956
+ namespaceResolved[key] = value;
957
+ }),
958
+ );
844
959
  result.namespace = namespaceResolved;
845
960
  await afterImportCallbacks.reduce(async (previous, afterImportCallback) => {
846
961
  await previous;