aimyapi 1.0.8 → 1.0.10
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 +21 -21
- package/README.md +221 -195
- package/dist/index.cjs +233 -110
- package/dist/index.d.cts +16 -8
- package/dist/index.d.mts +16 -8
- package/dist/index.d.ts +16 -8
- package/dist/index.js +233 -110
- package/dist/index.mjs +235 -112
- package/example/example1.ts +41 -30
- package/example/example2.ts +58 -58
- package/example/example3.ts +69 -69
- package/example/ordering_api.md +94 -94
- package/example/ordering_api.ts +191 -191
- package/example/ordering_api_impl.ts +207 -207
- package/example/sales_api.md +1 -5
- package/example/sales_api.ts +31 -29
- package/example/sales_api_impl.ts +74 -60
- package/package.json +2 -3
- package/prompts/generate-code-prompt.md +37 -0
- package/src/index.ts +79 -55
- package/src/log-tester-inject.ts +233 -0
- package/src/log-tester.ts +185 -0
- package/src/logger.ts +113 -0
- package/src/sandbox-wrappers.ts +296 -249
- package/src/sandbox.ts +35 -58
- package/src/utils.ts +33 -3
- package/tsconfig.json +12 -12
- package/prompts/create-task-prompt.md +0 -37
package/src/sandbox-wrappers.ts
CHANGED
|
@@ -1,250 +1,297 @@
|
|
|
1
|
-
import "quickjs-emscripten";
|
|
2
|
-
import { QuickJSDeferredPromise } from "quickjs-emscripten";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
wrappedArgs.
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
return
|
|
58
|
-
} else if (
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
return vm.
|
|
81
|
-
} else {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
1
|
+
import "quickjs-emscripten";
|
|
2
|
+
import { isSuccess, QuickJSContext, QuickJSDeferredPromise } from "quickjs-emscripten";
|
|
3
|
+
import { z, ZodError, ZodObject } from "zod";
|
|
4
|
+
import { Logger } from "./logger";
|
|
5
|
+
|
|
6
|
+
type QuickJSPromiseWithId = QuickJSDeferredPromise & { _promiseId: number };
|
|
7
|
+
|
|
8
|
+
let promiseId = 0;
|
|
9
|
+
let openPromises: Record<number, QuickJSPromiseWithId | null> = {};
|
|
10
|
+
|
|
11
|
+
export function wrapPromise(vm: QuickJSContext, promise: Promise<any>, beginAsyncProcess: () => void, endAsyncProcess: () => void, logger: Logger): any {
|
|
12
|
+
promiseId += 1;
|
|
13
|
+
|
|
14
|
+
const vmPromise = vm.newPromise() as QuickJSPromiseWithId
|
|
15
|
+
vmPromise._promiseId = promiseId;
|
|
16
|
+
beginAsyncProcess();
|
|
17
|
+
promise.then((...args) => {
|
|
18
|
+
//console.log("Promised resolved", args);
|
|
19
|
+
endAsyncProcess();
|
|
20
|
+
const wrappedArgs = args.map((arg) => wrap(vm, arg, undefined, beginAsyncProcess, endAsyncProcess, logger));
|
|
21
|
+
openPromises[vmPromise._promiseId] = null;
|
|
22
|
+
vmPromise.resolve(...wrappedArgs);
|
|
23
|
+
wrappedArgs.forEach((arg) => arg.dispose());
|
|
24
|
+
}).catch(error => {
|
|
25
|
+
vmPromise.reject(vm.newError(error?.message || "An error occurred"));
|
|
26
|
+
|
|
27
|
+
openPromises[vmPromise._promiseId] = null;
|
|
28
|
+
});
|
|
29
|
+
vmPromise.settled.then( () => {
|
|
30
|
+
endAsyncProcess();
|
|
31
|
+
vm.runtime.executePendingJobs();
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
openPromises[promiseId] = vmPromise;
|
|
35
|
+
|
|
36
|
+
return vmPromise.handle
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function rejectOpenPromises(vm: QuickJSContext) {
|
|
40
|
+
for (const [id, promise ] of Object.entries(openPromises)) {
|
|
41
|
+
if (promise !== null) {
|
|
42
|
+
(promise as QuickJSDeferredPromise).reject(vm.newError("Shutting down"));
|
|
43
|
+
openPromises[id as unknown as number] = null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
vm.runtime.executePendingJobs();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const isPromise = (value: any) => { return (typeof value === 'object' && typeof value.then === 'function') };
|
|
51
|
+
|
|
52
|
+
// Value - member variable to wrap
|
|
53
|
+
// context - owning object
|
|
54
|
+
export function wrap(vm: QuickJSContext, value: any, context: object | undefined, beginAsyncProcess: () => void, endAsyncProcess: () => void, logger: Logger): any {
|
|
55
|
+
if (value === null) {
|
|
56
|
+
|
|
57
|
+
return null;
|
|
58
|
+
} else if (isPromise(value)) {
|
|
59
|
+
return wrapPromise(vm, value, beginAsyncProcess, endAsyncProcess, logger);
|
|
60
|
+
} else if (typeof value === "function") {
|
|
61
|
+
//console.log("Wrapped function")
|
|
62
|
+
return wrapGenericFunction(vm, value, context, beginAsyncProcess, endAsyncProcess, logger);
|
|
63
|
+
} else if (Array.isArray(value)) {
|
|
64
|
+
//console.log("Wrapped array")
|
|
65
|
+
return wrapArray(vm, value, beginAsyncProcess, endAsyncProcess, logger);
|
|
66
|
+
} else if (value === null) {
|
|
67
|
+
//console.log("Wrapped null")
|
|
68
|
+
return vm.null;
|
|
69
|
+
} else if (value instanceof Date) {
|
|
70
|
+
const res = vm.evalCode(`new Date(${value.getTime()})`);
|
|
71
|
+
return isSuccess(res) ? res.value : null;
|
|
72
|
+
} else if (typeof value === "object") {
|
|
73
|
+
//console.log("Wrapped object")
|
|
74
|
+
return wrapObject(vm, value, beginAsyncProcess, endAsyncProcess, logger);
|
|
75
|
+
} else if (typeof value === "string") {
|
|
76
|
+
//console.log("Wrapped string")
|
|
77
|
+
return vm.newString(value)
|
|
78
|
+
} else if (typeof value === "number") {
|
|
79
|
+
//console.log("Wrapped number")
|
|
80
|
+
return vm.newNumber(value);
|
|
81
|
+
} else if (typeof value === "bigint") {
|
|
82
|
+
//console.log("Wrapped bigint")
|
|
83
|
+
return vm.newBigInt(value);
|
|
84
|
+
} else if (typeof value === "boolean") {
|
|
85
|
+
// since there is no newBoolean, we have to do this
|
|
86
|
+
const res = vm.evalCode(value ? "true" : "false")
|
|
87
|
+
return isSuccess(res) ? res.value : null;
|
|
88
|
+
} else if (typeof value === "undefined") {
|
|
89
|
+
return vm.undefined
|
|
90
|
+
} else {
|
|
91
|
+
console.error("Unknown type", value)
|
|
92
|
+
return null
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function wrapObject(vm: QuickJSContext, obj: any, beginAsyncProcess: () => void, endAsyncProcess: () => void, logger: Logger): any {
|
|
97
|
+
const vmObject = vm.newObject();
|
|
98
|
+
|
|
99
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
100
|
+
let wrappedValue = wrap(vm, value, obj, beginAsyncProcess, endAsyncProcess, logger);
|
|
101
|
+
|
|
102
|
+
if (wrappedValue !== null) {
|
|
103
|
+
vm.setProp(vmObject, key, wrappedValue);
|
|
104
|
+
if (wrappedValue != vm.undefined && wrappedValue != vm.null && wrappedValue.dispose) {
|
|
105
|
+
wrappedValue.dispose();
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return vmObject;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function wrapObjectWhitelist(vm: QuickJSContext, obj: any, whitelist: string[], beginAsyncProcess: () => void, endAsyncProcess: () => void, logger: Logger): any {
|
|
114
|
+
const vmObject = vm.newObject();
|
|
115
|
+
|
|
116
|
+
whitelist.forEach((key) => {
|
|
117
|
+
// console.log("wrapping", key, value)
|
|
118
|
+
const value = obj[key];
|
|
119
|
+
const wrappedValue = wrap(vm, value, obj, beginAsyncProcess, endAsyncProcess, logger);
|
|
120
|
+
|
|
121
|
+
if (wrappedValue !== null) {
|
|
122
|
+
vm.setProp(vmObject, key, wrappedValue);
|
|
123
|
+
if (wrappedValue != vm.undefined && wrappedValue != vm.null && wrappedValue.dispose) {
|
|
124
|
+
wrappedValue.dispose();
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
return vmObject;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export function wrapArray(vm: QuickJSContext, arr: any[], beginAsyncProcess: () => void, endAsyncProcess: () => void, logger: Logger): any {
|
|
133
|
+
const vmArray = vm.newArray();
|
|
134
|
+
|
|
135
|
+
for (let i = 0; i < arr.length; i++) {
|
|
136
|
+
let wrappedValue = wrap(vm, arr[i], arr, beginAsyncProcess, endAsyncProcess, logger);
|
|
137
|
+
vm.setProp(vmArray, i, wrappedValue);
|
|
138
|
+
if (wrappedValue != vm.undefined && wrappedValue != vm.null) {
|
|
139
|
+
wrappedValue.dispose();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return vmArray;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function validationDecorator(schema: ZodObject) {
|
|
147
|
+
return function(...args: unknown[]) {
|
|
148
|
+
let argumentObject: Record<string, unknown> = {};
|
|
149
|
+
const params = Object.keys(schema.def.shape);
|
|
150
|
+
args.forEach((value, index) => {
|
|
151
|
+
if(index < params.length) {
|
|
152
|
+
argumentObject[params[index]] = value;
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
schema.parse(argumentObject);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export function wrapGenericFunction(vm: QuickJSContext, fn: Function, context: object | undefined = undefined, beginAsyncProcess: () => void, endAsyncProcess: () => void, logger: Logger): any {
|
|
161
|
+
const vmFn = vm.newFunction(fn.name, (...args) => {
|
|
162
|
+
const unwrappedArgs: any[] = args.map(vm.dump)
|
|
163
|
+
//console.log("Wrapped function called", fn.name, unwrappedArgs )
|
|
164
|
+
try {
|
|
165
|
+
const validatorName = `_params_${fn.name}`;
|
|
166
|
+
const hasValidator = context != undefined && validatorName in context && "parse" in (context as Record<string, any>)[validatorName];
|
|
167
|
+
|
|
168
|
+
if(hasValidator) {
|
|
169
|
+
const schema = (context as Record<string, ZodObject>)[validatorName];
|
|
170
|
+
try {
|
|
171
|
+
const validator = validationDecorator(schema);
|
|
172
|
+
validator(...unwrappedArgs); // will throw if validation fails
|
|
173
|
+
} catch(e) {
|
|
174
|
+
// Throwing (not vm.throw) is how a host function raises an exception in the VM;
|
|
175
|
+
// newFunction catches it and turns it into a sandbox exception.
|
|
176
|
+
if(e instanceof ZodError) {
|
|
177
|
+
throw new Error(`Parameter validation failed for function "${fn.name}". Expected Parameters: [${Object.keys(schema.def.shape).join(",")}]. Errors:\n${z.prettifyError(e)}`);
|
|
178
|
+
}
|
|
179
|
+
throw new Error(`Parameter validation error calling ${fn.name}`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const result = fn.call(context, ...unwrappedArgs);
|
|
184
|
+
|
|
185
|
+
logger.trace(fn.name, unwrappedArgs, result);
|
|
186
|
+
|
|
187
|
+
const wrappedResult = wrap(vm, result, undefined, beginAsyncProcess, endAsyncProcess, logger);
|
|
188
|
+
return wrappedResult;
|
|
189
|
+
} catch (e: any) {
|
|
190
|
+
logger.error([e], "sandbox");
|
|
191
|
+
if(e instanceof Error) {
|
|
192
|
+
throw e;
|
|
193
|
+
}
|
|
194
|
+
throw new Error("An exception occurred calling " + fn.name);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
});
|
|
198
|
+
return vmFn;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export function injectTimingFunctions(vm: QuickJSContext, cbAddedTimer: () => void, cbRemovedTimer: () => void, maxTimeout = 600000): void {
|
|
202
|
+
// Should we impose a limit on how long things can run for?
|
|
203
|
+
const timeoutFunctionHandles: any = {};
|
|
204
|
+
const _setTimeout = vm.newFunction("setTimeout", (vmFnHandle, timeoutHandle) => {
|
|
205
|
+
// Make a copy because otherwise vmFnHandle does not live long enough to call after the timeout
|
|
206
|
+
const vmFnHandleCopy = vmFnHandle.dup()
|
|
207
|
+
let timeout = vm.dump(timeoutHandle)
|
|
208
|
+
|
|
209
|
+
// cap timeout at max timeout
|
|
210
|
+
if(timeout > maxTimeout) {
|
|
211
|
+
timeout = maxTimeout;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// console.log("Sandbox calling timeout for: " + timeout);
|
|
215
|
+
cbAddedTimer();
|
|
216
|
+
const timeoutID = setTimeout(() => {
|
|
217
|
+
timeoutFunctionHandles[timeoutID.toString()] = null;
|
|
218
|
+
// callFunction(vmFnHandleCopy) will call the vm function
|
|
219
|
+
// in the context of the vm
|
|
220
|
+
// we pass vm.undefined because we need to pass something for the "this" argument
|
|
221
|
+
//console.log("Sandbox called timeout function")
|
|
222
|
+
cbRemovedTimer();
|
|
223
|
+
vm.callFunction(vmFnHandleCopy, vm.undefined)
|
|
224
|
+
vmFnHandleCopy.dispose()
|
|
225
|
+
vm.runtime.executePendingJobs();
|
|
226
|
+
}, timeout)
|
|
227
|
+
timeoutFunctionHandles[timeoutID.toString()] = vmFnHandleCopy;
|
|
228
|
+
|
|
229
|
+
return vm.newNumber(timeoutID as unknown as number);
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
vm.setProp(vm.global, "setTimeout", _setTimeout);
|
|
233
|
+
_setTimeout.dispose();
|
|
234
|
+
const intervalFunctionHandles: any = {};
|
|
235
|
+
const _setInterval = vm.newFunction("setInterval", (vmFnHandle, timeoutHandle) => {
|
|
236
|
+
// Make a copy because otherwise vmFnHandle does not live long enough to call after the timeout
|
|
237
|
+
const vmFnHandleCopy = vmFnHandle.dup()
|
|
238
|
+
let timeout = vm.dump(timeoutHandle)
|
|
239
|
+
|
|
240
|
+
// cap timeout at max timeout
|
|
241
|
+
if(timeout > maxTimeout) {
|
|
242
|
+
timeout = maxTimeout;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
//console.log("Sandbox calling interval for: " + timeout);
|
|
246
|
+
const maxRepetitions = 99;
|
|
247
|
+
let repetitions = 0;
|
|
248
|
+
cbAddedTimer();
|
|
249
|
+
const intervalId = setInterval(() => {
|
|
250
|
+
repetitions += 1;
|
|
251
|
+
intervalFunctionHandles[intervalId.toString()] = null
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
// callFunction(vmFnHandleCopy) will call the vm function
|
|
255
|
+
// in the context of the vm
|
|
256
|
+
// we pass vm.undefined because we need to pass something for the "this" argument
|
|
257
|
+
vm.callFunction(vmFnHandleCopy, vm.undefined)
|
|
258
|
+
vm.runtime.executePendingJobs();
|
|
259
|
+
|
|
260
|
+
if (repetitions > maxRepetitions) {
|
|
261
|
+
console.log("Sandbox interval exceeded max repetitions");
|
|
262
|
+
clearInterval(intervalId);
|
|
263
|
+
cbRemovedTimer();
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
}, timeout);
|
|
267
|
+
intervalFunctionHandles[intervalId.toString()] = vmFnHandleCopy;
|
|
268
|
+
|
|
269
|
+
return vm.newNumber(intervalId as unknown as number);
|
|
270
|
+
});
|
|
271
|
+
vm.setProp(vm.global, "setInterval", _setInterval);
|
|
272
|
+
_setInterval.dispose();
|
|
273
|
+
|
|
274
|
+
const _clearTimeout = vm.newFunction("clearTimeout", (timeoutIdHandle) => {
|
|
275
|
+
const timeoutId = vm.dump(timeoutIdHandle);
|
|
276
|
+
const timeoutHandle = timeoutFunctionHandles[timeoutId.toString()];
|
|
277
|
+
if (timeoutHandle) {
|
|
278
|
+
cbRemovedTimer();
|
|
279
|
+
timeoutHandle.dispose();
|
|
280
|
+
clearTimeout(timeoutId);
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
vm.setProp(vm.global, "clearTimeout", _clearTimeout);
|
|
284
|
+
_clearTimeout.dispose();
|
|
285
|
+
|
|
286
|
+
const _clearInterval = vm.newFunction("clearInterval", (intervalIdHandle) => {
|
|
287
|
+
const intervalId = vm.dump(intervalIdHandle);
|
|
288
|
+
const intervalHandle = intervalFunctionHandles[intervalId.toString()];
|
|
289
|
+
if (intervalId) {
|
|
290
|
+
cbRemovedTimer();
|
|
291
|
+
intervalHandle.dispose();
|
|
292
|
+
clearInterval(intervalId);
|
|
293
|
+
}
|
|
294
|
+
});
|
|
295
|
+
vm.setProp(vm.global, "clearInterval", _clearInterval);
|
|
296
|
+
_clearInterval.dispose();
|
|
250
297
|
}
|