2008 12 05Sidestepping JavascriptCore's JSEvaluateScript
JSEvaluateScript
takes a parameter to use as the this
object, but it always uses the global object instead. Oups ! The bug is known and marked as fixed but unfortunately my version of JavascriptCore still fails.
Why use JSEvaluateScript
anyway ? A quick example : to know if your object (a JSObjectRef
) is an array, evaluate this.constructor == Array.prototype.constructor
with this
as your object and voilà ! JSValueToBoolean
will then give you the answer. If you couldn't do that, you'd have to get your object's constructor
property, then get a reference to the global Array
class, then get its prototype
property, then … well you get the idea. This kind of defeats the simpleness of Javascript :)
To work around that, create a quick anonymous function and call it. Instead of using this
to get to your object, pass it as an argument. Then return
your result.
JSStringRef scriptJS = JSStringCreateWithUTF8CString("return arguments[0].constructor == Array.prototype.constructor"); JSObjectRef fn = JSObjectMakeFunction(ctx, NULL, 0, NULL, scriptJS, NULL, 1, NULL); JSValueRef result = JSObjectCallAsFunction(ctx, fn, NULL, 1, (JSValueRef*)&jsObject, NULL);
It's anonymous, it specifies zero parameter names (therefore use arguments[0]
to get your object), and casts jsObject
to a C array of length 1 with (JSValueRef*)&jsObject
.
One benefit of using a function is using multiple arguments, eg a string and a pattern to match. Although at that point it may be better to have your functions in an external js file and call these.
And more good news : JSCocoa now bridges js arrays and js hashes toNSArray
and NSDictionary
. Therefore Core Animation code like layer.filters = [filter]
should work !