quickjs 0.2.3 → 0.3.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: 5f57f31bd8921f897f9d1c81d1c50d24774bbfba5d31a99528b138e82d3fad58
4
- data.tar.gz: 28216a7b1711fe08ad3e2a5b021abebaadd2b5d3808584ff259d0129abf0adf6
3
+ metadata.gz: ecc8aa4eddd6aca97baf0e773c4880b4479b4ac4597e0edf811d256eeb61aeb9
4
+ data.tar.gz: 37c8eeef2cad6e0d7773e89759c7d2d1659219247883cfd1817f2603ffbf1543
5
5
  SHA512:
6
- metadata.gz: 355b53297b3c27269b71dca93e057ecfe02eac70755b5bd336b212092fb6da3c14ff3b2dd2f77214a62891b28d860e33f961329374ddef485e168dea41b50097
7
- data.tar.gz: 7ff16986a8ef0efeff790389805fa6d36f6b03b5983e8f8131ff33f8369514344cc9f9b9f103f036ad305441e06dfdfdacd125bdb8b061967337235d4913c525
6
+ metadata.gz: 2728bcbae59fae1138bdb5aef4e2f22290db93ce6c1e81f031e25c43108287a4f4d93d20afcfd9cb19a0e55593e1ccdadf1d83ebfbb430ee802368b73994cc2b
7
+ data.tar.gz: d06939ece851f9f4fb1311846826cad5c92e594511948ac9659bb190ebe6f905fdce15b4b9d16cf5df3b08bc5483a6f27d847f3ddf752aaa18bfcf74fec087e1
@@ -1,22 +1,22 @@
1
1
  #include "quickjsrb.h"
2
2
 
3
- JSValue to_js_value(JSContext *ctx, VALUE r_value)
3
+ JSValue j_error_from_ruby_error(JSContext *ctx, VALUE r_error)
4
4
  {
5
- if (RTEST(rb_funcall(
6
- r_value,
7
- rb_intern("is_a?"),
8
- 1, rb_const_get(rb_cClass, rb_intern("Exception")))))
9
- {
10
- JSValue j_error = JS_NewError(ctx);
11
- VALUE r_str = rb_funcall(r_value, rb_intern("message"), 0, NULL);
12
- char *exceptionMessage = StringValueCStr(r_str);
13
- VALUE r_exception_name = rb_funcall(rb_funcall(r_value, rb_intern("class"), 0, NULL), rb_intern("name"), 0, NULL);
14
- char *exceptionName = StringValueCStr(r_exception_name);
15
- JS_SetPropertyStr(ctx, j_error, "name", JS_NewString(ctx, exceptionName));
16
- JS_SetPropertyStr(ctx, j_error, "message", JS_NewString(ctx, exceptionMessage));
17
- return JS_Throw(ctx, j_error);
18
- }
5
+ JSValue j_error = JS_NewError(ctx); // may wanna have custom error class to determine in JS' end
6
+
7
+ VALUE r_object_id = rb_funcall(r_error, rb_intern("object_id"), 0, NULL);
8
+ int objectId = NUM2INT(r_object_id);
9
+ JS_SetPropertyStr(ctx, j_error, "rb_object_id", JS_NewInt32(ctx, objectId));
10
+
11
+ VALUE r_exception_message = rb_funcall(r_error, rb_intern("message"), 0, NULL);
12
+ const char *errorMessage = StringValueCStr(r_exception_message);
13
+ JS_SetPropertyStr(ctx, j_error, "message", JS_NewString(ctx, errorMessage));
19
14
 
15
+ return j_error;
16
+ }
17
+
18
+ JSValue to_js_value(JSContext *ctx, VALUE r_value)
19
+ {
20
20
  switch (TYPE(r_value))
21
21
  {
22
22
  case T_NIL:
@@ -72,6 +72,13 @@ JSValue to_js_value(JSContext *ctx, VALUE r_value)
72
72
  }
73
73
  default:
74
74
  {
75
+ if (TYPE(r_value) == T_OBJECT && RTEST(rb_funcall(
76
+ r_value,
77
+ rb_intern("is_a?"),
78
+ 1, rb_const_get(rb_cClass, rb_intern("Exception")))))
79
+ {
80
+ return j_error_from_ruby_error(ctx, r_value);
81
+ }
75
82
  VALUE r_inspect_str = rb_funcall(r_value, rb_intern("inspect"), 0, NULL);
76
83
  char *str = StringValueCStr(r_inspect_str);
77
84
 
@@ -80,6 +87,11 @@ JSValue to_js_value(JSContext *ctx, VALUE r_value)
80
87
  }
81
88
  }
82
89
 
90
+ VALUE r_try_json_parse(VALUE r_str)
91
+ {
92
+ return rb_funcall(rb_const_get(rb_cClass, rb_intern("JSON")), rb_intern("parse"), 1, r_str);
93
+ }
94
+
83
95
  VALUE to_rb_value(JSContext *ctx, JSValue j_val)
84
96
  {
85
97
  switch (JS_VALUE_GET_NORM_TAG(j_val))
@@ -121,6 +133,23 @@ VALUE to_rb_value(JSContext *ctx, JSValue j_val)
121
133
  return Qnil;
122
134
  }
123
135
 
136
+ if (JS_IsError(ctx, j_val))
137
+ {
138
+ JSValue j_errorOriginalRubyObjectId = JS_GetPropertyStr(ctx, j_val, "rb_object_id");
139
+ int errorOriginalRubyObjectId = 0;
140
+ if (JS_VALUE_GET_NORM_TAG(j_errorOriginalRubyObjectId) == JS_TAG_INT)
141
+ {
142
+ JS_ToInt32(ctx, &errorOriginalRubyObjectId, j_errorOriginalRubyObjectId);
143
+ JS_FreeValue(ctx, j_errorOriginalRubyObjectId);
144
+ if (errorOriginalRubyObjectId > 0)
145
+ {
146
+ // may be nice if cover the case of object is missing
147
+ return rb_funcall(rb_const_get(rb_cClass, rb_intern("ObjectSpace")), rb_intern("_id2ref"), 1, INT2NUM(errorOriginalRubyObjectId));
148
+ }
149
+ }
150
+ // will support other errors
151
+ }
152
+
124
153
  JSValue j_global = JS_GetGlobalObject(ctx);
125
154
  JSValue j_jsonClass = JS_GetPropertyStr(ctx, j_global, "JSON");
126
155
  JSValue j_stringifyFunc = JS_GetPropertyStr(ctx, j_jsonClass, "stringify");
@@ -135,7 +164,21 @@ VALUE to_rb_value(JSContext *ctx, JSValue j_val)
135
164
  JS_FreeValue(ctx, j_jsonClass);
136
165
  JS_FreeValue(ctx, j_global);
137
166
 
138
- return rb_funcall(rb_const_get(rb_cClass, rb_intern("JSON")), rb_intern("parse"), 1, r_str);
167
+ if (rb_funcall(r_str, rb_intern("=="), 1, rb_str_new2("undefined")))
168
+ {
169
+ return QUICKJSRB_SYM(undefinedId);
170
+ }
171
+
172
+ int couldntParse;
173
+ VALUE r_result = rb_protect(r_try_json_parse, r_str, &couldntParse);
174
+ if (couldntParse)
175
+ {
176
+ return Qnil;
177
+ }
178
+ else
179
+ {
180
+ return r_result;
181
+ }
139
182
  }
140
183
  case JS_TAG_NULL:
141
184
  return Qnil;
@@ -146,6 +189,21 @@ VALUE to_rb_value(JSContext *ctx, JSValue j_val)
146
189
  JSValue j_exceptionVal = JS_GetException(ctx);
147
190
  if (JS_IsError(ctx, j_exceptionVal))
148
191
  {
192
+ JSValue j_errorOriginalRubyObjectId = JS_GetPropertyStr(ctx, j_exceptionVal, "rb_object_id");
193
+ int errorOriginalRubyObjectId = 0;
194
+ if (JS_VALUE_GET_NORM_TAG(j_errorOriginalRubyObjectId) == JS_TAG_INT)
195
+ {
196
+ JS_ToInt32(ctx, &errorOriginalRubyObjectId, j_errorOriginalRubyObjectId);
197
+ JS_FreeValue(ctx, j_errorOriginalRubyObjectId);
198
+ if (errorOriginalRubyObjectId > 0)
199
+ {
200
+ JS_FreeValue(ctx, j_exceptionVal);
201
+ // may be nice if cover the case of object is missing
202
+ rb_exc_raise(rb_funcall(rb_const_get(rb_cClass, rb_intern("ObjectSpace")), rb_intern("_id2ref"), 1, INT2NUM(errorOriginalRubyObjectId)));
203
+ return Qnil;
204
+ }
205
+ }
206
+
149
207
  JSValue j_errorClassName = JS_GetPropertyStr(ctx, j_exceptionVal, "name");
150
208
  const char *errorClassName = JS_ToCString(ctx, j_errorClassName);
151
209
 
@@ -165,11 +223,6 @@ VALUE to_rb_value(JSContext *ctx, JSValue j_val)
165
223
  r_error_class = QUICKJSRB_ERROR_FOR(QUICKJSRB_INTERRUPTED_ERROR);
166
224
  r_error_message = rb_str_new2("Code evaluation is interrupted by the timeout or something");
167
225
  }
168
- else if (strcmp(errorClassName, "InternalError") == 0 && strstr(errorClassMessage, "Ruby") != NULL)
169
- {
170
- r_error_class = QUICKJSRB_ERROR_FOR(QUICKJSRB_RUBY_FUNCTION_ERROR);
171
- }
172
-
173
226
  else if (strcmp(errorClassName, "Quickjs::InterruptedError") == 0)
174
227
  {
175
228
  r_error_class = QUICKJSRB_ERROR_FOR(QUICKJSRB_INTERRUPTED_ERROR);
@@ -251,7 +304,9 @@ static JSValue js_quickjsrb_call_global(JSContext *ctx, JSValueConst _this, int
251
304
  JSValue j_result;
252
305
  if (sadnessHappened)
253
306
  {
254
- j_result = JS_ThrowInternalError(ctx, "unintentional error is raised while executing the function by Ruby: `%s`", funcName);
307
+ VALUE r_error = rb_errinfo();
308
+ JSValue j_error = j_error_from_ruby_error(ctx, r_error);
309
+ return JS_Throw(ctx, j_error);
255
310
  }
256
311
  else
257
312
  {
@@ -475,13 +530,14 @@ static VALUE vm_m_import(int argc, VALUE *argv, VALUE r_self)
475
530
  rb_scan_args(argc, argv, "10:", &r_import_string, &r_opts);
476
531
  if (NIL_P(r_opts))
477
532
  r_opts = rb_hash_new();
478
- VALUE r_from = rb_hash_aref(r_opts, ID2SYM(rb_intern("from"))); // TODO: Use kwargs instead
533
+ VALUE r_from = rb_hash_aref(r_opts, ID2SYM(rb_intern("from")));
479
534
  if (NIL_P(r_from))
480
535
  {
481
536
  VALUE r_error_message = rb_str_new2("missing import source");
482
537
  rb_exc_raise(rb_funcall(QUICKJSRB_ERROR_FOR(QUICKJSRB_ROOT_RUNTIME_ERROR), rb_intern("new"), 2, r_error_message, Qnil));
483
538
  return Qnil;
484
539
  }
540
+ VALUE r_custom_exposure = rb_hash_aref(r_opts, ID2SYM(rb_intern("code_to_expose")));
485
541
 
486
542
  VMData *data;
487
543
  TypedData_Get_Struct(r_self, VMData, &vm_type, data);
@@ -499,8 +555,16 @@ static VALUE vm_m_import(int argc, VALUE *argv, VALUE r_self)
499
555
  r_import_string);
500
556
  VALUE r_import_name = rb_ary_entry(r_import_settings, 0);
501
557
  char *import_name = StringValueCStr(r_import_name);
502
- VALUE r_globalize = rb_ary_entry(r_import_settings, 1);
503
- char *globalize = StringValueCStr(r_globalize);
558
+ VALUE r_default_exposure = rb_ary_entry(r_import_settings, 1);
559
+ char *globalize;
560
+ if (RTEST(r_custom_exposure))
561
+ {
562
+ globalize = StringValueCStr(r_custom_exposure);
563
+ }
564
+ else
565
+ {
566
+ globalize = StringValueCStr(r_default_exposure);
567
+ }
504
568
 
505
569
  const char *importAndGlobalizeModule = "import %s from '%s';\n"
506
570
  "%s\n";
@@ -183,7 +183,6 @@ static VALUE r_define_log_class(VALUE r_parent_class)
183
183
  #define QUICKJSRB_ROOT_RUNTIME_ERROR "RuntimeError"
184
184
  #define QUICKJSRB_INTERRUPTED_ERROR "InterruptedError"
185
185
  #define QUICKJSRB_NO_AWAIT_ERROR "NoAwaitError"
186
- #define QUICKJSRB_RUBY_FUNCTION_ERROR "RubyFunctionError"
187
186
 
188
187
  #define QUICKJSRB_ERROR_FOR(name) \
189
188
  (VALUE) { rb_const_get(rb_const_get(rb_cClass, rb_intern("Quickjs")), rb_intern(name)) }
@@ -212,7 +211,6 @@ static void r_define_exception_classes(VALUE r_parent_class)
212
211
  // quickjsrb specific errors
213
212
  rb_define_class_under(r_parent_class, QUICKJSRB_INTERRUPTED_ERROR, r_runtime_error);
214
213
  rb_define_class_under(r_parent_class, QUICKJSRB_NO_AWAIT_ERROR, r_runtime_error);
215
- rb_define_class_under(r_parent_class, QUICKJSRB_RUBY_FUNCTION_ERROR, r_runtime_error);
216
214
  }
217
215
 
218
216
  #endif /* QUICKJSRB_H */
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Quickjs
4
- VERSION = "0.2.3"
4
+ VERSION = "0.3.0"
5
5
  end
data/lib/quickjs.rb CHANGED
@@ -16,7 +16,7 @@ module Quickjs
16
16
  def _with_timeout(msec, proc, args)
17
17
  Timeout.timeout(msec / 1_000.0) { proc.call(*args) }
18
18
  rescue Timeout::Error
19
- Quickjs::InterruptedError.new('Ruby runtime got timeout', nil)
19
+ raise Quickjs::InterruptedError.new('Ruby runtime got timeout', nil)
20
20
  rescue
21
21
  raise
22
22
  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.2.3
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - hmsk
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-10-31 00:00:00.000000000 Z
11
+ date: 2024-11-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json