@squiz/render-runtime-lib 1.2.1-alpha.100

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 (56) hide show
  1. package/README.md +11 -0
  2. package/lib/component-runner/component-runner.spec.d.ts +1 -0
  3. package/lib/component-runner/index.d.ts +22 -0
  4. package/lib/component-runner/worker/WorkerPool.d.ts +50 -0
  5. package/lib/component-runner/worker/getRuntimeModules.d.ts +1 -0
  6. package/lib/component-runner/worker/worker-root.d.ts +1 -0
  7. package/lib/index.d.ts +25 -0
  8. package/lib/index.js +112791 -0
  9. package/lib/index.js.map +7 -0
  10. package/lib/migrations/20220704054051_initial.sql +19 -0
  11. package/lib/migrations/20220718172237_adding_component_sets.sql +23 -0
  12. package/lib/migrations/20220728113941_add_env_vars_field.sql +1 -0
  13. package/lib/migrations/20220817113300_removing_null_props_from_jsonb.sql +41 -0
  14. package/lib/render-runtime-lib.spec.d.ts +1 -0
  15. package/lib/test/helpers/fixtures.d.ts +20 -0
  16. package/lib/test/helpers/stack.d.ts +6 -0
  17. package/lib/test/index.d.ts +2 -0
  18. package/lib/utils/convertFunctionStaticFilesToFqdn.d.ts +1 -0
  19. package/lib/utils/convertFunctionStaticFilesToFqdn.spec.d.ts +1 -0
  20. package/lib/utils/getFunctionDefinitionFromManifest.d.ts +2 -0
  21. package/lib/utils/getManifestPath.d.ts +1 -0
  22. package/lib/utils/getManifestPath.spec.d.ts +1 -0
  23. package/lib/utils/getPreviewFilePath.d.ts +1 -0
  24. package/lib/utils/getPreviewFilePath.spec.d.ts +1 -0
  25. package/lib/utils/isInProductionMode.d.ts +1 -0
  26. package/lib/utils/isInProductionMode.spec.d.ts +1 -0
  27. package/lib/utils/resolvePreviewOutput.d.ts +2 -0
  28. package/lib/utils/resolvePreviewOutput.spec.d.ts +1 -0
  29. package/lib/webserver/app.d.ts +4 -0
  30. package/lib/webserver/controllers/core.d.ts +3 -0
  31. package/lib/webserver/controllers/core.spec.d.ts +1 -0
  32. package/lib/webserver/controllers/definition.d.ts +3 -0
  33. package/lib/webserver/controllers/definition.spec.d.ts +1 -0
  34. package/lib/webserver/controllers/index.d.ts +4 -0
  35. package/lib/webserver/controllers/render.d.ts +3 -0
  36. package/lib/webserver/controllers/render.spec.d.ts +1 -0
  37. package/lib/webserver/controllers/static.d.ts +3 -0
  38. package/lib/webserver/controllers/static.spec.d.ts +1 -0
  39. package/lib/webserver/controllers/test/definition-route-tests.d.ts +1 -0
  40. package/lib/webserver/controllers/test/render-route-tests.d.ts +1 -0
  41. package/lib/webserver/controllers/test/static-route-tests.d.ts +1 -0
  42. package/lib/webserver/index.d.ts +22 -0
  43. package/lib/worker/bridge.js +1010 -0
  44. package/lib/worker/compiler.js +87 -0
  45. package/lib/worker/events.js +977 -0
  46. package/lib/worker/nodevm.js +503 -0
  47. package/lib/worker/resolver-compat.js +342 -0
  48. package/lib/worker/resolver.js +882 -0
  49. package/lib/worker/script.js +388 -0
  50. package/lib/worker/setup-node-sandbox.js +469 -0
  51. package/lib/worker/setup-sandbox.js +456 -0
  52. package/lib/worker/transformer.js +180 -0
  53. package/lib/worker/vm.js +539 -0
  54. package/lib/worker/worker-root.js +41743 -0
  55. package/lib/worker/worker-root.js.map +7 -0
  56. package/package.json +60 -0
@@ -0,0 +1,456 @@
1
+ /* global host, bridge, data, context */
2
+
3
+ 'use strict';
4
+
5
+ const {
6
+ Object: localObject,
7
+ Array: localArray,
8
+ Error: LocalError,
9
+ Reflect: localReflect,
10
+ Proxy: LocalProxy,
11
+ WeakMap: LocalWeakMap,
12
+ Function: localFunction,
13
+ Promise: localPromise,
14
+ eval: localEval
15
+ } = global;
16
+
17
+ const {
18
+ freeze: localObjectFreeze
19
+ } = localObject;
20
+
21
+ const {
22
+ getPrototypeOf: localReflectGetPrototypeOf,
23
+ apply: localReflectApply,
24
+ deleteProperty: localReflectDeleteProperty,
25
+ has: localReflectHas,
26
+ defineProperty: localReflectDefineProperty,
27
+ setPrototypeOf: localReflectSetPrototypeOf,
28
+ getOwnPropertyDescriptor: localReflectGetOwnPropertyDescriptor
29
+ } = localReflect;
30
+
31
+ const {
32
+ isArray: localArrayIsArray
33
+ } = localArray;
34
+
35
+ const {
36
+ ensureThis,
37
+ ReadOnlyHandler,
38
+ from,
39
+ fromWithFactory,
40
+ readonlyFactory,
41
+ connect,
42
+ addProtoMapping,
43
+ VMError,
44
+ ReadOnlyMockHandler
45
+ } = bridge;
46
+
47
+ const {
48
+ allowAsync,
49
+ GeneratorFunction,
50
+ AsyncFunction,
51
+ AsyncGeneratorFunction
52
+ } = data;
53
+
54
+ const {
55
+ get: localWeakMapGet,
56
+ set: localWeakMapSet
57
+ } = LocalWeakMap.prototype;
58
+
59
+ function localUnexpected() {
60
+ return new VMError('Should not happen');
61
+ }
62
+
63
+ // global is originally prototype of host.Object so it can be used to climb up from the sandbox.
64
+ if (!localReflectSetPrototypeOf(context, localObject.prototype)) throw localUnexpected();
65
+
66
+ Object.defineProperties(global, {
67
+ global: {value: global, writable: true, configurable: true, enumerable: true},
68
+ globalThis: {value: global, writable: true, configurable: true},
69
+ GLOBAL: {value: global, writable: true, configurable: true},
70
+ root: {value: global, writable: true, configurable: true}
71
+ });
72
+
73
+ if (!localReflectDefineProperty(global, 'VMError', {
74
+ __proto__: null,
75
+ value: VMError,
76
+ writable: true,
77
+ enumerable: false,
78
+ configurable: true
79
+ })) throw localUnexpected();
80
+
81
+ // Fixes buffer unsafe allocation
82
+ /* eslint-disable no-use-before-define */
83
+ class BufferHandler extends ReadOnlyHandler {
84
+
85
+ apply(target, thiz, args) {
86
+ if (args.length > 0 && typeof args[0] === 'number') {
87
+ return LocalBuffer.alloc(args[0]);
88
+ }
89
+ return localReflectApply(LocalBuffer.from, LocalBuffer, args);
90
+ }
91
+
92
+ construct(target, args, newTarget) {
93
+ if (args.length > 0 && typeof args[0] === 'number') {
94
+ return LocalBuffer.alloc(args[0]);
95
+ }
96
+ return localReflectApply(LocalBuffer.from, LocalBuffer, args);
97
+ }
98
+
99
+ }
100
+ /* eslint-enable no-use-before-define */
101
+
102
+ const LocalBuffer = fromWithFactory(obj => new BufferHandler(obj), host.Buffer);
103
+
104
+
105
+ if (!localReflectDefineProperty(global, 'Buffer', {
106
+ __proto__: null,
107
+ value: LocalBuffer,
108
+ writable: true,
109
+ enumerable: false,
110
+ configurable: true
111
+ })) throw localUnexpected();
112
+
113
+ addProtoMapping(LocalBuffer.prototype, host.Buffer.prototype, 'Uint8Array');
114
+
115
+ /**
116
+ *
117
+ * @param {*} size Size of new buffer
118
+ * @this LocalBuffer
119
+ * @return {LocalBuffer}
120
+ */
121
+ function allocUnsafe(size) {
122
+ return LocalBuffer.alloc(size);
123
+ }
124
+
125
+ connect(allocUnsafe, host.Buffer.allocUnsafe);
126
+
127
+ /**
128
+ *
129
+ * @param {*} size Size of new buffer
130
+ * @this LocalBuffer
131
+ * @return {LocalBuffer}
132
+ */
133
+ function allocUnsafeSlow(size) {
134
+ return LocalBuffer.alloc(size);
135
+ }
136
+
137
+ connect(allocUnsafeSlow, host.Buffer.allocUnsafeSlow);
138
+
139
+ /**
140
+ * Replacement for Buffer inspect
141
+ *
142
+ * @param {*} recurseTimes
143
+ * @param {*} ctx
144
+ * @this LocalBuffer
145
+ * @return {string}
146
+ */
147
+ function inspect(recurseTimes, ctx) {
148
+ // Mimic old behavior, could throw but didn't pass a test.
149
+ const max = host.INSPECT_MAX_BYTES;
150
+ const actualMax = Math.min(max, this.length);
151
+ const remaining = this.length - max;
152
+ let str = this.hexSlice(0, actualMax).replace(/(.{2})/g, '$1 ').trim();
153
+ if (remaining > 0) str += ` ... ${remaining} more byte${remaining > 1 ? 's' : ''}`;
154
+ return `<${this.constructor.name} ${str}>`;
155
+ }
156
+
157
+ connect(inspect, host.Buffer.prototype.inspect);
158
+
159
+ connect(localFunction.prototype.bind, host.Function.prototype.bind);
160
+
161
+ connect(localObject.prototype.__defineGetter__, host.Object.prototype.__defineGetter__);
162
+ connect(localObject.prototype.__defineSetter__, host.Object.prototype.__defineSetter__);
163
+ connect(localObject.prototype.__lookupGetter__, host.Object.prototype.__lookupGetter__);
164
+ connect(localObject.prototype.__lookupSetter__, host.Object.prototype.__lookupSetter__);
165
+
166
+ /*
167
+ * PrepareStackTrace sanitization
168
+ */
169
+
170
+ const oldPrepareStackTraceDesc = localReflectGetOwnPropertyDescriptor(LocalError, 'prepareStackTrace');
171
+
172
+ let currentPrepareStackTrace = LocalError.prepareStackTrace;
173
+ const wrappedPrepareStackTrace = new LocalWeakMap();
174
+ if (typeof currentPrepareStackTrace === 'function') {
175
+ wrappedPrepareStackTrace.set(currentPrepareStackTrace, currentPrepareStackTrace);
176
+ }
177
+
178
+ let OriginalCallSite;
179
+ LocalError.prepareStackTrace = (e, sst) => {
180
+ OriginalCallSite = sst[0].constructor;
181
+ };
182
+ new LocalError().stack;
183
+ if (typeof OriginalCallSite === 'function') {
184
+ LocalError.prepareStackTrace = undefined;
185
+
186
+ function makeCallSiteGetters(list) {
187
+ const callSiteGetters = [];
188
+ for (let i=0; i<list.length; i++) {
189
+ const name = list[i];
190
+ const func = OriginalCallSite.prototype[name];
191
+ callSiteGetters[i] = {__proto__: null,
192
+ name,
193
+ propName: '_' + name,
194
+ func: (thiz) => {
195
+ return localReflectApply(func, thiz, []);
196
+ }
197
+ };
198
+ }
199
+ return callSiteGetters;
200
+ }
201
+
202
+ function applyCallSiteGetters(thiz, callSite, getters) {
203
+ for (let i=0; i<getters.length; i++) {
204
+ const getter = getters[i];
205
+ localReflectDefineProperty(thiz, getter.propName, {
206
+ __proto__: null,
207
+ value: getter.func(callSite)
208
+ });
209
+ }
210
+ }
211
+
212
+ const callSiteGetters = makeCallSiteGetters([
213
+ 'getTypeName',
214
+ 'getFunctionName',
215
+ 'getMethodName',
216
+ 'getFileName',
217
+ 'getLineNumber',
218
+ 'getColumnNumber',
219
+ 'getEvalOrigin',
220
+ 'isToplevel',
221
+ 'isEval',
222
+ 'isNative',
223
+ 'isConstructor',
224
+ 'isAsync',
225
+ 'isPromiseAll',
226
+ 'getPromiseIndex'
227
+ ]);
228
+
229
+ class CallSite {
230
+ constructor(callSite) {
231
+ applyCallSiteGetters(this, callSite, callSiteGetters);
232
+ }
233
+ getThis() {
234
+ return undefined;
235
+ }
236
+ getFunction() {
237
+ return undefined;
238
+ }
239
+ toString() {
240
+ return 'CallSite {}';
241
+ }
242
+ }
243
+
244
+
245
+ for (let i=0; i<callSiteGetters.length; i++) {
246
+ const name = callSiteGetters[i].name;
247
+ const funcProp = localReflectGetOwnPropertyDescriptor(OriginalCallSite.prototype, name);
248
+ if (!funcProp) continue;
249
+ const propertyName = callSiteGetters[i].propName;
250
+ const func = {func() {
251
+ return this[propertyName];
252
+ }}.func;
253
+ const nameProp = localReflectGetOwnPropertyDescriptor(func, 'name');
254
+ if (!nameProp) throw localUnexpected();
255
+ nameProp.value = name;
256
+ if (!localReflectDefineProperty(func, 'name', nameProp)) throw localUnexpected();
257
+ funcProp.value = func;
258
+ if (!localReflectDefineProperty(CallSite.prototype, name, funcProp)) throw localUnexpected();
259
+ }
260
+
261
+ if (!localReflectDefineProperty(LocalError, 'prepareStackTrace', {
262
+ configurable: false,
263
+ enumerable: false,
264
+ get() {
265
+ return currentPrepareStackTrace;
266
+ },
267
+ set(value) {
268
+ if (typeof(value) !== 'function') {
269
+ currentPrepareStackTrace = value;
270
+ return;
271
+ }
272
+ const wrapped = localReflectApply(localWeakMapGet, wrappedPrepareStackTrace, [value]);
273
+ if (wrapped) {
274
+ currentPrepareStackTrace = wrapped;
275
+ return;
276
+ }
277
+ const newWrapped = (error, sst) => {
278
+ if (localArrayIsArray(sst)) {
279
+ for (let i=0; i < sst.length; i++) {
280
+ const cs = sst[i];
281
+ if (typeof cs === 'object' && localReflectGetPrototypeOf(cs) === OriginalCallSite.prototype) {
282
+ sst[i] = new CallSite(cs);
283
+ }
284
+ }
285
+ }
286
+ return value(error, sst);
287
+ };
288
+ localReflectApply(localWeakMapSet, wrappedPrepareStackTrace, [value, newWrapped]);
289
+ localReflectApply(localWeakMapSet, wrappedPrepareStackTrace, [newWrapped, newWrapped]);
290
+ currentPrepareStackTrace = newWrapped;
291
+ }
292
+ })) throw localUnexpected();
293
+ } else if (oldPrepareStackTraceDesc) {
294
+ localReflectDefineProperty(LocalError, 'prepareStackTrace', oldPrepareStackTraceDesc);
295
+ } else {
296
+ localReflectDeleteProperty(LocalError, 'prepareStackTrace');
297
+ }
298
+
299
+ /*
300
+ * Exception sanitization
301
+ */
302
+
303
+ const withProxy = localObjectFreeze({
304
+ __proto__: null,
305
+ has(target, key) {
306
+ if (key === host.INTERNAL_STATE_NAME) return false;
307
+ return localReflectHas(target, key);
308
+ }
309
+ });
310
+
311
+ const interanState = localObjectFreeze({
312
+ __proto__: null,
313
+ wrapWith(x) {
314
+ if (x === null || x === undefined) return x;
315
+ return new LocalProxy(localObject(x), withProxy);
316
+ },
317
+ handleException: ensureThis,
318
+ import(what) {
319
+ throw new VMError('Dynamic Import not supported');
320
+ }
321
+ });
322
+
323
+ if (!localReflectDefineProperty(global, host.INTERNAL_STATE_NAME, {
324
+ __proto__: null,
325
+ configurable: false,
326
+ enumerable: false,
327
+ writable: false,
328
+ value: interanState
329
+ })) throw localUnexpected();
330
+
331
+ /*
332
+ * Eval sanitization
333
+ */
334
+
335
+ function throwAsync() {
336
+ return new VMError('Async not available');
337
+ }
338
+
339
+ function makeFunction(inputArgs, isAsync, isGenerator) {
340
+ const lastArgs = inputArgs.length - 1;
341
+ let code = lastArgs >= 0 ? `${inputArgs[lastArgs]}` : '';
342
+ let args = lastArgs > 0 ? `${inputArgs[0]}` : '';
343
+ for (let i = 1; i < lastArgs; i++) {
344
+ args += `,${inputArgs[i]}`;
345
+ }
346
+ try {
347
+ code = host.transformAndCheck(args, code, isAsync, isGenerator, allowAsync);
348
+ } catch (e) {
349
+ throw bridge.from(e);
350
+ }
351
+ return localEval(code);
352
+ }
353
+
354
+ const FunctionHandler = {
355
+ __proto__: null,
356
+ apply(target, thiz, args) {
357
+ return makeFunction(args, this.isAsync, this.isGenerator);
358
+ },
359
+ construct(target, args, newTarget) {
360
+ return makeFunction(args, this.isAsync, this.isGenerator);
361
+ }
362
+ };
363
+
364
+ const EvalHandler = {
365
+ __proto__: null,
366
+ apply(target, thiz, args) {
367
+ if (args.length === 0) return undefined;
368
+ let code = `${args[0]}`;
369
+ try {
370
+ code = host.transformAndCheck(null, code, false, false, allowAsync);
371
+ } catch (e) {
372
+ throw bridge.from(e);
373
+ }
374
+ return localEval(code);
375
+ }
376
+ };
377
+
378
+ const AsyncErrorHandler = {
379
+ __proto__: null,
380
+ apply(target, thiz, args) {
381
+ throw throwAsync();
382
+ },
383
+ construct(target, args, newTarget) {
384
+ throw throwAsync();
385
+ }
386
+ };
387
+
388
+ function makeCheckFunction(isAsync, isGenerator) {
389
+ if (isAsync && !allowAsync) return AsyncErrorHandler;
390
+ return {
391
+ __proto__: FunctionHandler,
392
+ isAsync,
393
+ isGenerator
394
+ };
395
+ }
396
+
397
+ function overrideWithProxy(obj, prop, value, handler) {
398
+ const proxy = new LocalProxy(value, handler);
399
+ if (!localReflectDefineProperty(obj, prop, {__proto__: null, value: proxy})) throw localUnexpected();
400
+ return proxy;
401
+ }
402
+
403
+ const proxiedFunction = overrideWithProxy(localFunction.prototype, 'constructor', localFunction, makeCheckFunction(false, false));
404
+ if (GeneratorFunction) {
405
+ if (!localReflectSetPrototypeOf(GeneratorFunction, proxiedFunction)) throw localUnexpected();
406
+ overrideWithProxy(GeneratorFunction.prototype, 'constructor', GeneratorFunction, makeCheckFunction(false, true));
407
+ }
408
+ if (AsyncFunction) {
409
+ if (!localReflectSetPrototypeOf(AsyncFunction, proxiedFunction)) throw localUnexpected();
410
+ overrideWithProxy(AsyncFunction.prototype, 'constructor', AsyncFunction, makeCheckFunction(true, false));
411
+ }
412
+ if (AsyncGeneratorFunction) {
413
+ if (!localReflectSetPrototypeOf(AsyncGeneratorFunction, proxiedFunction)) throw localUnexpected();
414
+ overrideWithProxy(AsyncGeneratorFunction.prototype, 'constructor', AsyncGeneratorFunction, makeCheckFunction(true, true));
415
+ }
416
+
417
+ global.Function = proxiedFunction;
418
+ global.eval = new LocalProxy(localEval, EvalHandler);
419
+
420
+ /*
421
+ * Promise sanitization
422
+ */
423
+
424
+ if (localPromise && !allowAsync) {
425
+
426
+ const PromisePrototype = localPromise.prototype;
427
+
428
+ overrideWithProxy(PromisePrototype, 'then', PromisePrototype.then, AsyncErrorHandler);
429
+ // This seems not to work, and will produce
430
+ // UnhandledPromiseRejectionWarning: TypeError: Method Promise.prototype.then called on incompatible receiver [object Object].
431
+ // This is likely caused since the host.Promise.prototype.then cannot use the VM Proxy object.
432
+ // Contextify.connect(host.Promise.prototype.then, Promise.prototype.then);
433
+
434
+ if (PromisePrototype.finally) {
435
+ overrideWithProxy(PromisePrototype, 'finally', PromisePrototype.finally, AsyncErrorHandler);
436
+ // Contextify.connect(host.Promise.prototype.finally, Promise.prototype.finally);
437
+ }
438
+ if (Promise.prototype.catch) {
439
+ overrideWithProxy(PromisePrototype, 'catch', PromisePrototype.catch, AsyncErrorHandler);
440
+ // Contextify.connect(host.Promise.prototype.catch, Promise.prototype.catch);
441
+ }
442
+
443
+ }
444
+
445
+ function readonly(other, mock) {
446
+ // Note: other@other(unsafe) mock@other(unsafe) returns@this(unsafe) throws@this(unsafe)
447
+ if (!mock) return fromWithFactory(readonlyFactory, other);
448
+ const tmock = from(mock);
449
+ return fromWithFactory(obj=>new ReadOnlyMockHandler(obj, tmock), other);
450
+ }
451
+
452
+ return {
453
+ __proto__: null,
454
+ readonly,
455
+ global
456
+ };
@@ -0,0 +1,180 @@
1
+
2
+ const {Parser: AcornParser, isNewLine: acornIsNewLine, getLineInfo: acornGetLineInfo} = require('acorn');
3
+ const {full: acornWalkFull} = require('acorn-walk');
4
+
5
+ const INTERNAL_STATE_NAME = 'VM2_INTERNAL_STATE_DO_NOT_USE_OR_PROGRAM_WILL_FAIL';
6
+
7
+ function assertType(node, type) {
8
+ if (!node) throw new Error(`None existent node expected '${type}'`);
9
+ if (node.type !== type) throw new Error(`Invalid node type '${node.type}' expected '${type}'`);
10
+ return node;
11
+ }
12
+
13
+ function makeNiceSyntaxError(message, code, filename, location, tokenizer) {
14
+ const loc = acornGetLineInfo(code, location);
15
+ let end = location;
16
+ while (end < code.length && !acornIsNewLine(code.charCodeAt(end))) {
17
+ end++;
18
+ }
19
+ let markerEnd = tokenizer.start === location ? tokenizer.end : location + 1;
20
+ if (!markerEnd || markerEnd > end) markerEnd = end;
21
+ let markerLen = markerEnd - location;
22
+ if (markerLen <= 0) markerLen = 1;
23
+ if (message === 'Unexpected token') {
24
+ const type = tokenizer.type;
25
+ if (type.label === 'name' || type.label === 'privateId') {
26
+ message = 'Unexpected identifier';
27
+ } else if (type.label === 'eof') {
28
+ message = 'Unexpected end of input';
29
+ } else if (type.label === 'num') {
30
+ message = 'Unexpected number';
31
+ } else if (type.label === 'string') {
32
+ message = 'Unexpected string';
33
+ } else if (type.label === 'regexp') {
34
+ message = 'Unexpected token \'/\'';
35
+ markerLen = 1;
36
+ } else {
37
+ const token = tokenizer.value || type.label;
38
+ message = `Unexpected token '${token}'`;
39
+ }
40
+ }
41
+ const error = new SyntaxError(message);
42
+ if (!filename) return error;
43
+ const line = code.slice(location - loc.column, end);
44
+ const marker = line.slice(0, loc.column).replace(/\S/g, ' ') + '^'.repeat(markerLen);
45
+ error.stack = `${filename}:${loc.line}\n${line}\n${marker}\n\n${error.stack}`;
46
+ return error;
47
+ }
48
+
49
+ function transformer(args, body, isAsync, isGenerator, filename) {
50
+ let code;
51
+ let argsOffset;
52
+ if (args === null) {
53
+ code = body;
54
+ // Note: Keywords are not allows to contain u escapes
55
+ if (!/\b(?:catch|import|async)\b/.test(code)) {
56
+ return {__proto__: null, code, hasAsync: false};
57
+ }
58
+ } else {
59
+ code = isAsync ? '(async function' : '(function';
60
+ if (isGenerator) code += '*';
61
+ code += ' anonymous(';
62
+ code += args;
63
+ argsOffset = code.length;
64
+ code += '\n) {\n';
65
+ code += body;
66
+ code += '\n})';
67
+ }
68
+
69
+ const parser = new AcornParser({
70
+ __proto__: null,
71
+ ecmaVersion: 2022,
72
+ allowAwaitOutsideFunction: args === null && isAsync,
73
+ allowReturnOutsideFunction: args === null
74
+ }, code);
75
+ let ast;
76
+ try {
77
+ ast = parser.parse();
78
+ } catch (e) {
79
+ // Try to generate a nicer error message.
80
+ if (e instanceof SyntaxError && e.pos !== undefined) {
81
+ let message = e.message;
82
+ const match = message.match(/^(.*) \(\d+:\d+\)$/);
83
+ if (match) message = match[1];
84
+ e = makeNiceSyntaxError(message, code, filename, e.pos, parser);
85
+ }
86
+ throw e;
87
+ }
88
+
89
+ if (args !== null) {
90
+ const pBody = assertType(ast, 'Program').body;
91
+ if (pBody.length !== 1) throw new SyntaxError('Single function literal required');
92
+ const expr = pBody[0];
93
+ if (expr.type !== 'ExpressionStatement') throw new SyntaxError('Single function literal required');
94
+ const func = expr.expression;
95
+ if (func.type !== 'FunctionExpression') throw new SyntaxError('Single function literal required');
96
+ if (func.body.start !== argsOffset + 3) throw new SyntaxError('Unexpected end of arg string');
97
+ }
98
+
99
+ const insertions = [];
100
+ let hasAsync = false;
101
+
102
+ const TO_LEFT = -100;
103
+ const TO_RIGHT = 100;
104
+
105
+ let internStateValiable = undefined;
106
+
107
+ acornWalkFull(ast, (node, state, type) => {
108
+ if (type === 'Function') {
109
+ if (node.async) hasAsync = true;
110
+ }
111
+ const nodeType = node.type;
112
+ if (nodeType === 'CatchClause') {
113
+ const param = node.param;
114
+ if (param) {
115
+ const name = assertType(param, 'Identifier').name;
116
+ const cBody = assertType(node.body, 'BlockStatement');
117
+ if (cBody.body.length > 0) {
118
+ insertions.push({
119
+ __proto__: null,
120
+ pos: cBody.body[0].start,
121
+ order: TO_LEFT,
122
+ code: `${name}=${INTERNAL_STATE_NAME}.handleException(${name});`
123
+ });
124
+ }
125
+ }
126
+ } else if (nodeType === 'WithStatement') {
127
+ insertions.push({
128
+ __proto__: null,
129
+ pos: node.object.start,
130
+ order: TO_LEFT,
131
+ code: INTERNAL_STATE_NAME + '.wrapWith('
132
+ });
133
+ insertions.push({
134
+ __proto__: null,
135
+ pos: node.object.end,
136
+ order: TO_RIGHT,
137
+ code: ')'
138
+ });
139
+ } else if (nodeType === 'Identifier') {
140
+ if (node.name === INTERNAL_STATE_NAME) {
141
+ if (internStateValiable === undefined || internStateValiable.start > node.start) {
142
+ internStateValiable = node;
143
+ }
144
+ }
145
+ } else if (nodeType === 'ImportExpression') {
146
+ insertions.push({
147
+ __proto__: null,
148
+ pos: node.start,
149
+ order: TO_RIGHT,
150
+ code: INTERNAL_STATE_NAME + '.'
151
+ });
152
+ }
153
+ });
154
+
155
+ if (internStateValiable) {
156
+ throw makeNiceSyntaxError('Use of internal vm2 state variable', code, filename, internStateValiable.start, {
157
+ __proto__: null,
158
+ start: internStateValiable.start,
159
+ end: internStateValiable.end
160
+ });
161
+ }
162
+
163
+ if (insertions.length === 0) return {__proto__: null, code, hasAsync};
164
+
165
+ insertions.sort((a, b) => (a.pos == b.pos ? a.order - b.order : a.pos - b.pos));
166
+
167
+ let ncode = '';
168
+ let curr = 0;
169
+ for (let i = 0; i < insertions.length; i++) {
170
+ const change = insertions[i];
171
+ ncode += code.substring(curr, change.pos) + change.code;
172
+ curr = change.pos;
173
+ }
174
+ ncode += code.substring(curr);
175
+
176
+ return {__proto__: null, code: ncode, hasAsync};
177
+ }
178
+
179
+ exports.INTERNAL_STATE_NAME = INTERNAL_STATE_NAME;
180
+ exports.transformer = transformer;