quickjs 0.7.0 → 0.8.0

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: 44eedd9a617b8106c963b40fde4ffd9e9c3093be07a9d1528ae3cdac357abd9d
4
- data.tar.gz: 83821e76a40a152fea3516c4720e5a5240129f866dc44db2d2ef8350672ff80b
3
+ metadata.gz: dafb25d574a45620b440561078836c98c15d4bfbd262de5f18bf9f9eb8fc572e
4
+ data.tar.gz: 421c3d7ce93798a00a673d3cd15ee27c3fbdae62b4462d2b7100ad423d8d80e9
5
5
  SHA512:
6
- metadata.gz: 5b8f7d797869c7f02a7c529f47d0340831b700e7c91fd0f351df040e8e09f4e4a0e8ae42c9da0609603cd451d50246d6f491619c512e383ecd1f4a6a53c14feb
7
- data.tar.gz: 71bf4c8fd5d6f94db5edb6f341005dcc153b1bba13b4dbcdc1974b3eca01be2893de6dee5cf3a4e9be815afe1777febf2cd0c718df334f4e175fd25e01267ca6
6
+ metadata.gz: '0512949cf01227a5f924b9e04f199e8fc24bb486d854c6e72d08ba8cae4f52ba5490a3b205e9c02a39ed0b90d599f18c3e2e90f7aca9d59a755e4501a358cba2'
7
+ data.tar.gz: 95777d46e97ce2783593dd28f59beda26454f040741363a3f8190d65ce72ffe1874142f1983b7dd87dbbca99c0e37dfc5f01feb2e501a8b82bc538d3b7706371
data/README.md CHANGED
@@ -58,8 +58,8 @@ vm = Quickjs.eval_code(features: [::Quickjs::MODULE_STD])
58
58
  # Enable `os` module by quickjs: https://bellard.org/quickjs/quickjs.html#os-module
59
59
  vm = Quickjs.eval_code(features: [::Quickjs::MODULE_OS])
60
60
 
61
- # Expose `os.setTimouet` and `os.clearTimeout` from `os` module
62
- vm = Quickjs.eval_code(features: [::Quickjs::FEATURES_TIMEOUT])
61
+ # Provide `setTimeout` managed by CRuby
62
+ vm = Quickjs.eval_code(features: [::Quickjs::FEATURE_TIMEOUT])
63
63
 
64
64
  # Inject the polyfill of Intl
65
65
  vm = Quickjs.eval_code(features: [::Quickjs::POLYFILL_INTL])
@@ -98,8 +98,8 @@ vm = Quickjs::VM.new(features: [::Quickjs::MODULE_STD])
98
98
  # Enable `os` module by quickjs: https://bellard.org/quickjs/quickjs.html#os-module
99
99
  vm = Quickjs::VM.new(features: [::Quickjs::MODULE_OS])
100
100
 
101
- # Expose `os.setTimouet` and `os.clearTimeout` from `os` module
102
- vm = Quickjs::VM.new(features: [::Quickjs::FEATURES_TIMEOUT])
101
+ # Provide `setTimeout` managed by CRuby
102
+ vm = Quickjs::VM.new(features: [::Quickjs::FEATURE_TIMEOUT])
103
103
 
104
104
  # Inject the polyfill of Intl
105
105
  vm = Quickjs::VM.new(features: [::Quickjs::POLYFILL_INTL])
@@ -163,13 +163,13 @@ vm.logs.last.raw #=> ['log me', nil]
163
163
 
164
164
  - `ext/quickjsrb/quickjs`
165
165
  - [MIT License Copyright (c) 2017-2021 by Fabrice Bellard and Charlie Gordon](https://github.com/bellard/quickjs/blob/6e2e68fd0896957f92eb6c242a2e048c1ef3cae0/LICENSE).
166
- - `ext/quickjsrb/vendor/polyfill-intl-en.min.js`
166
+ - `ext/quickjsrb/vendor/polyfill-intl-en.min.js` (bundled and minified)
167
167
  - MIT License Copyright (c) 2023 FormatJS
168
- - `[@formatjs/intl-getcanonicallocales](https://github.com/formatjs/formatjs/blob/main/packages/intl-getcanonicallocales/LICENSE.md)
169
- - `[@formatjs/intl-locale](https://github.com/formatjs/formatjs/blob/main/packages/intl-locale/LICENSE.md)
170
- - `[@formatjs/intl-pluralrules](https://github.com/formatjs/formatjs/blob/main/packages/intl-pluralrules/LICENSE.md)
171
- - `[@formatjs/intl-numberformat](https://github.com/formatjs/formatjs/blob/main/packages/intl-numberformat/LICENSE.md)
172
- - `[@formatjs/intl-datetimeformat](https://github.com/formatjs/formatjs/blob/main/packages/intl-datetimeformat/LICENSE.md)
168
+ - [@formatjs/intl-getcanonicallocales](https://github.com/formatjs/formatjs/blob/main/packages/intl-getcanonicallocales/LICENSE.md)
169
+ - [@formatjs/intl-locale](https://github.com/formatjs/formatjs/blob/main/packages/intl-locale/LICENSE.md)
170
+ - [@formatjs/intl-pluralrules](https://github.com/formatjs/formatjs/blob/main/packages/intl-pluralrules/LICENSE.md)
171
+ - [@formatjs/intl-numberformat](https://github.com/formatjs/formatjs/blob/main/packages/intl-numberformat/LICENSE.md)
172
+ - [@formatjs/intl-datetimeformat](https://github.com/formatjs/formatjs/blob/main/packages/intl-datetimeformat/LICENSE.md)
173
173
  - MIT License Copyright (c) 2025 Michael Mclaughlin
174
174
  - [decimal.js](https://www.npmjs.com/package/decimal.js)
175
175
 
@@ -4,11 +4,11 @@ JSValue j_error_from_ruby_error(JSContext *ctx, VALUE r_error)
4
4
  {
5
5
  JSValue j_error = JS_NewError(ctx); // may wanna have custom error class to determine in JS' end
6
6
 
7
- VALUE r_object_id = rb_funcall(r_error, rb_intern("object_id"), 0, NULL);
7
+ VALUE r_object_id = rb_funcall(r_error, rb_intern("object_id"), 0);
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
- VALUE r_exception_message = rb_funcall(r_error, rb_intern("message"), 0, NULL);
11
+ VALUE r_exception_message = rb_funcall(r_error, rb_intern("message"), 0);
12
12
  const char *errorMessage = StringValueCStr(r_exception_message);
13
13
  JS_SetPropertyStr(ctx, j_error, "message", JS_NewString(ctx, errorMessage));
14
14
 
@@ -24,7 +24,7 @@ JSValue to_js_value(JSContext *ctx, VALUE r_value)
24
24
  case T_FIXNUM:
25
25
  case T_FLOAT:
26
26
  {
27
- VALUE r_str = rb_funcall(r_value, rb_intern("to_s"), 0, NULL);
27
+ VALUE r_str = rb_funcall(r_value, rb_intern("to_s"), 0);
28
28
  char *str = StringValueCStr(r_str);
29
29
  JSValue j_global = JS_GetGlobalObject(ctx);
30
30
  JSValue j_numberClass = JS_GetPropertyStr(ctx, j_global, "Number");
@@ -44,7 +44,7 @@ JSValue to_js_value(JSContext *ctx, VALUE r_value)
44
44
  }
45
45
  case T_SYMBOL:
46
46
  {
47
- VALUE r_str = rb_funcall(r_value, rb_intern("to_s"), 0, NULL);
47
+ VALUE r_str = rb_funcall(r_value, rb_intern("to_s"), 0);
48
48
  char *str = StringValueCStr(r_str);
49
49
 
50
50
  return JS_NewString(ctx, str);
@@ -56,7 +56,7 @@ JSValue to_js_value(JSContext *ctx, VALUE r_value)
56
56
  case T_HASH:
57
57
  case T_ARRAY:
58
58
  {
59
- VALUE r_json_str = rb_funcall(r_value, rb_intern("to_json"), 0, NULL);
59
+ VALUE r_json_str = rb_funcall(r_value, rb_intern("to_json"), 0);
60
60
  char *str = StringValueCStr(r_json_str);
61
61
  JSValue j_parsed = JS_ParseJSON(ctx, str, strlen(str), "<quickjsrb.c>");
62
62
 
@@ -71,7 +71,7 @@ JSValue to_js_value(JSContext *ctx, VALUE r_value)
71
71
  {
72
72
  return j_error_from_ruby_error(ctx, r_value);
73
73
  }
74
- VALUE r_inspect_str = rb_funcall(r_value, rb_intern("inspect"), 0, NULL);
74
+ VALUE r_inspect_str = rb_funcall(r_value, rb_intern("inspect"), 0);
75
75
  char *str = StringValueCStr(r_inspect_str);
76
76
 
77
77
  return JS_NewString(ctx, str);
@@ -284,7 +284,7 @@ VALUE to_rb_value(JSContext *ctx, JSValue j_val)
284
284
  JS_FreeValue(ctx, j_strigified);
285
285
  JS_FreeCString(ctx, msg);
286
286
 
287
- return rb_funcall(r_str, rb_intern("to_i"), 0, NULL);
287
+ return rb_funcall(r_str, rb_intern("to_i"), 0);
288
288
  }
289
289
  case JS_TAG_BIG_FLOAT:
290
290
  case JS_TAG_BIG_DECIMAL:
@@ -381,6 +381,37 @@ static JSValue js_quickjsrb_call_global(JSContext *ctx, JSValueConst _this, int
381
381
  }
382
382
  }
383
383
 
384
+ static JSValue js_delay_and_eval_job(JSContext *ctx, int argc, JSValueConst *argv)
385
+ {
386
+ VALUE rb_delay_msec = to_rb_value(ctx, argv[1]);
387
+ VALUE rb_delay_sec = rb_funcall(rb_delay_msec, rb_intern("/"), 1, rb_float_new(1000));
388
+ rb_thread_wait_for(rb_time_interval(rb_delay_sec));
389
+ JS_Call(ctx, argv[0], JS_UNDEFINED, 0, NULL);
390
+
391
+ return JS_UNDEFINED;
392
+ }
393
+
394
+ static JSValue js_quickjsrb_set_timeout(JSContext *ctx, JSValueConst _this, int argc, JSValueConst *argv)
395
+ {
396
+ JSValueConst func;
397
+ int64_t delay;
398
+
399
+ func = argv[0];
400
+ if (!JS_IsFunction(ctx, func))
401
+ return JS_ThrowTypeError(ctx, "not a function");
402
+ if (JS_ToInt64(ctx, &delay, argv[1])) // TODO: should be lower than global timeout
403
+ return JS_EXCEPTION;
404
+
405
+ JSValueConst args[2];
406
+ args[0] = func;
407
+ args[1] = argv[1]; // delay
408
+ // TODO: implement timer manager and poll with quickjs' queue
409
+ // Currently, queueing multiple js_delay_and_eval_job is not parallelized
410
+ JS_EnqueueJob(ctx, js_delay_and_eval_job, 2, args);
411
+
412
+ return JS_UNDEFINED;
413
+ }
414
+
384
415
  static JSValue js_quickjsrb_log(JSContext *ctx, JSValueConst _this, int argc, JSValueConst *argv, const char *severity)
385
416
  {
386
417
  VMData *data = JS_GetContextOpaque(ctx);
@@ -492,6 +523,8 @@ static VALUE vm_m_initialize(int argc, VALUE *argv, VALUE r_self)
492
523
  JS_SetModuleLoaderFunc(runtime, NULL, js_module_loader, NULL);
493
524
  js_std_init_handlers(runtime);
494
525
 
526
+ JSValue j_global = JS_GetGlobalObject(data->context);
527
+
495
528
  if (RTEST(rb_funcall(r_features, rb_intern("include?"), 1, QUICKJSRB_SYM(featureStdId))))
496
529
  {
497
530
  js_init_module_std(data->context, "std");
@@ -509,20 +542,11 @@ static VALUE vm_m_initialize(int argc, VALUE *argv, VALUE r_self)
509
542
  JSValue j_osEval = JS_Eval(data->context, enableOs, strlen(enableOs), "<vm>", JS_EVAL_TYPE_MODULE);
510
543
  JS_FreeValue(data->context, j_osEval);
511
544
  }
512
- else if (RTEST(rb_funcall(r_features, rb_intern("include?"), 1, QUICKJSRB_SYM(featureOsTimeoutId))))
545
+ else if (RTEST(rb_funcall(r_features, rb_intern("include?"), 1, QUICKJSRB_SYM(featureTimeoutId))))
513
546
  {
514
- char *filename = random_string();
515
- js_init_module_os(data->context, filename); // Better if this is limited just only for setTimeout and clearTimeout
516
- const char *enableTimeoutTemplate = "import * as _os from '%s';\n"
517
- "globalThis.setTimeout = _os.setTimeout;\n"
518
- "globalThis.clearTimeout = _os.clearTimeout;\n";
519
- int length = snprintf(NULL, 0, enableTimeoutTemplate, filename);
520
- char *enableTimeout = (char *)malloc(length + 1);
521
- snprintf(enableTimeout, length + 1, enableTimeoutTemplate, filename);
522
-
523
- JSValue j_timeoutEval = JS_Eval(data->context, enableTimeout, strlen(enableTimeout), "<vm>", JS_EVAL_TYPE_MODULE);
524
- free(enableTimeout);
525
- JS_FreeValue(data->context, j_timeoutEval);
547
+ JS_SetPropertyStr(
548
+ data->context, j_global, "setTimeout",
549
+ JS_NewCFunction(data->context, js_quickjsrb_set_timeout, "setTimeout", 2));
526
550
  }
527
551
 
528
552
  if (RTEST(rb_funcall(r_features, rb_intern("include?"), 1, QUICKJSRB_SYM(featurePolyfillIntlId))))
@@ -553,7 +577,6 @@ static VALUE vm_m_initialize(int argc, VALUE *argv, VALUE r_self)
553
577
  data->context, j_console, "error",
554
578
  JS_NewCFunction(data->context, js_console_error, "error", 1));
555
579
 
556
- JSValue j_global = JS_GetGlobalObject(data->context);
557
580
  JS_SetPropertyStr(data->context, j_global, "console", j_console);
558
581
  JS_FreeValue(data->context, j_global);
559
582
 
@@ -623,7 +646,7 @@ static VALUE vm_m_defineGlobalFunction(int argc, VALUE *argv, VALUE r_self)
623
646
  JS_FreeValue(data->context, ruby_data[0]);
624
647
  JS_FreeValue(data->context, ruby_data[1]);
625
648
 
626
- return rb_funcall(r_name, rb_intern("to_sym"), 0, NULL);
649
+ return rb_funcall(r_name, rb_intern("to_sym"), 0);
627
650
  }
628
651
 
629
652
  static VALUE vm_m_import(int argc, VALUE *argv, VALUE r_self)
@@ -17,7 +17,7 @@ extern const uint8_t qjsc_polyfill_intl_en_min;
17
17
 
18
18
  const char *featureStdId = "feature_std";
19
19
  const char *featureOsId = "feature_os";
20
- const char *featureOsTimeoutId = "feature_os_timeout";
20
+ const char *featureTimeoutId = "feature_timeout";
21
21
  const char *featurePolyfillIntlId = "feature_polyfill_intl";
22
22
 
23
23
  const char *undefinedId = "undefined";
@@ -136,7 +136,7 @@ static void r_define_constants(VALUE r_parent_class)
136
136
  {
137
137
  rb_define_const(r_parent_class, "MODULE_STD", QUICKJSRB_SYM(featureStdId));
138
138
  rb_define_const(r_parent_class, "MODULE_OS", QUICKJSRB_SYM(featureOsId));
139
- rb_define_const(r_parent_class, "FEATURES_TIMEOUT", QUICKJSRB_SYM(featureOsTimeoutId));
139
+ rb_define_const(r_parent_class, "FEATURE_TIMEOUT", QUICKJSRB_SYM(featureTimeoutId));
140
140
  rb_define_const(r_parent_class, "POLYFILL_INTL", QUICKJSRB_SYM(featurePolyfillIntlId));
141
141
 
142
142
  VALUE rb_cQuickjsValue = rb_define_class_under(r_parent_class, "Value", rb_cObject);
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Quickjs
4
- VERSION = "0.7.0"
4
+ VERSION = "0.8.0"
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.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - hmsk
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-03-21 00:00:00.000000000 Z
11
+ date: 2025-03-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -104,7 +104,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
104
104
  - !ruby/object:Gem::Version
105
105
  version: '0'
106
106
  requirements: []
107
- rubygems_version: 3.3.27
107
+ rubygems_version: 3.5.9
108
108
  signing_key:
109
109
  specification_version: 4
110
110
  summary: Run binding of QuickJS