#include <dlfcn.h>
-#define CYObjectiveTry_(context) { \
- JSContextRef context_(context); \
+#define CYObjectiveTry_ { \
try
#define CYObjectiveTry { \
+ JSContextRef context(context_); \
try
#define CYObjectiveCatch \
catch (const CYException &error) { \
- @throw CYCastNSObject(NULL, context_, error.CastJSValue(context_)); \
+ @throw CYCastNSObject(NULL, context, error.CastJSValue(context)); \
} \
}
BLOCK_HAS_SIGNATURE = 1 << 30,
};
-JSValueRef CYSendMessage(CYPool &pool, JSContextRef context, id self, Class super, SEL _cmd, size_t count, const JSValueRef arguments[], bool initialize, JSValueRef *exception);
+JSValueRef CYSendMessage(CYPool &pool, JSContextRef context, id self, Class super, SEL _cmd, size_t count, const JSValueRef arguments[], bool initialize);
/* Objective-C Pool Release {{{ */
void CYPoolRelease_(void *data) {
}
_finline bool CYJSValueIsInstanceOfCachedConstructor(JSContextRef context, JSValueRef value, JSStringRef cache) {
- JSValueRef exception(NULL);
- JSObjectRef constructor(CYGetCachedObject(context, cache));
- bool is(JSValueIsInstanceOfConstructor(context, value, constructor, &exception));
- CYThrow(context, exception);
- return is;
+ return _jsccall(JSValueIsInstanceOfConstructor, context, value, CYGetCachedObject(context, cache));
}
NSObject *CYMakeBlock(void (*invoke)(), sig::Signature &signature) {
}
- (JSValueRef) cy$getProperty:(NSString *)name inContext:(JSContextRef)context {
- CYObjectiveTry_(context) {
+ CYObjectiveTry_ {
if ([name isEqualToString:@"length"])
return CYCastJSValue(context, [self count]);
} CYObjectiveCatch
return objective ? value : [NSString stringWithFormat:@"@%@", value];
}
-- (JSValueRef) cy$valueOfInContext:(JSContextRef)context { CYObjectiveTry_(context) {
+- (JSValueRef) cy$valueOfInContext:(JSContextRef)context { CYObjectiveTry_ {
return CYCastJSValue(context, (bool) [self boolValue]);
} CYObjectiveCatch }
return objective ? value : [NSString stringWithFormat:@"@%@", value];
}
-- (JSValueRef) cy$valueOfInContext:(JSContextRef)context { CYObjectiveTry_(context) {
+- (JSValueRef) cy$valueOfInContext:(JSContextRef)context { CYObjectiveTry_ {
return [self cy$JSType] != kJSTypeBoolean ? CYCastJSValue(context, [self doubleValue]) : CYCastJSValue(context, static_cast<bool>([self boolValue]));
} CYObjectiveCatch }
return objective ? value : [NSString stringWithFormat:@"@%@", value];
}
-- (JSValueRef) cy$valueOfInContext:(JSContextRef)context { CYObjectiveTry_(context) {
+- (JSValueRef) cy$valueOfInContext:(JSContextRef)context { CYObjectiveTry_ {
return CYJSNull(context);
} CYObjectiveCatch }
return [self cy$valueOfInContext:context];
}
-- (JSValueRef) cy$valueOfInContext:(JSContextRef)context { CYObjectiveTry_(context) {
+- (JSValueRef) cy$valueOfInContext:(JSContextRef)context { CYObjectiveTry_ {
return NULL;
} CYObjectiveCatch }
return nil;
}
-- (JSValueRef) cy$getProperty:(NSString *)name inContext:(JSContextRef)context { CYObjectiveTry_(context) {
+- (JSValueRef) cy$getProperty:(NSString *)name inContext:(JSContextRef)context { CYObjectiveTry_ {
if (NSObject *value = [self cy$getProperty:name])
return CYCastJSValue(context, value);
return NULL;
}
}
-- (JSValueRef) cy$valueOfInContext:(JSContextRef)context { CYObjectiveTry_(context) {
+- (JSValueRef) cy$valueOfInContext:(JSContextRef)context { CYObjectiveTry_ {
return CYCastJSValue(context, CYJSString(context, self));
} CYObjectiveCatch }
//return objective ? value : [NSString stringWithFormat:@"@%@", value];
}
-- (JSValueRef) cy$valueOfInContext:(JSContextRef)context { CYObjectiveTry_(context) {
+- (JSValueRef) cy$valueOfInContext:(JSContextRef)context { CYObjectiveTry_ {
return CYJSUndefined(context);
} CYObjectiveCatch }
@implementation CYJSObject
-- (id) initWithJSObject:(JSObjectRef)object inContext:(JSContextRef)context { CYObjectiveTry {
+- (id) initWithJSObject:(JSObjectRef)object inContext:(JSContextRef)context { CYObjectiveTry_ {
if ((self = [super init]) != nil) {
object_ = object;
context_ = CYGetJSContext(context);
- (NSString *) cy$toCYON:(bool)objective { CYObjectiveTry {
CYPool pool;
- const char *cyon(CYPoolCCYON(pool, context_, object_));
+ const char *cyon(CYPoolCCYON(pool, context, object_));
if (cyon == NULL)
return [super cy$toCYON:objective];
else
} CYObjectiveCatch }
- (NSUInteger) count { CYObjectiveTry {
- JSPropertyNameArrayRef names(JSObjectCopyPropertyNames(context_, object_));
+ JSPropertyNameArrayRef names(JSObjectCopyPropertyNames(context, object_));
size_t size(JSPropertyNameArrayGetCount(names));
JSPropertyNameArrayRelease(names);
return size;
} CYObjectiveCatch }
- (id) objectForKey:(id)key { CYObjectiveTry {
- JSValueRef value(CYGetProperty(context_, object_, CYJSString(context_, (NSObject *) key)));
- if (JSValueIsUndefined(context_, value))
+ JSValueRef value(CYGetProperty(context, object_, CYJSString(context, (NSObject *) key)));
+ if (JSValueIsUndefined(context, value))
return nil;
- return CYCastNSObject(NULL, context_, value) ?: [NSNull null];
+ return CYCastNSObject(NULL, context, value) ?: [NSNull null];
} CYObjectiveCatch }
- (NSEnumerator *) keyEnumerator { CYObjectiveTry {
- JSPropertyNameArrayRef names(JSObjectCopyPropertyNames(context_, object_));
- NSEnumerator *enumerator([CYCastNSArray(context_, names) objectEnumerator]);
+ JSPropertyNameArrayRef names(JSObjectCopyPropertyNames(context, object_));
+ NSEnumerator *enumerator([CYCastNSArray(context, names) objectEnumerator]);
JSPropertyNameArrayRelease(names);
return enumerator;
} CYObjectiveCatch }
- (void) setObject:(id)object forKey:(id)key { CYObjectiveTry {
- CYSetProperty(context_, object_, CYJSString(context_, (NSObject *) key), CYCastJSValue(context_, (NSString *) object));
+ CYSetProperty(context, object_, CYJSString(context, (NSObject *) key), CYCastJSValue(context, (NSString *) object));
} CYObjectiveCatch }
- (void) removeObjectForKey:(id)key { CYObjectiveTry {
- JSValueRef exception(NULL);
- (void) JSObjectDeleteProperty(context_, object_, CYJSString(context_, (NSObject *) key), &exception);
- CYThrow(context_, exception);
+ (void) _jsccall(JSObjectDeleteProperty, context, object_, CYJSString(context, (NSObject *) key));
} CYObjectiveCatch }
@end
@implementation CYJSArray
-- (NSString *) cy$toCYON:(bool)objective {
+- (NSString *) cy$toCYON:(bool)objective { CYObjectiveTry {
CYPool pool;
- return [NSString stringWithUTF8String:CYPoolCCYON(pool, context_, object_)];
-}
+ return [NSString stringWithUTF8String:CYPoolCCYON(pool, context, object_)];
+} CYObjectiveCatch }
-- (id) initWithJSObject:(JSObjectRef)object inContext:(JSContextRef)context { CYObjectiveTry {
+- (id) initWithJSObject:(JSObjectRef)object inContext:(JSContextRef)context { CYObjectiveTry_ {
if ((self = [super init]) != nil) {
object_ = object;
context_ = CYGetJSContext(context);
} CYObjectiveCatch }
- (NSUInteger) count { CYObjectiveTry {
- return CYArrayLength(context_, object_);
+ return CYArrayLength(context, object_);
} CYObjectiveCatch }
- (id) objectAtIndex:(NSUInteger)index { CYObjectiveTry {
size_t bounds([self count]);
if (index >= bounds)
@throw [NSException exceptionWithName:NSRangeException reason:[NSString stringWithFormat:@"*** -[CYJSArray objectAtIndex:]: index (%zu) beyond bounds (%zu)", static_cast<size_t>(index), bounds] userInfo:nil];
- JSValueRef exception(NULL);
- JSValueRef value(JSObjectGetPropertyAtIndex(context_, object_, index, &exception));
- CYThrow(context_, exception);
- return CYCastNSObject(NULL, context_, value) ?: [NSNull null];
+ JSValueRef value(_jsccall(JSObjectGetPropertyAtIndex, context, object_, index));
+ return CYCastNSObject(NULL, context, value) ?: [NSNull null];
} CYObjectiveCatch }
- (void) addObject:(id)object { CYObjectiveTry {
- CYArrayPush(context_, object_, CYCastJSValue(context_, (NSObject *) object));
+ CYArrayPush(context, object_, CYCastJSValue(context, (NSObject *) object));
} CYObjectiveCatch }
- (void) insertObject:(id)object atIndex:(NSUInteger)index { CYObjectiveTry {
size_t bounds([self count] + 1);
if (index >= bounds)
@throw [NSException exceptionWithName:NSRangeException reason:[NSString stringWithFormat:@"*** -[CYJSArray insertObject:atIndex:]: index (%zu) beyond bounds (%zu)", static_cast<size_t>(index), bounds] userInfo:nil];
- JSValueRef exception(NULL);
JSValueRef arguments[3];
- arguments[0] = CYCastJSValue(context_, index);
- arguments[1] = CYCastJSValue(context_, 0);
- arguments[2] = CYCastJSValue(context_, (NSObject *) object);
- JSObjectRef Array(CYGetCachedObject(context_, CYJSString("Array_prototype")));
- JSObjectCallAsFunction(context_, CYCastJSObject(context_, CYGetProperty(context_, Array, splice_s)), object_, 3, arguments, &exception);
- CYThrow(context_, exception);
+ arguments[0] = CYCastJSValue(context, index);
+ arguments[1] = CYCastJSValue(context, 0);
+ arguments[2] = CYCastJSValue(context, (NSObject *) object);
+ JSObjectRef Array(CYGetCachedObject(context, CYJSString("Array_prototype")));
+ _jsccall(JSObjectCallAsFunction, context, CYCastJSObject(context, CYGetProperty(context, Array, splice_s)), object_, 3, arguments);
} CYObjectiveCatch }
- (void) removeLastObject { CYObjectiveTry {
- JSValueRef exception(NULL);
- JSObjectRef Array(CYGetCachedObject(context_, CYJSString("Array_prototype")));
- JSObjectCallAsFunction(context_, CYCastJSObject(context_, CYGetProperty(context_, Array, pop_s)), object_, 0, NULL, &exception);
- CYThrow(context_, exception);
+ JSObjectRef Array(CYGetCachedObject(context, CYJSString("Array_prototype")));
+ _jsccall(JSObjectCallAsFunction, context, CYCastJSObject(context, CYGetProperty(context, Array, pop_s)), object_, 0, NULL);
} CYObjectiveCatch }
- (void) removeObjectAtIndex:(NSUInteger)index { CYObjectiveTry {
size_t bounds([self count]);
if (index >= bounds)
@throw [NSException exceptionWithName:NSRangeException reason:[NSString stringWithFormat:@"*** -[CYJSArray removeObjectAtIndex:]: index (%zu) beyond bounds (%zu)", static_cast<size_t>(index), bounds] userInfo:nil];
- JSValueRef exception(NULL);
JSValueRef arguments[2];
- arguments[0] = CYCastJSValue(context_, index);
- arguments[1] = CYCastJSValue(context_, 1);
- JSObjectRef Array(CYGetCachedObject(context_, CYJSString("Array_prototype")));
- JSObjectCallAsFunction(context_, CYCastJSObject(context_, CYGetProperty(context_, Array, splice_s)), object_, 2, arguments, &exception);
- CYThrow(context_, exception);
+ arguments[0] = CYCastJSValue(context, index);
+ arguments[1] = CYCastJSValue(context, 1);
+ JSObjectRef Array(CYGetCachedObject(context, CYJSString("Array_prototype")));
+ _jsccall(JSObjectCallAsFunction, context, CYCastJSObject(context, CYGetProperty(context, Array, splice_s)), object_, 2, arguments);
} CYObjectiveCatch }
- (void) replaceObjectAtIndex:(NSUInteger)index withObject:(id)object { CYObjectiveTry {
size_t bounds([self count]);
if (index >= bounds)
@throw [NSException exceptionWithName:NSRangeException reason:[NSString stringWithFormat:@"*** -[CYJSArray replaceObjectAtIndex:withObject:]: index (%zu) beyond bounds (%zu)", static_cast<size_t>(index), bounds] userInfo:nil];
- CYSetProperty(context_, object_, index, CYCastJSValue(context_, (NSObject *) object));
+ CYSetProperty(context, object_, index, CYCastJSValue(context, (NSObject *) object));
} CYObjectiveCatch }
@end
@implementation CYInternal
-- (void) dealloc {
+- (void) dealloc { CYObjectiveTry {
JSValueUnprotect(context_, object_);
JSGlobalContextRelease(context_);
[super dealloc];
-}
+} CYObjectiveCatch }
-- (id) initInContext:(JSContextRef)context {
+- (id) initInContext:(JSContextRef)context { CYObjectiveTry_ {
if ((self = [super init]) != nil) {
context_ = CYGetJSContext(context);
JSGlobalContextRetain(context_);
} return self;
-}
+} CYObjectiveCatch }
- (bool) hasProperty:(JSStringRef)name inContext:(JSContextRef)context {
if (object_ == NULL)
if (objc_property_t property = class_getProperty(_class, string)) {
PropertyAttributes attributes(property);
SEL sel(sel_registerName(attributes.Getter()));
- return CYSendMessage(pool, context, self, NULL, sel, 0, NULL, false, exception);
+ return CYSendMessage(pool, context, self, NULL, sel, 0, NULL, false);
}
#endif
if (CYHasImplicitProperties(_class))
if (SEL sel = sel_getUid(string))
if (CYImplements(self, _class, sel, true))
- return CYSendMessage(pool, context, self, NULL, sel, 0, NULL, false, exception);
+ return CYSendMessage(pool, context, self, NULL, sel, 0, NULL, false);
return NULL;
} CYCatch(NULL) }
if (const char *setter = attributes.Setter()) {
SEL sel(sel_registerName(setter));
JSValueRef arguments[1] = {value};
- CYSendMessage(pool, context, self, NULL, sel, 1, arguments, false, exception);
+ CYSendMessage(pool, context, self, NULL, sel, 1, arguments, false);
return true;
}
}
if (SEL sel = sel_getUid(set))
if (CYImplements(self, _class, sel)) {
JSValueRef arguments[1] = {value};
- CYSendMessage(pool, context, self, NULL, sel, 1, arguments, false, exception);
+ CYSendMessage(pool, context, self, NULL, sel, 1, arguments, false);
return true;
}
sig::sig_ffi_cif(pool, &sig::ObjectiveC, &signature, &cif);
void (*function)() = reinterpret_cast<void (*)()>(literal->invoke);
- return CYCallFunction(pool, context, 1, setup, count, arguments, false, exception, &signature, &cif, function);
+ return CYCallFunction(pool, context, 1, setup, count, arguments, false, &signature, &cif, function);
}
}
return false;
}
+static void CYBitField(unsigned &length, unsigned &shift, id self, Ivar ivar, const char *encoding, unsigned offset) {
+ length = CYCastDouble(encoding + 1);
+ shift = 0;
+
+ unsigned int size;
+ objc_ivar **ivars(class_copyIvarList(object_getClass(self), &size));
+ for (size_t i(0); i != size; ++i)
+ if (ivars[i] == ivar)
+ break;
+ else if (ivar_getOffset(ivars[i]) == offset) {
+ const char *encoding(ivar_getTypeEncoding(ivars[i]));
+ _assert(encoding[0] == 'b');
+ shift += CYCastDouble(encoding + 1);
+ }
+ free(ivars);
+}
+
static JSValueRef Internal_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
Internal *internal(reinterpret_cast<Internal *>(JSObjectGetPrivate(object)));
CYPool pool;
const char *encoding(ivar_getTypeEncoding(ivar));
if (encoding[0] == 'b') {
- unsigned length(CYCastDouble(encoding + 1));
- unsigned shift(0);
-
- unsigned int size;
- objc_ivar **ivars(class_copyIvarList(object_getClass(self), &size));
- for (size_t i(0); i != size; ++i)
- if (ivars[i] == ivar)
- break;
- else if (ivar_getOffset(ivars[i]) == offset) {
- const char *encoding(ivar_getTypeEncoding(ivars[i]));
- _assert(encoding[0] == 'b');
- shift += CYCastDouble(encoding + 1);
- }
- free(ivars);
-
+ unsigned length, shift;
+ CYBitField(length, shift, self, ivar, encoding, offset);
_assert(shift + length <= sizeof(uintptr_t) * 8);
- return CYCastJSValue(context, (*reinterpret_cast<uintptr_t *>(data) >> shift) & (1 << length) - 1);
+ uintptr_t &field(*reinterpret_cast<uintptr_t *>(data));
+ uintptr_t mask((1 << length) - 1);
+ return CYCastJSValue(context, (field >> shift) & mask);
} else {
Type_privateData type(pool, ivar_getTypeEncoding(ivar));
return CYFromFFI(context, type.type_, type.GetFFI(), data);
const char *name(CYPoolCString(pool, context, property));
if (objc_ivar *ivar = object_getInstanceVariable(self, name, NULL)) {
- Type_privateData type(pool, ivar_getTypeEncoding(ivar));
- CYPoolFFI(&pool, context, type.type_, type.GetFFI(), reinterpret_cast<uint8_t *>(self) + ivar_getOffset(ivar), value);
- return true;
+ ptrdiff_t offset(ivar_getOffset(ivar));
+ void *data(reinterpret_cast<uint8_t *>(self) + offset);
+
+ const char *encoding(ivar_getTypeEncoding(ivar));
+ if (encoding[0] == 'b') {
+ unsigned length, shift;
+ CYBitField(length, shift, self, ivar, encoding, offset);
+ _assert(shift + length <= sizeof(uintptr_t) * 8);
+ uintptr_t &field(*reinterpret_cast<uintptr_t *>(data));
+ uintptr_t mask((1 << length) - 1);
+ field = field & ~(mask << shift) | (uintptr_t(CYCastDouble(context, value)) & mask) << shift;
+ } else {
+ Type_privateData type(pool, ivar_getTypeEncoding(ivar));
+ CYPoolFFI(&pool, context, type.type_, type.GetFFI(), reinterpret_cast<uint8_t *>(self) + ivar_getOffset(ivar), value);
+ return true;
+ }
}
return false;
#endif
#endif
-JSValueRef CYSendMessage(CYPool &pool, JSContextRef context, id self, Class _class, SEL _cmd, size_t count, const JSValueRef arguments[], bool initialize, JSValueRef *exception) { CYTry {
+JSValueRef CYSendMessage(CYPool &pool, JSContextRef context, id self, Class _class, SEL _cmd, size_t count, const JSValueRef arguments[], bool initialize) {
const char *type;
if (_class == NULL)
}
void (*function)() = reinterpret_cast<void (*)()>(imp);
- return CYCallFunction(pool, context, 2, setup, count, arguments, initialize, exception, &signature, &cif, function);
-} CYCatch(NULL) }
+ return CYCallFunction(pool, context, 2, setup, count, arguments, initialize, &signature, &cif, function);
+}
static JSValueRef $objc_msgSend(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
if (count < 2)
_cmd = CYCastSEL(context, arguments[1]);
- return CYSendMessage(pool, context, self, _class, _cmd, count - 2, arguments + 2, uninitialized, exception);
+ return CYSendMessage(pool, context, self, _class, _cmd, count - 2, arguments + 2, uninitialized);
} CYCatch(NULL) }
static JSValueRef Selector_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
setup[0] = &self;
setup[1] = &internal->sel_;
- return CYCallFunction(pool, context, 2, setup, count, arguments, false, exception, &internal->signature_, &internal->cif_, internal->GetValue());
+ return CYCallFunction(pool, context, 2, setup, count, arguments, false, &internal->signature_, &internal->cif_, internal->GetValue());
} CYCatch(NULL) }
static JSObjectRef Super_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
};
#ifdef __APPLE__
-JSValueRef NSCFType$cy$toJSON$inContext$(id self, SEL sel, JSValueRef key, JSContextRef context) { CYObjectiveTry_(context) {
+JSValueRef NSCFType$cy$toJSON$inContext$(id self, SEL sel, JSValueRef key, JSContextRef context) { CYObjectiveTry_ {
return CYCastJSValue(context, [(NSString *) CFCopyDescription((CFTypeRef) self) autorelease]);
} CYObjectiveCatch }
#endif
ObjectiveC_Protocols_ = JSClassCreate(&definition);
#ifdef __APPLE__
+// XXX: this is horrible; there has to be a better way to do this
+#ifdef __LP64__
+ class_addMethod(NSCFType_, @selector(cy$toJSON:inContext:), reinterpret_cast<IMP>(&NSCFType$cy$toJSON$inContext$), "^{OpaqueJSValue=}32@0:8@16^{OpaqueJSContext=}24");
+#else
class_addMethod(NSCFType_, @selector(cy$toJSON:inContext:), reinterpret_cast<IMP>(&NSCFType$cy$toJSON$inContext$), "^{OpaqueJSValue=}16@0:4@8^{OpaqueJSContext=}12");
#endif
+#endif
} CYPoolCatch() }
void CYObjectiveC_SetupContext(JSContextRef context) { CYPoolTry {