1
+ import { getQuickJS , newQuickJSAsyncWASMModule } from "quickjs-emscripten" ;
2
+
3
+ // the example smart contract code loaded from Arweave blockchain
4
+ const code = `
5
+ function handle(state, action) {
6
+ console.log('handle before timeout');
7
+ const timeoutResult = timeout(100); // no 'await' here, because fuck logic
8
+ console.log('handle after timeout:', timeoutResult);
9
+
10
+ const someShit = {};
11
+
12
+ for (i = 0; i < 100000; i++) {
13
+ someShit[""+i] = i*i;
14
+ }
15
+
16
+ return 1;
17
+ }
18
+ ` . trim ( ) ;
19
+
20
+ async function main ( ) {
21
+
22
+ // 1. creating the QJS context
23
+ const QuickJS = await newQuickJSAsyncWASMModule ( ) ;
24
+ const runtime = QuickJS . newRuntime ( ) ;
25
+ // "Should be enough for everyone" -- attributed to B. Gates
26
+ // runtime.setMemoryLimit(1024 * 640);
27
+ // Limit stack size
28
+ runtime . setMaxStackSize ( 1024 * 320 ) ;
29
+ let interruptCycles = 0
30
+ runtime . setInterruptHandler ( ( runtime ) => { interruptCycles ++ } ) ;
31
+
32
+ const vm = runtime . newContext ( ) ;
33
+
34
+ // 2. registering APIs
35
+ const logHandle = vm . newFunction ( "log" , ( ...args ) => {
36
+ const nativeArgs = args . map ( vm . dump )
37
+ console . log ( "QuickJS:" , ...nativeArgs )
38
+ } ) ;
39
+
40
+ const consoleHandle = vm . newObject ( ) ;
41
+ vm . setProp ( consoleHandle , "log" , logHandle ) ;
42
+ vm . setProp ( vm . global , "console" , consoleHandle ) ;
43
+ consoleHandle . dispose ( ) ;
44
+ logHandle . dispose ( ) ;
45
+
46
+ const timeoutHandle = vm . newAsyncifiedFunction ( "timeout" , async ( msHandle ) => {
47
+ const ms = vm . getNumber ( msHandle ) ;
48
+ console . log ( "omg, that's an async shit!" ) ;
49
+ await timeout ( 1000 ) ;
50
+ return vm . newString ( "check your head!" ) ;
51
+ } )
52
+ timeoutHandle . consume ( ( fn ) => vm . setProp ( vm . global , "timeout" , fn ) )
53
+
54
+ // 4. calling the "handle" function
55
+ const result = await vm . evalCodeAsync ( `(() => {
56
+ ${ code }
57
+ return handle();
58
+ })()` ) ;
59
+
60
+ if ( result . error ) {
61
+ console . log ( 'Execution failed:' , vm . dump ( result . error ) ) ;
62
+ result . error . dispose ( ) ;
63
+ } else {
64
+ const parsedResult = vm . unwrapResult ( result ) . consume ( vm . getNumber ) ;
65
+ console . log ( "result" , parsedResult ) ;
66
+ console . log ( "Cycles" , interruptCycles ) ;
67
+ }
68
+
69
+ vm . dispose ( ) ;
70
+ runtime . dispose ( ) ;
71
+ }
72
+
73
+ main ( ) . finally ( ) ;
74
+
75
+ function timeout ( delay ) {
76
+ return new Promise ( function ( resolve ) {
77
+ setTimeout ( resolve , delay ) ;
78
+ } ) ;
79
+ }
0 commit comments