@@ -173,16 +173,13 @@ def method_missing(sym, *args, &block)
173173 if sym_str . end_with? ( "?" )
174174 # When a JS method is called with a ? suffix, it is treated as a predicate method,
175175 # and the return value is converted to a Ruby boolean value automatically.
176- result = self . call ( sym_str [ 0 ..-2 ] . to_sym , *args , &block )
177-
176+ result = invoke_js_method ( sym_str [ 0 ..-2 ] . to_sym , *args , &block )
178177 # Type coerce the result to boolean type
179178 # to match the true/false determination in JavaScript's if statement.
180- JS . global . Boolean ( result ) == JS ::True
181- elsif self [ sym ] . typeof == "function"
182- self . call ( sym , *args , &block )
183- else
184- super
179+ return JS . global . Boolean ( result ) == JS ::True
185180 end
181+
182+ invoke_js_method ( sym , *args , &block )
186183 end
187184
188185 # Check if a JavaScript method exists
@@ -195,10 +192,10 @@ def respond_to_missing?(sym, include_private)
195192 self [ sym ] . typeof == "function"
196193 end
197194
198- # Call the receiver (a JavaScript function) with `undefined` as its receiver context.
195+ # Call the receiver (a JavaScript function) with `undefined` as its receiver context.
199196 # This method is similar to JS::Object#call, but it is used to call a function that is not
200197 # a method of an object.
201- #
198+ #
202199 # floor = JS.global[:Math][:floor]
203200 # floor.apply(3.14) # => 3
204201 # JS.global[:Promise].new do |resolve, reject|
@@ -239,6 +236,24 @@ def await
239236 promise = JS . global [ :Promise ] . resolve ( self )
240237 JS . promise_scheduler . await ( promise )
241238 end
239+
240+ private
241+
242+ # Invoke a JavaScript method
243+ # If the property of JavaScritp object does not exist, raise a `NoMethodError`.
244+ # If the property exists but is not a function, raise a `TypeError`.
245+ def invoke_js_method ( sym , *args , &block )
246+ return self . call ( sym , *args , &block ) if self [ sym ] . typeof == "function"
247+
248+ # Check to see if a non-functional property exists.
249+ if JS . global [ :Reflect ] . call ( :has , self , sym . to_s ) == JS ::True
250+ raise TypeError ,
251+ "`#{ sym } ` is not a function. To reference a property, use `[:#{ sym } ]` syntax instead."
252+ end
253+
254+ raise NoMethodError ,
255+ "undefined method `#{ sym } ' for an instance of JS::Object"
256+ end
242257end
243258
244259# A wrapper class for JavaScript Error to allow the Error to be thrown in Ruby.
0 commit comments