[MacRuby-devel] [MacRuby] #594: Not all methods visible to objective-c calls

MacRuby ruby-noreply at macosforge.org
Thu Apr 22 00:51:19 PDT 2010


#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/>



More information about the MacRuby-devel mailing list