X-Git-Url: https://git.saurik.com/cycript.git/blobdiff_plain/77f56624a75e39b19c72e6076e46e230ce3abbb1..9ec7dd188b51ba8245b33ed23be1a6202a0e749b:/ObjectiveC/Library.mm diff --git a/ObjectiveC/Library.mm b/ObjectiveC/Library.mm index a113779..5863e95 100644 --- a/ObjectiveC/Library.mm +++ b/ObjectiveC/Library.mm @@ -246,6 +246,7 @@ static JSClassRef FunctionInstance_; static JSClassRef ObjectInstance_; static JSClassRef StringInstance_; +static JSClassRef Class_; static JSClassRef Internal_; static JSClassRef Message_; static JSClassRef Messages_; @@ -290,9 +291,11 @@ Type_privateData *Selector_privateData::GetType() const { static JSValueRef Instance_callAsFunction_toString(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception); -JSValueRef CYGetClassPrototype(JSContextRef context, id self) { +JSValueRef CYGetClassPrototype(JSContextRef context, Class self, bool meta) { if (self == nil) return CYGetCachedObject(context, CYJSString("Instance_prototype")); + else if (meta && !class_isMetaClass(self)) + return CYGetCachedObject(context, CYJSString("Class_prototype")); JSObjectRef global(CYGetGlobalObject(context)); JSObjectRef cy(CYCastJSObject(context, CYGetProperty(context, global, cy_s))); @@ -317,7 +320,7 @@ JSValueRef CYGetClassPrototype(JSContextRef context, id self) { else if (self == NSString_) prototype = CYGetCachedObject(context, CYJSString("StringInstance_prototype")); else - prototype = CYGetClassPrototype(context, class_getSuperclass(self)); + prototype = CYGetClassPrototype(context, class_getSuperclass(self), meta); JSObjectRef object(JSObjectMake(context, _class, NULL)); JSObjectSetPrototype(context, object, prototype); @@ -326,14 +329,14 @@ JSValueRef CYGetClassPrototype(JSContextRef context, id self) { return object; } -JSObjectRef Messages::Make(JSContextRef context, Class _class, bool array) { +_finline JSValueRef CYGetClassPrototype(JSContextRef context, Class self) { + return CYGetClassPrototype(context, self, class_isMetaClass(self)); +} + +JSObjectRef Messages::Make(JSContextRef context, Class _class) { JSObjectRef value(JSObjectMake(context, Messages_, new Messages(_class))); - if (_class == NSArray_) - array = true; if (Class super = class_getSuperclass(_class)) - JSObjectSetPrototype(context, value, Messages::Make(context, super, array)); - /*else if (array) - JSObjectSetPrototype(context, value, Array_prototype_);*/ + JSObjectSetPrototype(context, value, Messages::Make(context, super)); return value; } @@ -394,11 +397,12 @@ JSObjectRef CYMakeInstance(JSContextRef context, id object, bool transient) { - (JSValueRef) cy$valueOfInContext:(JSContextRef)context; - (JSType) cy$JSType; -- (NSObject *) cy$toJSON:(NSString *)key; +- (JSValueRef) cy$toJSON:(NSString *)key inContext:(JSContextRef)context; - (NSString *) cy$toCYON:(bool)objective; - (bool) cy$hasProperty:(NSString *)name; - (NSObject *) cy$getProperty:(NSString *)name; +- (JSValueRef) cy$getProperty:(NSString *)name inContext:(JSContextRef)context; - (bool) cy$setProperty:(NSString *)name to:(NSObject *)value; - (bool) cy$deleteProperty:(NSString *)name; - (void) cy$getPropertyNames:(JSPropertyNameAccumulatorRef)names inContext:(JSContextRef)context; @@ -538,12 +542,6 @@ struct PropertyAttributes { }; #endif -#ifdef __APPLE__ -NSObject *NSCFType$cy$toJSON(id self, SEL sel, NSString *key) { - return [(NSString *) CFCopyDescription((CFTypeRef) self) autorelease]; -} -#endif - #ifndef __APPLE__ @interface CYWebUndefined : NSObject { } @@ -572,8 +570,6 @@ NSObject *NSCFType$cy$toJSON(id self, SEL sel, NSString *key) { - (id) initWithJSObject:(JSObjectRef)object inContext:(JSContextRef)context; -- (NSObject *) cy$toJSON:(NSString *)key; - - (NSUInteger) count; - (id) objectForKey:(id)key; - (NSEnumerator *) keyEnumerator; @@ -602,6 +598,10 @@ NSObject *NSCFType$cy$toJSON(id self, SEL sel, NSString *key) { @end /* }}} */ +_finline bool CYJSValueIsNSObject(JSContextRef context, JSValueRef value) { + return JSValueIsObjectOfClass(context, value, Instance_); +} + _finline bool CYJSValueIsInstanceOfCachedConstructor(JSContextRef context, JSValueRef value, JSStringRef cache) { JSValueRef exception(NULL); JSObjectRef constructor(CYGetCachedObject(context, cache)); @@ -611,7 +611,7 @@ _finline bool CYJSValueIsInstanceOfCachedConstructor(JSContextRef context, JSVal } NSObject *CYCastNSObject(apr_pool_t *pool, JSContextRef context, JSObjectRef object) { - if (JSValueIsObjectOfClass(context, object, Instance_)) { + if (CYJSValueIsNSObject(context, object)) { Instance *internal(reinterpret_cast(JSObjectGetPrivate(object))); return internal->GetValue(); } @@ -738,15 +738,6 @@ NSObject *CYCopyNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef valu } - (NSObject *) cy$getProperty:(NSString *)name { - if ([name isEqualToString:@"length"]) { - NSUInteger count([self count]); -#ifdef __APPLE__ - return [NSNumber numberWithUnsignedInteger:count]; -#else - return [NSNumber numberWithUnsignedInt:count]; -#endif - } - size_t index(CYGetIndex(name)); if (index == _not(size_t) || index >= [self count]) return [super cy$getProperty:name]; @@ -754,6 +745,15 @@ NSObject *CYCopyNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef valu return [self objectAtIndex:index]; } +- (JSValueRef) cy$getProperty:(NSString *)name inContext:(JSContextRef)context { + CYObjectiveTry_(context) { + if ([name isEqualToString:@"length"]) + return CYCastJSValue(context, [self count]); + } CYObjectiveCatch + + return [super cy$getProperty:name inContext:context]; +} + - (void) cy$getPropertyNames:(JSPropertyNameAccumulatorRef)names inContext:(JSContextRef)context { [super cy$getPropertyNames:names inContext:context]; @@ -788,10 +788,6 @@ NSObject *CYCopyNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef valu return kJSTypeBoolean; } -- (NSObject *) cy$toJSON:(NSString *)key { - return self; -} - - (NSString *) cy$toCYON:(bool)objective { NSString *value([self boolValue] ? @"true" : @"false"); return objective ? value : [NSString stringWithFormat:@"@%@", value]; @@ -949,10 +945,6 @@ NSObject *CYCopyNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef valu return kJSTypeNumber; } -- (NSObject *) cy$toJSON:(NSString *)key { - return self; -} - - (NSString *) cy$toCYON:(bool)objective { NSString *value([self cy$JSType] != kJSTypeBoolean ? [self stringValue] : [self boolValue] ? @"true" : @"false"); return objective ? value : [NSString stringWithFormat:@"@%@", value]; @@ -971,15 +963,15 @@ NSObject *CYCopyNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef valu return kJSTypeNull; } -- (NSObject *) cy$toJSON:(NSString *)key { - return self; -} - - (NSString *) cy$toCYON:(bool)objective { NSString *value(@"null"); return objective ? value : [NSString stringWithFormat:@"@%@", value]; } +- (JSValueRef) cy$valueOfInContext:(JSContextRef)context { CYObjectiveTry_(context) { + return CYJSNull(context); +} CYObjectiveCatch } + @end /* }}} */ /* Bridge: NSObject {{{ */ @@ -989,6 +981,10 @@ NSObject *CYCopyNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef valu return self; } +- (JSValueRef) cy$toJSON:(NSString *)key inContext:(JSContextRef)context { + return [self cy$valueOfInContext:context]; +} + - (JSValueRef) cy$valueOfInContext:(JSContextRef)context { CYObjectiveTry_(context) { return NULL; } CYObjectiveCatch } @@ -997,12 +993,8 @@ NSObject *CYCopyNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef valu return kJSTypeObject; } -- (NSObject *) cy$toJSON:(NSString *)key { - return [self description]; -} - - (NSString *) cy$toCYON:(bool)objective { - return [[self cy$toJSON:@""] cy$toCYON:objective]; + return [[self description] cy$toCYON:objective]; } - (bool) cy$hasProperty:(NSString *)name { @@ -1013,6 +1005,12 @@ NSObject *CYCopyNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef valu return nil; } +- (JSValueRef) cy$getProperty:(NSString *)name inContext:(JSContextRef)context { CYObjectiveTry_(context) { + if (NSObject *value = [self cy$getProperty:name]) + return CYCastJSValue(context, value); + return NULL; +} CYObjectiveCatch } + - (bool) cy$setProperty:(NSString *)name to:(NSObject *)value { return false; } @@ -1033,12 +1031,8 @@ NSObject *CYCopyNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef valu /* Bridge: NSProxy {{{ */ @implementation NSProxy (Cycript) -- (NSObject *) cy$toJSON:(NSString *)key { - return [self description]; -} - - (NSString *) cy$toCYON:(bool)objective { - return [[self cy$toJSON:@""] cy$toCYON:objective]; + return [[self description] cy$toCYON:objective]; } @end @@ -1054,10 +1048,6 @@ NSObject *CYCopyNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef valu return kJSTypeString; } -- (NSObject *) cy$toJSON:(NSString *)key { - return self; -} - - (NSString *) cy$toCYON:(bool)objective { std::ostringstream str; if (!objective) @@ -1069,9 +1059,6 @@ NSObject *CYCopyNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef valu } - (bool) cy$hasProperty:(NSString *)name { - if ([name isEqualToString:@"length"]) - return true; - size_t index(CYGetIndex(name)); if (index == _not(size_t) || index >= [self length]) return [super cy$hasProperty:name]; @@ -1080,15 +1067,6 @@ NSObject *CYCopyNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef valu } - (NSObject *) cy$getProperty:(NSString *)name { - if ([name isEqualToString:@"length"]) { - NSUInteger count([self length]); -#ifdef __APPLE__ - return [NSNumber numberWithUnsignedInteger:count]; -#else - return [NSNumber numberWithUnsignedInt:count]; -#endif - } - size_t index(CYGetIndex(name)); if (index == _not(size_t) || index >= [self length]) return [super cy$getProperty:name]; @@ -1106,11 +1084,6 @@ NSObject *CYCopyNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef valu } } -// XXX: this might be overly restrictive for NSString; I think I need a half-way between /injecting/ implicit properties and /accepting/ implicit properties -+ (bool) cy$hasImplicitProperties { - return false; -} - - (JSValueRef) cy$valueOfInContext:(JSContextRef)context { CYObjectiveTry_(context) { return CYCastJSValue(context, CYJSString(context, self)); } CYObjectiveCatch } @@ -1124,11 +1097,7 @@ NSObject *CYCopyNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef valu return kJSTypeUndefined; } -- (NSObject *) cy$toJSON:(NSString *)key { - return self; -} - -- (NSString *) cy$toCYON { +- (NSString *) cy$toCYON:(bool)objective { NSString *value(@"undefined"); return value; // XXX: maybe use the below code, adding @undefined? //return objective ? value : [NSString stringWithFormat:@"@%@", value]; @@ -1143,8 +1112,7 @@ NSObject *CYCopyNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef valu static bool CYIsClass(id self) { #ifdef __APPLE__ - // XXX: this is a lame object_isClass - return class_getInstanceMethod(object_getClass(self), @selector(alloc)) != NULL; + return class_isMetaClass(object_getClass(self)); #else return GSObjCIsClass(self); #endif @@ -1191,18 +1159,6 @@ JSValueRef CYCastJSValue(JSContextRef context, NSObject *value) { CYPoolTry { [super dealloc]; } CYObjectiveCatch } -- (NSObject *) cy$toJSON:(NSString *)key { CYObjectiveTry { - JSValueRef toJSON(CYGetProperty(context_, object_, toJSON_s)); - if (!CYIsCallable(context_, toJSON)) - return [super cy$toJSON:key]; - else { - JSValueRef arguments[1] = {CYCastJSValue(context_, key)}; - JSValueRef value(CYCallAsFunction(context_, (JSObjectRef) toJSON, object_, 1, arguments)); - // XXX: do I really want an NSNull here?! - return CYCastNSObject(NULL, context_, value) ?: [NSNull null]; - } -} CYObjectiveCatch } - - (NSString *) cy$toCYON:(bool)objective { CYObjectiveTry { CYPool pool; JSValueRef exception(NULL); @@ -1529,21 +1485,13 @@ static const char *CYPoolTypeEncoding(apr_pool_t *pool, JSContextRef context, SE return NULL; } -static void MessageClosure_(ffi_cif *cif, void *result, void **arguments, void *arg) { - Closure_privateData *internal(reinterpret_cast(arg)); - - JSContextRef context(internal->context_); - - size_t count(internal->cif_.nargs); - JSValueRef values[count]; - - for (size_t index(0); index != count; ++index) - values[index] = CYFromFFI(context, internal->signature_.elements[1 + index].type, internal->cif_.arg_types[index], arguments[index]); - +static JSValueRef MessageAdapter_(JSContextRef context, size_t count, JSValueRef values[], JSObjectRef function) { JSObjectRef _this(CYCastJSObject(context, values[0])); + return CYCallAsFunction(context, function, _this, count - 2, values + 2); +} - JSValueRef value(CYCallAsFunction(context, internal->function_, _this, count - 2, values + 2)); - CYPoolFFI(NULL, context, internal->signature_.elements[0].type, internal->cif_.rtype, result, value); +static void MessageClosure_(ffi_cif *cif, void *result, void **arguments, void *arg) { + CYExecuteClosure(cif, result, arguments, arg, &MessageAdapter_); } static JSObjectRef CYMakeMessage(JSContextRef context, SEL sel, IMP imp, const char *type) { @@ -1721,8 +1669,8 @@ static JSValueRef Instance_getProperty(JSContextRef context, JSObjectRef object, return value; CYPoolTry { - if (NSObject *data = [self cy$getProperty:name]) - return CYCastJSValue(context, data); + if (JSValueRef value = [self cy$getProperty:name inContext:context]) + return value; } CYPoolCatch(NULL) const char *string(CYPoolCString(pool, context, name)); @@ -1958,7 +1906,7 @@ static bool Instance_hasInstance(JSContextRef context, JSObjectRef constructor, if (!CYIsClass(_class)) return false; - if (JSValueIsObjectOfClass(context, instance, Instance_)) { + if (CYJSValueIsNSObject(context, instance)) { Instance *linternal(reinterpret_cast(JSObjectGetPrivate((JSObjectRef) instance))); // XXX: this isn't always safe return [linternal->GetValue() isKindOfClass:_class]; @@ -2276,7 +2224,7 @@ static JSValueRef $objc_msgSend(JSContextRef context, JSObjectRef object, JSObje self = internal->GetValue(); _class = internal->class_;; uninitialized = false; - } else if (JSValueIsObjectOfClass(context, arguments[0], Instance_)) { + } else if (CYJSValueIsNSObject(context, arguments[0])) { Instance *internal(reinterpret_cast(JSObjectGetPrivate((JSObjectRef) arguments[0]))); self = internal->GetValue(); _class = nil; @@ -2388,7 +2336,7 @@ static JSValueRef Instance_getProperty_messages(JSContextRef context, JSObjectRe } static JSValueRef Instance_callAsFunction_toCYON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { - if (!JSValueIsObjectOfClass(context, _this, Instance_)) + if (!CYJSValueIsNSObject(context, _this)) return NULL; Instance *internal(reinterpret_cast(JSObjectGetPrivate(_this))); @@ -2396,10 +2344,11 @@ static JSValueRef Instance_callAsFunction_toCYON(JSContextRef context, JSObjectR } CYCatch } static JSValueRef Instance_callAsFunction_toJSON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { - if (!JSValueIsObjectOfClass(context, _this, Instance_)) + if (!CYJSValueIsNSObject(context, _this)) return NULL; Instance *internal(reinterpret_cast(JSObjectGetPrivate(_this))); + id value(internal->GetValue()); CYPoolTry { NSString *key; @@ -2407,13 +2356,18 @@ static JSValueRef Instance_callAsFunction_toJSON(JSContextRef context, JSObjectR key = nil; else key = CYCastNSString(NULL, context, CYJSString(context, arguments[0])); - // XXX: check for support of cy$toJSON? - return CYCastJSValue(context, CYJSString(context, [internal->GetValue() cy$toJSON:key])); + + if (!CYImplements(value, object_getClass(value), @selector(cy$toJSON:inContext:))) + return CYJSUndefined(context); + else if (JSValueRef json = [value cy$toJSON:key inContext:context]) + return json; + else + return CYCastJSValue(context, CYJSString(context, [value description])); } CYPoolCatch(NULL) } CYCatch return /*XXX*/ NULL; } static JSValueRef Instance_callAsFunction_valueOf(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { - if (!JSValueIsObjectOfClass(context, _this, Instance_)) + if (!CYJSValueIsNSObject(context, _this)) return NULL; Instance *internal(reinterpret_cast(JSObjectGetPrivate(_this))); @@ -2429,7 +2383,7 @@ static JSValueRef Instance_callAsFunction_valueOf(JSContextRef context, JSObject } CYCatch return /*XXX*/ NULL; } static JSValueRef Instance_callAsFunction_toPointer(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { - if (!JSValueIsObjectOfClass(context, _this, Instance_)) + if (!CYJSValueIsNSObject(context, _this)) return NULL; Instance *internal(reinterpret_cast(JSObjectGetPrivate(_this))); @@ -2438,21 +2392,40 @@ static JSValueRef Instance_callAsFunction_toPointer(JSContextRef context, JSObje } CYCatch return /*XXX*/ NULL; } static JSValueRef Instance_callAsFunction_toString(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { - if (!JSValueIsObjectOfClass(context, _this, Instance_)) + if (!CYJSValueIsNSObject(context, _this)) return NULL; Instance *internal(reinterpret_cast(JSObjectGetPrivate(_this))); id value(internal->GetValue()); - if (value == nil) - return CYCastJSValue(context, "nil"); - CYPoolTry { // XXX: this seems like a stupid implementation; what if it crashes? why not use the CYONifier backend? return CYCastJSValue(context, CYJSString(context, [value description])); } CYPoolCatch(NULL) } CYCatch return /*XXX*/ NULL; } +static JSValueRef Class_callAsFunction_pointerTo(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { + if (!CYJSValueIsNSObject(context, _this)) + return NULL; + + Instance *internal(reinterpret_cast(JSObjectGetPrivate(_this))); + id value(internal->GetValue()); + + if (!CYIsClass(value)) + CYThrow("non-Class object cannot be used as Type"); + + // XXX: this is a very silly implementation + + std::ostringstream type; + type << "@\""; + type << class_getName(value); + type << "\""; + + CYPoolTry { + return CYMakeType(context, type.str().c_str()); + } CYPoolCatch(NULL) +} CYCatch return /*XXX*/ NULL; } + static JSValueRef Selector_callAsFunction_toString(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { Selector_privateData *internal(reinterpret_cast(JSObjectGetPrivate(_this))); return CYCastJSValue(context, sel_getName(internal->GetValue())); @@ -2515,6 +2488,11 @@ static JSStaticFunction Instance_staticFunctions[7] = { {NULL, NULL, 0} }; +static JSStaticFunction Class_staticFunctions[2] = { + {"pointerTo", &Class_callAsFunction_pointerTo, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {NULL, NULL, 0} +}; + static JSStaticFunction Internal_staticFunctions[2] = { {"$cya", &Internal_callAsFunction_$cya, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {NULL, NULL, 0} @@ -2528,6 +2506,12 @@ static JSStaticFunction Selector_staticFunctions[5] = { {NULL, NULL, 0} }; +#ifdef __APPLE__ +JSValueRef NSCFType$cy$toJSON$inContext$(id self, SEL sel, JSValueRef key, JSContextRef context) { CYObjectiveTry_(context) { + return CYCastJSValue(context, [(NSString *) CFCopyDescription((CFTypeRef) self) autorelease]); +} CYObjectiveCatch } +#endif + void CYObjectiveC_Initialize() { /*XXX*/ JSContextRef context(NULL); CYPoolTry { $objc_setAssociatedObject = reinterpret_cast(dlsym(RTLD_DEFAULT, "objc_setAssociatedObject")); $objc_getAssociatedObject = reinterpret_cast(dlsym(RTLD_DEFAULT, "objc_getAssociatedObject")); @@ -2578,14 +2562,19 @@ void CYObjectiveC_Initialize() { /*XXX*/ JSContextRef context(NULL); CYPoolTry { definition.className = "ArrayInstance"; ArrayInstance_ = JSClassCreate(&definition); + definition.className = "FunctionInstance"; + FunctionInstance_ = JSClassCreate(&definition); + definition.className = "ObjectInstance"; ObjectInstance_ = JSClassCreate(&definition); definition.className = "StringInstance"; StringInstance_ = JSClassCreate(&definition); - definition.className = "FunctionInstance"; - FunctionInstance_ = JSClassCreate(&definition); + definition = kJSClassDefinitionEmpty; + definition.className = "Class"; + definition.staticFunctions = Class_staticFunctions; + Class_ = JSClassCreate(&definition); definition = kJSClassDefinitionEmpty; definition.className = "Internal"; @@ -2663,7 +2652,7 @@ void CYObjectiveC_Initialize() { /*XXX*/ JSContextRef context(NULL); CYPoolTry { ObjectiveC_Protocols_ = JSClassCreate(&definition); #ifdef __APPLE__ - class_addMethod(NSCFType_, @selector(cy$toJSON:), reinterpret_cast(&NSCFType$cy$toJSON), "@12@0:4@8"); + class_addMethod(NSCFType_, @selector(cy$toJSON:inContext:), reinterpret_cast(&NSCFType$cy$toJSON$inContext$), "^{OpaqueJSValue=}16@0:4@8^{OpaqueJSContext=}12"); #endif } CYPoolCatch() } @@ -2693,6 +2682,7 @@ void CYObjectiveC_SetupContext(JSContextRef context) { CYPoolTry { CYSetProperty(context, ObjectiveC, CYJSString("images"), JSObjectMake(context, ObjectiveC_Images_, NULL)); #endif + JSObjectRef Class(JSObjectMakeConstructor(context, Class_, NULL)); JSObjectRef Instance(JSObjectMakeConstructor(context, Instance_, &Instance_new)); JSObjectRef Message(JSObjectMakeConstructor(context, Message_, NULL)); JSObjectRef Selector(JSObjectMakeConstructor(context, Selector_, &Selector_new)); @@ -2725,6 +2715,10 @@ void CYObjectiveC_SetupContext(JSContextRef context) { CYPoolTry { JSObjectRef String_prototype(CYGetCachedObject(context, CYJSString("String_prototype"))); JSObjectSetPrototype(context, StringInstance_prototype, String_prototype); + JSObjectRef Class_prototype(CYCastJSObject(context, CYGetProperty(context, Class, prototype_s))); + CYSetProperty(context, cy, CYJSString("Class_prototype"), Class_prototype); + JSObjectSetPrototype(context, Class_prototype, Instance_prototype); + CYSetProperty(context, cycript, CYJSString("Instance"), Instance); CYSetProperty(context, cycript, CYJSString("Selector"), Selector); CYSetProperty(context, cycript, CYJSString("Super"), Super);