@casual-simulation/aux-runtime 3.2.7-alpha.6226622763
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.
- package/LICENSE.txt +21 -0
- package/README.md +82 -0
- package/index.d.ts +26 -0
- package/index.js +26 -0
- package/index.js.map +1 -0
- package/package.json +79 -0
- package/runtime/AuxCompiler.d.ts +258 -0
- package/runtime/AuxCompiler.js +722 -0
- package/runtime/AuxCompiler.js.map +1 -0
- package/runtime/AuxDevice.d.ts +28 -0
- package/runtime/AuxDevice.js +2 -0
- package/runtime/AuxDevice.js.map +1 -0
- package/runtime/AuxGlobalContext.d.ts +572 -0
- package/runtime/AuxGlobalContext.js +606 -0
- package/runtime/AuxGlobalContext.js.map +1 -0
- package/runtime/AuxLibrary.d.ts +2566 -0
- package/runtime/AuxLibrary.js +10210 -0
- package/runtime/AuxLibrary.js.map +1 -0
- package/runtime/AuxLibraryDefinitions.def +12288 -0
- package/runtime/AuxPartitionRealtimeEditModeProvider.d.ts +9 -0
- package/runtime/AuxPartitionRealtimeEditModeProvider.js +21 -0
- package/runtime/AuxPartitionRealtimeEditModeProvider.js.map +1 -0
- package/runtime/AuxRealtimeEditModeProvider.d.ts +35 -0
- package/runtime/AuxRealtimeEditModeProvider.js +34 -0
- package/runtime/AuxRealtimeEditModeProvider.js.map +1 -0
- package/runtime/AuxResults.d.ts +77 -0
- package/runtime/AuxResults.js +6 -0
- package/runtime/AuxResults.js.map +1 -0
- package/runtime/AuxRuntime.d.ts +252 -0
- package/runtime/AuxRuntime.js +2688 -0
- package/runtime/AuxRuntime.js.map +1 -0
- package/runtime/AuxRuntimeDynamicImports.d.ts +14 -0
- package/runtime/AuxRuntimeDynamicImports.js +24 -0
- package/runtime/AuxRuntimeDynamicImports.js.map +1 -0
- package/runtime/AuxVersion.d.ts +39 -0
- package/runtime/AuxVersion.js +2 -0
- package/runtime/AuxVersion.js.map +1 -0
- package/runtime/CasualOSError.d.ts +37 -0
- package/runtime/CasualOSError.js +25 -0
- package/runtime/CasualOSError.js.map +1 -0
- package/runtime/CompiledBot.d.ts +107 -0
- package/runtime/CompiledBot.js +44 -0
- package/runtime/CompiledBot.js.map +1 -0
- package/runtime/PerformanceNowPolyfill.d.ts +1 -0
- package/runtime/PerformanceNowPolyfill.js +8 -0
- package/runtime/PerformanceNowPolyfill.js.map +1 -0
- package/runtime/RecordsEvents.d.ts +1025 -0
- package/runtime/RecordsEvents.js +449 -0
- package/runtime/RecordsEvents.js.map +1 -0
- package/runtime/RuntimeBot.d.ts +177 -0
- package/runtime/RuntimeBot.js +732 -0
- package/runtime/RuntimeBot.js.map +1 -0
- package/runtime/RuntimeEvents.d.ts +126 -0
- package/runtime/RuntimeEvents.js +29 -0
- package/runtime/RuntimeEvents.js.map +1 -0
- package/runtime/RuntimeStateVersion.d.ts +23 -0
- package/runtime/RuntimeStateVersion.js +22 -0
- package/runtime/RuntimeStateVersion.js.map +1 -0
- package/runtime/Transpiler.d.ts +174 -0
- package/runtime/Transpiler.js +611 -0
- package/runtime/Transpiler.js.map +1 -0
- package/runtime/Utils.d.ts +44 -0
- package/runtime/Utils.js +253 -0
- package/runtime/Utils.js.map +1 -0
- package/runtime/index.d.ts +13 -0
- package/runtime/index.js +13 -0
- package/runtime/index.js.map +1 -0
- package/runtime/test/TestScriptBotFactory.d.ts +16 -0
- package/runtime/test/TestScriptBotFactory.js +107 -0
- package/runtime/test/TestScriptBotFactory.js.map +1 -0
|
@@ -0,0 +1,722 @@
|
|
|
1
|
+
import { calculateFinalLineLocation, calculateOriginalLineLocation, Transpiler, } from './Transpiler';
|
|
2
|
+
import { isScript, parseScript, hasValue, } from '@casual-simulation/aux-common/bots';
|
|
3
|
+
import { flatMap } from 'lodash';
|
|
4
|
+
import ErrorStackParser from '@casual-simulation/error-stack-parser';
|
|
5
|
+
import StackFrame from 'stackframe';
|
|
6
|
+
import { unwind, INTERPRETER_OBJECT, } from '@casual-simulation/js-interpreter/InterpreterUtils';
|
|
7
|
+
/**
|
|
8
|
+
* A symbol that identifies a function as having been compiled using the AuxCompiler.
|
|
9
|
+
*/
|
|
10
|
+
export const COMPILED_SCRIPT_SYMBOL = Symbol('compiled_script');
|
|
11
|
+
/**
|
|
12
|
+
* The symbol that is used to tag specific functions as interpretable.
|
|
13
|
+
*/
|
|
14
|
+
export const INTERPRETABLE_FUNCTION = Symbol('interpretable_function');
|
|
15
|
+
/**
|
|
16
|
+
* The symbol that is used to tag function modules with the metadata for a function.
|
|
17
|
+
*/
|
|
18
|
+
export const FUNCTION_METADATA = Symbol('function_metadata');
|
|
19
|
+
/**
|
|
20
|
+
* Creates a new interpretable function based on the given function.
|
|
21
|
+
* @param interpretableFunc
|
|
22
|
+
*/
|
|
23
|
+
export function createInterpretableFunction(interpretableFunc) {
|
|
24
|
+
const normalFunc = ((...args) => unwind(interpretableFunc(...args)));
|
|
25
|
+
normalFunc[INTERPRETABLE_FUNCTION] = interpretableFunc;
|
|
26
|
+
return normalFunc;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Sets the INTERPRETABLE_FUNCTION property on the given object (semantically a function) to the given interpretable version and returns the object.
|
|
30
|
+
* @param interpretableFunc The version of the function that should be used as the interpretable version of the function.
|
|
31
|
+
* @param normalFunc The function that should be tagged.
|
|
32
|
+
*/
|
|
33
|
+
export function tagAsInterpretableFunction(interpretableFunc, normalFunc) {
|
|
34
|
+
normalFunc[INTERPRETABLE_FUNCTION] = interpretableFunc;
|
|
35
|
+
return normalFunc;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Determines if the given object has been tagged with the GENERATOR_FUNCTION_TAG.
|
|
39
|
+
* @param obj The object.
|
|
40
|
+
*/
|
|
41
|
+
export function isInterpretableFunction(obj) {
|
|
42
|
+
return ((typeof obj === 'function' || typeof obj === 'object') &&
|
|
43
|
+
obj !== null &&
|
|
44
|
+
!!obj[INTERPRETABLE_FUNCTION]);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Gets the interpretable version of the given function.
|
|
48
|
+
*/
|
|
49
|
+
export function getInterpretableFunction(obj) {
|
|
50
|
+
return isInterpretableFunction(obj)
|
|
51
|
+
? obj[INTERPRETABLE_FUNCTION]
|
|
52
|
+
: null;
|
|
53
|
+
}
|
|
54
|
+
const JSX_FACTORY = 'html.h';
|
|
55
|
+
const JSX_FRAGMENT_FACTORY = 'html.f';
|
|
56
|
+
/**
|
|
57
|
+
* Defines a class that can compile scripts and formulas
|
|
58
|
+
* into functions.
|
|
59
|
+
*/
|
|
60
|
+
export class AuxCompiler {
|
|
61
|
+
constructor() {
|
|
62
|
+
this._transpiler = new Transpiler({
|
|
63
|
+
jsxFactory: JSX_FACTORY,
|
|
64
|
+
jsxFragment: JSX_FRAGMENT_FACTORY,
|
|
65
|
+
});
|
|
66
|
+
this._functionCache = new Map();
|
|
67
|
+
/**
|
|
68
|
+
* The offset that should be applied to error line numbers when calculating their original
|
|
69
|
+
* position. Needed because Node.js Windows produces different line numbers than Mac/Linux.
|
|
70
|
+
*
|
|
71
|
+
* Node.js versions greater than v12.14.0 have an issue with identifying the correct line number
|
|
72
|
+
* for errors and stack traces. This issue is fixed in Node.js v14 and later (possibly also fixed in v13 but I didn't check that).
|
|
73
|
+
*/
|
|
74
|
+
this.functionErrorLineOffset = 0;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Calculates the "original" stack trace that the given error occurred at
|
|
78
|
+
* within the given function.
|
|
79
|
+
* Returns null if the original stack trace was unable to be determined.
|
|
80
|
+
* @param functionNameMap A map of function names to their scripts.
|
|
81
|
+
* @param error The error that occurred.
|
|
82
|
+
*/
|
|
83
|
+
calculateOriginalStackTrace(functionNameMap, error) {
|
|
84
|
+
if (INTERPRETER_OBJECT in error) {
|
|
85
|
+
return this._calculateInterpreterErrorOriginalStackTrace(functionNameMap, error);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
return this._calculateNativeErrorOriginalStackTrace(functionNameMap, error);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
_calculateInterpreterErrorOriginalStackTrace(functionNameMap, error) {
|
|
92
|
+
var _a, _b, _c, _d, _e, _f;
|
|
93
|
+
const frames = ErrorStackParser.parse(error);
|
|
94
|
+
if (frames.length < 1) {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
let transformedFrames = [];
|
|
98
|
+
let lastScriptFrameIndex = -1;
|
|
99
|
+
let lastScript;
|
|
100
|
+
for (let i = frames.length - 1; i >= 0; i--) {
|
|
101
|
+
const frame = frames[i];
|
|
102
|
+
let savedFrame = false;
|
|
103
|
+
let functionName = frame.functionName;
|
|
104
|
+
const lastDotIndex = functionName.lastIndexOf('.');
|
|
105
|
+
if (lastDotIndex >= 0) {
|
|
106
|
+
functionName = functionName.slice(lastDotIndex + 1);
|
|
107
|
+
}
|
|
108
|
+
const script = functionNameMap.get(functionName);
|
|
109
|
+
let isWrapperFunc = false;
|
|
110
|
+
if (!/^__wrapperFunc/.test(frame.functionName)) {
|
|
111
|
+
if (script) {
|
|
112
|
+
lastScript = script;
|
|
113
|
+
const location = {
|
|
114
|
+
lineNumber: frame.lineNumber + this.functionErrorLineOffset,
|
|
115
|
+
column: frame.columnNumber,
|
|
116
|
+
};
|
|
117
|
+
const originalLocation = this.calculateOriginalLineLocation(script, location);
|
|
118
|
+
savedFrame = true;
|
|
119
|
+
if (lastScriptFrameIndex < 0) {
|
|
120
|
+
lastScriptFrameIndex = i;
|
|
121
|
+
}
|
|
122
|
+
transformedFrames.unshift(new StackFrame({
|
|
123
|
+
functionName: (_a = lastScript.metadata.diagnosticFunctionName) !== null && _a !== void 0 ? _a : functionName,
|
|
124
|
+
fileName: (_b = script.metadata.fileName) !== null && _b !== void 0 ? _b : functionName,
|
|
125
|
+
lineNumber: Math.max(originalLocation.lineNumber + 1, 1),
|
|
126
|
+
columnNumber: Math.max(originalLocation.column + 1, 1),
|
|
127
|
+
}));
|
|
128
|
+
}
|
|
129
|
+
else if (lastScript) {
|
|
130
|
+
if (typeof frame.lineNumber === 'number' &&
|
|
131
|
+
typeof frame.columnNumber === 'number') {
|
|
132
|
+
const location = {
|
|
133
|
+
lineNumber: frame.lineNumber + this.functionErrorLineOffset,
|
|
134
|
+
column: frame.columnNumber,
|
|
135
|
+
};
|
|
136
|
+
const originalLocation = this.calculateOriginalLineLocation(lastScript, location);
|
|
137
|
+
savedFrame = true;
|
|
138
|
+
transformedFrames.unshift(new StackFrame({
|
|
139
|
+
functionName: (_c = lastScript.metadata
|
|
140
|
+
.diagnosticFunctionName) !== null && _c !== void 0 ? _c : functionName,
|
|
141
|
+
fileName: (_d = lastScript.metadata.fileName) !== null && _d !== void 0 ? _d : functionName,
|
|
142
|
+
lineNumber: Math.max(originalLocation.lineNumber + 1, 1),
|
|
143
|
+
columnNumber: Math.max(originalLocation.column + 1, 1),
|
|
144
|
+
}));
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
savedFrame = true;
|
|
148
|
+
transformedFrames.unshift(new StackFrame({
|
|
149
|
+
functionName: (_e = lastScript.metadata
|
|
150
|
+
.diagnosticFunctionName) !== null && _e !== void 0 ? _e : functionName,
|
|
151
|
+
fileName: (_f = lastScript.metadata.fileName) !== null && _f !== void 0 ? _f : functionName,
|
|
152
|
+
}));
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
isWrapperFunc = true;
|
|
158
|
+
}
|
|
159
|
+
if (!savedFrame && isWrapperFunc) {
|
|
160
|
+
savedFrame = true;
|
|
161
|
+
if (lastScriptFrameIndex > i) {
|
|
162
|
+
lastScriptFrameIndex -= 1;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
if (!savedFrame) {
|
|
166
|
+
transformedFrames.unshift(frame);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
if (lastScriptFrameIndex >= 0) {
|
|
170
|
+
const finalFrames = [
|
|
171
|
+
...transformedFrames.slice(0, lastScriptFrameIndex + 1),
|
|
172
|
+
new StackFrame({
|
|
173
|
+
fileName: '[Native CasualOS Code]',
|
|
174
|
+
functionName: '<CasualOS>',
|
|
175
|
+
}),
|
|
176
|
+
];
|
|
177
|
+
const stack = finalFrames
|
|
178
|
+
.map((frame) => ' at ' + frame.toString())
|
|
179
|
+
.join('\n');
|
|
180
|
+
return error.toString() + '\n' + stack;
|
|
181
|
+
}
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
_calculateNativeErrorOriginalStackTrace(functionNameMap, error) {
|
|
185
|
+
var _a, _b, _c, _d;
|
|
186
|
+
const frames = ErrorStackParser.parse(error);
|
|
187
|
+
if (frames.length < 1) {
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
let transformedFrames = [];
|
|
191
|
+
let lastScriptFrameIndex = -1;
|
|
192
|
+
let lastScript;
|
|
193
|
+
for (let i = frames.length - 1; i >= 0; i--) {
|
|
194
|
+
const frame = frames[i];
|
|
195
|
+
const originFrame = frame.evalOrigin;
|
|
196
|
+
let savedFrame = false;
|
|
197
|
+
if (!!originFrame &&
|
|
198
|
+
originFrame.functionName === '__constructFunction') {
|
|
199
|
+
let functionName = frame.functionName;
|
|
200
|
+
const lastDotIndex = functionName.lastIndexOf('.');
|
|
201
|
+
if (lastDotIndex >= 0) {
|
|
202
|
+
functionName = functionName.slice(lastDotIndex + 1);
|
|
203
|
+
}
|
|
204
|
+
const script = functionNameMap.get(functionName);
|
|
205
|
+
if (script) {
|
|
206
|
+
lastScript = script;
|
|
207
|
+
const location = {
|
|
208
|
+
lineNumber: originFrame.lineNumber +
|
|
209
|
+
this.functionErrorLineOffset,
|
|
210
|
+
column: originFrame.columnNumber,
|
|
211
|
+
};
|
|
212
|
+
const originalLocation = this.calculateOriginalLineLocation(script, location);
|
|
213
|
+
savedFrame = true;
|
|
214
|
+
if (lastScriptFrameIndex < 0) {
|
|
215
|
+
lastScriptFrameIndex = i;
|
|
216
|
+
}
|
|
217
|
+
transformedFrames.unshift(new StackFrame({
|
|
218
|
+
functionName: (_a = lastScript.metadata.diagnosticFunctionName) !== null && _a !== void 0 ? _a : functionName,
|
|
219
|
+
fileName: (_b = script.metadata.fileName) !== null && _b !== void 0 ? _b : functionName,
|
|
220
|
+
lineNumber: originalLocation.lineNumber + 1,
|
|
221
|
+
columnNumber: originalLocation.column + 1,
|
|
222
|
+
}));
|
|
223
|
+
}
|
|
224
|
+
else if (lastScript) {
|
|
225
|
+
const location = {
|
|
226
|
+
lineNumber: originFrame.lineNumber +
|
|
227
|
+
this.functionErrorLineOffset,
|
|
228
|
+
column: originFrame.columnNumber,
|
|
229
|
+
};
|
|
230
|
+
const originalLocation = this.calculateOriginalLineLocation(lastScript, location);
|
|
231
|
+
savedFrame = true;
|
|
232
|
+
transformedFrames.unshift(new StackFrame({
|
|
233
|
+
functionName: (_c = lastScript.metadata.diagnosticFunctionName) !== null && _c !== void 0 ? _c : functionName,
|
|
234
|
+
fileName: (_d = lastScript.metadata.fileName) !== null && _d !== void 0 ? _d : functionName,
|
|
235
|
+
lineNumber: originalLocation.lineNumber + 1,
|
|
236
|
+
columnNumber: originalLocation.column + 1,
|
|
237
|
+
}));
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
if (!savedFrame) {
|
|
241
|
+
if (frame.functionName === '__wrapperFunc') {
|
|
242
|
+
savedFrame = true;
|
|
243
|
+
if (lastScriptFrameIndex > i) {
|
|
244
|
+
lastScriptFrameIndex -= 1;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
if (!savedFrame) {
|
|
249
|
+
transformedFrames.unshift(frame);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
if (lastScriptFrameIndex >= 0) {
|
|
253
|
+
const finalFrames = [
|
|
254
|
+
...transformedFrames.slice(0, lastScriptFrameIndex + 1),
|
|
255
|
+
new StackFrame({
|
|
256
|
+
fileName: '[Native CasualOS Code]',
|
|
257
|
+
functionName: '<CasualOS>',
|
|
258
|
+
}),
|
|
259
|
+
];
|
|
260
|
+
const stack = finalFrames
|
|
261
|
+
.map((frame) => ' at ' + frame.toString())
|
|
262
|
+
.join('\n');
|
|
263
|
+
return error.toString() + '\n' + stack;
|
|
264
|
+
}
|
|
265
|
+
return null;
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Calculates the original location within the given function for the given location.
|
|
269
|
+
* The returned location uses zero-based line and column numbers.
|
|
270
|
+
* @param func The function.
|
|
271
|
+
* @param location The location. Line and column numbers are one-based.
|
|
272
|
+
*/
|
|
273
|
+
calculateOriginalLineLocation(func, location) {
|
|
274
|
+
// Line numbers should be one based
|
|
275
|
+
if (location.lineNumber <
|
|
276
|
+
func.metadata.scriptLineOffset + func.metadata.transpilerLineOffset) {
|
|
277
|
+
return {
|
|
278
|
+
lineNumber: 0,
|
|
279
|
+
column: 0,
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
let transpiledLocation = {
|
|
283
|
+
lineNumber: location.lineNumber - func.metadata.scriptLineOffset - 1,
|
|
284
|
+
column: location.column - 1,
|
|
285
|
+
};
|
|
286
|
+
let result = calculateOriginalLineLocation(func.metadata.transpilerResult, transpiledLocation);
|
|
287
|
+
return {
|
|
288
|
+
lineNumber: result.lineNumber - func.metadata.transpilerLineOffset,
|
|
289
|
+
column: result.column,
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Calculates the final location within the given function for the given location.
|
|
294
|
+
* @param func The function.
|
|
295
|
+
* @param location The location. Line and column numbers are zero based.
|
|
296
|
+
*/
|
|
297
|
+
calculateFinalLineLocation(func, location) {
|
|
298
|
+
// Line numbers should be zero based
|
|
299
|
+
if (location.lineNumber < 0) {
|
|
300
|
+
return {
|
|
301
|
+
lineNumber: 0,
|
|
302
|
+
column: 0,
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
let transpiledLocation = {
|
|
306
|
+
lineNumber: location.lineNumber + func.metadata.transpilerLineOffset,
|
|
307
|
+
column: location.column,
|
|
308
|
+
};
|
|
309
|
+
let result = calculateFinalLineLocation(func.metadata.transpilerResult, transpiledLocation);
|
|
310
|
+
return {
|
|
311
|
+
lineNumber: result.lineNumber + func.metadata.scriptLineOffset,
|
|
312
|
+
column: result.column,
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Compiles the given script into a function.
|
|
317
|
+
* @param script The script to compile.
|
|
318
|
+
* @param options The options that should be used to compile the script.
|
|
319
|
+
*/
|
|
320
|
+
compile(script, options) {
|
|
321
|
+
var _a;
|
|
322
|
+
let { func, scriptLineOffset, transpilerLineOffset, async, transpilerResult, constructedFunction, } = this._compileFunction(script, options || {});
|
|
323
|
+
const scriptFunction = func;
|
|
324
|
+
const meta = {
|
|
325
|
+
scriptFunction,
|
|
326
|
+
scriptLineOffset,
|
|
327
|
+
transpilerLineOffset,
|
|
328
|
+
transpilerResult,
|
|
329
|
+
fileName: options === null || options === void 0 ? void 0 : options.fileName,
|
|
330
|
+
diagnosticFunctionName: options === null || options === void 0 ? void 0 : options.diagnosticFunctionName,
|
|
331
|
+
isAsync: async,
|
|
332
|
+
constructedFunction,
|
|
333
|
+
context: options === null || options === void 0 ? void 0 : options.context,
|
|
334
|
+
};
|
|
335
|
+
if (options) {
|
|
336
|
+
if (options.before ||
|
|
337
|
+
options.after ||
|
|
338
|
+
options.onError ||
|
|
339
|
+
options.invoke ||
|
|
340
|
+
async) {
|
|
341
|
+
const before = options.before || (() => { });
|
|
342
|
+
const after = options.after || (() => { });
|
|
343
|
+
const onError = options.onError ||
|
|
344
|
+
((err) => {
|
|
345
|
+
throw err;
|
|
346
|
+
});
|
|
347
|
+
const invoke = options.invoke;
|
|
348
|
+
const context = options.context;
|
|
349
|
+
const scriptFunc = func;
|
|
350
|
+
const finalFunc = invoke
|
|
351
|
+
? (...args) => invoke(() => scriptFunc(...args), context)
|
|
352
|
+
: scriptFunc;
|
|
353
|
+
if (async) {
|
|
354
|
+
func = function __wrapperFunc(...args) {
|
|
355
|
+
before(context);
|
|
356
|
+
try {
|
|
357
|
+
let result = finalFunc(...args);
|
|
358
|
+
if (!(result instanceof Promise)) {
|
|
359
|
+
result = new Promise((resolve, reject) => {
|
|
360
|
+
result.then(resolve, reject);
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
return result.catch((ex) => {
|
|
364
|
+
onError(ex, context, meta);
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
catch (ex) {
|
|
368
|
+
onError(ex, context, meta);
|
|
369
|
+
}
|
|
370
|
+
finally {
|
|
371
|
+
after(context);
|
|
372
|
+
}
|
|
373
|
+
};
|
|
374
|
+
if (isInterpretableFunction(scriptFunc)) {
|
|
375
|
+
const interpretableFunc = getInterpretableFunction(scriptFunc);
|
|
376
|
+
const finalFunc = invoke
|
|
377
|
+
? (...args) => invoke(() => interpretableFunc(...args), context)
|
|
378
|
+
: interpretableFunc;
|
|
379
|
+
const interpretable = function* __wrapperFunc(...args) {
|
|
380
|
+
before(context);
|
|
381
|
+
try {
|
|
382
|
+
let result = yield* finalFunc(...args);
|
|
383
|
+
if (!(result instanceof Promise)) {
|
|
384
|
+
result = new Promise((resolve, reject) => {
|
|
385
|
+
result.then(resolve, reject);
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
return result.catch((ex) => {
|
|
389
|
+
onError(ex, context, meta);
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
catch (ex) {
|
|
393
|
+
onError(ex, context, meta);
|
|
394
|
+
}
|
|
395
|
+
finally {
|
|
396
|
+
after(context);
|
|
397
|
+
}
|
|
398
|
+
};
|
|
399
|
+
tagAsInterpretableFunction(interpretable, func);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
else {
|
|
403
|
+
func = function __wrapperFunc(...args) {
|
|
404
|
+
before(context);
|
|
405
|
+
try {
|
|
406
|
+
return finalFunc(...args);
|
|
407
|
+
}
|
|
408
|
+
catch (ex) {
|
|
409
|
+
onError(ex, context, meta);
|
|
410
|
+
}
|
|
411
|
+
finally {
|
|
412
|
+
after(context);
|
|
413
|
+
}
|
|
414
|
+
};
|
|
415
|
+
if (isInterpretableFunction(scriptFunc)) {
|
|
416
|
+
const interpretableFunc = getInterpretableFunction(scriptFunc);
|
|
417
|
+
const finalFunc = invoke
|
|
418
|
+
? (...args) => invoke(() => interpretableFunc(...args), context)
|
|
419
|
+
: interpretableFunc;
|
|
420
|
+
const interpretable = function* __wrapperFunc(...args) {
|
|
421
|
+
before(context);
|
|
422
|
+
try {
|
|
423
|
+
return yield* finalFunc(...args);
|
|
424
|
+
}
|
|
425
|
+
catch (ex) {
|
|
426
|
+
onError(ex, context, meta);
|
|
427
|
+
}
|
|
428
|
+
finally {
|
|
429
|
+
after(context);
|
|
430
|
+
}
|
|
431
|
+
};
|
|
432
|
+
tagAsInterpretableFunction(interpretable, func);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
const final = func;
|
|
438
|
+
final.metadata = meta;
|
|
439
|
+
if ((_a = meta.constructedFunction) === null || _a === void 0 ? void 0 : _a.module) {
|
|
440
|
+
Object.defineProperty(meta.constructedFunction.module, FUNCTION_METADATA, {
|
|
441
|
+
value: meta,
|
|
442
|
+
writable: false,
|
|
443
|
+
enumerable: false,
|
|
444
|
+
configurable: true,
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
return final;
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Finds the line number information for a function created with this compiler using the
|
|
451
|
+
* given stack trace and metadata.
|
|
452
|
+
* @param stackTrace The stack trace.
|
|
453
|
+
* @param metadata The metadata.
|
|
454
|
+
*/
|
|
455
|
+
findLineInfo(stackTrace, metadata) {
|
|
456
|
+
const frame = stackTrace.find((f) => {
|
|
457
|
+
const func = f.getFunction();
|
|
458
|
+
return func && func[COMPILED_SCRIPT_SYMBOL] === true;
|
|
459
|
+
});
|
|
460
|
+
if (frame) {
|
|
461
|
+
const line = frame.getLineNumber();
|
|
462
|
+
const column = frame.getColumnNumber();
|
|
463
|
+
const result = {
|
|
464
|
+
line: null,
|
|
465
|
+
column: null,
|
|
466
|
+
};
|
|
467
|
+
if (hasValue(line)) {
|
|
468
|
+
result.line = line - metadata.scriptLineOffset;
|
|
469
|
+
}
|
|
470
|
+
if (hasValue(column)) {
|
|
471
|
+
result.column = column;
|
|
472
|
+
}
|
|
473
|
+
return result;
|
|
474
|
+
}
|
|
475
|
+
return null;
|
|
476
|
+
}
|
|
477
|
+
/**
|
|
478
|
+
* Sets the given breakpoint.
|
|
479
|
+
* @param breakpoint The breakpoint that should be set.
|
|
480
|
+
*/
|
|
481
|
+
setBreakpoint(breakpoint) {
|
|
482
|
+
const metadata = breakpoint.func.metadata;
|
|
483
|
+
if (!metadata.constructedFunction) {
|
|
484
|
+
throw new Error('Cannot set breakpoints for non-interpreted functions.');
|
|
485
|
+
}
|
|
486
|
+
if (!breakpoint.interpreter) {
|
|
487
|
+
throw new Error('You must provide an interpreter when setting a breakpoint.');
|
|
488
|
+
}
|
|
489
|
+
const func = metadata.constructedFunction;
|
|
490
|
+
const interpreter = breakpoint.interpreter;
|
|
491
|
+
const loc = this.calculateFinalLineLocation(breakpoint.func, {
|
|
492
|
+
lineNumber: breakpoint.lineNumber - 1,
|
|
493
|
+
column: breakpoint.columnNumber - 1,
|
|
494
|
+
});
|
|
495
|
+
interpreter.setBreakpoint({
|
|
496
|
+
id: breakpoint.id,
|
|
497
|
+
func,
|
|
498
|
+
lineNumber: loc.lineNumber + 1,
|
|
499
|
+
columnNumber: loc.column + 1,
|
|
500
|
+
states: breakpoint.states,
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
listPossibleBreakpoints(func, interpreter) {
|
|
504
|
+
const metadata = func.metadata;
|
|
505
|
+
if (!metadata.constructedFunction) {
|
|
506
|
+
throw new Error('Cannot list possible breakpoints for non-interpreted functions.');
|
|
507
|
+
}
|
|
508
|
+
if (!interpreter) {
|
|
509
|
+
throw new Error('You must provide an interpreter when listing possible breakpoints.');
|
|
510
|
+
}
|
|
511
|
+
const code = metadata.constructedFunction.func
|
|
512
|
+
.ECMAScriptCode;
|
|
513
|
+
const returnStatement = code.FunctionStatementList.find((s) => s.type === 'ReturnStatement');
|
|
514
|
+
const functionDeclaration = returnStatement.Expression;
|
|
515
|
+
const body = 'FunctionBody' in functionDeclaration
|
|
516
|
+
? functionDeclaration.FunctionBody
|
|
517
|
+
: functionDeclaration.AsyncFunctionBody;
|
|
518
|
+
const possibleBreakpoints = interpreter.listPossibleBreakpoints(body);
|
|
519
|
+
let returnedValues = [];
|
|
520
|
+
for (let pb of possibleBreakpoints) {
|
|
521
|
+
if (pb.lineNumber <
|
|
522
|
+
metadata.scriptLineOffset + metadata.transpilerLineOffset) {
|
|
523
|
+
continue;
|
|
524
|
+
}
|
|
525
|
+
const loc = this.calculateOriginalLineLocation(func, {
|
|
526
|
+
lineNumber: pb.lineNumber,
|
|
527
|
+
column: pb.columnNumber,
|
|
528
|
+
});
|
|
529
|
+
if (loc.lineNumber < 0 || loc.column < 0) {
|
|
530
|
+
continue;
|
|
531
|
+
}
|
|
532
|
+
returnedValues.push({
|
|
533
|
+
lineNumber: loc.lineNumber + 1,
|
|
534
|
+
columnNumber: loc.column + 1,
|
|
535
|
+
possibleStates: pb.possibleStates,
|
|
536
|
+
});
|
|
537
|
+
}
|
|
538
|
+
return returnedValues;
|
|
539
|
+
}
|
|
540
|
+
_parseScript(script) {
|
|
541
|
+
return script;
|
|
542
|
+
}
|
|
543
|
+
_compileFunction(script, options) {
|
|
544
|
+
// Yes this code is super ugly.
|
|
545
|
+
// Some day we will engineer this into a real
|
|
546
|
+
// compiler, but for now this ad-hoc method
|
|
547
|
+
// seems to work.
|
|
548
|
+
var _a, _b;
|
|
549
|
+
let async = false;
|
|
550
|
+
if (isScript(script)) {
|
|
551
|
+
script = parseScript(script);
|
|
552
|
+
}
|
|
553
|
+
if (script.indexOf('await ') >= 0) {
|
|
554
|
+
async = true;
|
|
555
|
+
}
|
|
556
|
+
script = this._parseScript(script);
|
|
557
|
+
let transpilerLineOffset = 0;
|
|
558
|
+
let scriptLineOffset = 0;
|
|
559
|
+
let customGlobalThis = false;
|
|
560
|
+
let constantsCode = '';
|
|
561
|
+
if (options.constants) {
|
|
562
|
+
const lines = Object.keys(options.constants)
|
|
563
|
+
.filter((v) => v !== 'this')
|
|
564
|
+
.map((v) => `const ${v} = constants["${v}"];`);
|
|
565
|
+
customGlobalThis =
|
|
566
|
+
!options.interpreter && 'globalThis' in options.constants;
|
|
567
|
+
constantsCode = lines.join('\n') + '\n';
|
|
568
|
+
scriptLineOffset += 1 + Math.max(lines.length - 1, 0);
|
|
569
|
+
}
|
|
570
|
+
let variablesCode = '';
|
|
571
|
+
if (options.variables) {
|
|
572
|
+
const lines = Object.keys(options.variables)
|
|
573
|
+
.filter((v) => v !== 'this')
|
|
574
|
+
.map((v) => `const ${v} = variables["${v}"](context);`);
|
|
575
|
+
variablesCode = '\n' + lines.join('\n');
|
|
576
|
+
transpilerLineOffset += 1 + Math.max(lines.length - 1, 0);
|
|
577
|
+
}
|
|
578
|
+
let argumentsCode = '';
|
|
579
|
+
if (options.arguments) {
|
|
580
|
+
const lines = flatMap(options.arguments
|
|
581
|
+
.filter((v) => v !== 'this')
|
|
582
|
+
.map((v, i) => Array.isArray(v)
|
|
583
|
+
? [v, i]
|
|
584
|
+
: [[v], i]), ([v, i]) => v.map((name) => `const ${name} = args[${i}];`));
|
|
585
|
+
argumentsCode = '\n' + lines.join('\n');
|
|
586
|
+
transpilerLineOffset += 1 + Math.max(lines.length - 1, 0);
|
|
587
|
+
}
|
|
588
|
+
let scriptCode;
|
|
589
|
+
scriptCode = `\n { \n${script}\n }`;
|
|
590
|
+
transpilerLineOffset += 2;
|
|
591
|
+
let withCodeStart = '';
|
|
592
|
+
let withCodeEnd = '';
|
|
593
|
+
if (customGlobalThis) {
|
|
594
|
+
withCodeStart = 'with(__globalObj) {\n';
|
|
595
|
+
withCodeEnd = '}';
|
|
596
|
+
scriptLineOffset += 1;
|
|
597
|
+
}
|
|
598
|
+
let syntaxErrorLineOffset = 0;
|
|
599
|
+
// Function needs a name because acorn doesn't understand
|
|
600
|
+
// that this function is allowed to be anonymous.
|
|
601
|
+
let functionCode = `function ${(_a = options.functionName) !== null && _a !== void 0 ? _a : '_'}(...args) { ${argumentsCode}${variablesCode}${scriptCode}\n }`;
|
|
602
|
+
if (async) {
|
|
603
|
+
functionCode = `async ` + functionCode;
|
|
604
|
+
}
|
|
605
|
+
try {
|
|
606
|
+
if (options.forceSync) {
|
|
607
|
+
async = false;
|
|
608
|
+
}
|
|
609
|
+
this._transpiler.forceSync = (_b = options.forceSync) !== null && _b !== void 0 ? _b : false;
|
|
610
|
+
const transpiled = this._transpiler.transpileWithMetadata(functionCode);
|
|
611
|
+
if (options.interpreter) {
|
|
612
|
+
const finalCode = `${constantsCode}return ${transpiled.code};`;
|
|
613
|
+
syntaxErrorLineOffset += 1;
|
|
614
|
+
scriptLineOffset += 1;
|
|
615
|
+
const func = options.interpreter.createFunction('test', finalCode, 'constants', 'variables', 'context');
|
|
616
|
+
let result = unwind(options.interpreter.callFunction(func, options.constants, options.variables, options.interpreter.proxyObject(options.context)));
|
|
617
|
+
let finalFunc = result;
|
|
618
|
+
if (options.variables) {
|
|
619
|
+
if ('this' in options.variables) {
|
|
620
|
+
finalFunc = result.bind(options.variables['this'](options.context));
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
if (INTERPRETER_OBJECT in result) {
|
|
624
|
+
finalFunc = createInterpretableFunction(finalFunc);
|
|
625
|
+
finalFunc[INTERPRETER_OBJECT] = result[INTERPRETER_OBJECT];
|
|
626
|
+
}
|
|
627
|
+
return {
|
|
628
|
+
func: finalFunc,
|
|
629
|
+
scriptLineOffset,
|
|
630
|
+
transpilerLineOffset,
|
|
631
|
+
async,
|
|
632
|
+
transpilerResult: transpiled,
|
|
633
|
+
constructedFunction: func,
|
|
634
|
+
};
|
|
635
|
+
}
|
|
636
|
+
else {
|
|
637
|
+
const finalCode = `${withCodeStart}return function(constants, variables, context) { ${constantsCode}return ${transpiled.code}; }${withCodeEnd}`;
|
|
638
|
+
let func = this._buildFunction(finalCode, options);
|
|
639
|
+
func[COMPILED_SCRIPT_SYMBOL] = true;
|
|
640
|
+
// Add 1 extra line to count the line feeds that
|
|
641
|
+
// is automatically inserted at the start of the script as part of the process of
|
|
642
|
+
// compiling the dynamic script.
|
|
643
|
+
// See https://tc39.es/ecma262/#sec-createdynamicfunction
|
|
644
|
+
scriptLineOffset += 2;
|
|
645
|
+
if (options.variables) {
|
|
646
|
+
if ('this' in options.variables) {
|
|
647
|
+
func = func.bind(options.variables['this'](options.context));
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
return {
|
|
651
|
+
func,
|
|
652
|
+
scriptLineOffset: scriptLineOffset,
|
|
653
|
+
transpilerLineOffset: transpilerLineOffset,
|
|
654
|
+
async,
|
|
655
|
+
transpilerResult: transpiled,
|
|
656
|
+
constructedFunction: null,
|
|
657
|
+
};
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
catch (err) {
|
|
661
|
+
if (err instanceof SyntaxError) {
|
|
662
|
+
const replaced = replaceSyntaxErrorLineNumber(err, (location) => ({
|
|
663
|
+
lineNumber: location.lineNumber -
|
|
664
|
+
transpilerLineOffset -
|
|
665
|
+
syntaxErrorLineOffset,
|
|
666
|
+
column: location.column,
|
|
667
|
+
}));
|
|
668
|
+
if (replaced) {
|
|
669
|
+
throw replaced;
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
throw err;
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
_buildFunction(finalCode, options) {
|
|
676
|
+
var _a;
|
|
677
|
+
return this.__constructFunction(finalCode)((_a = options.constants) === null || _a === void 0 ? void 0 : _a.globalThis)(options.constants, options.variables, options.context);
|
|
678
|
+
}
|
|
679
|
+
__constructFunction(finalCode) {
|
|
680
|
+
let existing = this._functionCache.get(finalCode);
|
|
681
|
+
if (!existing) {
|
|
682
|
+
existing = Function('__globalObj', finalCode);
|
|
683
|
+
this._functionCache.set(finalCode, existing);
|
|
684
|
+
}
|
|
685
|
+
return existing;
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
const SYNTAX_ERROR_LINE_NUMBER_REGEX = /\((\d+):(\d+)\)$/;
|
|
689
|
+
/**
|
|
690
|
+
* Parses the line and column numbers from the the given syntax error, transforms them with the given function,
|
|
691
|
+
* and returns a new syntax error that contains the new location. Returns null if the line and column numbers could not be parsed.
|
|
692
|
+
* @param error The error to transform.
|
|
693
|
+
* @param transform The function that should be used to transform the errors.
|
|
694
|
+
* @returns
|
|
695
|
+
*/
|
|
696
|
+
export function replaceSyntaxErrorLineNumber(error, transform) {
|
|
697
|
+
const matches = SYNTAX_ERROR_LINE_NUMBER_REGEX.exec(error.message);
|
|
698
|
+
if (matches) {
|
|
699
|
+
const [str, line, column] = matches;
|
|
700
|
+
const lineNumber = parseInt(line);
|
|
701
|
+
const columnNumber = parseInt(column);
|
|
702
|
+
const location = transform({
|
|
703
|
+
lineNumber,
|
|
704
|
+
column: columnNumber,
|
|
705
|
+
});
|
|
706
|
+
return new SyntaxError(error.message.replace(str, `(${location.lineNumber}:${location.column})`));
|
|
707
|
+
}
|
|
708
|
+
else {
|
|
709
|
+
return null;
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
// export class CompiledScriptError extends Error {
|
|
713
|
+
// /**
|
|
714
|
+
// * The inner error.
|
|
715
|
+
// */
|
|
716
|
+
// error: Error;
|
|
717
|
+
// constructor(error: Error) {
|
|
718
|
+
// super(error.message);
|
|
719
|
+
// this.error = error;
|
|
720
|
+
// }
|
|
721
|
+
// }
|
|
722
|
+
//# sourceMappingURL=AuxCompiler.js.map
|