I have two JSContexts, and I want to swap JSValues between them from time to time. However, I'm having difficulty moving a JSValue to a new context, if that's possible.
I'm trying this:
newContext[@"newValue"] = [JSValue valueWithObject:newValue inContext:newContext];
While the new context now has that value, the value still retains its old context. Unfortunately, it still retains its old context. Any suggestions?
I suggest you extract the value of the JSValue from its old javascript context into an ordinary objective-c object before creating the new JSValue in the new context. Looking at JSValue.h shows that the JSValue class has a read-only property that holds the JSContext that the value originates from.
I can't tell what type of value you are dealing with from your code above, but for example (for simple types):
NSString *newString = [newValue toString]; // Extract from old JSValue
newContext[@"newValue"] = newString;
or for a more complex object:
@protocol MyPointExports <JSExport>
@property double x;
@property double y;
@end
@interface MyPoint : NSObject <MyPointExports>
// Put methods and properties not visible to JavaScript code here.
@end
newcontext[@"MyPoint"] = [MyPoint class]; // Define the class in Javascript
...
MyPoint *p = [newValue toObject]; // Extract from old JSValue
newContext[@"newValue"] = p;
Note that the value will still exist in the old JSContext (the old JSContext will remain alive whilst the old value is retained). You may want to remove this reference by:
oldContext[@"oldValue"] = nil; // Assuming the var in the oldContext was called oldValue
Note also that you don't need to use the constructor:
+ (JSValue *)valueWithObject:(id)value inContext:(JSContext *)context;
since JavaScriptCore has built-in conversion for the following (see JSValue.h):
Objective-C type | JavaScript type
--------------------+---------------------
nil | undefined
NSNull | null
NSString | string
NSNumber | number, boolean
NSDictionary | Object object
NSArray | Array object
NSDate | Date object
NSBlock * | Function object *
id ** | Wrapper object **
Class *** | Constructor object ***
* Instances of NSBlock with supported arguments types will be presented to
JavaScript as a callable Function object. For more information on supported
argument types see JSExport.h. If a JavaScript Function originating from an
Objective-C block is converted back to an Objective-C object the block will
be returned. All other JavaScript functions will be converted in the same
manner as a JavaScript object of type Object.
** For Objective-C instances that do not derive from the set of types listed
above, a wrapper object to provide a retaining handle to the Objective-C
instance from JavaScript. For more information on these wrapper objects, see
JSExport.h. When a JavaScript wrapper object is converted back to Objective-C
the Objective-C instance being retained by the wrapper is returned.
*** For Objective-C Class objects a constructor object containing exported
class methods will be returned. See JSExport.h for more information on
constructor objects.