Oolite 1.91.0.7604-240417-a536cbe
Loading...
Searching...
No Matches
OOJSFunction.m
Go to the documentation of this file.
1/*
2
3OOJSFunction.m
4
5
6JavaScript support for Oolite
7Copyright (C) 2007-2013 David Taylor and Jens Ayton.
8
9This program is free software; you can redistribute it and/or
10modify it under the terms of the GNU General Public License
11as published by the Free Software Foundation; either version 2
12of the License, or (at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with this program; if not, write to the Free Software
21Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22MA 02110-1301, USA.
23
24*/
25
26#import "OOJSFunction.h"
27#import "OOJSScript.h"
29
30
31@implementation OOJSFunction
32
33- (id) initWithFunction:(JSFunction *)function context:(JSContext *)context
34{
35 NSParameterAssert(context != NULL);
36
37 if (function == NULL)
38 {
39 [self release];
40 return nil;
41 }
42
43 if ((self = [super init]))
44 {
45 _function = function;
46 OOJSAddGCObjectRoot(context, (JSObject **)&_function, "OOJSFunction._function");
47 _name = [OOStringFromJSString(context, JS_GetFunctionId(function)) retain];
48
49 [[NSNotificationCenter defaultCenter] addObserver:self
50 selector:@selector(deleteJSValue)
51 name:kOOJavaScriptEngineWillResetNotification
53 }
54
55 return self;
56}
57
58
59- (id) initWithName:(NSString *)name
60 scope:(JSObject *)scope
61 code:(NSString *)code
62 argumentCount:(NSUInteger)argCount
63 argumentNames:(const char **)argNames
64 fileName:(NSString *)fileName
65 lineNumber:(NSUInteger)lineNumber
66 context:(JSContext *)context
67{
68 BOOL OK = YES;
69 BOOL releaseContext = NO;
70 jschar *buffer = NULL;
71 size_t length = 0;
72 JSFunction *function;
73
74 if (context == NULL)
75 {
76 context = OOJSAcquireContext();
77 releaseContext = YES;
78 }
79 if (scope == NULL) scope = [[OOJavaScriptEngine sharedEngine] globalObject];
80
81 if (code == nil || (argCount > 0 && argNames == NULL)) OK = NO;
82
83 if (OK)
84 {
85 // jschar and unichar are both defined to be 16-bit elements.
86 assert(sizeof(jschar) == sizeof(unichar));
87
88 length = [code length];
89 buffer = malloc(sizeof(jschar) * length);
90 if (buffer == NULL) OK = NO;
91 }
92
93 if (OK)
94 {
95 assert(argCount < UINT32_MAX);
96
97 [code getCharacters:buffer];
98
99 function = JS_CompileUCFunction(context, scope, [name UTF8String], (uint32_t)argCount, argNames, buffer, length, [fileName UTF8String], (uint32_t)lineNumber);
100 if (function == NULL) OK = NO;
101
102 free(buffer);
103 }
104
105 if (OK)
106 {
107 self = [self initWithFunction:function context:context];
108 }
109 else
110 {
111 DESTROY(self);
112 }
113
114 if (releaseContext) OOJSRelinquishContext(context);
115
116 return self;
117}
118
119
120- (void) deleteJSValue
121{
122 if (_function != NULL)
123 {
124 JSContext *context = OOJSAcquireContext();
125 JS_RemoveObjectRoot(context, (JSObject **)&_function);
126 OOJSRelinquishContext(context);
127
128 _function = NULL;
129 [[NSNotificationCenter defaultCenter] removeObserver:self
130 name:kOOJavaScriptEngineWillResetNotification
132 }
133}
134
135
136- (void) dealloc
137{
138 [self deleteJSValue];
139 DESTROY(_name);
140
141 [super dealloc];
142}
143
144
145- (NSString *) descriptionComponents
146{
147 NSString *name = [self name];
148 if (name == nil) name = @"<anonymous>";
149 return [NSString stringWithFormat:@"%@()", name];
150}
151
152
153- (NSString *) name
154{
155 return _name;
156}
157
158
159- (JSFunction *) function
160{
161 return _function;
162}
163
164
165- (jsval) functionValue
166{
167 if (EXPECT(_function != NULL))
168 {
169 return OBJECT_TO_JSVAL(JS_GetFunctionObject(_function));
170 }
171 else
172 {
173 return JSVAL_NULL;
174 }
175
176}
177
178
179- (BOOL) evaluateWithContext:(JSContext *)context
180 scope:(JSObject *)jsThis
181 argc:(uintN)argc
182 argv:(jsval *)argv
183 result:(jsval *)result
184{
187 BOOL OK = JS_CallFunction(context, jsThis, _function, argc, argv, result);
189 [OOJSScript popScript:nil];
190
191 return OK;
192}
193
194// Semi-raw evaluation shared by convenience methods below.
195- (BOOL) evaluateWithContext:(JSContext *)context
196 scope:(id)jsThis
197 arguments:(NSArray *)arguments
198 result:(jsval *)result
199{
200 NSUInteger i, argc = [arguments count];
201 assert(argc < UINT32_MAX);
202 jsval argv[argc];
203
204 for (i = 0; i < argc; i++)
205 {
206 argv[i] = [[arguments objectAtIndex:i] oo_jsValueInContext:context];
207 OOJSAddGCValueRoot(context, &argv[i], "OOJSFunction argv");
208 }
209
210 JSObject *scopeObj = NULL;
211 BOOL OK = YES;
212 if (jsThis != nil) OK = JS_ValueToObject(context, [jsThis oo_jsValueInContext:context], &scopeObj);
213 if (OK) OK = [self evaluateWithContext:context
214 scope:scopeObj
215 argc:(uint32_t)argc
216 argv:argv
217 result:result];
218
219 for (i = 0; i < argc; i++)
220 {
221 JS_RemoveValueRoot(context, &argv[i]);
222 }
223
224 return OK;
225}
226
227
228- (id) evaluateWithContext:(JSContext *)context
229 scope:(id)jsThis
230 arguments:(NSArray *)arguments
231{
232 jsval result;
233 BOOL OK = [self evaluateWithContext:context
234 scope:jsThis
235 arguments:arguments
236 result:&result];
237 if (!OK) return nil;
238
239 return OOJSNativeObjectFromJSValue(context, result);
240}
241
242
243- (BOOL) evaluatePredicateWithContext:(JSContext *)context
244 scope:(id)jsThis
245 arguments:(NSArray *)arguments
246{
247 jsval result;
248 BOOL OK = [self evaluateWithContext:context
249 scope:jsThis
250 arguments:arguments
251 result:&result];
252 JSBool retval = NO;
253 if (OK) OK = JS_ValueToBoolean(context, result, &retval);
254 return OK && retval;
255}
256
257@end
#define DESTROY(x)
Definition OOCocoa.h:77
#define EXPECT(x)
#define OOJSStopTimeLimiter()
#define OOJSStartTimeLimiter()
id OOJSNativeObjectFromJSValue(JSContext *context, jsval value)
OOINLINE JSContext * OOJSAcquireContext(void)
#define OOJSAddGCObjectRoot(context, root, name)
OOINLINE void OOJSRelinquishContext(JSContext *context)
#define OOJSAddGCValueRoot(context, root, name)
return nil
jsval functionValue()
NSString * descriptionComponents()
JSFunction * function()
JSFunction * _function
NSString * name()
NSString * _name
void pushScript:(OOJSScript *script)
Definition OOJSScript.m:537
void popScript:(OOJSScript *script)
Definition OOJSScript.m:550
OOJavaScriptEngine * sharedEngine()