Skip to content

Commit

Permalink
support all built-in error classes
Browse files Browse the repository at this point in the history
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error

In addition to SyntaxError
- Quickj::TypeError
- Quickjs::ReferenceError
- Quickjs::RangeError,
- Quickjs::EvalError,
- Quickjs::URIError
- Quickjs::AggregateError
  • Loading branch information
hmsk committed Jul 25, 2024
1 parent e9bfa22 commit 906293e
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 2 deletions.
40 changes: 39 additions & 1 deletion ext/quickjsrb/quickjsrb.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ static VALUE vm_alloc(VALUE r_self)
}

VALUE rb_mQuickjs;
VALUE rb_cQuickjsSyntaxError, rb_cQuickjsRuntimeError, rb_cQuickjsInterruptedError, rb_cQuickjsNoAwaitError;
VALUE rb_cQuickjsSyntaxError, rb_cQuickjsRuntimeError, rb_cQuickjsInterruptedError, rb_cQuickjsNoAwaitError, rb_cQuickjsTypeError, rb_cQuickjsReferenceError, rb_cQuickjsRangeError, rb_cQuickjsEvalError, rb_cQuickjsURIError, rb_cQuickjsAggregateError;
const char *undefinedId = "undefined";
const char *nanId = "NaN";

Expand Down Expand Up @@ -235,6 +235,36 @@ VALUE to_rb_value(JSContext *ctx, JSValue j_val)
r_error_class = rb_cQuickjsSyntaxError;
r_error_message = rb_str_new2(errorClassMessage);
}
else if (strcmp(errorClassName, "TypeError") == 0)
{
r_error_class = rb_cQuickjsTypeError;
r_error_message = rb_str_new2(errorClassMessage);
}
else if (strcmp(errorClassName, "ReferenceError") == 0)
{
r_error_class = rb_cQuickjsReferenceError;
r_error_message = rb_str_new2(errorClassMessage);
}
else if (strcmp(errorClassName, "RangeError") == 0)
{
r_error_class = rb_cQuickjsRangeError;
r_error_message = rb_str_new2(errorClassMessage);
}
else if (strcmp(errorClassName, "EvalError") == 0)
{
r_error_class = rb_cQuickjsEvalError;
r_error_message = rb_str_new2(errorClassMessage);
}
else if (strcmp(errorClassName, "URIError") == 0)
{
r_error_class = rb_cQuickjsURIError;
r_error_message = rb_str_new2(errorClassMessage);
}
else if (strcmp(errorClassName, "AggregateError") == 0)
{
r_error_class = rb_cQuickjsAggregateError;
r_error_message = rb_str_new2(errorClassMessage);
}
else if (strcmp(errorClassName, "InternalError") == 0 && strstr(errorClassMessage, "interrupted") != NULL)
{
r_error_class = rb_cQuickjsInterruptedError;
Expand Down Expand Up @@ -470,7 +500,15 @@ Init_quickjsrb(void)
rb_define_method(vmClass, "define_function", vm_m_defineGlobalFunction, 1);

rb_cQuickjsRuntimeError = rb_define_class_under(rb_mQuickjs, "RuntimeError", rb_eRuntimeError);

rb_cQuickjsSyntaxError = rb_define_class_under(rb_mQuickjs, "SyntaxError", rb_cQuickjsRuntimeError);
rb_cQuickjsTypeError = rb_define_class_under(rb_mQuickjs, "TypeError", rb_cQuickjsRuntimeError);
rb_cQuickjsRangeError = rb_define_class_under(rb_mQuickjs, "RangeError", rb_cQuickjsRuntimeError);
rb_cQuickjsReferenceError = rb_define_class_under(rb_mQuickjs, "ReferenceError", rb_cQuickjsRuntimeError);
rb_cQuickjsURIError = rb_define_class_under(rb_mQuickjs, "URIError", rb_cQuickjsRuntimeError);
rb_cQuickjsEvalError = rb_define_class_under(rb_mQuickjs, "EvalError", rb_cQuickjsRuntimeError);
rb_cQuickjsAggregateError = rb_define_class_under(rb_mQuickjs, "AggregateError", rb_cQuickjsRuntimeError);

rb_cQuickjsInterruptedError = rb_define_class_under(rb_mQuickjs, "InterruptedError", rb_cQuickjsRuntimeError);
rb_cQuickjsNoAwaitError = rb_define_class_under(rb_mQuickjs, "NoAwaitError", rb_cQuickjsRuntimeError);
}
26 changes: 25 additions & 1 deletion test/quickjs_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,34 @@ class ResultConversion < QuickjsTest
end

class Exceptions < QuickjsTest
test "throws an exception transparently" do
test "throws Quickjs::SyntaxError if SyntaxError happens" do
assert_raise_with_message(Quickjs::SyntaxError, /unexpected token in/) { ::Quickjs.eval_code("}{") }
end

test "throws Quickjs::TypeError if TypeError happens" do
assert_raise_with_message(Quickjs::TypeError, /not a function/) { ::Quickjs.eval_code("globalThis.func()") }
end

test "throws Quickjs::ReferenceError if ReferenceError happens" do
assert_raise_with_message(Quickjs::ReferenceError, /is not defined/) { ::Quickjs.eval_code("let a = undefinedVariable;") }
end

test "throws Quickjs::RangeError if RangeError happens" do
assert_raise_with_message(Quickjs::RangeError, /out of range/) { ::Quickjs.eval_code("throw new RangeError('out of range')") }
end

test "throws Quickjs::EvalError if EvalError happens" do
assert_raise_with_message(Quickjs::EvalError, /I am old/) { ::Quickjs.eval_code("throw new EvalError('I am old')") }
end

test "throws Quickjs::URIError if URIError happens" do
assert_raise_with_message(Quickjs::URIError, /expecting/) { ::Quickjs.eval_code("decodeURIComponent('%')") }
end

test "throws Quickjs::AggregateError if AggregateError happens" do
assert_raise_with_message(Quickjs::AggregateError, /aggregated/) { ::Quickjs.eval_code("throw new AggregateError([new Error('some error')], 'aggregated')") }
end

test "throws is awaited Promise is rejected" do
assert_raise_with_message(Quickjs::RuntimeError, /asynchronously sad/) do
::Quickjs.eval_code("const promise = new Promise((res) => { throw 'asynchronously sad' });await promise")
Expand Down

0 comments on commit 906293e

Please sign in to comment.