@jsenv/core 28.0.1 → 28.1.1

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.
Files changed (57) hide show
  1. package/dist/controllable_child_process.mjs +1 -2
  2. package/dist/controllable_worker_thread.mjs +1 -2
  3. package/dist/js/autoreload.js +25 -9
  4. package/dist/js/execute_using_dynamic_import.js +804 -1
  5. package/dist/js/script_type_module_supervisor.js +122 -0
  6. package/dist/js/supervisor.js +933 -0
  7. package/dist/js/{wrapper.mjs → ws.js} +0 -0
  8. package/dist/main.js +452 -504
  9. package/package.json +13 -13
  10. package/readme.md +1 -1
  11. package/src/build/inject_global_version_mappings.js +3 -3
  12. package/src/dev/start_dev_server.js +2 -2
  13. package/src/execute/execute.js +1 -1
  14. package/src/execute/run.js +26 -38
  15. package/src/execute/runtimes/browsers/from_playwright.js +51 -77
  16. package/src/execute/runtimes/node/node_child_process.js +36 -36
  17. package/src/execute/runtimes/node/node_worker_thread.js +36 -36
  18. package/src/omega/kitchen.js +28 -9
  19. package/src/omega/omega_server.js +2 -2
  20. package/src/omega/server/file_service.js +2 -2
  21. package/src/omega/url_graph/url_info_transformations.js +8 -1
  22. package/src/plugins/autoreload/client/reload.js +20 -7
  23. package/src/plugins/autoreload/jsenv_plugin_autoreload_client.js +4 -4
  24. package/src/plugins/import_meta_hot/html_hot_dependencies.js +2 -2
  25. package/src/plugins/importmap/jsenv_plugin_importmap.js +5 -3
  26. package/src/plugins/inject_globals/inject_globals.js +3 -3
  27. package/src/plugins/inline/jsenv_plugin_data_urls.js +1 -1
  28. package/src/plugins/inline/jsenv_plugin_html_inline_content.js +10 -5
  29. package/src/plugins/node_esm_resolution/jsenv_plugin_node_esm_resolution.js +2 -13
  30. package/src/plugins/plugins.js +5 -5
  31. package/src/plugins/server_events/jsenv_plugin_server_events_client_injection.js +4 -4
  32. package/src/plugins/supervisor/client/script_type_module_supervisor.js +99 -0
  33. package/src/plugins/supervisor/client/supervisor.js +933 -0
  34. package/src/plugins/{html_supervisor/jsenv_plugin_html_supervisor.js → supervisor/jsenv_plugin_supervisor.js} +128 -102
  35. package/src/plugins/toolbar/client/execution/toolbar_execution.js +1 -1
  36. package/src/plugins/toolbar/jsenv_plugin_toolbar.js +4 -4
  37. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic.js +7 -5
  38. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic_html.js +5 -4
  39. package/src/plugins/transpilation/babel/jsenv_plugin_babel.js +13 -7
  40. package/src/plugins/transpilation/babel/new_stylesheet/babel_plugin_new_stylesheet_as_jsenv_import.js +6 -4
  41. package/src/plugins/transpilation/jsenv_plugin_transpilation.js +4 -2
  42. package/src/plugins/url_analysis/html/html_urls.js +11 -10
  43. package/src/test/coverage/babel_plugin_instrument.js +1 -35
  44. package/src/test/coverage/empty_coverage_factory.js +1 -1
  45. package/src/test/execute_plan.js +7 -3
  46. package/src/test/execute_test_plan.js +2 -1
  47. package/src/test/logs_file_execution.js +49 -8
  48. package/dist/js/html_supervisor_installer.js +0 -1091
  49. package/dist/js/html_supervisor_setup.js +0 -89
  50. package/dist/js/uneval.js +0 -804
  51. package/src/plugins/html_supervisor/client/error_formatter.js +0 -426
  52. package/src/plugins/html_supervisor/client/error_in_notification.js +0 -21
  53. package/src/plugins/html_supervisor/client/error_overlay.js +0 -191
  54. package/src/plugins/html_supervisor/client/html_supervisor_installer.js +0 -315
  55. package/src/plugins/html_supervisor/client/html_supervisor_setup.js +0 -89
  56. package/src/plugins/html_supervisor/client/perf_browser.js +0 -17
  57. package/src/plugins/html_supervisor/client/uneval_exception.js +0 -8
@@ -2,6 +2,809 @@ import { writeFileSync } from "node:fs";
2
2
  import { Session } from "node:inspector";
3
3
  import { PerformanceObserver, performance } from "node:perf_hooks";
4
4
 
5
+ // https://developer.mozilla.org/en-US/docs/Glossary/Primitive
6
+ const isComposite = value => {
7
+ if (value === null) {
8
+ return false;
9
+ }
10
+
11
+ const type = typeof value;
12
+
13
+ if (type === "object") {
14
+ return true;
15
+ }
16
+
17
+ if (type === "function") {
18
+ return true;
19
+ }
20
+
21
+ return false;
22
+ };
23
+
24
+ const compositeWellKnownMap = new WeakMap();
25
+ const primitiveWellKnownMap = new Map();
26
+ const getCompositeGlobalPath = value => compositeWellKnownMap.get(value);
27
+ const getPrimitiveGlobalPath = value => primitiveWellKnownMap.get(value);
28
+
29
+ const visitGlobalObject = value => {
30
+ const visitValue = (value, path) => {
31
+ if (isComposite(value)) {
32
+ // prevent infinite recursion
33
+ if (compositeWellKnownMap.has(value)) {
34
+ return;
35
+ }
36
+
37
+ compositeWellKnownMap.set(value, path);
38
+
39
+ const visitProperty = property => {
40
+ let descriptor;
41
+
42
+ try {
43
+ descriptor = Object.getOwnPropertyDescriptor(value, property);
44
+ } catch (e) {
45
+ if (e.name === "SecurityError") {
46
+ return;
47
+ }
48
+
49
+ throw e;
50
+ }
51
+
52
+ if (!descriptor) {
53
+ // it's apparently possible to have getOwnPropertyNames returning
54
+ // a property that later returns a null descriptor
55
+ // for instance window.showModalDialog in webkit 13.0
56
+ return;
57
+ } // do not trigger getter/setter
58
+
59
+
60
+ if ("value" in descriptor) {
61
+ const propertyValue = descriptor.value;
62
+ visitValue(propertyValue, [...path, property]);
63
+ }
64
+ };
65
+
66
+ Object.getOwnPropertyNames(value).forEach(name => visitProperty(name));
67
+ Object.getOwnPropertySymbols(value).forEach(symbol => visitProperty(symbol));
68
+ }
69
+
70
+ primitiveWellKnownMap.set(value, path);
71
+ return;
72
+ };
73
+
74
+ visitValue(value, []);
75
+ };
76
+
77
+ if (typeof window === "object") visitGlobalObject(window);
78
+ if (typeof global === "object") visitGlobalObject(global);
79
+
80
+ /**
81
+ * transforms a javascript value into an object describing it.
82
+ *
83
+ */
84
+ const decompose = (mainValue, {
85
+ functionAllowed,
86
+ prototypeStrict,
87
+ ignoreSymbols
88
+ }) => {
89
+ const valueMap = {};
90
+ const recipeArray = [];
91
+
92
+ const valueToIdentifier = (value, path = []) => {
93
+ if (!isComposite(value)) {
94
+ const existingIdentifier = identifierForPrimitive(value);
95
+
96
+ if (existingIdentifier !== undefined) {
97
+ return existingIdentifier;
98
+ }
99
+
100
+ const identifier = identifierForNewValue(value);
101
+ recipeArray[identifier] = primitiveToRecipe(value);
102
+ return identifier;
103
+ }
104
+
105
+ if (typeof Promise === "function" && value instanceof Promise) {
106
+ throw new Error(createPromiseAreNotSupportedMessage({
107
+ path
108
+ }));
109
+ }
110
+
111
+ if (typeof WeakSet === "function" && value instanceof WeakSet) {
112
+ throw new Error(createWeakSetAreNotSupportedMessage({
113
+ path
114
+ }));
115
+ }
116
+
117
+ if (typeof WeakMap === "function" && value instanceof WeakMap) {
118
+ throw new Error(createWeakMapAreNotSupportedMessage({
119
+ path
120
+ }));
121
+ }
122
+
123
+ if (typeof value === "function" && !functionAllowed) {
124
+ throw new Error(createForbiddenFunctionMessage({
125
+ path
126
+ }));
127
+ }
128
+
129
+ const existingIdentifier = identifierForComposite(value);
130
+
131
+ if (existingIdentifier !== undefined) {
132
+ return existingIdentifier;
133
+ }
134
+
135
+ const identifier = identifierForNewValue(value);
136
+ const compositeGlobalPath = getCompositeGlobalPath(value);
137
+
138
+ if (compositeGlobalPath) {
139
+ recipeArray[identifier] = createGlobalReferenceRecipe(compositeGlobalPath);
140
+ return identifier;
141
+ }
142
+
143
+ const propertyDescriptionArray = [];
144
+ Object.getOwnPropertyNames(value).forEach(propertyName => {
145
+ const propertyDescriptor = Object.getOwnPropertyDescriptor(value, propertyName);
146
+ const propertyNameIdentifier = valueToIdentifier(propertyName, [...path, propertyName]);
147
+ const propertyDescription = computePropertyDescription(propertyDescriptor, propertyName, path);
148
+ propertyDescriptionArray.push({
149
+ propertyNameIdentifier,
150
+ propertyDescription
151
+ });
152
+ });
153
+ const symbolDescriptionArray = [];
154
+
155
+ if (!ignoreSymbols) {
156
+ Object.getOwnPropertySymbols(value).forEach(symbol => {
157
+ const propertyDescriptor = Object.getOwnPropertyDescriptor(value, symbol);
158
+ const symbolIdentifier = valueToIdentifier(symbol, [...path, `[${symbol.toString()}]`]);
159
+ const propertyDescription = computePropertyDescription(propertyDescriptor, symbol, path);
160
+ symbolDescriptionArray.push({
161
+ symbolIdentifier,
162
+ propertyDescription
163
+ });
164
+ });
165
+ }
166
+
167
+ const methodDescriptionArray = computeMethodDescriptionArray(value, path);
168
+ const extensible = Object.isExtensible(value);
169
+ recipeArray[identifier] = createCompositeRecipe({
170
+ propertyDescriptionArray,
171
+ symbolDescriptionArray,
172
+ methodDescriptionArray,
173
+ extensible
174
+ });
175
+ return identifier;
176
+ };
177
+
178
+ const computePropertyDescription = (propertyDescriptor, propertyNameOrSymbol, path) => {
179
+ if (propertyDescriptor.set && !functionAllowed) {
180
+ throw new Error(createForbiddenPropertySetterMessage({
181
+ path,
182
+ propertyNameOrSymbol
183
+ }));
184
+ }
185
+
186
+ if (propertyDescriptor.get && !functionAllowed) {
187
+ throw new Error(createForbiddenPropertyGetterMessage({
188
+ path,
189
+ propertyNameOrSymbol
190
+ }));
191
+ }
192
+
193
+ return {
194
+ configurable: propertyDescriptor.configurable,
195
+ writable: propertyDescriptor.writable,
196
+ enumerable: propertyDescriptor.enumerable,
197
+ getIdentifier: "get" in propertyDescriptor ? valueToIdentifier(propertyDescriptor.get, [...path, String(propertyNameOrSymbol), "[[descriptor:get]]"]) : undefined,
198
+ setIdentifier: "set" in propertyDescriptor ? valueToIdentifier(propertyDescriptor.set, [...path, String(propertyNameOrSymbol), "[[descriptor:set]]"]) : undefined,
199
+ valueIdentifier: "value" in propertyDescriptor ? valueToIdentifier(propertyDescriptor.value, [...path, String(propertyNameOrSymbol), "[[descriptor:value]]"]) : undefined
200
+ };
201
+ };
202
+
203
+ const computeMethodDescriptionArray = (value, path) => {
204
+ const methodDescriptionArray = [];
205
+
206
+ if (typeof Set === "function" && value instanceof Set) {
207
+ const callArray = [];
208
+ value.forEach((entryValue, index) => {
209
+ const entryValueIdentifier = valueToIdentifier(entryValue, [...path, `[[SetEntryValue]]`, index]);
210
+ callArray.push([entryValueIdentifier]);
211
+ });
212
+ methodDescriptionArray.push({
213
+ methodNameIdentifier: valueToIdentifier("add"),
214
+ callArray
215
+ });
216
+ }
217
+
218
+ if (typeof Map === "function" && value instanceof Map) {
219
+ const callArray = [];
220
+ value.forEach((entryValue, entryKey) => {
221
+ const entryKeyIdentifier = valueToIdentifier(entryKey, [...path, "[[MapEntryKey]]", entryKey]);
222
+ const entryValueIdentifier = valueToIdentifier(entryValue, [...path, "[[MapEntryValue]]", entryValue]);
223
+ callArray.push([entryKeyIdentifier, entryValueIdentifier]);
224
+ });
225
+ methodDescriptionArray.push({
226
+ methodNameIdentifier: valueToIdentifier("set"),
227
+ callArray
228
+ });
229
+ }
230
+
231
+ return methodDescriptionArray;
232
+ };
233
+
234
+ const identifierForPrimitive = value => {
235
+ return Object.keys(valueMap).find(existingIdentifier => {
236
+ const existingValue = valueMap[existingIdentifier];
237
+ if (Object.is(value, existingValue)) return true;
238
+ return value === existingValue;
239
+ });
240
+ };
241
+
242
+ const identifierForComposite = value => {
243
+ return Object.keys(valueMap).find(existingIdentifier => {
244
+ const existingValue = valueMap[existingIdentifier];
245
+ return value === existingValue;
246
+ });
247
+ };
248
+
249
+ const identifierForNewValue = value => {
250
+ const identifier = nextIdentifier();
251
+ valueMap[identifier] = value;
252
+ return identifier;
253
+ };
254
+
255
+ let currentIdentifier = -1;
256
+
257
+ const nextIdentifier = () => {
258
+ const identifier = String(parseInt(currentIdentifier) + 1);
259
+ currentIdentifier = identifier;
260
+ return identifier;
261
+ };
262
+
263
+ const mainIdentifier = valueToIdentifier(mainValue); // prototype, important to keep after the whole structure was visited
264
+ // so that we discover if any prototype is part of the value
265
+
266
+ const prototypeValueToIdentifier = prototypeValue => {
267
+ // prototype is null
268
+ if (prototypeValue === null) {
269
+ return valueToIdentifier(prototypeValue);
270
+ } // prototype found somewhere already
271
+
272
+
273
+ const prototypeExistingIdentifier = identifierForComposite(prototypeValue);
274
+
275
+ if (prototypeExistingIdentifier !== undefined) {
276
+ return prototypeExistingIdentifier;
277
+ } // mark prototype as visited
278
+
279
+
280
+ const prototypeIdentifier = identifierForNewValue(prototypeValue); // prototype is a global reference ?
281
+
282
+ const prototypeGlobalPath = getCompositeGlobalPath(prototypeValue);
283
+
284
+ if (prototypeGlobalPath) {
285
+ recipeArray[prototypeIdentifier] = createGlobalReferenceRecipe(prototypeGlobalPath);
286
+ return prototypeIdentifier;
287
+ } // otherwise prototype is unknown
288
+
289
+
290
+ if (prototypeStrict) {
291
+ throw new Error(createUnknownPrototypeMessage({
292
+ prototypeValue
293
+ }));
294
+ }
295
+
296
+ return prototypeValueToIdentifier(Object.getPrototypeOf(prototypeValue));
297
+ };
298
+
299
+ const identifierForValueOf = (value, path = []) => {
300
+ if (value instanceof Array) {
301
+ return valueToIdentifier(value.length, [...path, "length"]);
302
+ }
303
+
304
+ if ("valueOf" in value === false) {
305
+ return undefined;
306
+ }
307
+
308
+ if (typeof value.valueOf !== "function") {
309
+ return undefined;
310
+ }
311
+
312
+ const valueOfReturnValue = value.valueOf();
313
+
314
+ if (!isComposite(valueOfReturnValue)) {
315
+ return valueToIdentifier(valueOfReturnValue, [...path, "valueOf()"]);
316
+ }
317
+
318
+ if (valueOfReturnValue === value) {
319
+ return undefined;
320
+ }
321
+
322
+ throw new Error(createUnexpectedValueOfReturnValueMessage());
323
+ };
324
+
325
+ recipeArray.slice().forEach((recipe, index) => {
326
+ if (recipe.type === "composite") {
327
+ const value = valueMap[index];
328
+
329
+ if (typeof value === "function") {
330
+ const valueOfIdentifier = nextIdentifier();
331
+ recipeArray[valueOfIdentifier] = {
332
+ type: "primitive",
333
+ value
334
+ };
335
+ recipe.valueOfIdentifier = valueOfIdentifier;
336
+ return;
337
+ }
338
+
339
+ if (value instanceof RegExp) {
340
+ const valueOfIdentifier = nextIdentifier();
341
+ recipeArray[valueOfIdentifier] = {
342
+ type: "primitive",
343
+ value
344
+ };
345
+ recipe.valueOfIdentifier = valueOfIdentifier;
346
+ return;
347
+ } // valueOf, mandatory to uneval new Date(10) for instance.
348
+
349
+
350
+ recipe.valueOfIdentifier = identifierForValueOf(value);
351
+ const prototypeValue = Object.getPrototypeOf(value);
352
+ recipe.prototypeIdentifier = prototypeValueToIdentifier(prototypeValue);
353
+ }
354
+ });
355
+ return {
356
+ recipeArray,
357
+ mainIdentifier,
358
+ valueMap
359
+ };
360
+ };
361
+
362
+ const primitiveToRecipe = value => {
363
+ if (typeof value === "symbol") {
364
+ return symbolToRecipe(value);
365
+ }
366
+
367
+ return createPimitiveRecipe(value);
368
+ };
369
+
370
+ const symbolToRecipe = symbol => {
371
+ const globalSymbolKey = Symbol.keyFor(symbol);
372
+
373
+ if (globalSymbolKey !== undefined) {
374
+ return createGlobalSymbolRecipe(globalSymbolKey);
375
+ }
376
+
377
+ const symbolGlobalPath = getPrimitiveGlobalPath(symbol);
378
+
379
+ if (!symbolGlobalPath) {
380
+ throw new Error(createUnknownSymbolMessage({
381
+ symbol
382
+ }));
383
+ }
384
+
385
+ return createGlobalReferenceRecipe(symbolGlobalPath);
386
+ };
387
+
388
+ const createPimitiveRecipe = value => {
389
+ return {
390
+ type: "primitive",
391
+ value
392
+ };
393
+ };
394
+
395
+ const createGlobalReferenceRecipe = path => {
396
+ const recipe = {
397
+ type: "global-reference",
398
+ path
399
+ };
400
+ return recipe;
401
+ };
402
+
403
+ const createGlobalSymbolRecipe = key => {
404
+ return {
405
+ type: "global-symbol",
406
+ key
407
+ };
408
+ };
409
+
410
+ const createCompositeRecipe = ({
411
+ prototypeIdentifier,
412
+ valueOfIdentifier,
413
+ propertyDescriptionArray,
414
+ symbolDescriptionArray,
415
+ methodDescriptionArray,
416
+ extensible
417
+ }) => {
418
+ return {
419
+ type: "composite",
420
+ prototypeIdentifier,
421
+ valueOfIdentifier,
422
+ propertyDescriptionArray,
423
+ symbolDescriptionArray,
424
+ methodDescriptionArray,
425
+ extensible
426
+ };
427
+ };
428
+
429
+ const createPromiseAreNotSupportedMessage = ({
430
+ path
431
+ }) => {
432
+ if (path.length === 0) {
433
+ return `promise are not supported.`;
434
+ }
435
+
436
+ return `promise are not supported.
437
+ promise found at: ${path.join("")}`;
438
+ };
439
+
440
+ const createWeakSetAreNotSupportedMessage = ({
441
+ path
442
+ }) => {
443
+ if (path.length === 0) {
444
+ return `weakSet are not supported.`;
445
+ }
446
+
447
+ return `weakSet are not supported.
448
+ weakSet found at: ${path.join("")}`;
449
+ };
450
+
451
+ const createWeakMapAreNotSupportedMessage = ({
452
+ path
453
+ }) => {
454
+ if (path.length === 0) {
455
+ return `weakMap are not supported.`;
456
+ }
457
+
458
+ return `weakMap are not supported.
459
+ weakMap found at: ${path.join("")}`;
460
+ };
461
+
462
+ const createForbiddenFunctionMessage = ({
463
+ path
464
+ }) => {
465
+ if (path.length === 0) {
466
+ return `function are not allowed.`;
467
+ }
468
+
469
+ return `function are not allowed.
470
+ function found at: ${path.join("")}`;
471
+ };
472
+
473
+ const createForbiddenPropertyGetterMessage = ({
474
+ path,
475
+ propertyNameOrSymbol
476
+ }) => `property getter are not allowed.
477
+ getter found on property: ${String(propertyNameOrSymbol)}
478
+ at: ${path.join("")}`;
479
+
480
+ const createForbiddenPropertySetterMessage = ({
481
+ path,
482
+ propertyNameOrSymbol
483
+ }) => `property setter are not allowed.
484
+ setter found on property: ${String(propertyNameOrSymbol)}
485
+ at: ${path.join("")}`;
486
+
487
+ const createUnexpectedValueOfReturnValueMessage = () => `valueOf() must return a primitive of the object itself.`;
488
+
489
+ const createUnknownSymbolMessage = ({
490
+ symbol
491
+ }) => `symbol must be global, like Symbol.iterator, or created using Symbol.for().
492
+ symbol: ${symbol.toString()}`;
493
+
494
+ const createUnknownPrototypeMessage = ({
495
+ prototypeValue
496
+ }) => `prototype must be global, like Object.prototype, or somewhere in the value.
497
+ prototype constructor name: ${prototypeValue.constructor.name}`;
498
+
499
+ // be carefull because this function is mutating recipe objects inside the recipeArray.
500
+ // this is not an issue because each recipe object is not accessible from the outside
501
+ // when used internally by uneval
502
+ const sortRecipe = recipeArray => {
503
+ const findInRecipePrototypeChain = (recipe, callback) => {
504
+ let currentRecipe = recipe; // eslint-disable-next-line no-constant-condition
505
+
506
+ while (true) {
507
+ if (currentRecipe.type !== "composite") {
508
+ break;
509
+ }
510
+
511
+ const prototypeIdentifier = currentRecipe.prototypeIdentifier;
512
+
513
+ if (prototypeIdentifier === undefined) {
514
+ break;
515
+ }
516
+
517
+ currentRecipe = recipeArray[prototypeIdentifier];
518
+
519
+ if (callback(currentRecipe, prototypeIdentifier)) {
520
+ return prototypeIdentifier;
521
+ }
522
+ }
523
+
524
+ return undefined;
525
+ };
526
+
527
+ const recipeArrayOrdered = recipeArray.slice();
528
+ recipeArrayOrdered.sort((leftRecipe, rightRecipe) => {
529
+ const leftType = leftRecipe.type;
530
+ const rightType = rightRecipe.type;
531
+
532
+ if (leftType === "composite" && rightType === "composite") {
533
+ const rightRecipeIsInLeftRecipePrototypeChain = findInRecipePrototypeChain(leftRecipe, recipeCandidate => recipeCandidate === rightRecipe); // if left recipe requires right recipe, left must be after right
534
+
535
+ if (rightRecipeIsInLeftRecipePrototypeChain) {
536
+ return 1;
537
+ }
538
+
539
+ const leftRecipeIsInRightRecipePrototypeChain = findInRecipePrototypeChain(rightRecipe, recipeCandidate => recipeCandidate === leftRecipe); // if right recipe requires left recipe, right must be after left
540
+
541
+ if (leftRecipeIsInRightRecipePrototypeChain) {
542
+ return -1;
543
+ }
544
+ }
545
+
546
+ if (leftType !== rightType) {
547
+ // if left is a composite, left must be after right
548
+ if (leftType === "composite") {
549
+ return 1;
550
+ } // if right is a composite, right must be after left
551
+
552
+
553
+ if (rightType === "composite") {
554
+ return -1;
555
+ }
556
+ }
557
+
558
+ const leftIndex = recipeArray.indexOf(leftRecipe);
559
+ const rightIndex = recipeArray.indexOf(rightRecipe); // left was before right, don't change that
560
+
561
+ if (leftIndex < rightIndex) {
562
+ return -1;
563
+ } // right was after left, don't change that
564
+
565
+
566
+ return 1;
567
+ });
568
+ return recipeArrayOrdered;
569
+ };
570
+
571
+ // https://github.com/joliss/js-string-escape/blob/master/index.js
572
+ // http://javascript.crockford.com/remedial.html
573
+ const escapeString = value => {
574
+ const string = String(value);
575
+ let i = 0;
576
+ const j = string.length;
577
+ var escapedString = "";
578
+
579
+ while (i < j) {
580
+ const char = string[i];
581
+ let escapedChar;
582
+
583
+ if (char === '"' || char === "'" || char === "\\") {
584
+ escapedChar = `\\${char}`;
585
+ } else if (char === "\n") {
586
+ escapedChar = "\\n";
587
+ } else if (char === "\r") {
588
+ escapedChar = "\\r";
589
+ } else if (char === "\u2028") {
590
+ escapedChar = "\\u2028";
591
+ } else if (char === "\u2029") {
592
+ escapedChar = "\\u2029";
593
+ } else {
594
+ escapedChar = char;
595
+ }
596
+
597
+ escapedString += escapedChar;
598
+ i++;
599
+ }
600
+
601
+ return escapedString;
602
+ };
603
+
604
+ const uneval = (value, {
605
+ functionAllowed = false,
606
+ prototypeStrict = false,
607
+ ignoreSymbols = false
608
+ } = {}) => {
609
+ const {
610
+ recipeArray,
611
+ mainIdentifier,
612
+ valueMap
613
+ } = decompose(value, {
614
+ functionAllowed,
615
+ prototypeStrict,
616
+ ignoreSymbols
617
+ });
618
+ const recipeArraySorted = sortRecipe(recipeArray);
619
+ let source = `(function () {
620
+ var globalObject
621
+ try {
622
+ globalObject = Function('return this')() || (42, eval)('this');
623
+ } catch(e) {
624
+ globalObject = window;
625
+ }
626
+
627
+ function safeDefineProperty(object, propertyNameOrSymbol, descriptor) {
628
+ var currentDescriptor = Object.getOwnPropertyDescriptor(object, propertyNameOrSymbol);
629
+ if (currentDescriptor && !currentDescriptor.configurable) return
630
+ Object.defineProperty(object, propertyNameOrSymbol, descriptor)
631
+ };
632
+ `;
633
+ const variableNameMap = {};
634
+ recipeArray.forEach((recipe, index) => {
635
+ const indexSorted = recipeArraySorted.indexOf(recipe);
636
+ variableNameMap[index] = `_${indexSorted}`;
637
+ });
638
+
639
+ const identifierToVariableName = identifier => variableNameMap[identifier];
640
+
641
+ const recipeToSetupSource = recipe => {
642
+ if (recipe.type === "primitive") return primitiveRecipeToSetupSource(recipe);
643
+ if (recipe.type === "global-symbol") return globalSymbolRecipeToSetupSource(recipe);
644
+ if (recipe.type === "global-reference") return globalReferenceRecipeToSetupSource(recipe);
645
+ return compositeRecipeToSetupSource(recipe);
646
+ };
647
+
648
+ const primitiveRecipeToSetupSource = ({
649
+ value
650
+ }) => {
651
+ const type = typeof value;
652
+
653
+ if (type === "string") {
654
+ return `"${escapeString(value)}";`;
655
+ }
656
+
657
+ if (type === "bigint") {
658
+ return `${value.toString()}n`;
659
+ }
660
+
661
+ if (Object.is(value, -0)) {
662
+ return "-0;";
663
+ }
664
+
665
+ return `${String(value)};`;
666
+ };
667
+
668
+ const globalSymbolRecipeToSetupSource = recipe => {
669
+ return `Symbol.for("${escapeString(recipe.key)}");`;
670
+ };
671
+
672
+ const globalReferenceRecipeToSetupSource = recipe => {
673
+ const pathSource = recipe.path.map(part => `["${escapeString(part)}"]`).join("");
674
+ return `globalObject${pathSource};`;
675
+ };
676
+
677
+ const compositeRecipeToSetupSource = ({
678
+ prototypeIdentifier,
679
+ valueOfIdentifier
680
+ }) => {
681
+ if (prototypeIdentifier === undefined) {
682
+ return identifierToVariableName(valueOfIdentifier);
683
+ }
684
+
685
+ const prototypeValue = valueMap[prototypeIdentifier];
686
+
687
+ if (prototypeValue === null) {
688
+ return `Object.create(null);`;
689
+ }
690
+
691
+ const prototypeConstructor = prototypeValue.constructor;
692
+
693
+ if (prototypeConstructor === Object) {
694
+ return `Object.create(${identifierToVariableName(prototypeIdentifier)});`;
695
+ }
696
+
697
+ if (valueOfIdentifier === undefined) {
698
+ return `new ${prototypeConstructor.name}();`;
699
+ }
700
+
701
+ if (prototypeConstructor.name === "BigInt") {
702
+ return `Object(${identifierToVariableName(valueOfIdentifier)})`;
703
+ }
704
+
705
+ return `new ${prototypeConstructor.name}(${identifierToVariableName(valueOfIdentifier)});`;
706
+ };
707
+
708
+ recipeArraySorted.forEach(recipe => {
709
+ const recipeVariableName = identifierToVariableName(recipeArray.indexOf(recipe));
710
+ source += `var ${recipeVariableName} = ${recipeToSetupSource(recipe)}
711
+ `;
712
+ });
713
+
714
+ const recipeToMutateSource = (recipe, recipeVariableName) => {
715
+ if (recipe.type === "composite") {
716
+ return compositeRecipeToMutateSource(recipe, recipeVariableName);
717
+ }
718
+
719
+ return ``;
720
+ };
721
+
722
+ const compositeRecipeToMutateSource = ({
723
+ propertyDescriptionArray,
724
+ symbolDescriptionArray,
725
+ methodDescriptionArray,
726
+ extensible
727
+ }, recipeVariableName) => {
728
+ let mutateSource = ``;
729
+ propertyDescriptionArray.forEach(({
730
+ propertyNameIdentifier,
731
+ propertyDescription
732
+ }) => {
733
+ mutateSource += generateDefinePropertySource(recipeVariableName, propertyNameIdentifier, propertyDescription);
734
+ });
735
+ symbolDescriptionArray.forEach(({
736
+ symbolIdentifier,
737
+ propertyDescription
738
+ }) => {
739
+ mutateSource += generateDefinePropertySource(recipeVariableName, symbolIdentifier, propertyDescription);
740
+ });
741
+ methodDescriptionArray.forEach(({
742
+ methodNameIdentifier,
743
+ callArray
744
+ }) => {
745
+ mutateSource += generateMethodCallSource(recipeVariableName, methodNameIdentifier, callArray);
746
+ });
747
+
748
+ if (!extensible) {
749
+ mutateSource += generatePreventExtensionSource(recipeVariableName);
750
+ }
751
+
752
+ return mutateSource;
753
+ };
754
+
755
+ const generateDefinePropertySource = (recipeVariableName, propertyNameOrSymbolIdentifier, propertyDescription) => {
756
+ const propertyOrSymbolVariableName = identifierToVariableName(propertyNameOrSymbolIdentifier);
757
+ const propertyDescriptorSource = generatePropertyDescriptorSource(propertyDescription);
758
+ return `safeDefineProperty(${recipeVariableName}, ${propertyOrSymbolVariableName}, ${propertyDescriptorSource});`;
759
+ };
760
+
761
+ const generatePropertyDescriptorSource = ({
762
+ configurable,
763
+ writable,
764
+ enumerable,
765
+ getIdentifier,
766
+ setIdentifier,
767
+ valueIdentifier
768
+ }) => {
769
+ if (valueIdentifier === undefined) {
770
+ return `{
771
+ configurable: ${configurable},
772
+ enumerable: ${enumerable},
773
+ get: ${getIdentifier === undefined ? undefined : identifierToVariableName(getIdentifier)},
774
+ set: ${setIdentifier === undefined ? undefined : identifierToVariableName(setIdentifier)},
775
+ }`;
776
+ }
777
+
778
+ return `{
779
+ configurable: ${configurable},
780
+ writable: ${writable},
781
+ enumerable: ${enumerable},
782
+ value: ${valueIdentifier === undefined ? undefined : identifierToVariableName(valueIdentifier)}
783
+ }`;
784
+ };
785
+
786
+ const generateMethodCallSource = (recipeVariableName, methodNameIdentifier, callArray) => {
787
+ let methodCallSource = ``;
788
+ const methodVariableName = identifierToVariableName(methodNameIdentifier);
789
+ callArray.forEach(argumentIdentifiers => {
790
+ const argumentVariableNames = argumentIdentifiers.map(argumentIdentifier => identifierToVariableName(argumentIdentifier));
791
+ methodCallSource += `${recipeVariableName}[${methodVariableName}](${argumentVariableNames.join(",")});`;
792
+ });
793
+ return methodCallSource;
794
+ };
795
+
796
+ const generatePreventExtensionSource = recipeVariableName => {
797
+ return `Object.preventExtensions(${recipeVariableName});`;
798
+ };
799
+
800
+ recipeArraySorted.forEach(recipe => {
801
+ const recipeVariableName = identifierToVariableName(recipeArray.indexOf(recipe));
802
+ source += `${recipeToMutateSource(recipe, recipeVariableName)}`;
803
+ });
804
+ source += `return ${identifierToVariableName(mainIdentifier)}; })()`;
805
+ return source;
806
+ };
807
+
5
808
  /*
6
809
  * Calling Profiler.startPreciseCoverage DO NOT propagate to
7
810
  * subprocesses (new Worker or child_process.fork())
@@ -168,4 +971,4 @@ const executeUsingDynamicImport = async ({
168
971
  return result;
169
972
  };
170
973
 
171
- export { executeUsingDynamicImport as e };
974
+ export { executeUsingDynamicImport as e, uneval as u };