Skip to content

Commit

Permalink
All delegate methods working
Browse files Browse the repository at this point in the history
  • Loading branch information
parmanoir committed Mar 10, 2009
1 parent 14fd4b7 commit 67f8248
Show file tree
Hide file tree
Showing 6 changed files with 4,628 additions and 14,024 deletions.
19 changes: 15 additions & 4 deletions JSCocoa/JSCocoaController.h
Expand Up @@ -168,20 +168,31 @@ typedef struct JSValueRefAndContextRef JSValueRefAndContextRef;
// Return NO to let JSCocoa handle calling
- (JSValueRef) JSCocoa:(JSCocoaController*)controller callMethod:(NSString*)methodName ofObject:(id)object argumentCount:(int)argumentCount arguments:(JSValueRef*)arguments inContext:(JSContextRef)ctx exception:(JSValueRef*)exception;

//
// Getting global properties (classes, structures, C function names, enums via OSXObject_getProperty)
//
// Check if getting property is allowed
- (BOOL) JSCocoa:(JSCocoaController*)controller canGetGlobalProperty:(NSString*)propertyName inContext:(JSContextRef)ctx exception:(JSValueRef*)exception;
// Custom handler for getting properties
// Return a custom JSValueRef to bypass JSCocoa
// Return NULL to let JSCocoa handle getProperty
// Return JSValueMakeNull() to return a Javascript null
- (JSValueRef) JSCocoa:(JSCocoaController*)controller getGlobalProperty:(NSString*)propertyName inContext:(JSContextRef)ctx exception:(JSValueRef*)exception;

//
// Returning values to Javascript
//
// Called before returning any value to Javascript : return a new value or the original one
- (JSValueRef) JSCocoa:(JSCocoaController*)controller willReturnValue:(JSValueRef)value inContext:(JSContextRef)ctx exception:(JSValueRef*)exception;
//- (JSValueRef) JSCocoa:(JSCocoaController*)controller willReturnValue:(JSValueRef)value inContext:(JSContextRef)ctx exception:(JSValueRef*)exception;

//
// Evaling
//
// Check if file can be loaded
- (NSString*)JSCocoa:(JSCocoaController*)controller canLoadJSFile:(NSString*)script;
- (BOOL)JSCocoa:(JSCocoaController*)controller canLoadJSFile:(NSString*)path;
// Check if script can be evaluated
- (NSString*)JSCocoa:(JSCocoaController*)controller canEvaluateScript:(NSString*)script;
// Called before evalJSString
- (BOOL)JSCocoa:(JSCocoaController*)controller canEvaluateScript:(NSString*)script;
// Called before evalJSString, used to modify script about to be evaluated
// Return a custom NSString (eg a macro expanded version of the source)
// Return NULL to let JSCocoa handle evaluation
- (NSString*)JSCocoa:(JSCocoaController*)controller willEvaluateScript:(NSString*)script;
Expand Down
139 changes: 98 additions & 41 deletions JSCocoa/JSCocoaController.m
Expand Up @@ -262,6 +262,8 @@ + (id)controllerFromContext:(JSContextRef)ctx
JSStringRelease(jsName);
id jsc = nil;
[JSCocoaFFIArgument unboxJSValueRef:jsValue toObject:&jsc inContext:ctx];
// Commented as it falsely reports failure when controller is cleaning up while being deallocated
// if (!jsc) NSLog(@"controllerFromContext couldn't find found the JSCocoaController in ctx %x", ctx);
return jsc;
}

Expand All @@ -278,12 +280,30 @@ - (BOOL)evalJSFile:(NSString*)path toJSValueRef:(JSValueRef*)returnValue
// Skip .DS_Store and directories
if (script == nil) return NSLog(@"evalJSFile could not open %@ (%@) — Check file encoding (should be UTF8) and file build phase (should be in \"Copy Bundle Resources\")", path, error), NO;

//
// Delegate canLoadJSFile
//
if (_delegate && [_delegate respondsToSelector:@selector(JSCocoa:canLoadJSFile:)] && ![_delegate JSCocoa:self canLoadJSFile:path]) return NO;

// Expand macros
if ([self hasJSFunctionNamed:@"expandJSMacros"])
{
script = [self unboxJSValueRef:[self callJSFunctionNamed:@"expandJSMacros" withArguments:script, nil]];
id expandedScript = [self unboxJSValueRef:[self callJSFunctionNamed:@"expandJSMacros" withArguments:script, nil]];
// Bail if expansion failed
if (!script || ![script isKindOfClass:[NSString class]]) return NSLog(@"Macro expansion failed on %@", path), NO;
if (!expandedScript || ![expandedScript isKindOfClass:[NSString class]])
{
return NSLog(@"Macro expansion failed on %@ (%@)", path, expandedScript), NO;
}
script = expandedScript;
}

//
// Delegate canEvaluateScript, willEvaluateScript
//
if (_delegate)
{
if ([_delegate respondsToSelector:@selector(JSCocoa:canEvaluateScript:)] && ![_delegate JSCocoa:self canEvaluateScript:script]) return NO;
if ([_delegate respondsToSelector:@selector(JSCocoa:willEvaluateScript:)]) script = [_delegate JSCocoa:self willEvaluateScript:script];
}

// Convert script and script URL to js strings
Expand Down Expand Up @@ -320,25 +340,29 @@ - (BOOL)evalJSFile:(NSString*)path
//
- (JSValueRef)evalJSString:(NSString*)script
{
// JSValueRefAndContextRef v = { JSValueMakeNull(ctx), NULL };
if (!script) return NULL;

//
// Delegate canEvaluateScript, willEvaluateScript
//
if (_delegate)
{
if ([_delegate respondsToSelector:@selector(JSCocoa:canEvaluateScript:)] && ![_delegate JSCocoa:self canEvaluateScript:script]) return NULL;
if ([_delegate respondsToSelector:@selector(JSCocoa:willEvaluateScript:)]) script = [_delegate JSCocoa:self willEvaluateScript:script];
}

JSStringRef scriptJS = JSStringCreateWithCFString((CFStringRef)script);
JSValueRef exception = NULL;
JSValueRef result = JSEvaluateScript(ctx, scriptJS, NULL, scriptJS, 1, &exception);
JSStringRelease(scriptJS);

// v.ctx = ctx;
// v.value = JSValueMakeNull(ctx);
if (exception)
{
[self callDelegateForException:exception];
return NULL;
}

return result;
// v.ctx = ctx;
// v.value = result;
// return v;
}

//
Expand Down Expand Up @@ -1704,25 +1728,55 @@ + (JSValueRef)instanceWithContext:(JSContextRef)ctx argumentCount:(size_t)argume

#pragma mark JS OSX object

/*
//
//
// Global resolver
//
//


Global resolver

*/
JSValueRef OSXObject_getProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyNameJS, JSValueRef* exception)
{
NSString* propertyName = (NSString*)JSStringCopyCFString(kCFAllocatorDefault, propertyNameJS);
[NSMakeCollectable(propertyName) autorelease];

if ([propertyName isEqualToString:@"__jsc__"]) return NULL;

// NSLog(@"Asking for global property %@", propertyName);
JSCocoaController* jsc = [JSCocoaController controllerFromContext:ctx];
id delegate = jsc.delegate;
//
// Delegate canGetGlobalProperty, getGlobalProperty
//
if (delegate)
{
// Check if getting is allowed
if ([delegate respondsToSelector:@selector(JSCocoa:canGetGlobalProperty:inContext:exception:)])
{
BOOL canGetGlobal = [delegate JSCocoa:jsc canGetGlobalProperty:propertyName inContext:ctx exception:exception];
if (!canGetGlobal)
{
if (!*exception) throwException(ctx, exception, [NSString stringWithFormat:@"Delegate does not allow getting global property %@", propertyName]);
return NULL;
}
}
// Check if delegate handles getting
if ([delegate respondsToSelector:@selector(JSCocoa:getGlobalProperty:inContext:exception:)])
{
JSValueRef delegateGetGlobal = [delegate JSCocoa:jsc getGlobalProperty:propertyName inContext:ctx exception:exception];
if (delegateGetGlobal) return delegateGetGlobal;
}
}

//
// ObjC class
//
Class objCClass = NSClassFromString(propertyName);
if (objCClass && ![propertyName isEqualToString:@"Object"])
{
return [JSCocoaController boxedJSObject:objCClass inContext:ctx];
JSValueRef ret = [JSCocoaController boxedJSObject:objCClass inContext:ctx];
return ret;
}

id xml;
Expand Down Expand Up @@ -1806,7 +1860,6 @@ JSValueRef OSXObject_getProperty(JSContextRef ctx, JSObjectRef object, JSStringR
double doubleValue = 0;
value = [value stringValue];
if (![[NSScanner scannerWithString:value] scanDouble:&doubleValue]) return NSLog(@"(OSX_getPropertyCallback) scanning %@ enum failed", propertyName), NULL;

return JSValueMakeNumber(ctx, doubleValue);
}
}
Expand Down Expand Up @@ -1960,7 +2013,6 @@ static void jsCocoaObject_finalize(JSObjectRef object)
}



//
// getProperty
// Return property in object's internal Javascript hash if its contains propertyName
Expand Down Expand Up @@ -2007,7 +2059,7 @@ static JSValueRef jsCocoaObject_getProperty(JSContextRef ctx, JSObjectRef object
if ([delegate respondsToSelector:@selector(JSCocoa:getProperty:ofObject:inContext:exception:)])
{
JSValueRef delegateGet = [delegate JSCocoa:jsc getProperty:propertyName ofObject:privateObject.object inContext:ctx exception:exception];
if (delegateGet) return delegateGet;
if (delegateGet) return delegateGet;
}
}

Expand Down Expand Up @@ -2069,8 +2121,10 @@ static JSValueRef jsCocoaObject_getProperty(JSContextRef ctx, JSObjectRef object
{
JSValueRefAndContextRef name = { JSValueMakeString(ctx, propertyNameJS), ctx } ;
JSValueRef hashProperty = [callee JSValueForJSName:name].value;
if (hashProperty && !JSValueIsNull(ctx, hashProperty))
if (hashProperty && !JSValueIsNull(ctx, hashProperty))
{
return hashProperty;
}
}


Expand Down Expand Up @@ -2104,7 +2158,8 @@ static JSValueRef jsCocoaObject_getProperty(JSContextRef ctx, JSObjectRef object
if ([delegate respondsToSelector:@selector(JSCocoa:callMethod:ofObject:argumentCount:arguments:inContext:exception:)])
{
JSValueRef delegateCall = [delegate JSCocoa:jsc callMethod:propertyName ofObject:callee argumentCount:0 arguments:NULL inContext:ctx exception:exception];
if (delegateCall) return delegateCall;
if (delegateCall)
return delegateCall;
}
}

Expand Down Expand Up @@ -2437,7 +2492,7 @@ static bool jsCocoaObject_setProperty(JSContextRef ctx, JSObjectRef object, JSSt
if ([delegate respondsToSelector:@selector(JSCocoa:callMethod:ofObject:argumentCount:arguments:inContext:exception:)])
{
JSValueRef delegateCall = [delegate JSCocoa:jsc callMethod:setterName ofObject:callee argumentCount:0 arguments:NULL inContext:ctx exception:exception];
if (delegateCall) return delegateCall;
if (delegateCall) return !!delegateCall;
}
}

Expand Down Expand Up @@ -2629,6 +2684,29 @@ static JSValueRef jsCocoaObject_callAsFunction_ffi(JSContextRef ctx, JSObjectRef
methodName = superSelector ? superSelector : [NSMutableString stringWithString:privateObject.methodName];
// NSLog(@"calling %@.%@", callee, methodName);

//
// Delegate canCallMethod, callMethod
// Called first so it gets a chance to do handle custom messages
//
if (delegate)
{
// Check if calling is allowed
if ([delegate respondsToSelector:@selector(JSCocoa:canCallMethod:ofObject:argumentCount:arguments:inContext:exception:)])
{
BOOL canCall = [delegate JSCocoa:jsc canCallMethod:methodName ofObject:callee argumentCount:argumentCount arguments:arguments inContext:ctx exception:exception];
if (!canCall)
{
if (!*exception) throwException(ctx, exception, [NSString stringWithFormat:@"Delegate does not allow calling [%@ %@]", callee, methodName]);
return NULL;
}
}
// Check if delegate handles calling
if ([delegate respondsToSelector:@selector(JSCocoa:callMethod:ofObject:argumentCount:arguments:inContext:exception:)])
{
JSValueRef delegateCall = [delegate JSCocoa:jsc callMethod:methodName ofObject:callee argumentCount:argumentCount arguments:arguments inContext:ctx exception:exception];
if (delegateCall) return delegateCall;
}
}

// Instance call
if ([callee class] == callee && [methodName isEqualToString:@"instance"])
Expand Down Expand Up @@ -2661,28 +2739,6 @@ static JSValueRef jsCocoaObject_callAsFunction_ffi(JSContextRef ctx, JSObjectRef
}
}

//
// Delegate canCallMethod, callMethod
//
if (delegate)
{
// Check if calling is allowed
if ([delegate respondsToSelector:@selector(JSCocoa:canCallMethod:ofObject:argumentCount:arguments:inContext:exception:)])
{
BOOL canCall = [delegate JSCocoa:jsc canCallMethod:methodName ofObject:callee argumentCount:argumentCount arguments:arguments inContext:ctx exception:exception];
if (!canCall)
{
if (!*exception) throwException(ctx, exception, [NSString stringWithFormat:@"Delegate does not allow calling [%@ %@]", callee, methodName]);
return NULL;
}
}
// Check if delegate handles calling
if ([delegate respondsToSelector:@selector(JSCocoa:callMethod:ofObject:argumentCount:arguments:inContext:exception:)])
{
JSValueRef delegateCall = [delegate JSCocoa:jsc callMethod:methodName ofObject:callee argumentCount:argumentCount arguments:arguments inContext:ctx exception:exception];
if (delegateCall) return delegateCall;
}
}

// NSDistantObject
if ([callee class] == [NSDistantObject class]) {
Expand Down Expand Up @@ -2944,7 +3000,8 @@ static JSValueRef jsCocoaObject_callAsFunction(JSContextRef ctx, JSObjectRef fun
if ([privateObject jsValueRef] && [privateObject.type isEqualToString:@"jsFunction"])
{
JSObjectRef jsFunction = JSValueToObject(ctx, [privateObject jsValueRef], NULL);
return JSObjectCallAsFunction(ctx, jsFunction, thisObject, argumentCount, arguments, exception);
JSValueRef ret = JSObjectCallAsFunction(ctx, jsFunction, thisObject, argumentCount, arguments, exception);
return ret;
}
// Javascript custom methods
if ([privateObject.methodName isEqualToString:@"toString"] || [privateObject.methodName isEqualToString:@"valueOf"])
Expand Down
1 change: 1 addition & 0 deletions Tests/0 blank.js
@@ -1,2 +1,3 @@

// blank
// log('hello from blank')

0 comments on commit 67f8248

Please sign in to comment.