在AHK中,可以使用以下代码将AHK函数注入Internet Explorer的JavaScript引擎:
#Persistent
html =
(
<html>
<head>
<script>
document.setVar = function`(name,val`){
document[name]=val;
}
</script>
</head>
<body>
<h1>Hello!</h1>
</body>
</html>
)
ie := ComObjCreate("InternetExplorer.Application")
ie.navigate("about:blank")
sleep, 2000
msgbox, %html%
ie.document.writeln(html)
ie.visible := true
ie.document.setVar("someFunc",Func("someFunc"))
someFunc(){
msgbox, "hello"
}
注入函数后,JavaScript可以调用document.someFunc()
,这将导致JavaScript调用AHK函数,并最终运行消息框。
我想将此代码移植到Ruby。到目前为止,我有这个:
require 'win32ole'
ie = WIN32OLE.new('InternetExplorer.Application')
ie.navigate("about:blank")
sleep(0.1) until !ie.busy
html = <<Heredoc
<html>
<head>
<script>
document.setVar = function(name,val){
document[name]=val;
}
</script>
</head>
<body>
<h1>Hello!</h1>
</body>
</html>
Heredoc
ie.document.writeln(html)
ie.visible = true
现在我们在这里应该可以注入Ruby方法,但是目前我不知道如何实现此方法。每次尝试尝试时,JavaScript引擎都会冻结。我尝试过的一些事情:
ie.document.setVar("someFunc",method(:someFunc))
#----------------------------------
ie.document.setVar("someFunc",->{puts "hello"})
#----------------------------------
class someClass
def someFunc
puts "hello"
end
end
ie.document.setVar("someClass",someClass})
#----------------------------------
closure = Class.new(Fiddle::Closure) {
def call
puts "hello world"
end
}.new(Fiddle::TYPE_INT,[])
someFunc = Fiddle::Function.new(closure, [], Fiddle::TYPE_INT)
#Both:
doc.setVar("someFunc",closure)
#and
doc.setVar("someFunc",someFunc)
#----------------------------------
以上方法均无效。最后,他们最终都冻结了JavaScript引擎...有人知道我如何将对Ruby函数的实际引用传递给JavaScript吗?
答案 0 :(得分:0)
经过一周的搜索,我什么都没找到,我想:“如果我们天真并传递一个定义了method_missing
的对象,该怎么办?”
30分钟后,我可以从JavaScript调用Ruby。
class MyFunc
# Called when no arguments are passed to JavaScript function
def call
#Execute any ruby code here!!
#You can also return values back to JavaScript!!
return 1
end
# Called when arguments are passed to JavaScript function
def value(*args)
if args.length == 0
# This will be called if the function is called without parenthesis in JS
# e.g. console.log(document.someFunc)
return nil
else
#This is called with the parsed arguments. Note: Functions passed in from JS are of type WIN32OLE. Theoretically this should be callable, but better would be to make a JS function which can call other JS functions
#Execute any ruby code here!!
puts "#{args.inspect}"
#Can also return values here as well
return 1
end
end
end
ie.document.setVar("myFunc",MyFunc.new})
您还可以初始化和访问实例变量:
class MyClass
def initialize
@hello = "world"
end
end
ie.document.setVar("myClass",MyClass.new})
#IN IE: document.myClass["hello"] //=> "world"
注意:
某些事情可能会严重出错,甚至导致红宝石崩溃。某些不起作用的示例:
document.myObj
。 JavaScript会将函数解释为Object,也许就像人们期望的那样。document.myObj["hello"]
。document.myObj["hello"]=1
。有些事情根本没有意义,例如,我做了以下循环:
上课:
class MyClass
def call
puts "Call"
end
def method_missing(m,*args,&block)
puts "#{m}(#{args.inspect})"
end
end
ie.document.setVar("obj",MyClass.new)
和JavaScript:
for(var i=0;i<24;i++){
document.obj[chars[i]]()
}
这将执行以字母字符命名的obj的所有功能。确实,它在大多数情况下都这样做,但是有时却没有。有时它将调用主要的call
方法,而在document.obj.j()
的情况下,它将什么都不做...
完整日志:
a([])
b([])
c([])
d([])
e([])
f([])
Hello world
h([])
i([])
k([])
Hello world
m([])
n([])
o([])
q([])
s([])
t([])
Hello world
v([])
w([])
x([])
y([])
Hello world
编辑
I've written a GIST,这通常更容易实现。例如。要将File
对象传递给IE,您可以执行以下操作:
ie.document.setVar("RubyFile",WIN32OLE::getDispatch(File))