+void CYThrow(JSContextRef ctx, JSValueRef value) {
+ if (value == NULL)
+ return;
+ @throw CYCastNSObject(ctx, value);
+}
+
+JSValueRef CYCastJSValue(JSContextRef ctx, id value) {
+ return [value cy$JSValueInContext:ctx];
+}
+
+JSStringRef CYCopyJSString(JSContextRef ctx, id value) {
+ return JSStringCreateWithCFString(reinterpret_cast<CFStringRef>([value description]));
+}
+
+@implementation CY$JSObject
+
+- (id) initWithJSObject:(JSObjectRef)object inContext:(JSContextRef)context {
+ if ((self = [super init]) != nil) {
+ object_ = object;
+ context_ = context;
+ } return self;
+}
+
+- (NSUInteger) count {
+ JSPropertyNameArrayRef names(JSObjectCopyPropertyNames(context_, object_));
+ size_t size(JSPropertyNameArrayGetCount(names));
+ JSPropertyNameArrayRelease(names);
+ return size;
+}
+
+- (id) objectForKey:(id)key {
+ JSValueRef exception(NULL);
+ JSStringRef string(CYCopyJSString(context_, key));
+ JSValueRef value(JSObjectGetProperty(context_, object_, string, &exception));
+ JSStringRelease(string);
+ CYThrow(context_, exception);
+ return CYCastNSObject(context_, value);
+}
+
+- (NSEnumerator *) keyEnumerator {
+ JSPropertyNameArrayRef names(JSObjectCopyPropertyNames(context_, object_));
+ NSEnumerator *enumerator([CYCastNSArray(names) objectEnumerator]);
+ JSPropertyNameArrayRelease(names);
+ return enumerator;
+}
+
+- (void) setObject:(id)object forKey:(id)key {
+ JSValueRef exception(NULL);
+ JSStringRef string(CYCopyJSString(context_, key));
+ JSObjectSetProperty(context_, object_, string, CYCastJSValue(context_, object), kJSPropertyAttributeNone, &exception);
+ JSStringRelease(string);
+ CYThrow(context_, exception);
+}
+
+- (void) removeObjectForKey:(id)key {
+ JSValueRef exception(NULL);
+ JSStringRef string(CYCopyJSString(context_, key));
+ // XXX: this returns a bool
+ JSObjectDeleteProperty(context_, object_, string, &exception);
+ JSStringRelease(string);
+ CYThrow(context_, exception);
+}
+
+@end
+