Skip to content

Commit

Permalink
Merge pull request #531 from ledsun/improve_errer_mesage_for_property
Browse files Browse the repository at this point in the history
Improve errer mesage for property
  • Loading branch information
kateinoigakukun committed Oct 1, 2024
2 parents d90b881 + ad4ba8a commit d5da762
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 16 deletions.
33 changes: 24 additions & 9 deletions packages/gems/js/lib/js.rb
Original file line number Diff line number Diff line change
Expand Up @@ -173,16 +173,13 @@ def method_missing(sym, *args, &block)
if sym_str.end_with?("?")
# When a JS method is called with a ? suffix, it is treated as a predicate method,
# and the return value is converted to a Ruby boolean value automatically.
result = self.call(sym_str[0..-2].to_sym, *args, &block)

result = invoke_js_method(sym_str[0..-2].to_sym, *args, &block)
# Type coerce the result to boolean type
# to match the true/false determination in JavaScript's if statement.
JS.global.Boolean(result) == JS::True
elsif self[sym].typeof == "function"
self.call(sym, *args, &block)
else
super
return JS.global.Boolean(result) == JS::True
end

invoke_js_method(sym, *args, &block)
end

# Check if a JavaScript method exists
Expand All @@ -195,10 +192,10 @@ def respond_to_missing?(sym, include_private)
self[sym].typeof == "function"
end

# Call the receiver (a JavaScript function) with `undefined` as its receiver context.
# Call the receiver (a JavaScript function) with `undefined` as its receiver context.
# This method is similar to JS::Object#call, but it is used to call a function that is not
# a method of an object.
#
#
# floor = JS.global[:Math][:floor]
# floor.apply(3.14) # => 3
# JS.global[:Promise].new do |resolve, reject|
Expand Down Expand Up @@ -239,6 +236,24 @@ def await
promise = JS.global[:Promise].resolve(self)
JS.promise_scheduler.await(promise)
end

private

# Invoke a JavaScript method
# If the property of JavaScritp object does not exist, raise a `NoMethodError`.
# If the property exists but is not a function, raise a `TypeError`.
def invoke_js_method(sym, *args, &block)
return self.call(sym, *args, &block) if self[sym].typeof == "function"

# Check to see if a non-functional property exists.
if JS.global[:Reflect].call(:has, self, sym.to_s) == JS::True
raise TypeError,
"`#{sym}` is not a function. To reference a property, use `[:#{sym}]` syntax instead."
end

raise NoMethodError,
"undefined method `#{sym}' for an instance of JS::Object"
end
end

# A wrapper class for JavaScript Error to allow the Error to be thrown in Ruby.
Expand Down
34 changes: 27 additions & 7 deletions packages/npm-packages/ruby-wasm-wasi/test/unit/test_object.rb
Original file line number Diff line number Diff line change
Expand Up @@ -310,13 +310,6 @@ def test_method_missing_with_block
assert_true block_called
end

def test_method_missing_with_undefined_method
object = JS.eval(<<~JS)
return { foo() { return true; } };
JS
assert_raise(NoMethodError) { object.bar }
end

def test_method_missing_with_?
object = JS.eval(<<~JS)
return {
Expand Down Expand Up @@ -344,6 +337,33 @@ def test_method_missing_with_?
assert_false object.return_empty_string?
end

def test_method_missing_with_property
object = JS.eval(<<~JS)
return { property: 42 };
JS

e = assert_raise(TypeError) { object.property }
assert_equal "`property` is not a function. To reference a property, use `[:property]` syntax instead.",
e.message

e = assert_raise(TypeError) { object.property? }
assert_equal "`property` is not a function. To reference a property, use `[:property]` syntax instead.",
e.message
end

def test_method_missing_with_undefined_method
object = JS.eval(<<~JS)
return { foo() { return true; } };
JS
e = assert_raise(NoMethodError) { object.bar }
assert_equal "undefined method `bar' for an instance of JS::Object",
e.message

e = assert_raise(NoMethodError) { object.bar? }
assert_equal "undefined method `bar' for an instance of JS::Object",
e.message
end

def test_respond_to_missing?
object = JS.eval(<<~JS)
return { foo() { return true; } };
Expand Down

0 comments on commit d5da762

Please sign in to comment.