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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 558b76a18b29f977c09990bec267141fb9feae1f04ddd4265971c7c24e823b9b
4
- data.tar.gz: b2dbe1a4a121e92e7f1792690fe755ce021091a4ff402a773b9853c885256dcc
3
+ metadata.gz: 8eba12c1c34fab81270517de72da6a8b3c9b561d521a42b80c14411c23555684
4
+ data.tar.gz: 4bced848c986a41c787306e799b40622d97dff999994b64e615cd3b1c79e586e
5
5
  SHA512:
6
- metadata.gz: 338bc63e7590c7043cf86c7045f3e93c8269110d3daf49be87ef6477cd99086700a6c0a26dcdc8cf7eb2ce43acc025c419812eeb23ab0b155b59ddd335454db5
7
- data.tar.gz: cb075876cdc10e081b95c40882acbe7ed272dacca56050564888a8df5a68c058c31fa61d9151bddf794d6846c1f00052ae74e3d439c493761bf47154f6fcfdc2
6
+ metadata.gz: 3598ef1f8b5bcbeedf916c101387477b8318e6550a1aa52b6fa4ddb269e261447768428eb4b644e2a0a9cc64ae084830c511cb077b7e25e292eb5d8e84a96460
7
+ data.tar.gz: 686a93a0a00d747c99d8a0a0f0072a2d0451cc6bfdeeeb512f02817288636d7192a2e2dda52d0e9bf05b92ebb1930f503ca7ce2251c8419ca568c66f825bca1f
data/README.md CHANGED
@@ -96,12 +96,6 @@ vm = Quickjs::VM.new(
96
96
  )
97
97
  ```
98
98
 
99
- #### Dispose VM explicitly
100
-
101
- ```rb
102
- vm.dispose!
103
- ```
104
-
105
99
  #### Define a global function for JS
106
100
 
107
101
  ```rb
@@ -11,7 +11,6 @@ $srcs = [
11
11
  'cutils.c',
12
12
  'quickjs.c',
13
13
  'quickjs-libc.c',
14
- 'procs.c',
15
14
  'quickjsrb.c',
16
15
  ]
17
16
 
@@ -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
- char alive;
9
+ typedef struct VMData
10
+ {
10
11
  struct JSContext *context;
11
- struct ProcEntryMap *procs;
12
+ VALUE defined_functions;
12
13
  struct EvalTime *eval_time;
13
14
  } VMData;
14
15
 
15
- void vm_free(void* data)
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
- free(data);
32
+ return sizeof(VMData);
18
33
  }
19
34
 
20
- size_t vm_size(const void* data)
35
+ static void vm_mark(void *ptr)
21
36
  {
22
- return sizeof(data);
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
- .wrap_struct_name = "vm",
27
- .function = {
28
- .dmark = NULL,
29
- .dfree = vm_free,
30
- .dsize = vm_size,
31
- },
32
- .data = NULL,
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
- return TypedData_Make_Struct(self, VMData, &vm_type, data);
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
- switch (TYPE(r_value)) {
51
- case T_NIL:
52
- return JS_NULL;
53
- case T_FIXNUM:
54
- case T_FLOAT: {
55
- VALUE r_str = rb_funcall(r_value, rb_intern("to_s"), 0, NULL);
56
- char *str = StringValueCStr(r_str);
57
- JSValue global = JS_GetGlobalObject(ctx);
58
- JSValue numberClass = JS_GetPropertyStr(ctx, global, "Number");
59
- JSValue j_str = JS_NewString(ctx, str);
60
- JSValue stringified = JS_Call(ctx, numberClass, JS_UNDEFINED, 1, &j_str);
61
- JS_FreeValue(ctx, global);
62
- JS_FreeValue(ctx, numberClass);
63
-
64
- return stringified;
65
- }
66
- case T_STRING: {
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
- return JS_NewString(ctx, str);
70
- }
71
- case T_SYMBOL: {
72
- VALUE r_str = rb_funcall(r_value, rb_intern("to_s"), 0, NULL);
73
- char *str = StringValueCStr(r_str);
92
+ return stringified;
93
+ }
94
+ case T_STRING:
95
+ {
96
+ char *str = StringValueCStr(r_value);
74
97
 
75
- return JS_NewString(ctx, str);
76
- }
77
- case T_TRUE:
78
- return JS_TRUE;
79
- case T_FALSE:
80
- return JS_FALSE;
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
- return JS_NewString(ctx, str);
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
- switch(JS_VALUE_GET_NORM_TAG(jsv)) {
107
- case JS_TAG_INT: {
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
- if (JS_VALUE_IS_NAN(jsv)) {
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
- return to_rb_value(js_std_await(ctx, jsv), ctx); // should have timeout
132
- } else if (promiseState == JS_PROMISE_REJECTED) {
133
- return to_rb_value(JS_Throw(ctx, JS_PromiseResult(ctx, jsv)), ctx);
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
- rb_raise(rb_eRuntimeError, "%s: %s", errorClassName, errorClassMessage);
168
- } else {
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
- rb_raise(rb_eRuntimeError, "%s", errorMessage);
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 = get_proc(data->procs, funcName);
203
- if (proc == Qnil) { // Shouldn't happen
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* argv, VALUE self)
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)) r_opts = rb_hash_new();
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)) r_memoryLimit = UINT2NUM(1024 * 1024 * 128);
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)) r_maxStackSize = UINT2NUM(1024 * 1024 * 4);
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)) r_features = rb_ary_new();
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)) r_timeout_msec= UINT2NUM(100);
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
- "globalThis.std = std;\n";
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
- "globalThis.os = os;\n";
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
- EvalTime *eval_time = opaque;
281
- return clock() >= eval_time->started_at + eval_time->limit ? 1 : 0;
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
- set_proc(data->procs, funcName, proc);
385
+ rb_hash_aset(data->defined_functions, r_name, proc);
318
386
 
319
- const char* template = "globalThis.__ruby['%s'] = (...args) => rubyGlobal('%s', args);\nglobalThis['%s'] = globalThis.__ruby['%s'];\n";
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* result = (char*)malloc(length + 1);
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
  }
@@ -12,6 +12,4 @@
12
12
  #include <string.h>
13
13
  #include <time.h>
14
14
 
15
- #include "procs.h"
16
-
17
15
  #endif /* QUICKJSRB_H */
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Quickjs
4
- VERSION = "0.1.8"
4
+ VERSION = "0.1.10"
5
5
  end
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.8
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-10 00:00:00.000000000 Z
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
@@ -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
- }
@@ -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);