#594: Not all methods visible to objective-c calls ------------------------------+--------------------------------------------- Reporter: michael@… | Owner: lsansonetti@… Type: defect | Status: new Priority: critical | Milestone: Component: MacRuby | Keywords: ------------------------------+--------------------------------------------- Changes (by martinlagardette@…): * priority: blocker => critical Old description:
The following code is taken from http://code.reflectivepixel.com/post/103638573/require-hotcocoa- framework-webkit-class and is just a short example of showing the problem:
{{{ require 'hotcocoa' framework 'webkit' class Application include HotCocoa FULL={:expand => [:width,:height]} BASE=<<-END <html><head><style type="text/css"> * { font-family: Monaco; } </style><script type="text/javascript"> function say(arg) { window.TheBridge.click(arg);} </script> </head><body><h3>Ruby JavaScript Bridge</h3> <a href="#" onclick="say('hi')">tell</a></body></html> END def click(arg) #called from javascript root = document.createElement("div"); root.innerHTML="javascript tells ruby: #{arg}" document.body.appendChild(root) end def document @web_view.mainFrame.DOMDocument end def self.webScriptNameForSelector(sel) #hide : in name sel.to_s.sub(/:$/,'') if is_available_selector?(sel) end def self.isSelectorExcludedFromWebScript(sel) ! is_available_selector?(sel) end def self.isKeyExcludedFromWebScript(key) true end def self.is_available_selector?(sel) ['click:'].include?(sel.to_s) end def start application :name => "MyBridge" do |app| app.delegate = self window :title => "MyBridge", :frame => [10, 620, 330, 230] do |win| win << @web_view=web_view(:layout => FULL) do |wv| wv.mainFrame.loadHTMLString BASE, baseURL: nil wv.frameLoadDelegate=self wso=wv.windowScriptObject #make visible to JS wso.setValue(self, forKey:"TheBridge") end win.will_close { exit } end end end end Application.new.start }}}
In this example, clicking on "tell" does not work. It seems, that the selector for "click:" is not found. When logging for example the selector values in {{{ self.isSelectorExcludedFromWebScript(sel) }}}, the "click:" selector is not amongst the results.
This is not related to hotcocoa, this example can be simply reworked without using hotcocoa, just with a simple WebView embedded in a NSWindow from Interface Builder.
New description: The following code is taken from http://code.reflectivepixel.com/post/103638573/require-hotcocoa-framework- webkit-class and is just a short example of showing the problem: {{{ #!ruby require 'hotcocoa' framework 'webkit' class Application include HotCocoa FULL={:expand => [:width,:height]} BASE=<<-END <html><head><style type="text/css"> * { font-family: Monaco; } </style><script type="text/javascript"> function say(arg) { window.TheBridge.click(arg);} </script> </head><body><h3>Ruby JavaScript Bridge</h3> <a href="#" onclick="say('hi')">tell</a></body></html> END def click(arg) #called from javascript root = document.createElement("div"); root.innerHTML="javascript tells ruby: #{arg}" document.body.appendChild(root) end def document @web_view.mainFrame.DOMDocument end def self.webScriptNameForSelector(sel) #hide : in name sel.to_s.sub(/:$/,'') if is_available_selector?(sel) end def self.isSelectorExcludedFromWebScript(sel) ! is_available_selector?(sel) end def self.isKeyExcludedFromWebScript(key) true end def self.is_available_selector?(sel) ['click:'].include?(sel.to_s) end def start application :name => "MyBridge" do |app| app.delegate = self window :title => "MyBridge", :frame => [10, 620, 330, 230] do |win| win << @web_view=web_view(:layout => FULL) do |wv| wv.mainFrame.loadHTMLString BASE, baseURL: nil wv.frameLoadDelegate=self wso=wv.windowScriptObject #make visible to JS wso.setValue(self, forKey:"TheBridge") end win.will_close { exit } end end end end Application.new.start }}} In this example, clicking on "tell" does not work. It seems, that the selector for "click:" is not found. When logging for example the selector values in {{{ self.isSelectorExcludedFromWebScript(sel) }}} the "click:" selector is not amongst the results. This is not related to hotcocoa, this example can be simply reworked without using hotcocoa, just with a simple WebView embedded in a NSWindow from Interface Builder. -- Comment: I confirm this is not related to HotCocoa. I created a MacRuby project with Xcode + IB, set up a WebKit view, and the issue is happening. The problem comes from how MacRuby handles resolving methods compared to how WebKit retrieves an object's callable methods. For performance reason, MacRuby doesn't register all methods in the ObjC runtime at boot time, and only register them once they are resolved at runtime. This will be changed in a future version (either 0.7 or greater). The workaround for the moment is to call `object.methodSignatureForSelector("method:")`, which will JIT the method, insert it in the ObjC runtime, thus making it visible to WebKit. Attached is the test project (to show it's not related to HotCocoa, and for further resolution). -- Ticket URL: <http://www.macruby.org/trac/ticket/594#comment:1> MacRuby <http://macruby.org/>