quickjs 0.1.11 → 0.1.12

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: 81c0e4a716d292ddbfd58f559f37ddb1d86adb7059779f29bfa0a2b8a8180214
4
- data.tar.gz: f45ff31a1913c4ab807ddd5d8f08c17c9bc58236b09308f31f5adbf5d9241ffe
3
+ metadata.gz: 362c16217cefda63b3d8a4e0c41bdf4036c24e49540e5c223efc0751d5c84e44
4
+ data.tar.gz: 0415d93639765ffc7191964418e3a12f3c5fd51a547e854ff68141f1239c8e91
5
5
  SHA512:
6
- metadata.gz: 24c0349dc9e911936932a78e3c7aa0ac75ea36eb776258ae8d8d20d215eaa79a2d79a64c0b1eb0878182033eee8945f7e3f65dd1272e5290a332ac07bde7b7a9
7
- data.tar.gz: e7e472520ece228398482ea753157ffc4bf08b2f446b56dd2439b27a9c1006ffc9439ca5d1eb27015e6fa19b68e5663d82339c082b82fa085235e8c8108b5d3b
6
+ metadata.gz: d03afbf875aa53a7bbda02ed4ad84bab4f264b77446373f352c0c19d0d6c7cf824e3fd8b5c108cb0dd13872b8f8e53b12488052bd5f80190287c685f8f5bd6b0
7
+ data.tar.gz: 2fa7eae61259f74229e1ee71c2dd4a6016ef7f26cb1e47cdbe2646b871bb7a0eb41c8e74b3805d4471e5e953153fab2f8ab14f17e934969264cb231ae5a08556
@@ -11,6 +11,7 @@ typedef struct VMData
11
11
  struct JSContext *context;
12
12
  VALUE defined_functions;
13
13
  struct EvalTime *eval_time;
14
+ VALUE logs;
14
15
  } VMData;
15
16
 
16
17
  static void vm_free(void *ptr)
@@ -36,6 +37,7 @@ static void vm_mark(void *ptr)
36
37
  {
37
38
  VMData *data = (VMData *)ptr;
38
39
  rb_gc_mark_movable(data->defined_functions);
40
+ rb_gc_mark_movable(data->logs);
39
41
  }
40
42
 
41
43
  static const rb_data_type_t vm_type = {
@@ -53,6 +55,7 @@ static VALUE vm_alloc(VALUE r_self)
53
55
  VMData *data;
54
56
  VALUE obj = TypedData_Make_Struct(r_self, VMData, &vm_type, data);
55
57
  data->defined_functions = rb_hash_new();
58
+ data->logs = rb_ary_new();
56
59
 
57
60
  EvalTime *eval_time = malloc(sizeof(EvalTime));
58
61
  data->eval_time = eval_time;
@@ -63,7 +66,7 @@ static VALUE vm_alloc(VALUE r_self)
63
66
  return obj;
64
67
  }
65
68
 
66
- VALUE rb_mQuickjs;
69
+ VALUE rb_cQuickjsVMLog, rb_cQuickjsSyntaxError, rb_cQuickjsRuntimeError, rb_cQuickjsInterruptedError, rb_cQuickjsNoAwaitError, rb_cQuickjsTypeError, rb_cQuickjsReferenceError, rb_cQuickjsRangeError, rb_cQuickjsEvalError, rb_cQuickjsURIError, rb_cQuickjsAggregateError;
67
70
  const char *undefinedId = "undefined";
68
71
  const char *nanId = "NaN";
69
72
 
@@ -78,11 +81,13 @@ JSValue to_js_value(JSContext *ctx, VALUE r_value)
78
81
  rb_intern("is_a?"),
79
82
  1, rb_const_get(rb_cClass, rb_intern("Exception")))))
80
83
  {
81
- VALUE r_str = rb_funcall(r_value, rb_intern("message"), 0, NULL);
82
- char *str = StringValueCStr(r_str);
83
84
  JSValue j_error = JS_NewError(ctx);
84
- JSValue j_str = JS_NewString(ctx, str);
85
- JS_SetPropertyStr(ctx, j_error, "message", j_str);
85
+ VALUE r_str = rb_funcall(r_value, rb_intern("message"), 0, NULL);
86
+ char *exceptionMessage = StringValueCStr(r_str);
87
+ VALUE r_exception_name = rb_funcall(rb_funcall(r_value, rb_intern("class"), 0, NULL), rb_intern("name"), 0, NULL);
88
+ char *exceptionName = StringValueCStr(r_exception_name);
89
+ JS_SetPropertyStr(ctx, j_error, "name", JS_NewString(ctx, exceptionName));
90
+ JS_SetPropertyStr(ctx, j_error, "message", JS_NewString(ctx, exceptionMessage));
86
91
  return JS_Throw(ctx, j_error);
87
92
  }
88
93
 
@@ -225,19 +230,67 @@ VALUE to_rb_value(JSContext *ctx, JSValue j_val)
225
230
  JS_FreeValue(ctx, j_errorClassName);
226
231
 
227
232
  VALUE r_error_message = rb_sprintf("%s: %s", errorClassName, errorClassMessage);
233
+ VALUE r_error_class = rb_eRuntimeError;
234
+
235
+ if (strcmp(errorClassName, "SyntaxError") == 0)
236
+ {
237
+ r_error_class = rb_cQuickjsSyntaxError;
238
+ r_error_message = rb_str_new2(errorClassMessage);
239
+ }
240
+ else if (strcmp(errorClassName, "TypeError") == 0)
241
+ {
242
+ r_error_class = rb_cQuickjsTypeError;
243
+ r_error_message = rb_str_new2(errorClassMessage);
244
+ }
245
+ else if (strcmp(errorClassName, "ReferenceError") == 0)
246
+ {
247
+ r_error_class = rb_cQuickjsReferenceError;
248
+ r_error_message = rb_str_new2(errorClassMessage);
249
+ }
250
+ else if (strcmp(errorClassName, "RangeError") == 0)
251
+ {
252
+ r_error_class = rb_cQuickjsRangeError;
253
+ r_error_message = rb_str_new2(errorClassMessage);
254
+ }
255
+ else if (strcmp(errorClassName, "EvalError") == 0)
256
+ {
257
+ r_error_class = rb_cQuickjsEvalError;
258
+ r_error_message = rb_str_new2(errorClassMessage);
259
+ }
260
+ else if (strcmp(errorClassName, "URIError") == 0)
261
+ {
262
+ r_error_class = rb_cQuickjsURIError;
263
+ r_error_message = rb_str_new2(errorClassMessage);
264
+ }
265
+ else if (strcmp(errorClassName, "AggregateError") == 0)
266
+ {
267
+ r_error_class = rb_cQuickjsAggregateError;
268
+ r_error_message = rb_str_new2(errorClassMessage);
269
+ }
270
+ else if (strcmp(errorClassName, "InternalError") == 0 && strstr(errorClassMessage, "interrupted") != NULL)
271
+ {
272
+ r_error_class = rb_cQuickjsInterruptedError;
273
+ r_error_message = rb_str_new2("Code evaluation is interrupted by the timeout or something");
274
+ }
275
+ else if (strcmp(errorClassName, "Quickjs::InterruptedError") == 0)
276
+ {
277
+ r_error_class = rb_cQuickjsInterruptedError;
278
+ r_error_message = rb_str_new2(errorClassMessage);
279
+ }
228
280
  JS_FreeCString(ctx, errorClassName);
229
281
  JS_FreeCString(ctx, errorClassMessage);
230
282
  JS_FreeValue(ctx, j_exceptionVal);
231
- rb_exc_raise(rb_exc_new_str(rb_eRuntimeError, r_error_message));
283
+
284
+ rb_exc_raise(rb_exc_new_str(r_error_class, r_error_message));
232
285
  }
233
- else
286
+ else // exception without Error object
234
287
  {
235
288
  const char *errorMessage = JS_ToCString(ctx, j_exceptionVal);
236
289
  VALUE r_error_message = rb_sprintf("%s", errorMessage);
237
290
 
238
291
  JS_FreeCString(ctx, errorMessage);
239
292
  JS_FreeValue(ctx, j_exceptionVal);
240
- rb_exc_raise(rb_exc_new_str(rb_eRuntimeError, r_error_message));
293
+ rb_exc_raise(rb_exc_new_str(rb_cQuickjsRuntimeError, r_error_message));
241
294
  }
242
295
  return Qnil;
243
296
  }
@@ -287,6 +340,40 @@ static JSValue js_quickjsrb_call_global(JSContext *ctx, JSValueConst _this, int
287
340
  return to_js_value(ctx, r_result);
288
341
  }
289
342
 
343
+ static JSValue js_quickjsrb_log(JSContext *ctx, JSValueConst _this, int _argc, JSValueConst *argv)
344
+ {
345
+ VMData *data = JS_GetContextOpaque(ctx);
346
+ JSValue j_severity = JS_ToString(ctx, argv[0]);
347
+ const char *severity = JS_ToCString(ctx, j_severity);
348
+ JS_FreeValue(ctx, j_severity);
349
+
350
+ VALUE r_log = rb_funcall(rb_cQuickjsVMLog, rb_intern("new"), 0);
351
+ rb_iv_set(r_log, "@severity", ID2SYM(rb_intern(severity)));
352
+
353
+ VALUE r_row = rb_ary_new();
354
+ int i;
355
+ JSValue j_length = JS_GetPropertyStr(ctx, argv[1], "length");
356
+ int count;
357
+ JS_ToInt32(ctx, &count, j_length);
358
+ JS_FreeValue(ctx, j_length);
359
+ for (i = 0; i < count; i++)
360
+ {
361
+ JSValue j_logged = JS_GetPropertyUint32(ctx, argv[1], i);
362
+ const char *body = JS_ToCString(ctx, j_logged);
363
+ VALUE r_loghash = rb_hash_new();
364
+ rb_hash_aset(r_loghash, ID2SYM(rb_intern("c")), rb_str_new2(body));
365
+ rb_ary_push(r_row, r_loghash);
366
+ JS_FreeValue(ctx, j_logged);
367
+ JS_FreeCString(ctx, body);
368
+ }
369
+
370
+ rb_iv_set(r_log, "@row", r_row);
371
+ rb_ary_push(data->logs, r_log);
372
+ JS_FreeCString(ctx, severity);
373
+
374
+ return JS_UNDEFINED;
375
+ }
376
+
290
377
  static VALUE vm_m_initialize(int argc, VALUE *argv, VALUE r_self)
291
378
  {
292
379
  VALUE r_opts;
@@ -321,7 +408,6 @@ static VALUE vm_m_initialize(int argc, VALUE *argv, VALUE r_self)
321
408
  JS_AddIntrinsicBigDecimal(data->context);
322
409
  JS_AddIntrinsicOperators(data->context);
323
410
  JS_EnableBignumExt(data->context, TRUE);
324
- js_std_add_helpers(data->context, 0, NULL);
325
411
 
326
412
  JS_SetModuleLoaderFunc(runtime, NULL, js_module_loader, NULL);
327
413
  js_std_init_handlers(runtime);
@@ -353,15 +439,29 @@ static VALUE vm_m_initialize(int argc, VALUE *argv, VALUE r_self)
353
439
  JS_FreeValue(data->context, j_timeoutEval);
354
440
  }
355
441
 
356
- const char *setupGlobalRuby = "globalThis.__ruby = {};\n";
357
- JSValue j_rubyEval = JS_Eval(data->context, setupGlobalRuby, strlen(setupGlobalRuby), "<vm>", JS_EVAL_TYPE_MODULE);
358
- JS_FreeValue(data->context, j_rubyEval);
359
-
360
442
  JSValue j_global = JS_GetGlobalObject(data->context);
361
- JSValue j_func = JS_NewCFunction(data->context, js_quickjsrb_call_global, "rubyGlobal", 2);
362
- JS_SetPropertyStr(data->context, j_global, "rubyGlobal", j_func);
443
+ JSValue j_quickjsrbGlobal = JS_NewObject(data->context);
444
+ JS_SetPropertyStr(
445
+ data->context, j_quickjsrbGlobal, "runRubyMethod",
446
+ JS_NewCFunction(data->context, js_quickjsrb_call_global, "runRubyMethod", 2));
447
+
448
+ JS_SetPropertyStr(data->context, j_global, "__quickjsrb", j_quickjsrbGlobal);
449
+
450
+ JSValue j_console = JS_NewObject(data->context);
451
+ JS_SetPropertyStr(
452
+ data->context, j_quickjsrbGlobal, "log",
453
+ JS_NewCFunction(data->context, js_quickjsrb_log, "log", 2));
454
+ JS_SetPropertyStr(data->context, j_global, "console", j_console);
363
455
  JS_FreeValue(data->context, j_global);
364
456
 
457
+ const char *defineLoggers = "console.log = (...args) => __quickjsrb.log('info', args);\n"
458
+ "console.debug = (...args) => __quickjsrb.log('verbose', args);\n"
459
+ "console.info = (...args) => __quickjsrb.log('info', args);\n"
460
+ "console.warn = (...args) => __quickjsrb.log('warning', args);\n"
461
+ "console.error = (...args) => __quickjsrb.log('error', args);\n";
462
+ JSValue j_defineLoggers = JS_Eval(data->context, defineLoggers, strlen(defineLoggers), "<vm>", JS_EVAL_TYPE_GLOBAL);
463
+ JS_FreeValue(data->context, j_defineLoggers);
464
+
365
465
  return r_self;
366
466
  }
367
467
 
@@ -389,7 +489,7 @@ static VALUE vm_m_evalCode(VALUE r_self, VALUE r_code)
389
489
  JS_FreeValue(data->context, j_returnedValue);
390
490
  JS_FreeValue(data->context, j_awaitedResult);
391
491
  VALUE r_error_message = rb_str_new2("An unawaited Promise was returned to the top-level");
392
- rb_exc_raise(rb_exc_new_str(rb_eRuntimeError, r_error_message));
492
+ rb_exc_raise(rb_exc_new_str(rb_cQuickjsNoAwaitError, r_error_message));
393
493
  return Qnil;
394
494
  }
395
495
  else
@@ -414,11 +514,10 @@ static VALUE vm_m_defineGlobalFunction(VALUE r_self, VALUE r_name)
414
514
  rb_hash_aset(data->defined_functions, r_name, r_proc);
415
515
  char *funcName = StringValueCStr(r_name);
416
516
 
417
- const char *template = "globalThis.__ruby['%s'] = (...args) => rubyGlobal('%s', args);\n"
418
- "globalThis['%s'] = globalThis.__ruby['%s'];\n";
419
- int length = snprintf(NULL, 0, template, funcName, funcName, funcName, funcName);
517
+ const char *template = "globalThis['%s'] = (...args) => __quickjsrb.runRubyMethod('%s', args);\n";
518
+ int length = snprintf(NULL, 0, template, funcName, funcName);
420
519
  char *result = (char *)malloc(length + 1);
421
- snprintf(result, length + 1, template, funcName, funcName, funcName, funcName);
520
+ snprintf(result, length + 1, template, funcName, funcName);
422
521
 
423
522
  JSValue j_codeResult = JS_Eval(data->context, result, strlen(result), "<vm>", JS_EVAL_TYPE_MODULE);
424
523
 
@@ -430,21 +529,103 @@ static VALUE vm_m_defineGlobalFunction(VALUE r_self, VALUE r_name)
430
529
  return Qnil;
431
530
  }
432
531
 
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
+ static VALUE vm_m_import(int argc, VALUE *argv, VALUE r_self)
538
+ {
539
+ VALUE r_import_string, r_opts;
540
+ rb_scan_args(argc, argv, "10:", &r_import_string, &r_opts);
541
+ if (NIL_P(r_opts))
542
+ r_opts = rb_hash_new();
543
+ VALUE r_from = rb_hash_aref(r_opts, ID2SYM(rb_intern("from")));
544
+ if (NIL_P(r_from))
545
+ {
546
+ VALUE r_error_message = rb_str_new2("missing import source");
547
+ rb_exc_raise(rb_exc_new_str(rb_eRuntimeError, r_error_message));
548
+ return Qnil;
549
+ }
550
+
551
+ VMData *data;
552
+ TypedData_Get_Struct(r_self, VMData, &vm_type, data);
553
+
554
+ char *source = StringValueCStr(r_from);
555
+ char *import_name = StringValueCStr(r_import_string);
556
+ JSValue func = JS_Eval(data->context, source, strlen(source), "mmmodule", JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY);
557
+ js_module_set_import_meta(data->context, func, TRUE, FALSE);
558
+ JS_FreeValue(data->context, func);
559
+
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);
563
+ char *result = (char *)malloc(length + 1);
564
+ snprintf(result, length + 1, importAndGlobalizeModule, import_name, import_name, import_name);
565
+
566
+ JSValue j_codeResult = JS_Eval(data->context, result, strlen(result), "<vm>", JS_EVAL_TYPE_MODULE);
567
+ free(result);
568
+ JS_FreeValue(data->context, j_codeResult);
569
+
570
+ return Qtrue;
571
+ }
572
+
573
+ static VALUE vm_m_getLogs(VALUE r_self)
574
+ {
575
+ VMData *data;
576
+ TypedData_Get_Struct(r_self, VMData, &vm_type, data);
577
+
578
+ return data->logs;
579
+ }
580
+
581
+ static VALUE pick_c(VALUE block_arg, VALUE data, int argc, const VALUE *argv, VALUE blockarg)
582
+ {
583
+ return rb_hash_aref(block_arg, ID2SYM(rb_intern("c")));
584
+ }
585
+
586
+ static VALUE vm_m_to_s(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_c, Qnil);
590
+
591
+ return rb_funcall(r_ary, rb_intern("join"), 1, rb_str_new2(" "));
592
+ }
593
+
433
594
  RUBY_FUNC_EXPORTED void
434
595
  Init_quickjsrb(void)
435
596
  {
436
- rb_mQuickjs = rb_define_module("Quickjs");
597
+ VALUE rb_mQuickjs = rb_define_module("Quickjs");
437
598
  rb_define_const(rb_mQuickjs, "MODULE_STD", ID2SYM(rb_intern(featureStdId)));
438
599
  rb_define_const(rb_mQuickjs, "MODULE_OS", ID2SYM(rb_intern(featureOsId)));
439
600
  rb_define_const(rb_mQuickjs, "FEATURES_TIMEOUT", ID2SYM(rb_intern(featureOsTimeoutId)));
440
601
 
441
- VALUE valueClass = rb_define_class_under(rb_mQuickjs, "Value", rb_cObject);
442
- rb_define_const(valueClass, "UNDEFINED", ID2SYM(rb_intern(undefinedId)));
443
- rb_define_const(valueClass, "NAN", ID2SYM(rb_intern(nanId)));
444
-
445
- VALUE vmClass = rb_define_class_under(rb_mQuickjs, "VM", rb_cObject);
446
- rb_define_alloc_func(vmClass, vm_alloc);
447
- rb_define_method(vmClass, "initialize", vm_m_initialize, -1);
448
- rb_define_method(vmClass, "eval_code", vm_m_evalCode, 1);
449
- rb_define_method(vmClass, "define_function", vm_m_defineGlobalFunction, 1);
602
+ VALUE rb_cQuickjsValue = rb_define_class_under(rb_mQuickjs, "Value", rb_cObject);
603
+ rb_define_const(rb_cQuickjsValue, "UNDEFINED", ID2SYM(rb_intern(undefinedId)));
604
+ rb_define_const(rb_cQuickjsValue, "NAN", ID2SYM(rb_intern(nanId)));
605
+
606
+ VALUE rb_cQuickjsVM = rb_define_class_under(rb_mQuickjs, "VM", rb_cObject);
607
+ rb_define_alloc_func(rb_cQuickjsVM, vm_alloc);
608
+ rb_define_method(rb_cQuickjsVM, "initialize", vm_m_initialize, -1);
609
+ rb_define_method(rb_cQuickjsVM, "eval_code", vm_m_evalCode, 1);
610
+ rb_define_method(rb_cQuickjsVM, "define_function", vm_m_defineGlobalFunction, 1);
611
+ rb_define_method(rb_cQuickjsVM, "import", vm_m_import, -1);
612
+ rb_define_method(rb_cQuickjsVM, "logs", vm_m_getLogs, 0);
613
+
614
+ rb_cQuickjsVMLog = rb_define_class_under(rb_cQuickjsVM, "Log", rb_cObject);
615
+ rb_define_attr(rb_cQuickjsVMLog, "severity", 1, 0);
616
+ rb_define_method(rb_cQuickjsVMLog, "to_s", vm_m_to_s, 0);
617
+ rb_define_method(rb_cQuickjsVMLog, "inspect", vm_m_to_s, 0);
618
+
619
+ rb_cQuickjsRuntimeError = rb_define_class_under(rb_mQuickjs, "RuntimeError", rb_eRuntimeError);
620
+
621
+ rb_cQuickjsSyntaxError = rb_define_class_under(rb_mQuickjs, "SyntaxError", rb_cQuickjsRuntimeError);
622
+ rb_cQuickjsTypeError = rb_define_class_under(rb_mQuickjs, "TypeError", rb_cQuickjsRuntimeError);
623
+ rb_cQuickjsRangeError = rb_define_class_under(rb_mQuickjs, "RangeError", rb_cQuickjsRuntimeError);
624
+ rb_cQuickjsReferenceError = rb_define_class_under(rb_mQuickjs, "ReferenceError", rb_cQuickjsRuntimeError);
625
+ rb_cQuickjsURIError = rb_define_class_under(rb_mQuickjs, "URIError", rb_cQuickjsRuntimeError);
626
+ rb_cQuickjsEvalError = rb_define_class_under(rb_mQuickjs, "EvalError", rb_cQuickjsRuntimeError);
627
+ rb_cQuickjsAggregateError = rb_define_class_under(rb_mQuickjs, "AggregateError", rb_cQuickjsRuntimeError);
628
+
629
+ rb_cQuickjsInterruptedError = rb_define_class_under(rb_mQuickjs, "InterruptedError", rb_cQuickjsRuntimeError);
630
+ rb_cQuickjsNoAwaitError = rb_define_class_under(rb_mQuickjs, "NoAwaitError", rb_cQuickjsRuntimeError);
450
631
  }
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Quickjs
4
- VERSION = "0.1.11"
4
+ VERSION = "0.1.12"
5
5
  end
data/lib/quickjs.rb CHANGED
@@ -17,7 +17,7 @@ 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
- RuntimeError.new('interrupted')
20
+ Quickjs::InterruptedError.new('Ruby runtime got timeout')
21
21
  rescue => e
22
22
  e
23
23
  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.11
4
+ version: 0.1.12
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-22 00:00:00.000000000 Z
11
+ date: 2024-09-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json