quickjs 0.1.8 → 0.1.9

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: f0461f98dbe3171e88609b060aa9fb414ba881b0977d983d6ec7897726a0559c
4
+ data.tar.gz: 84ed4cf19c1d5191e9cd57b789cc3138691f7ad2059b515a2ce4280051105c46
5
5
  SHA512:
6
- metadata.gz: 338bc63e7590c7043cf86c7045f3e93c8269110d3daf49be87ef6477cd99086700a6c0a26dcdc8cf7eb2ce43acc025c419812eeb23ab0b155b59ddd335454db5
7
- data.tar.gz: cb075876cdc10e081b95c40882acbe7ed272dacca56050564888a8df5a68c058c31fa61d9151bddf794d6846c1f00052ae74e3d439c493761bf47154f6fcfdc2
6
+ metadata.gz: c98d7daf116e5513a19b99e4ef387f3b1b60389c3bb9f91822cc1d437bf87cc72041cd97c7cdf2a8a8cb55a86df93a3cf7fe472733017ae4a315831397a56cd5
7
+ data.tar.gz: f177d0e31b8d6499fcf922bd85dc594aa2acd0bf8d93d696256c4a3a7a1595eeb874df7e14e8447694a3045b3f2b9d8279633550e535fc8f257311c613c043b6
@@ -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
 
@@ -8,13 +8,15 @@ typedef struct EvalTime {
8
8
  typedef struct VMData {
9
9
  char alive;
10
10
  struct JSContext *context;
11
- struct ProcEntryMap *procs;
11
+ VALUE defined_functions;
12
12
  struct EvalTime *eval_time;
13
13
  } VMData;
14
14
 
15
- void vm_free(void* data)
15
+ static void vm_free(void* ptr)
16
16
  {
17
- free(data);
17
+ VMData *data = (VMData *)ptr;
18
+ free(data->eval_time);
19
+ xfree(ptr);
18
20
  }
19
21
 
20
22
  size_t vm_size(const void* data)
@@ -22,10 +24,16 @@ size_t vm_size(const void* data)
22
24
  return sizeof(data);
23
25
  }
24
26
 
27
+ static void vm_mark(void *ptr)
28
+ {
29
+ VMData *data = (VMData *)ptr;
30
+ rb_gc_mark_movable(data->defined_functions);
31
+ }
32
+
25
33
  static const rb_data_type_t vm_type = {
26
- .wrap_struct_name = "vm",
34
+ .wrap_struct_name = "quickjsvm",
27
35
  .function = {
28
- .dmark = NULL,
36
+ .dmark = vm_mark,
29
37
  .dfree = vm_free,
30
38
  .dsize = vm_size,
31
39
  },
@@ -33,10 +41,16 @@ static const rb_data_type_t vm_type = {
33
41
  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
34
42
  };
35
43
 
36
- VALUE vm_alloc(VALUE self)
44
+ static VALUE vm_alloc(VALUE self)
37
45
  {
38
46
  VMData *data;
39
- return TypedData_Make_Struct(self, VMData, &vm_type, data);
47
+ VALUE obj = TypedData_Make_Struct(self, VMData, &vm_type, data);
48
+ data->defined_functions = rb_hash_new();
49
+
50
+ EvalTime *eval_time = malloc(sizeof(EvalTime));
51
+ data->eval_time = eval_time;
52
+
53
+ return obj;
40
54
  }
41
55
 
42
56
  VALUE rb_mQuickjs;
@@ -60,6 +74,7 @@ JSValue to_js_value(JSContext *ctx, VALUE r_value) {
60
74
  JSValue stringified = JS_Call(ctx, numberClass, JS_UNDEFINED, 1, &j_str);
61
75
  JS_FreeValue(ctx, global);
62
76
  JS_FreeValue(ctx, numberClass);
77
+ JS_FreeValue(ctx, j_str);
63
78
 
64
79
  return stringified;
65
80
  }
@@ -88,8 +103,9 @@ JSValue to_js_value(JSContext *ctx, VALUE r_value) {
88
103
  JSValue j_str = JS_NewString(ctx, str);
89
104
  JSValue stringified = JS_Call(ctx, parseFunc, jsonClass, 1, &j_str);
90
105
  JS_FreeValue(ctx, global);
91
- JS_FreeValue(ctx, parseFunc);
92
106
  JS_FreeValue(ctx, jsonClass);
107
+ JS_FreeValue(ctx, parseFunc);
108
+ JS_FreeValue(ctx, j_str);
93
109
 
94
110
  return stringified;
95
111
  }
@@ -123,14 +139,23 @@ VALUE to_rb_value(JSValue jsv, JSContext *ctx) {
123
139
  case JS_TAG_STRING: {
124
140
  JSValue maybeString = JS_ToString(ctx, jsv);
125
141
  const char *msg = JS_ToCString(ctx, maybeString);
142
+ JS_FreeValue(ctx, maybeString);
126
143
  return rb_str_new2(msg);
127
144
  }
128
145
  case JS_TAG_OBJECT: {
129
146
  int promiseState = JS_PromiseState(ctx, jsv);
130
147
  if (promiseState == JS_PROMISE_FULFILLED || promiseState == JS_PROMISE_PENDING) {
131
- return to_rb_value(js_std_await(ctx, jsv), ctx); // should have timeout
148
+ JSValue awaited = js_std_await(ctx, jsv);
149
+ VALUE rb_awaited = to_rb_value(awaited, ctx); // TODO: should have timeout
150
+ JS_FreeValue(ctx, awaited);
151
+ return rb_awaited;
132
152
  } else if (promiseState == JS_PROMISE_REJECTED) {
133
- return to_rb_value(JS_Throw(ctx, JS_PromiseResult(ctx, jsv)), ctx);
153
+ JSValue promiseResult = JS_PromiseResult(ctx, jsv);
154
+ JSValue throw = JS_Throw(ctx, promiseResult);
155
+ JS_FreeValue(ctx, promiseResult);
156
+ VALUE rb_errored = to_rb_value(throw, ctx);
157
+ JS_FreeValue(ctx, throw);
158
+ return rb_errored;
134
159
  }
135
160
 
136
161
  JSValue global = JS_GetGlobalObject(ctx);
@@ -199,16 +224,17 @@ static JSValue js_quickjsrb_call_global(JSContext *ctx, JSValueConst _this, int
199
224
  const char *funcName = JS_ToCString(ctx, maybeFuncName);
200
225
  JS_FreeValue(ctx, maybeFuncName);
201
226
 
202
- VALUE proc = get_proc(data->procs, funcName);
227
+ VALUE proc = rb_hash_aref(data->defined_functions, rb_str_new2(funcName));
203
228
  if (proc == Qnil) { // Shouldn't happen
204
229
  return JS_ThrowReferenceError(ctx, "Proc `%s` is not defined", funcName);
205
230
  }
206
231
 
232
+ // TODO: cover timeout for calling proc
207
233
  VALUE r_result = rb_apply(proc, rb_intern("call"), to_rb_value(argv[1], ctx));
208
234
  return to_js_value(ctx, r_result);
209
235
  }
210
236
 
211
- VALUE vm_m_initialize(int argc, VALUE* argv, VALUE self)
237
+ static VALUE vm_m_initialize(int argc, VALUE* argv, VALUE self)
212
238
  {
213
239
  VALUE r_opts;
214
240
  rb_scan_args(argc, argv, ":", &r_opts);
@@ -228,10 +254,6 @@ VALUE vm_m_initialize(int argc, VALUE* argv, VALUE self)
228
254
 
229
255
  JSRuntime *runtime = JS_NewRuntime();
230
256
  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
257
  data->eval_time->limit = (clock_t)(CLOCKS_PER_SEC * NUM2UINT(r_timeout_msec) / 1000);
236
258
  data->alive = 1;
237
259
  JS_SetContextOpaque(data->context, data);
@@ -281,7 +303,7 @@ static int interrupt_handler(JSRuntime *runtime, void *opaque) {
281
303
  return clock() >= eval_time->started_at + eval_time->limit ? 1 : 0;
282
304
  }
283
305
 
284
- VALUE vm_m_evalCode(VALUE self, VALUE r_code)
306
+ static VALUE vm_m_evalCode(VALUE self, VALUE r_code)
285
307
  {
286
308
  VMData *data;
287
309
  TypedData_Get_Struct(self, VMData, &vm_type, data);
@@ -302,7 +324,7 @@ VALUE vm_m_evalCode(VALUE self, VALUE r_code)
302
324
  return result;
303
325
  }
304
326
 
305
- VALUE vm_m_defineGlobalFunction(VALUE self, VALUE r_name)
327
+ static VALUE vm_m_defineGlobalFunction(VALUE self, VALUE r_name)
306
328
  {
307
329
  rb_need_block();
308
330
 
@@ -314,7 +336,7 @@ VALUE vm_m_defineGlobalFunction(VALUE self, VALUE r_name)
314
336
 
315
337
  char *funcName = StringValueCStr(r_name);
316
338
 
317
- set_proc(data->procs, funcName, proc);
339
+ rb_hash_aset(data->defined_functions, r_name, proc);
318
340
 
319
341
  const char* template = "globalThis.__ruby['%s'] = (...args) => rubyGlobal('%s', args);\nglobalThis['%s'] = globalThis.__ruby['%s'];\n";
320
342
  int length = snprintf(NULL, 0, template, funcName, funcName, funcName, funcName);
@@ -331,7 +353,7 @@ VALUE vm_m_defineGlobalFunction(VALUE self, VALUE r_name)
331
353
  return Qnil;
332
354
  }
333
355
 
334
- VALUE vm_m_dispose(VALUE self)
356
+ static VALUE vm_m_dispose(VALUE self)
335
357
  {
336
358
  VMData *data;
337
359
  TypedData_Get_Struct(self, VMData, &vm_type, data);
@@ -339,7 +361,6 @@ VALUE vm_m_dispose(VALUE self)
339
361
  JSRuntime *runtime = JS_GetRuntime(data->context);
340
362
  JS_SetInterruptHandler(runtime, NULL, NULL);
341
363
  js_std_free_handlers(runtime);
342
- free_proc_entry_map(data->procs);
343
364
  JS_FreeContext(data->context);
344
365
  JS_FreeRuntime(runtime);
345
366
  data->alive = 0;
@@ -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.9"
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.9
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-15 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);