static JSClassRef ObjectInstance_;
static JSClassRef StringInstance_;
+static JSClassRef Class_;
static JSClassRef Internal_;
static JSClassRef Message_;
static JSClassRef Messages_;
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)));
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);
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;
}
- (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;
@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));
}
NSObject *CYCastNSObject(apr_pool_t *pool, JSContextRef context, JSObjectRef object) {
- if (JSValueIsObjectOfClass(context, object, Instance_)) {
+ if (CYJSValueIsNSObject(context, object)) {
Instance *internal(reinterpret_cast<Instance *>(JSObjectGetPrivate(object)));
return internal->GetValue();
}
}
- (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];
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];
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;
}
}
- (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];
}
- (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];
}
}
-// 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 }
return kJSTypeUndefined;
}
-- (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];
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
return NULL;
}
-static void MessageClosure_(ffi_cif *cif, void *result, void **arguments, void *arg) {
- Closure_privateData *internal(reinterpret_cast<Closure_privateData *>(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) {
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));
if (!CYIsClass(_class))
return false;
- if (JSValueIsObjectOfClass(context, instance, Instance_)) {
+ if (CYJSValueIsNSObject(context, instance)) {
Instance *linternal(reinterpret_cast<Instance *>(JSObjectGetPrivate((JSObjectRef) instance)));
// XXX: this isn't always safe
return [linternal->GetValue() isKindOfClass:_class];
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<Instance *>(JSObjectGetPrivate((JSObjectRef) arguments[0])));
self = internal->GetValue();
_class = nil;
}
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<Instance *>(JSObjectGetPrivate(_this)));
} 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<Instance *>(JSObjectGetPrivate(_this)));
} 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<Instance *>(JSObjectGetPrivate(_this)));
} 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<Instance *>(JSObjectGetPrivate(_this)));
} 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<Instance *>(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<Instance *>(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<Selector_privateData *>(JSObjectGetPrivate(_this)));
return CYCastJSValue(context, sel_getName(internal->GetValue()));
{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}
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";
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));
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);