quickjs 0.1.12 → 0.2.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: 362c16217cefda63b3d8a4e0c41bdf4036c24e49540e5c223efc0751d5c84e44
4
- data.tar.gz: 0415d93639765ffc7191964418e3a12f3c5fd51a547e854ff68141f1239c8e91
3
+ metadata.gz: 30027c93cb2dd5dbb85d43ab40700f7ee06679a824b503bee42786a42bc5dc26
4
+ data.tar.gz: 51c60a962c82bbbbaa3a3fc4202255809751848d1474f9a4e9f6b7ebe4df0277
5
5
  SHA512:
6
- metadata.gz: d03afbf875aa53a7bbda02ed4ad84bab4f264b77446373f352c0c19d0d6c7cf824e3fd8b5c108cb0dd13872b8f8e53b12488052bd5f80190287c685f8f5bd6b0
7
- data.tar.gz: 2fa7eae61259f74229e1ee71c2dd4a6016ef7f26cb1e47cdbe2646b871bb7a0eb41c8e74b3805d4471e5e953153fab2f8ab14f17e934969264cb231ae5a08556
6
+ metadata.gz: e1f248cbafcc56ceba481f658aae542660ac8de6036b7fc1e9425e5f214f4f51a918a3051b82e796a075ed83726f59ba6b8dcc85e8b1c38ee1369b089ebd410a
7
+ data.tar.gz: 7c7346da3a318d3ed07bfd490561ced7deda800678bda0cb23c4f2b19b84b9720191a7999a7d9a5225d91d4c2140b7fffae03f16d75b791cd4d3b746bbab50a9
data/README.md CHANGED
@@ -104,6 +104,16 @@ vm = Quickjs::VM.new(
104
104
  )
105
105
  ```
106
106
 
107
+ #### ⚡️ Import ESM from source
108
+
109
+ ```rb
110
+ vm = Quickjs::VM.new
111
+ vm.import({ default: 'aliasedDefault', member: 'member' }, from: File.read('exports.esm.js'))
112
+
113
+ vm.eval_code("aliasedDefault()") #=> Exported `default` of the ESM is called
114
+ vm.eval_code("member()") #=> Exported `member` of the ESM is called
115
+ ```
116
+
107
117
  #### ⚡️ Define a global function for JS by Ruby
108
118
 
109
119
  ```rb
@@ -191,7 +191,7 @@ VALUE to_rb_value(JSContext *ctx, JSValue j_val)
191
191
  if (promiseState != -1)
192
192
  {
193
193
  VALUE r_error_message = rb_str_new2("cannot translate a Promise to Ruby. await within JavaScript's end");
194
- rb_exc_raise(rb_exc_new_str(rb_eRuntimeError, r_error_message));
194
+ rb_exc_raise(rb_funcall(rb_cQuickjsRuntimeError, rb_intern("new"), 2, r_error_message, Qnil));
195
195
  return Qnil;
196
196
  }
197
197
 
@@ -229,43 +229,35 @@ VALUE to_rb_value(JSContext *ctx, JSValue j_val)
229
229
  JS_FreeValue(ctx, j_errorClassMessage);
230
230
  JS_FreeValue(ctx, j_errorClassName);
231
231
 
232
- VALUE r_error_message = rb_sprintf("%s: %s", errorClassName, errorClassMessage);
233
- VALUE r_error_class = rb_eRuntimeError;
232
+ VALUE r_error_class, r_error_message = rb_str_new2(errorClassMessage);
234
233
 
235
234
  if (strcmp(errorClassName, "SyntaxError") == 0)
236
235
  {
237
236
  r_error_class = rb_cQuickjsSyntaxError;
238
- r_error_message = rb_str_new2(errorClassMessage);
239
237
  }
240
238
  else if (strcmp(errorClassName, "TypeError") == 0)
241
239
  {
242
240
  r_error_class = rb_cQuickjsTypeError;
243
- r_error_message = rb_str_new2(errorClassMessage);
244
241
  }
245
242
  else if (strcmp(errorClassName, "ReferenceError") == 0)
246
243
  {
247
244
  r_error_class = rb_cQuickjsReferenceError;
248
- r_error_message = rb_str_new2(errorClassMessage);
249
245
  }
250
246
  else if (strcmp(errorClassName, "RangeError") == 0)
251
247
  {
252
248
  r_error_class = rb_cQuickjsRangeError;
253
- r_error_message = rb_str_new2(errorClassMessage);
254
249
  }
255
250
  else if (strcmp(errorClassName, "EvalError") == 0)
256
251
  {
257
252
  r_error_class = rb_cQuickjsEvalError;
258
- r_error_message = rb_str_new2(errorClassMessage);
259
253
  }
260
254
  else if (strcmp(errorClassName, "URIError") == 0)
261
255
  {
262
256
  r_error_class = rb_cQuickjsURIError;
263
- r_error_message = rb_str_new2(errorClassMessage);
264
257
  }
265
258
  else if (strcmp(errorClassName, "AggregateError") == 0)
266
259
  {
267
260
  r_error_class = rb_cQuickjsAggregateError;
268
- r_error_message = rb_str_new2(errorClassMessage);
269
261
  }
270
262
  else if (strcmp(errorClassName, "InternalError") == 0 && strstr(errorClassMessage, "interrupted") != NULL)
271
263
  {
@@ -275,13 +267,16 @@ VALUE to_rb_value(JSContext *ctx, JSValue j_val)
275
267
  else if (strcmp(errorClassName, "Quickjs::InterruptedError") == 0)
276
268
  {
277
269
  r_error_class = rb_cQuickjsInterruptedError;
278
- r_error_message = rb_str_new2(errorClassMessage);
270
+ }
271
+ else
272
+ {
273
+ r_error_class = rb_cQuickjsRuntimeError;
279
274
  }
280
275
  JS_FreeCString(ctx, errorClassName);
281
276
  JS_FreeCString(ctx, errorClassMessage);
282
277
  JS_FreeValue(ctx, j_exceptionVal);
283
278
 
284
- rb_exc_raise(rb_exc_new_str(r_error_class, r_error_message));
279
+ rb_exc_raise(rb_funcall(r_error_class, rb_intern("new"), 2, r_error_message, rb_str_new2(errorClassName)));
285
280
  }
286
281
  else // exception without Error object
287
282
  {
@@ -290,7 +285,7 @@ VALUE to_rb_value(JSContext *ctx, JSValue j_val)
290
285
 
291
286
  JS_FreeCString(ctx, errorMessage);
292
287
  JS_FreeValue(ctx, j_exceptionVal);
293
- rb_exc_raise(rb_exc_new_str(rb_cQuickjsRuntimeError, r_error_message));
288
+ rb_exc_raise(rb_funcall(rb_cQuickjsRuntimeError, rb_intern("new"), 2, r_error_message, Qnil));
294
289
  }
295
290
  return Qnil;
296
291
  }
@@ -362,6 +357,7 @@ static JSValue js_quickjsrb_log(JSContext *ctx, JSValueConst _this, int _argc, J
362
357
  const char *body = JS_ToCString(ctx, j_logged);
363
358
  VALUE r_loghash = rb_hash_new();
364
359
  rb_hash_aset(r_loghash, ID2SYM(rb_intern("c")), rb_str_new2(body));
360
+ rb_hash_aset(r_loghash, ID2SYM(rb_intern("raw")), to_rb_value(ctx, j_logged));
365
361
  rb_ary_push(r_row, r_loghash);
366
362
  JS_FreeValue(ctx, j_logged);
367
363
  JS_FreeCString(ctx, body);
@@ -489,7 +485,7 @@ static VALUE vm_m_evalCode(VALUE r_self, VALUE r_code)
489
485
  JS_FreeValue(data->context, j_returnedValue);
490
486
  JS_FreeValue(data->context, j_awaitedResult);
491
487
  VALUE r_error_message = rb_str_new2("An unawaited Promise was returned to the top-level");
492
- rb_exc_raise(rb_exc_new_str(rb_cQuickjsNoAwaitError, r_error_message));
488
+ rb_exc_raise(rb_funcall(rb_cQuickjsNoAwaitError, rb_intern("new"), 2, r_error_message, Qnil));
493
489
  return Qnil;
494
490
  }
495
491
  else
@@ -529,11 +525,6 @@ static VALUE vm_m_defineGlobalFunction(VALUE r_self, VALUE r_name)
529
525
  return Qnil;
530
526
  }
531
527
 
532
- // WISH: vm.import('hey', from: '...source...') imports just default
533
- // WISH: vm.import('{ member, member2 }', from: '...source...')
534
- // WISH: vm.import('{ member as aliasedName }', from: '...source...')
535
- // WISH: vm.import('defaultMember, { member }', from: '...source...')
536
- // WISH: vm.import('* as all', from: '...source...')
537
528
  static VALUE vm_m_import(int argc, VALUE *argv, VALUE r_self)
538
529
  {
539
530
  VALUE r_import_string, r_opts;
@@ -544,7 +535,7 @@ static VALUE vm_m_import(int argc, VALUE *argv, VALUE r_self)
544
535
  if (NIL_P(r_from))
545
536
  {
546
537
  VALUE r_error_message = rb_str_new2("missing import source");
547
- rb_exc_raise(rb_exc_new_str(rb_eRuntimeError, r_error_message));
538
+ rb_exc_raise(rb_funcall(rb_cQuickjsRuntimeError, rb_intern("new"), 2, r_error_message, Qnil));
548
539
  return Qnil;
549
540
  }
550
541
 
@@ -552,16 +543,25 @@ static VALUE vm_m_import(int argc, VALUE *argv, VALUE r_self)
552
543
  TypedData_Get_Struct(r_self, VMData, &vm_type, data);
553
544
 
554
545
  char *source = StringValueCStr(r_from);
555
- char *import_name = StringValueCStr(r_import_string);
556
546
  JSValue func = JS_Eval(data->context, source, strlen(source), "mmmodule", JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY);
557
547
  js_module_set_import_meta(data->context, func, TRUE, FALSE);
558
548
  JS_FreeValue(data->context, func);
559
549
 
560
- const char *importAndGlobalizeModule = "import * as %s from 'mmmodule';\n"
561
- "globalThis['%s'] = %s;\n";
562
- int length = snprintf(NULL, 0, importAndGlobalizeModule, import_name, import_name, import_name);
550
+ VALUE r_import_settings = rb_funcall(
551
+ rb_const_get(rb_cClass, rb_intern("Quickjs")),
552
+ rb_intern("_build_import"),
553
+ 1,
554
+ r_import_string);
555
+ VALUE r_import_name = rb_ary_entry(r_import_settings, 0);
556
+ char *import_name = StringValueCStr(r_import_name);
557
+ VALUE r_globalize = rb_ary_entry(r_import_settings, 1);
558
+ char *globalize = StringValueCStr(r_globalize);
559
+
560
+ const char *importAndGlobalizeModule = "import %s from 'mmmodule';\n"
561
+ "%s\n";
562
+ int length = snprintf(NULL, 0, importAndGlobalizeModule, import_name, globalize);
563
563
  char *result = (char *)malloc(length + 1);
564
- snprintf(result, length + 1, importAndGlobalizeModule, import_name, import_name, import_name);
564
+ snprintf(result, length + 1, importAndGlobalizeModule, import_name, globalize);
565
565
 
566
566
  JSValue j_codeResult = JS_Eval(data->context, result, strlen(result), "<vm>", JS_EVAL_TYPE_MODULE);
567
567
  free(result);
@@ -578,6 +578,19 @@ static VALUE vm_m_getLogs(VALUE r_self)
578
578
  return data->logs;
579
579
  }
580
580
 
581
+ static VALUE pick_raw(VALUE block_arg, VALUE data, int argc, const VALUE *argv, VALUE blockarg)
582
+ {
583
+ return rb_hash_aref(block_arg, ID2SYM(rb_intern("raw")));
584
+ }
585
+
586
+ static VALUE vm_m_raw(VALUE r_self)
587
+ {
588
+ VALUE row = rb_iv_get(r_self, "@row");
589
+ VALUE r_ary = rb_block_call(row, rb_intern("map"), 0, NULL, pick_raw, Qnil);
590
+
591
+ return r_ary;
592
+ }
593
+
581
594
  static VALUE pick_c(VALUE block_arg, VALUE data, int argc, const VALUE *argv, VALUE blockarg)
582
595
  {
583
596
  return rb_hash_aref(block_arg, ID2SYM(rb_intern("c")));
@@ -591,8 +604,15 @@ static VALUE vm_m_to_s(VALUE r_self)
591
604
  return rb_funcall(r_ary, rb_intern("join"), 1, rb_str_new2(" "));
592
605
  }
593
606
 
594
- RUBY_FUNC_EXPORTED void
595
- Init_quickjsrb(void)
607
+ VALUE vm_m_initialize_quickjs_error(VALUE self, VALUE r_message, VALUE r_js_name)
608
+ {
609
+ rb_call_super(1, &r_message);
610
+ rb_iv_set(self, "@js_name", r_js_name);
611
+
612
+ return self;
613
+ }
614
+
615
+ RUBY_FUNC_EXPORTED void Init_quickjsrb(void)
596
616
  {
597
617
  VALUE rb_mQuickjs = rb_define_module("Quickjs");
598
618
  rb_define_const(rb_mQuickjs, "MODULE_STD", ID2SYM(rb_intern(featureStdId)));
@@ -613,10 +633,13 @@ Init_quickjsrb(void)
613
633
 
614
634
  rb_cQuickjsVMLog = rb_define_class_under(rb_cQuickjsVM, "Log", rb_cObject);
615
635
  rb_define_attr(rb_cQuickjsVMLog, "severity", 1, 0);
636
+ rb_define_method(rb_cQuickjsVMLog, "raw", vm_m_raw, 0);
616
637
  rb_define_method(rb_cQuickjsVMLog, "to_s", vm_m_to_s, 0);
617
638
  rb_define_method(rb_cQuickjsVMLog, "inspect", vm_m_to_s, 0);
618
639
 
619
640
  rb_cQuickjsRuntimeError = rb_define_class_under(rb_mQuickjs, "RuntimeError", rb_eRuntimeError);
641
+ rb_define_method(rb_cQuickjsRuntimeError, "initialize", vm_m_initialize_quickjs_error, 2);
642
+ rb_define_attr(rb_cQuickjsRuntimeError, "js_name", 1, 0);
620
643
 
621
644
  rb_cQuickjsSyntaxError = rb_define_class_under(rb_mQuickjs, "SyntaxError", rb_cQuickjsRuntimeError);
622
645
  rb_cQuickjsTypeError = rb_define_class_under(rb_mQuickjs, "TypeError", rb_cQuickjsRuntimeError);
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Quickjs
4
- VERSION = "0.1.12"
4
+ VERSION = "0.2.0"
5
5
  end
data/lib/quickjs.rb CHANGED
@@ -17,9 +17,21 @@ module Quickjs
17
17
  def _with_timeout(msec, proc, args)
18
18
  Timeout.timeout(msec / 1_000.0) { proc.call(*args) }
19
19
  rescue Timeout::Error
20
- Quickjs::InterruptedError.new('Ruby runtime got timeout')
20
+ Quickjs::InterruptedError.new('Ruby runtime got timeout', nil)
21
21
  rescue => e
22
22
  e
23
23
  end
24
24
  module_function :_with_timeout
25
+
26
+ def _build_import(mappings)
27
+ imports, aliases = mappings.to_a.map do |imp|
28
+ ["#{imp[0]} as #{imp[1]}", imp[1].to_s]
29
+ end.transpose
30
+
31
+ [
32
+ imports.join(", ").yield_self{|s| '{ %s }' % s },
33
+ aliases.map {|name| "globalThis['#{name}'] = #{name};"}.join("\n")
34
+ ]
35
+ end
36
+ module_function :_build_import
25
37
  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.12
4
+ version: 0.2.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-09-30 00:00:00.000000000 Z
11
+ date: 2024-10-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json