quickjs 0.11.1 → 0.11.2

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: cb155f6499b100170fefe4f9e8d3a24eb221bf5cd3363adaae7c1dda6d157f12
4
- data.tar.gz: 7b51767a21b911a62eab5f561aaebc14461fa9078874491db8163fd92bdced5a
3
+ metadata.gz: 29ad9419055f853b82d642f0c5404d24d476dcc3d0d8e7da4364f06a819b10a3
4
+ data.tar.gz: 77b07d4c214663c8fd716ab2c9dda3d88c327f3f77b0d350f2987d506a70677e
5
5
  SHA512:
6
- metadata.gz: f45ea57fcb653f3f886443fef85ebd9138cdfd0ddff0322ac628a25d18033f6eb23fc81f578951d04af23dff604fe7196efca663cf46d74d1820ef3f346bd7ce
7
- data.tar.gz: 4e721e1621759230776b78194657de9199e9fc7af61d6b091e31a379b010cd2f7a76ce825d6e693595a2cb12bc7b12d76d9fa9ef683b1b726ef1a8e03851ec06
6
+ metadata.gz: 75ba55882ce0d5371e3ba3d584849d012c06a955d230e7b9975266852753dae3db45244fc8b9bf967f86ba25fff52d7c6d8118bab131f9e8b61bb421356597c0
7
+ data.tar.gz: 97964de7f1ef9f20c548cc8e69da09fe058112193593bb433e8b93e3e42424582f111a306df13df78dd583442dd712bc71e6da8ff0ce17116f19618f8aa803d2
@@ -37,7 +37,8 @@ else
37
37
  end
38
38
 
39
39
  append_cflags('-fwrapv')
40
- $CFLAGS << ' ' << '-D_GNU_SOURCE -DCONFIG_VERSION=\"2024-02-14\"'
40
+ # NDEBUG: suppress QuickJS debug assertions that conflict with Ruby 4.0 GC
41
+ $CFLAGS << ' ' << '-D_GNU_SOURCE -DCONFIG_VERSION=\"2024-02-14\" -DNDEBUG'
41
42
 
42
43
  abort('could not find quickjs.h') unless find_header('quickjs.h')
43
44
  abort('could not find cutils.h') unless find_header('cutils.h')
@@ -8,6 +8,10 @@ JSValue j_error_from_ruby_error(JSContext *ctx, VALUE r_error)
8
8
  int objectId = NUM2INT(r_object_id);
9
9
  JS_SetPropertyStr(ctx, j_error, "rb_object_id", JS_NewInt32(ctx, objectId));
10
10
 
11
+ // Keep the error alive in VMData to prevent GC before find_ruby_error retrieves it
12
+ VMData *data = JS_GetContextOpaque(ctx);
13
+ rb_hash_aset(data->alive_errors, r_object_id, r_error);
14
+
11
15
  VALUE r_exception_message = rb_funcall(r_error, rb_intern("message"), 0);
12
16
  const char *errorMessage = StringValueCStr(r_exception_message);
13
17
  JS_SetPropertyStr(ctx, j_error, "message", JS_NewString(ctx, errorMessage));
@@ -89,8 +93,11 @@ VALUE find_ruby_error(JSContext *ctx, JSValue j_error)
89
93
  JS_FreeValue(ctx, j_errorOriginalRubyObjectId);
90
94
  if (errorOriginalRubyObjectId > 0)
91
95
  {
92
- // may be nice if cover the case of object is missing
93
- return rb_funcall(rb_const_get(rb_cClass, rb_intern("ObjectSpace")), rb_intern("_id2ref"), 1, INT2NUM(errorOriginalRubyObjectId));
96
+ VMData *data = JS_GetContextOpaque(ctx);
97
+ VALUE r_key = INT2NUM(errorOriginalRubyObjectId);
98
+ VALUE r_error = rb_hash_aref(data->alive_errors, r_key);
99
+ rb_hash_delete(data->alive_errors, r_key);
100
+ return r_error;
94
101
  }
95
102
  }
96
103
  else
@@ -329,7 +336,7 @@ static JSValue js_quickjsrb_call_global(JSContext *ctx, JSValueConst _this, int
329
336
  JS_FreeValue(ctx, j_v);
330
337
  }
331
338
  rb_ary_push(r_call_args, r_argv);
332
- rb_ary_push(r_call_args, ULONG2NUM(data->eval_time->limit * 1000 / CLOCKS_PER_SEC));
339
+ rb_ary_push(r_call_args, ULONG2NUM(data->eval_time->limit_ms));
333
340
 
334
341
  int sadnessHappened;
335
342
 
@@ -507,7 +514,7 @@ static VALUE vm_m_initialize(int argc, VALUE *argv, VALUE r_self)
507
514
  VMData *data;
508
515
  TypedData_Get_Struct(r_self, VMData, &vm_type, data);
509
516
 
510
- data->eval_time->limit = (clock_t)(CLOCKS_PER_SEC * NUM2UINT(r_timeout_msec) / 1000);
517
+ data->eval_time->limit_ms = (int64_t)NUM2UINT(r_timeout_msec);
511
518
  JS_SetContextOpaque(data->context, data);
512
519
  JSRuntime *runtime = JS_GetRuntime(data->context);
513
520
 
@@ -580,7 +587,11 @@ static VALUE vm_m_initialize(int argc, VALUE *argv, VALUE r_self)
580
587
  static int interrupt_handler(JSRuntime *runtime, void *opaque)
581
588
  {
582
589
  EvalTime *eval_time = opaque;
583
- return clock() >= eval_time->started_at + eval_time->limit ? 1 : 0;
590
+ struct timespec now;
591
+ clock_gettime(CLOCK_MONOTONIC, &now);
592
+ int64_t elapsed_ms = (int64_t)(now.tv_sec - eval_time->started_at.tv_sec) * 1000
593
+ + (now.tv_nsec - eval_time->started_at.tv_nsec) / 1000000;
594
+ return elapsed_ms >= eval_time->limit_ms ? 1 : 0;
584
595
  }
585
596
 
586
597
  static VALUE vm_m_evalCode(VALUE r_self, VALUE r_code)
@@ -594,7 +605,7 @@ static VALUE vm_m_evalCode(VALUE r_self, VALUE r_code)
594
605
  rb_raise(rb_eTypeError, "JavaScript code must be a String, got %s", StringValueCStr(r_code_class));
595
606
  }
596
607
 
597
- data->eval_time->started_at = clock();
608
+ clock_gettime(CLOCK_MONOTONIC, &data->eval_time->started_at);
598
609
  JS_SetInterruptHandler(JS_GetRuntime(data->context), interrupt_handler, data->eval_time);
599
610
 
600
611
  char *code = StringValueCStr(r_code);
@@ -612,9 +623,12 @@ static VALUE vm_m_evalCode(VALUE r_self, VALUE r_code)
612
623
  }
613
624
  else
614
625
  {
626
+ // Free j_awaitedResult before to_rb_value because to_rb_value may
627
+ // raise (longjmp) for JS exceptions, which would skip any cleanup
628
+ // after it and leak JS GC objects.
629
+ JS_FreeValue(data->context, j_awaitedResult);
615
630
  VALUE result = to_rb_value(data->context, j_returnedValue);
616
631
  JS_FreeValue(data->context, j_returnedValue);
617
- JS_FreeValue(data->context, j_awaitedResult);
618
632
  return result;
619
633
  }
620
634
  }
@@ -39,8 +39,8 @@ const char *native_errors[] = {
39
39
 
40
40
  typedef struct EvalTime
41
41
  {
42
- clock_t limit;
43
- clock_t started_at;
42
+ int64_t limit_ms;
43
+ struct timespec started_at;
44
44
  } EvalTime;
45
45
 
46
46
  typedef struct VMData
@@ -49,6 +49,7 @@ typedef struct VMData
49
49
  VALUE defined_functions;
50
50
  struct EvalTime *eval_time;
51
51
  VALUE logs;
52
+ VALUE alive_errors;
52
53
  } VMData;
53
54
 
54
55
  static void vm_free(void *ptr)
@@ -75,6 +76,15 @@ static void vm_mark(void *ptr)
75
76
  VMData *data = (VMData *)ptr;
76
77
  rb_gc_mark_movable(data->defined_functions);
77
78
  rb_gc_mark_movable(data->logs);
79
+ rb_gc_mark_movable(data->alive_errors);
80
+ }
81
+
82
+ static void vm_compact(void *ptr)
83
+ {
84
+ VMData *data = (VMData *)ptr;
85
+ data->defined_functions = rb_gc_location(data->defined_functions);
86
+ data->logs = rb_gc_location(data->logs);
87
+ data->alive_errors = rb_gc_location(data->alive_errors);
78
88
  }
79
89
 
80
90
  static const rb_data_type_t vm_type = {
@@ -83,6 +93,7 @@ static const rb_data_type_t vm_type = {
83
93
  .dmark = vm_mark,
84
94
  .dfree = vm_free,
85
95
  .dsize = vm_size,
96
+ .dcompact = vm_compact,
86
97
  },
87
98
  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
88
99
  };
@@ -93,6 +104,7 @@ static VALUE vm_alloc(VALUE r_self)
93
104
  VALUE obj = TypedData_Make_Struct(r_self, VMData, &vm_type, data);
94
105
  data->defined_functions = rb_hash_new();
95
106
  data->logs = rb_ary_new();
107
+ data->alive_errors = rb_hash_new();
96
108
 
97
109
  EvalTime *eval_time = malloc(sizeof(EvalTime));
98
110
  data->eval_time = eval_time;
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Quickjs
4
- VERSION = "0.11.1"
4
+ VERSION = "0.11.2"
5
5
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quickjs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.1
4
+ version: 0.11.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - hmsk
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2026-01-30 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: json
@@ -89,7 +88,6 @@ metadata:
89
88
  homepage_uri: https://github.com/hmsk/quickjs.rb
90
89
  source_code_uri: https://github.com/hmsk/quickjs.rb
91
90
  changelog_uri: https://github.com/hmsk/quickjs.rb/blob/main/CHANGELOG.md
92
- post_install_message:
93
91
  rdoc_options: []
94
92
  require_paths:
95
93
  - lib
@@ -104,8 +102,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
104
102
  - !ruby/object:Gem::Version
105
103
  version: '0'
106
104
  requirements: []
107
- rubygems_version: 3.5.9
108
- signing_key:
105
+ rubygems_version: 4.0.3
109
106
  specification_version: 4
110
107
  summary: Run binding of QuickJS
111
108
  test_files: []