git-svn-id: http://svn.berlios.de/svnroot/repos/oolite-linux/trunk@3853 127b21dd-08f5-0310-b4b7-95ae10353056
218 lines
4.8 KiB
Objective-C
218 lines
4.8 KiB
Objective-C
/*
|
|
|
|
OOJSFunction.m
|
|
|
|
|
|
JavaScript support for Oolite
|
|
Copyright (C) 2007-2010 David Taylor and Jens Ayton.
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
#import "OOJSFunction.h"
|
|
#import "OOJSScript.h"
|
|
|
|
|
|
@implementation OOJSFunction
|
|
|
|
- (id) initWithFunction:(JSFunction *)function context:(JSContext *)context
|
|
{
|
|
NSParameterAssert(context != NULL);
|
|
|
|
if (function == NULL)
|
|
{
|
|
[self release];
|
|
return nil;
|
|
}
|
|
|
|
if ((self = [super init]))
|
|
{
|
|
_function = function;
|
|
OOJS_AddGCObjectRoot(context, (JSObject **)&_function, "OOJSFunction._function");
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
|
|
- (id) initWithName:(NSString *)name
|
|
scope:(JSObject *)scope
|
|
code:(NSString *)code
|
|
argumentCount:(OOUInteger)argCount
|
|
argumentNames:(const char **)argNames
|
|
fileName:(NSString *)fileName
|
|
lineNumber:(OOUInteger)lineNumber
|
|
context:(JSContext *)context
|
|
{
|
|
BOOL OK = YES;
|
|
BOOL releaseContext = NO;
|
|
jschar *buffer = NULL;
|
|
size_t length;
|
|
JSFunction *function;
|
|
|
|
if (context == NULL)
|
|
{
|
|
context = [[OOJavaScriptEngine sharedEngine] acquireContext];
|
|
releaseContext = YES;
|
|
}
|
|
if (scope == NULL) scope = [[OOJavaScriptEngine sharedEngine] globalObject];
|
|
|
|
if (code == nil || (argCount > 0 && argNames == NULL)) OK = NO;
|
|
|
|
if (OK)
|
|
{
|
|
// jschar and unichar are both defined to be 16-bit elements.
|
|
assert(sizeof(jschar) == sizeof(unichar));
|
|
|
|
length = [code length];
|
|
buffer = malloc(sizeof(jschar) * length);
|
|
if (buffer == NULL) OK = NO;
|
|
}
|
|
|
|
if (OK)
|
|
{
|
|
[code getCharacters:buffer];
|
|
function = JS_CompileUCFunction(context, scope, [name UTF8String], argCount, argNames, buffer, length, [fileName UTF8String], lineNumber);
|
|
if (function == NULL) OK = NO;
|
|
|
|
free(buffer);
|
|
}
|
|
|
|
if (OK)
|
|
{
|
|
self = [self initWithFunction:function context:context];
|
|
}
|
|
else
|
|
{
|
|
DESTROY(self);
|
|
}
|
|
|
|
if (releaseContext) [[OOJavaScriptEngine sharedEngine] releaseContext:context];
|
|
|
|
return self;
|
|
}
|
|
|
|
|
|
- (void) dealloc
|
|
{
|
|
[[OOJavaScriptEngine sharedEngine] removeGCObjectRoot:(JSObject **)&_function];
|
|
|
|
[super dealloc];
|
|
}
|
|
|
|
|
|
- (NSString *) descriptionComponents
|
|
{
|
|
NSString *name = [self name];
|
|
if (name == nil) name = @"<anonymous>";
|
|
return [NSString stringWithFormat:@"%@()", name];
|
|
}
|
|
|
|
|
|
- (NSString *) name
|
|
{
|
|
JSString *name = JS_GetFunctionId(_function);
|
|
return [NSString stringWithJavaScriptString:name];
|
|
}
|
|
|
|
|
|
- (JSFunction *) function
|
|
{
|
|
return _function;
|
|
}
|
|
|
|
|
|
- (BOOL) evaluateWithContext:(JSContext *)context
|
|
scope:(JSObject *)jsThis
|
|
argc:(uintN)argc
|
|
argv:(jsval *)argv
|
|
result:(jsval *)result
|
|
{
|
|
[OOJSScript pushScript:nil];
|
|
OOJSStartTimeLimiter();
|
|
BOOL OK = JS_CallFunction(context, jsThis, _function, argc, argv, result);
|
|
OOJSStopTimeLimiter();
|
|
[OOJSScript popScript:nil];
|
|
|
|
return OK;
|
|
}
|
|
|
|
// Semi-raw evaluation shared by convenience methods below.
|
|
- (BOOL) evaluateWithContext:(JSContext *)context
|
|
scope:(id)jsThis
|
|
arguments:(NSArray *)arguments
|
|
result:(jsval *)result
|
|
{
|
|
OOUInteger i, argc = [arguments count];
|
|
jsval argv[argc];
|
|
|
|
for (i = 0; i < argc; i++)
|
|
{
|
|
argv[i] = [[arguments objectAtIndex:i] javaScriptValueInContext:context];
|
|
OOJS_AddGCValueRoot(context, &argv[i], "OOJSFunction argv");
|
|
}
|
|
|
|
JSObject *scopeObj = NULL;
|
|
BOOL OK = YES;
|
|
if (jsThis != nil) OK = JS_ValueToObject(context, [jsThis javaScriptValueInContext:context], &scopeObj);
|
|
if (OK) OK = [self evaluateWithContext:context
|
|
scope:scopeObj
|
|
argc:argc
|
|
argv:argv
|
|
result:result];
|
|
|
|
for (i = 0; i < argc; i++)
|
|
{
|
|
JS_RemoveValueRoot(context, &argv[i]);
|
|
}
|
|
|
|
return OK;
|
|
}
|
|
|
|
|
|
- (id) evaluateWithContext:(JSContext *)context
|
|
scope:(id)jsThis
|
|
arguments:(NSArray *)arguments
|
|
{
|
|
jsval result;
|
|
BOOL OK = [self evaluateWithContext:context
|
|
scope:jsThis
|
|
arguments:arguments
|
|
result:&result];
|
|
if (!OK) return nil;
|
|
|
|
return JSValueToObject(context, result);
|
|
}
|
|
|
|
|
|
- (BOOL) evaluatePredicateWithContext:(JSContext *)context
|
|
scope:(id)jsThis
|
|
arguments:(NSArray *)arguments
|
|
{
|
|
jsval result;
|
|
BOOL OK = [self evaluateWithContext:context
|
|
scope:jsThis
|
|
arguments:arguments
|
|
result:&result];
|
|
JSBool retval = NO;
|
|
if (OK) OK = JS_ValueToBoolean(context, result, &retval);
|
|
|
|
return OK && retval;
|
|
}
|
|
|
|
@end
|