quickjs 0.1.8 → 0.1.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.
- checksums.yaml +4 -4
- data/README.md +0 -6
- data/ext/quickjsrb/extconf.rb +0 -1
- data/ext/quickjsrb/quickjsrb.c +192 -141
- data/ext/quickjsrb/quickjsrb.h +0 -2
- data/lib/quickjs/version.rb +1 -1
- metadata +2 -4
- data/ext/quickjsrb/procs.c +0 -80
- data/ext/quickjsrb/procs.h +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8eba12c1c34fab81270517de72da6a8b3c9b561d521a42b80c14411c23555684
|
4
|
+
data.tar.gz: 4bced848c986a41c787306e799b40622d97dff999994b64e615cd3b1c79e586e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3598ef1f8b5bcbeedf916c101387477b8318e6550a1aa52b6fa4ddb269e261447768428eb4b644e2a0a9cc64ae084830c511cb077b7e25e292eb5d8e84a96460
|
7
|
+
data.tar.gz: 686a93a0a00d747c99d8a0a0f0072a2d0451cc6bfdeeeb512f02817288636d7192a2e2dda52d0e9bf05b92ebb1930f503ca7ce2251c8419ca568c66f825bca1f
|
data/README.md
CHANGED
data/ext/quickjsrb/extconf.rb
CHANGED
data/ext/quickjsrb/quickjsrb.c
CHANGED
@@ -1,42 +1,66 @@
|
|
1
1
|
#include "quickjsrb.h"
|
2
2
|
|
3
|
-
typedef struct EvalTime
|
3
|
+
typedef struct EvalTime
|
4
|
+
{
|
4
5
|
clock_t limit;
|
5
6
|
clock_t started_at;
|
6
7
|
} EvalTime;
|
7
8
|
|
8
|
-
typedef struct VMData
|
9
|
-
|
9
|
+
typedef struct VMData
|
10
|
+
{
|
10
11
|
struct JSContext *context;
|
11
|
-
|
12
|
+
VALUE defined_functions;
|
12
13
|
struct EvalTime *eval_time;
|
13
14
|
} VMData;
|
14
15
|
|
15
|
-
void vm_free(void*
|
16
|
+
static void vm_free(void *ptr)
|
17
|
+
{
|
18
|
+
VMData *data = (VMData *)ptr;
|
19
|
+
free(data->eval_time);
|
20
|
+
|
21
|
+
JSRuntime *runtime = JS_GetRuntime(data->context);
|
22
|
+
JS_SetInterruptHandler(runtime, NULL, NULL);
|
23
|
+
js_std_free_handlers(runtime);
|
24
|
+
JS_FreeContext(data->context);
|
25
|
+
JS_FreeRuntime(runtime);
|
26
|
+
|
27
|
+
xfree(ptr);
|
28
|
+
}
|
29
|
+
|
30
|
+
size_t vm_size(const void *data)
|
16
31
|
{
|
17
|
-
|
32
|
+
return sizeof(VMData);
|
18
33
|
}
|
19
34
|
|
20
|
-
|
35
|
+
static void vm_mark(void *ptr)
|
21
36
|
{
|
22
|
-
|
37
|
+
VMData *data = (VMData *)ptr;
|
38
|
+
rb_gc_mark_movable(data->defined_functions);
|
23
39
|
}
|
24
40
|
|
25
41
|
static const rb_data_type_t vm_type = {
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
|
42
|
+
.wrap_struct_name = "quickjsvm",
|
43
|
+
.function = {
|
44
|
+
.dmark = vm_mark,
|
45
|
+
.dfree = vm_free,
|
46
|
+
.dsize = vm_size,
|
47
|
+
},
|
48
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
|
34
49
|
};
|
35
50
|
|
36
|
-
VALUE vm_alloc(VALUE self)
|
51
|
+
static VALUE vm_alloc(VALUE self)
|
37
52
|
{
|
38
53
|
VMData *data;
|
39
|
-
|
54
|
+
VALUE obj = TypedData_Make_Struct(self, VMData, &vm_type, data);
|
55
|
+
data->defined_functions = rb_hash_new();
|
56
|
+
|
57
|
+
EvalTime *eval_time = malloc(sizeof(EvalTime));
|
58
|
+
data->eval_time = eval_time;
|
59
|
+
|
60
|
+
JSRuntime *runtime = JS_NewRuntime();
|
61
|
+
data->context = JS_NewContext(runtime);
|
62
|
+
|
63
|
+
return obj;
|
40
64
|
}
|
41
65
|
|
42
66
|
VALUE rb_mQuickjs;
|
@@ -46,91 +70,121 @@ const char *nanId = "NaN";
|
|
46
70
|
const char *featureStdId = "feature_std";
|
47
71
|
const char *featureOsId = "feature_os";
|
48
72
|
|
49
|
-
JSValue to_js_value(JSContext *ctx, VALUE r_value)
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
char *str = StringValueCStr(r_value);
|
73
|
+
JSValue to_js_value(JSContext *ctx, VALUE r_value)
|
74
|
+
{
|
75
|
+
switch (TYPE(r_value))
|
76
|
+
{
|
77
|
+
case T_NIL:
|
78
|
+
return JS_NULL;
|
79
|
+
case T_FIXNUM:
|
80
|
+
case T_FLOAT:
|
81
|
+
{
|
82
|
+
VALUE r_str = rb_funcall(r_value, rb_intern("to_s"), 0, NULL);
|
83
|
+
char *str = StringValueCStr(r_str);
|
84
|
+
JSValue global = JS_GetGlobalObject(ctx);
|
85
|
+
JSValue numberClass = JS_GetPropertyStr(ctx, global, "Number");
|
86
|
+
JSValue j_str = JS_NewString(ctx, str);
|
87
|
+
JSValue stringified = JS_Call(ctx, numberClass, JS_UNDEFINED, 1, &j_str);
|
88
|
+
JS_FreeValue(ctx, global);
|
89
|
+
JS_FreeValue(ctx, numberClass);
|
90
|
+
JS_FreeValue(ctx, j_str);
|
68
91
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
92
|
+
return stringified;
|
93
|
+
}
|
94
|
+
case T_STRING:
|
95
|
+
{
|
96
|
+
char *str = StringValueCStr(r_value);
|
74
97
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
case T_HASH:
|
82
|
-
case T_ARRAY: {
|
83
|
-
VALUE r_json_str = rb_funcall(r_value, rb_intern("to_json"), 0, NULL);
|
84
|
-
char *str = StringValueCStr(r_json_str);
|
85
|
-
JSValue global = JS_GetGlobalObject(ctx);
|
86
|
-
JSValue jsonClass = JS_GetPropertyStr(ctx, global, "JSON");
|
87
|
-
JSValue parseFunc = JS_GetPropertyStr(ctx, jsonClass, "parse");
|
88
|
-
JSValue j_str = JS_NewString(ctx, str);
|
89
|
-
JSValue stringified = JS_Call(ctx, parseFunc, jsonClass, 1, &j_str);
|
90
|
-
JS_FreeValue(ctx, global);
|
91
|
-
JS_FreeValue(ctx, parseFunc);
|
92
|
-
JS_FreeValue(ctx, jsonClass);
|
93
|
-
|
94
|
-
return stringified;
|
95
|
-
}
|
96
|
-
default: {
|
97
|
-
VALUE r_inspect_str = rb_funcall(r_value, rb_intern("inspect"), 0, NULL);
|
98
|
-
char *str = StringValueCStr(r_inspect_str);
|
98
|
+
return JS_NewString(ctx, str);
|
99
|
+
}
|
100
|
+
case T_SYMBOL:
|
101
|
+
{
|
102
|
+
VALUE r_str = rb_funcall(r_value, rb_intern("to_s"), 0, NULL);
|
103
|
+
char *str = StringValueCStr(r_str);
|
99
104
|
|
100
|
-
|
101
|
-
|
105
|
+
return JS_NewString(ctx, str);
|
106
|
+
}
|
107
|
+
case T_TRUE:
|
108
|
+
return JS_TRUE;
|
109
|
+
case T_FALSE:
|
110
|
+
return JS_FALSE;
|
111
|
+
case T_HASH:
|
112
|
+
case T_ARRAY:
|
113
|
+
{
|
114
|
+
VALUE r_json_str = rb_funcall(r_value, rb_intern("to_json"), 0, NULL);
|
115
|
+
char *str = StringValueCStr(r_json_str);
|
116
|
+
JSValue global = JS_GetGlobalObject(ctx);
|
117
|
+
JSValue jsonClass = JS_GetPropertyStr(ctx, global, "JSON");
|
118
|
+
JSValue parseFunc = JS_GetPropertyStr(ctx, jsonClass, "parse");
|
119
|
+
JSValue j_str = JS_NewString(ctx, str);
|
120
|
+
JSValue stringified = JS_Call(ctx, parseFunc, jsonClass, 1, &j_str);
|
121
|
+
JS_FreeValue(ctx, global);
|
122
|
+
JS_FreeValue(ctx, jsonClass);
|
123
|
+
JS_FreeValue(ctx, parseFunc);
|
124
|
+
JS_FreeValue(ctx, j_str);
|
125
|
+
|
126
|
+
return stringified;
|
127
|
+
}
|
128
|
+
default:
|
129
|
+
{
|
130
|
+
VALUE r_inspect_str = rb_funcall(r_value, rb_intern("inspect"), 0, NULL);
|
131
|
+
char *str = StringValueCStr(r_inspect_str);
|
132
|
+
|
133
|
+
return JS_NewString(ctx, str);
|
134
|
+
}
|
102
135
|
}
|
103
136
|
}
|
104
137
|
|
105
|
-
VALUE to_rb_value(JSValue jsv, JSContext *ctx)
|
106
|
-
|
107
|
-
|
138
|
+
VALUE to_rb_value(JSValue jsv, JSContext *ctx)
|
139
|
+
{
|
140
|
+
switch (JS_VALUE_GET_NORM_TAG(jsv))
|
141
|
+
{
|
142
|
+
case JS_TAG_INT:
|
143
|
+
{
|
108
144
|
int int_res = 0;
|
109
145
|
JS_ToInt32(ctx, &int_res, jsv);
|
110
146
|
return INT2NUM(int_res);
|
111
147
|
}
|
112
|
-
case JS_TAG_FLOAT64:
|
113
|
-
|
148
|
+
case JS_TAG_FLOAT64:
|
149
|
+
{
|
150
|
+
if (JS_VALUE_IS_NAN(jsv))
|
151
|
+
{
|
114
152
|
return ID2SYM(rb_intern(nanId));
|
115
153
|
}
|
116
154
|
double double_res;
|
117
155
|
JS_ToFloat64(ctx, &double_res, jsv);
|
118
156
|
return DBL2NUM(double_res);
|
119
157
|
}
|
120
|
-
case JS_TAG_BOOL:
|
158
|
+
case JS_TAG_BOOL:
|
159
|
+
{
|
121
160
|
return JS_ToBool(ctx, jsv) > 0 ? Qtrue : Qfalse;
|
122
161
|
}
|
123
|
-
case JS_TAG_STRING:
|
162
|
+
case JS_TAG_STRING:
|
163
|
+
{
|
124
164
|
JSValue maybeString = JS_ToString(ctx, jsv);
|
125
165
|
const char *msg = JS_ToCString(ctx, maybeString);
|
166
|
+
JS_FreeValue(ctx, maybeString);
|
167
|
+
JS_FreeCString(ctx, msg);
|
126
168
|
return rb_str_new2(msg);
|
127
169
|
}
|
128
|
-
case JS_TAG_OBJECT:
|
170
|
+
case JS_TAG_OBJECT:
|
171
|
+
{
|
129
172
|
int promiseState = JS_PromiseState(ctx, jsv);
|
130
|
-
if (promiseState == JS_PROMISE_FULFILLED || promiseState == JS_PROMISE_PENDING)
|
131
|
-
|
132
|
-
|
133
|
-
|
173
|
+
if (promiseState == JS_PROMISE_FULFILLED || promiseState == JS_PROMISE_PENDING)
|
174
|
+
{
|
175
|
+
JSValue awaited = js_std_await(ctx, jsv);
|
176
|
+
VALUE rb_awaited = to_rb_value(awaited, ctx); // TODO: should have timeout
|
177
|
+
JS_FreeValue(ctx, awaited);
|
178
|
+
return rb_awaited;
|
179
|
+
}
|
180
|
+
else if (promiseState == JS_PROMISE_REJECTED)
|
181
|
+
{
|
182
|
+
JSValue promiseResult = JS_PromiseResult(ctx, jsv);
|
183
|
+
JSValue throw = JS_Throw(ctx, promiseResult);
|
184
|
+
JS_FreeValue(ctx, promiseResult);
|
185
|
+
VALUE rb_errored = to_rb_value(throw, ctx);
|
186
|
+
JS_FreeValue(ctx, throw);
|
187
|
+
return rb_errored;
|
134
188
|
}
|
135
189
|
|
136
190
|
JSValue global = JS_GetGlobalObject(ctx);
|
@@ -140,6 +194,7 @@ VALUE to_rb_value(JSValue jsv, JSContext *ctx) {
|
|
140
194
|
|
141
195
|
const char *msg = JS_ToCString(ctx, strigified);
|
142
196
|
VALUE rbString = rb_str_new2(msg);
|
197
|
+
JS_FreeCString(ctx, msg);
|
143
198
|
|
144
199
|
JS_FreeValue(ctx, global);
|
145
200
|
JS_FreeValue(ctx, strigified);
|
@@ -152,9 +207,11 @@ VALUE to_rb_value(JSValue jsv, JSContext *ctx) {
|
|
152
207
|
return Qnil;
|
153
208
|
case JS_TAG_UNDEFINED:
|
154
209
|
return ID2SYM(rb_intern(undefinedId));
|
155
|
-
case JS_TAG_EXCEPTION:
|
210
|
+
case JS_TAG_EXCEPTION:
|
211
|
+
{
|
156
212
|
JSValue exceptionVal = JS_GetException(ctx);
|
157
|
-
if (JS_IsError(ctx, exceptionVal))
|
213
|
+
if (JS_IsError(ctx, exceptionVal))
|
214
|
+
{
|
158
215
|
JSValue jsErrorClassName = JS_GetPropertyStr(ctx, exceptionVal, "name");
|
159
216
|
const char *errorClassName = JS_ToCString(ctx, jsErrorClassName);
|
160
217
|
|
@@ -164,24 +221,33 @@ VALUE to_rb_value(JSValue jsv, JSContext *ctx) {
|
|
164
221
|
JS_FreeValue(ctx, jsErrorClassMessage);
|
165
222
|
JS_FreeValue(ctx, jsErrorClassName);
|
166
223
|
|
167
|
-
|
168
|
-
|
224
|
+
VALUE rb_errorMessage = rb_sprintf("%s: %s", errorClassName, errorClassMessage);
|
225
|
+
JS_FreeCString(ctx, errorClassName);
|
226
|
+
JS_FreeCString(ctx, errorClassMessage);
|
227
|
+
JS_FreeValue(ctx, exceptionVal);
|
228
|
+
rb_exc_raise(rb_exc_new_str(rb_eRuntimeError, rb_errorMessage));
|
229
|
+
}
|
230
|
+
else
|
231
|
+
{
|
169
232
|
const char *errorMessage = JS_ToCString(ctx, exceptionVal);
|
170
233
|
|
171
|
-
|
234
|
+
VALUE rb_errorMessage = rb_sprintf("%s", errorMessage);
|
235
|
+
JS_FreeCString(ctx, errorMessage);
|
236
|
+
JS_FreeValue(ctx, exceptionVal);
|
237
|
+
rb_exc_raise(rb_exc_new_str(rb_eRuntimeError, rb_errorMessage));
|
172
238
|
}
|
173
|
-
|
174
|
-
JS_FreeValue(ctx, exceptionVal);
|
175
239
|
return Qnil;
|
176
240
|
}
|
177
|
-
case JS_TAG_BIG_INT:
|
241
|
+
case JS_TAG_BIG_INT:
|
242
|
+
{
|
178
243
|
JSValue toStringFunc = JS_GetPropertyStr(ctx, jsv, "toString");
|
179
244
|
JSValue strigified = JS_Call(ctx, toStringFunc, jsv, 0, NULL);
|
180
245
|
|
181
246
|
const char *msg = JS_ToCString(ctx, strigified);
|
182
247
|
VALUE rbString = rb_str_new2(msg);
|
183
|
-
JS_FreeValue(ctx, strigified);
|
184
248
|
JS_FreeValue(ctx, toStringFunc);
|
249
|
+
JS_FreeValue(ctx, strigified);
|
250
|
+
JS_FreeCString(ctx, msg);
|
185
251
|
|
186
252
|
return rb_funcall(rbString, rb_intern("to_i"), 0, NULL);
|
187
253
|
}
|
@@ -193,48 +259,51 @@ VALUE to_rb_value(JSValue jsv, JSContext *ctx) {
|
|
193
259
|
}
|
194
260
|
}
|
195
261
|
|
196
|
-
static JSValue js_quickjsrb_call_global(JSContext *ctx, JSValueConst _this, int _argc, JSValueConst *argv)
|
262
|
+
static JSValue js_quickjsrb_call_global(JSContext *ctx, JSValueConst _this, int _argc, JSValueConst *argv)
|
263
|
+
{
|
197
264
|
VMData *data = JS_GetContextOpaque(ctx);
|
198
265
|
JSValue maybeFuncName = JS_ToString(ctx, argv[0]);
|
199
266
|
const char *funcName = JS_ToCString(ctx, maybeFuncName);
|
200
267
|
JS_FreeValue(ctx, maybeFuncName);
|
201
268
|
|
202
|
-
VALUE proc =
|
203
|
-
if (proc == Qnil)
|
269
|
+
VALUE proc = rb_hash_aref(data->defined_functions, rb_str_new2(funcName));
|
270
|
+
if (proc == Qnil)
|
271
|
+
{ // Shouldn't happen
|
204
272
|
return JS_ThrowReferenceError(ctx, "Proc `%s` is not defined", funcName);
|
205
273
|
}
|
274
|
+
JS_FreeCString(ctx, funcName);
|
206
275
|
|
276
|
+
// TODO: cover timeout for calling proc
|
207
277
|
VALUE r_result = rb_apply(proc, rb_intern("call"), to_rb_value(argv[1], ctx));
|
208
278
|
return to_js_value(ctx, r_result);
|
209
279
|
}
|
210
280
|
|
211
|
-
VALUE vm_m_initialize(int argc, VALUE*
|
281
|
+
static VALUE vm_m_initialize(int argc, VALUE *argv, VALUE self)
|
212
282
|
{
|
213
283
|
VALUE r_opts;
|
214
284
|
rb_scan_args(argc, argv, ":", &r_opts);
|
215
|
-
if (NIL_P(r_opts))
|
285
|
+
if (NIL_P(r_opts))
|
286
|
+
r_opts = rb_hash_new();
|
216
287
|
|
217
288
|
VALUE r_memoryLimit = rb_hash_aref(r_opts, ID2SYM(rb_intern("memory_limit")));
|
218
|
-
if (NIL_P(r_memoryLimit))
|
289
|
+
if (NIL_P(r_memoryLimit))
|
290
|
+
r_memoryLimit = UINT2NUM(1024 * 1024 * 128);
|
219
291
|
VALUE r_maxStackSize = rb_hash_aref(r_opts, ID2SYM(rb_intern("max_stack_size")));
|
220
|
-
if (NIL_P(r_maxStackSize))
|
292
|
+
if (NIL_P(r_maxStackSize))
|
293
|
+
r_maxStackSize = UINT2NUM(1024 * 1024 * 4);
|
221
294
|
VALUE r_features = rb_hash_aref(r_opts, ID2SYM(rb_intern("features")));
|
222
|
-
if (NIL_P(r_features))
|
295
|
+
if (NIL_P(r_features))
|
296
|
+
r_features = rb_ary_new();
|
223
297
|
VALUE r_timeout_msec = rb_hash_aref(r_opts, ID2SYM(rb_intern("timeout_msec")));
|
224
|
-
if (NIL_P(r_timeout_msec))
|
298
|
+
if (NIL_P(r_timeout_msec))
|
299
|
+
r_timeout_msec = UINT2NUM(100);
|
225
300
|
|
226
301
|
VMData *data;
|
227
302
|
TypedData_Get_Struct(self, VMData, &vm_type, data);
|
228
303
|
|
229
|
-
JSRuntime *runtime = JS_NewRuntime();
|
230
|
-
data->context = JS_NewContext(runtime);
|
231
|
-
data->procs = create_proc_entries();
|
232
|
-
|
233
|
-
EvalTime *eval_time = malloc(sizeof(EvalTime));
|
234
|
-
data->eval_time = eval_time;
|
235
304
|
data->eval_time->limit = (clock_t)(CLOCKS_PER_SEC * NUM2UINT(r_timeout_msec) / 1000);
|
236
|
-
data->alive = 1;
|
237
305
|
JS_SetContextOpaque(data->context, data);
|
306
|
+
JSRuntime *runtime = JS_GetRuntime(data->context);
|
238
307
|
|
239
308
|
JS_SetMemoryLimit(runtime, NUM2UINT(r_memoryLimit));
|
240
309
|
JS_SetMaxStackSize(runtime, NUM2UINT(r_maxStackSize));
|
@@ -248,18 +317,20 @@ VALUE vm_m_initialize(int argc, VALUE* argv, VALUE self)
|
|
248
317
|
JS_SetModuleLoaderFunc(runtime, NULL, js_module_loader, NULL);
|
249
318
|
js_std_init_handlers(runtime);
|
250
319
|
|
251
|
-
if (RTEST(rb_funcall(r_features, rb_intern("include?"), 1, ID2SYM(rb_intern(featureStdId)))))
|
320
|
+
if (RTEST(rb_funcall(r_features, rb_intern("include?"), 1, ID2SYM(rb_intern(featureStdId)))))
|
321
|
+
{
|
252
322
|
js_init_module_std(data->context, "std");
|
253
323
|
const char *enableStd = "import * as std from 'std';\n"
|
254
|
-
|
324
|
+
"globalThis.std = std;\n";
|
255
325
|
JSValue stdEval = JS_Eval(data->context, enableStd, strlen(enableStd), "<vm>", JS_EVAL_TYPE_MODULE);
|
256
326
|
JS_FreeValue(data->context, stdEval);
|
257
327
|
}
|
258
328
|
|
259
|
-
if (RTEST(rb_funcall(r_features, rb_intern("include?"), 1, ID2SYM(rb_intern(featureOsId)))))
|
329
|
+
if (RTEST(rb_funcall(r_features, rb_intern("include?"), 1, ID2SYM(rb_intern(featureOsId)))))
|
330
|
+
{
|
260
331
|
js_init_module_os(data->context, "os");
|
261
332
|
const char *enableOs = "import * as os from 'os';\n"
|
262
|
-
|
333
|
+
"globalThis.os = os;\n";
|
263
334
|
JSValue osEval = JS_Eval(data->context, enableOs, strlen(enableOs), "<vm>", JS_EVAL_TYPE_MODULE);
|
264
335
|
JS_FreeValue(data->context, osEval);
|
265
336
|
}
|
@@ -276,21 +347,17 @@ VALUE vm_m_initialize(int argc, VALUE* argv, VALUE self)
|
|
276
347
|
return self;
|
277
348
|
}
|
278
349
|
|
279
|
-
static int interrupt_handler(JSRuntime *runtime, void *opaque)
|
280
|
-
|
281
|
-
|
350
|
+
static int interrupt_handler(JSRuntime *runtime, void *opaque)
|
351
|
+
{
|
352
|
+
EvalTime *eval_time = opaque;
|
353
|
+
return clock() >= eval_time->started_at + eval_time->limit ? 1 : 0;
|
282
354
|
}
|
283
355
|
|
284
|
-
VALUE vm_m_evalCode(VALUE self, VALUE r_code)
|
356
|
+
static VALUE vm_m_evalCode(VALUE self, VALUE r_code)
|
285
357
|
{
|
286
358
|
VMData *data;
|
287
359
|
TypedData_Get_Struct(self, VMData, &vm_type, data);
|
288
360
|
|
289
|
-
if (data->alive < 1) {
|
290
|
-
rb_raise(rb_eRuntimeError, "Quickjs::VM was disposed");
|
291
|
-
return Qnil;
|
292
|
-
}
|
293
|
-
|
294
361
|
data->eval_time->started_at = clock();
|
295
362
|
JS_SetInterruptHandler(JS_GetRuntime(data->context), interrupt_handler, data->eval_time);
|
296
363
|
|
@@ -302,51 +369,36 @@ VALUE vm_m_evalCode(VALUE self, VALUE r_code)
|
|
302
369
|
return result;
|
303
370
|
}
|
304
371
|
|
305
|
-
VALUE vm_m_defineGlobalFunction(VALUE self, VALUE r_name)
|
372
|
+
static VALUE vm_m_defineGlobalFunction(VALUE self, VALUE r_name)
|
306
373
|
{
|
307
374
|
rb_need_block();
|
308
375
|
|
309
376
|
VMData *data;
|
310
377
|
TypedData_Get_Struct(self, VMData, &vm_type, data);
|
311
378
|
|
312
|
-
if (rb_block_given_p())
|
379
|
+
if (rb_block_given_p())
|
380
|
+
{
|
313
381
|
VALUE proc = rb_block_proc();
|
314
382
|
|
315
383
|
char *funcName = StringValueCStr(r_name);
|
316
384
|
|
317
|
-
|
385
|
+
rb_hash_aset(data->defined_functions, r_name, proc);
|
318
386
|
|
319
|
-
const char*
|
387
|
+
const char *template = "globalThis.__ruby['%s'] = (...args) => rubyGlobal('%s', args);\nglobalThis['%s'] = globalThis.__ruby['%s'];\n";
|
320
388
|
int length = snprintf(NULL, 0, template, funcName, funcName, funcName, funcName);
|
321
|
-
char*
|
389
|
+
char *result = (char *)malloc(length + 1);
|
322
390
|
snprintf(result, length + 1, template, funcName, funcName, funcName, funcName);
|
323
391
|
|
324
392
|
JSValue codeResult = JS_Eval(data->context, result, strlen(result), "<vm>", JS_EVAL_TYPE_MODULE);
|
325
393
|
|
326
|
-
JS_FreeValue(data->context, codeResult);
|
327
394
|
free(result);
|
395
|
+
JS_FreeValue(data->context, codeResult);
|
328
396
|
return rb_funcall(r_name, rb_intern("to_sym"), 0, NULL);
|
329
397
|
}
|
330
398
|
|
331
399
|
return Qnil;
|
332
400
|
}
|
333
401
|
|
334
|
-
VALUE vm_m_dispose(VALUE self)
|
335
|
-
{
|
336
|
-
VMData *data;
|
337
|
-
TypedData_Get_Struct(self, VMData, &vm_type, data);
|
338
|
-
|
339
|
-
JSRuntime *runtime = JS_GetRuntime(data->context);
|
340
|
-
JS_SetInterruptHandler(runtime, NULL, NULL);
|
341
|
-
js_std_free_handlers(runtime);
|
342
|
-
free_proc_entry_map(data->procs);
|
343
|
-
JS_FreeContext(data->context);
|
344
|
-
JS_FreeRuntime(runtime);
|
345
|
-
data->alive = 0;
|
346
|
-
|
347
|
-
return Qnil;
|
348
|
-
}
|
349
|
-
|
350
402
|
RUBY_FUNC_EXPORTED void
|
351
403
|
Init_quickjsrb(void)
|
352
404
|
{
|
@@ -363,5 +415,4 @@ Init_quickjsrb(void)
|
|
363
415
|
rb_define_method(vmClass, "initialize", vm_m_initialize, -1);
|
364
416
|
rb_define_method(vmClass, "eval_code", vm_m_evalCode, 1);
|
365
417
|
rb_define_method(vmClass, "define_function", vm_m_defineGlobalFunction, 1);
|
366
|
-
rb_define_method(vmClass, "dispose!", vm_m_dispose, 0);
|
367
418
|
}
|
data/ext/quickjsrb/quickjsrb.h
CHANGED
data/lib/quickjs/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: quickjs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- hmsk
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-07-
|
11
|
+
date: 2024-07-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|
@@ -37,8 +37,6 @@ files:
|
|
37
37
|
- README.md
|
38
38
|
- Rakefile
|
39
39
|
- ext/quickjsrb/extconf.rb
|
40
|
-
- ext/quickjsrb/procs.c
|
41
|
-
- ext/quickjsrb/procs.h
|
42
40
|
- ext/quickjsrb/quickjs/LICENSE
|
43
41
|
- ext/quickjsrb/quickjs/cutils.c
|
44
42
|
- ext/quickjsrb/quickjs/cutils.h
|
data/ext/quickjsrb/procs.c
DELETED
@@ -1,80 +0,0 @@
|
|
1
|
-
#include "procs.h"
|
2
|
-
|
3
|
-
unsigned int hash(const char *key) {
|
4
|
-
unsigned long int value = 0;
|
5
|
-
unsigned int i = 0;
|
6
|
-
unsigned int key_len = strlen(key);
|
7
|
-
|
8
|
-
for (; i < key_len; ++i) {
|
9
|
-
value = value * 37 + key[i];
|
10
|
-
}
|
11
|
-
return value % MAX_NUM_OF_PROCS;
|
12
|
-
}
|
13
|
-
|
14
|
-
ProcEntry *create_proc_entry(const char *key, VALUE proc) {
|
15
|
-
ProcEntry *entry = malloc(sizeof(ProcEntry));
|
16
|
-
entry->key = strdup(key);
|
17
|
-
entry->proc = proc;
|
18
|
-
entry->next = NULL;
|
19
|
-
return entry;
|
20
|
-
}
|
21
|
-
|
22
|
-
ProcEntryMap *create_proc_entries() {
|
23
|
-
ProcEntryMap *entryMap = malloc(sizeof(ProcEntryMap));
|
24
|
-
entryMap->entries = malloc(sizeof(ProcEntry *) * MAX_NUM_OF_PROCS);
|
25
|
-
for (int i = 0; i < MAX_NUM_OF_PROCS; ++i) {
|
26
|
-
entryMap->entries[i] = NULL;
|
27
|
-
}
|
28
|
-
return entryMap;
|
29
|
-
}
|
30
|
-
|
31
|
-
void set_proc(ProcEntryMap *entryMap, const char *key, VALUE proc) {
|
32
|
-
unsigned int slot = hash(key);
|
33
|
-
ProcEntry *entry = entryMap->entries[slot];
|
34
|
-
|
35
|
-
if (entry == NULL) {
|
36
|
-
entryMap->entries[slot] = create_proc_entry(key, proc);
|
37
|
-
return;
|
38
|
-
}
|
39
|
-
|
40
|
-
ProcEntry *prev;
|
41
|
-
while (entry != NULL) {
|
42
|
-
if (strcmp(entry->key, key) == 0) {
|
43
|
-
entry->proc = proc;
|
44
|
-
return;
|
45
|
-
}
|
46
|
-
prev = entry;
|
47
|
-
entry = prev->next;
|
48
|
-
}
|
49
|
-
|
50
|
-
prev->next = create_proc_entry(key, proc);
|
51
|
-
}
|
52
|
-
|
53
|
-
VALUE get_proc(ProcEntryMap *entryMap, const char *key) {
|
54
|
-
unsigned int slot = hash(key);
|
55
|
-
|
56
|
-
ProcEntry *entry = entryMap->entries[slot];
|
57
|
-
|
58
|
-
while (entry != NULL) {
|
59
|
-
if (strcmp(entry->key, key) == 0) {
|
60
|
-
return entry->proc;
|
61
|
-
}
|
62
|
-
entry = entry->next;
|
63
|
-
}
|
64
|
-
|
65
|
-
return Qnil;
|
66
|
-
}
|
67
|
-
|
68
|
-
void free_proc_entry_map(ProcEntryMap *entryMap) {
|
69
|
-
for (int i = 0; i < MAX_NUM_OF_PROCS; ++i) {
|
70
|
-
ProcEntry *entry = entryMap->entries[i];
|
71
|
-
while (entry != NULL) {
|
72
|
-
ProcEntry *temp = entry;
|
73
|
-
entry = entry->next;
|
74
|
-
free(temp->key);
|
75
|
-
free(temp);
|
76
|
-
}
|
77
|
-
}
|
78
|
-
free(entryMap->entries);
|
79
|
-
free(entryMap);
|
80
|
-
}
|
data/ext/quickjsrb/procs.h
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
#include "ruby.h"
|
2
|
-
|
3
|
-
#define MAX_NUM_OF_PROCS 100
|
4
|
-
|
5
|
-
typedef struct ProcEntry {
|
6
|
-
char *key;
|
7
|
-
VALUE proc;
|
8
|
-
struct ProcEntry *next;
|
9
|
-
} ProcEntry;
|
10
|
-
|
11
|
-
typedef struct ProcEntryMap {
|
12
|
-
ProcEntry **entries;
|
13
|
-
} ProcEntryMap;
|
14
|
-
|
15
|
-
ProcEntryMap *create_proc_entries();
|
16
|
-
void set_proc(ProcEntryMap *entryMap, const char *key, VALUE proc);
|
17
|
-
VALUE get_proc(ProcEntryMap *entryMap, const char *key);
|
18
|
-
void free_proc_entry_map(ProcEntryMap *entryMap);
|