Skip to content

Commit

Permalink
Added a special check for NSArray (in addition to NSString) in order …
Browse files Browse the repository at this point in the history
…to call some JS functions on NSArray. We also look to see if length() is begin called on an NSArray, and then swap that out for count at runtime.
  • Loading branch information
ccgus committed Feb 5, 2013
1 parent d580d8a commit a0262dc
Showing 1 changed file with 38 additions and 10 deletions.
48 changes: 38 additions & 10 deletions Mocha/MochaRuntime.m
Expand Up @@ -61,7 +61,7 @@

static JSValueRef MOFunction_callAsFunction(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef *exception);

static JSValueRef MOStringPrototypeFunction(JSContextRef ctx, NSString *name);
static JSValueRef MOJSPrototypeFunctionForOBJCInstance(JSContextRef ctx, id instance, NSString *functionName);

NSString * const MORuntimeException = @"MORuntimeException";
NSString * const MOJavaScriptException = @"MOJavaScriptException";
Expand Down Expand Up @@ -1201,12 +1201,20 @@ static bool MOBoxedObject_hasProperty(JSContextRef ctx, JSObjectRef objectJS, JS
return YES;
}

if ([object isKindOfClass:[NSString class]]) {
// special case bridging of NSString w/ JS string functions
if ([object isKindOfClass:[NSString class]] || [object isKindOfClass:[NSArray class]]) {
// special case bridging of NSString & NSArray w/ JS functions

if (MOStringPrototypeFunction(ctx, propertyName)) {
if (MOJSPrototypeFunctionForOBJCInstance(ctx, object, propertyName)) {
return YES;
}

if ([object isKindOfClass:[NSArray class]]) {
// if we're calling length on an NSArray (which will happen from inside JS'a Array.forEach), we need to make sure
// to catch and do that right. We could also add a category to NSArray I suppose, but that feels a little dirty.
if ([propertyName isEqualToString:@"length"]) {
return YES;
}
}
}

return NO;
Expand Down Expand Up @@ -1331,14 +1339,22 @@ static JSValueRef MOBoxedObject_getProperty(JSContextRef ctx, JSObjectRef object
}
}

if ([object isKindOfClass:[NSString class]]) {
// special case bridging of NSString w/ JS string functions

JSValueRef jsPropertyValue = MOStringPrototypeFunction(ctx, propertyName);
if ([object isKindOfClass:[NSString class]] || [object isKindOfClass:[NSArray class]]) {
// special case bridging of NSString & NSArray w/ JS functions

JSValueRef jsPropertyValue = MOJSPrototypeFunctionForOBJCInstance(ctx, object, propertyName);
if (jsPropertyValue) {
return jsPropertyValue;
}

if ([object isKindOfClass:[NSArray class]]) {

// see the notes in MOBoxedObject_hasProperty
if ([propertyName isEqualToString:@"length"]) {
MOMethod *method = [MOMethod methodWithTarget:object selector:@selector(count)];
return MOFunctionInvoke(method, ctx, 0, NULL, exception);
}
}
}

// if (exception != NULL) {
Expand Down Expand Up @@ -1548,10 +1564,22 @@ static JSValueRef MOFunction_callAsFunction(JSContextRef ctx, JSObjectRef functi
return value;
}

static JSValueRef MOStringPrototypeFunction(JSContextRef ctx, NSString *name) {
static JSValueRef MOJSPrototypeFunctionForOBJCInstance(JSContextRef ctx, id instance, NSString *name) {

char *propName = nil;
if ([instance isKindOfClass:[NSString class]]) {
propName = "String";
}
else if ([instance isKindOfClass:[NSArray class]]) {
propName = "Array";
}

if (!propName) {
return NO;
}

JSValueRef exception = nil;
JSStringRef jsPropertyName = JSStringCreateWithUTF8CString("String");
JSStringRef jsPropertyName = JSStringCreateWithUTF8CString(propName);
JSValueRef jsPropertyValue = JSObjectGetProperty(ctx, JSContextGetGlobalObject(ctx), jsPropertyName, &exception);
JSStringRelease(jsPropertyName);

Expand Down

0 comments on commit a0262dc

Please sign in to comment.