Skip to content

Commit 3d60e16

Browse files
Stop responding to methods not defined in JS object
When passing JS::Object to `Kernel.puts`, it tries to convert the object to `Array` by `to_ary`. `JS::Object` pretended to be able to respond to `to_ary` without any check, but the inner JS Object doesn't have such method, so it caused mysterious error. This patch adds `JS::Object#respond_to_missing?` definition to avoid calling undefined method through `#method_missing`.
1 parent 7ae7778 commit 3d60e16

File tree

3 files changed

+29
-3
lines changed

3 files changed

+29
-3
lines changed

ext/js/lib/js.rb

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
11
require "js.so"
22

33
class JS::Object
4-
def method_missing(name, *args, &block)
5-
self.call(name, *args, &block)
4+
def method_missing(sym, *args, &block)
5+
if self[sym].typeof == "function"
6+
self.call(sym, *args, &block)
7+
else
8+
super
9+
end
10+
end
11+
12+
def respond_to_missing?(sym, include_private)
13+
return true if super
14+
self[sym].typeof == "function"
615
end
716
end

packages/npm-packages/ruby-wasm-wasi/test/package.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,5 +51,5 @@ describe("Packaging validation", () => {
5151
const mod = await WebAssembly.compile(binary.buffer);
5252
const nameSections = WebAssembly.Module.customSections(mod, "name");
5353
expect(nameSections.length).toBe(1);
54-
})
54+
});
5555
});
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { initRubyVM } from "./../init";
2+
3+
describe("JS::Object", () => {
4+
jest.setTimeout(10 /*sec*/ * 1000);
5+
describe("#method_missing", () => {
6+
test("raise NoMethodError if method is not defined in JS", async () => {
7+
const vm = await initRubyVM();
8+
const obj = vm.eval(`
9+
require 'js'
10+
obj = JS.eval(<<~JS)
11+
return { foo() { return true; } };
12+
JS
13+
`);
14+
expect(() => obj.call("bar")).toThrowError();
15+
});
16+
});
17+
});

0 commit comments

Comments
 (0)