[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