Oolite 1.91.0.7604-240417-a536cbe
Loading...
Searching...
No Matches
OOJSCall.m
Go to the documentation of this file.
1/*
2
3OOJSCall.h
4
5Basic JavaScript-to-ObjC bridge implementation.
6
7Oolite
8Copyright (C) 2004-2013 Giles C Williams and contributors
9
10This program is free software; you can redistribute it and/or
11modify it under the terms of the GNU General Public License
12as published by the Free Software Foundation; either version 2
13of the License, or (at your option) any later version.
14
15This program is distributed in the hope that it will be useful,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License
21along with this program; if not, write to the Free Software
22Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
23MA 02110-1301, USA.
24
25*/
26
27#ifndef NDEBUG
28
29
30#import "OOJSCall.h"
32
34#import "ShipEntity.h"
37#import "OOJSVector.h"
38#import "OOJSQuaternion.h"
39
40
65
66
67static MethodType GetMethodType(id object, SEL selector);
69
70
71BOOL OOJSCallObjCObjectMethod(JSContext *context, id object, NSString *oo_jsClassName, uintN argc, jsval *argv, jsval *outResult)
72{
74
75 NSString *selectorString = nil;
76 SEL selector = NULL;
77 NSString *paramString = nil;
78 MethodType type;
79 BOOL haveParameter = NO,
80 error = NO;
81 id result = nil;
82
83 if (argc == 0)
84 {
85 OOJSReportError(context, @"%@.callObjC(): no selector specified.", oo_jsClassName);
86 return NO;
87 }
88
89 if ([object isKindOfClass:[ShipEntity class]])
90 {
91 [PLAYER setScriptTarget:object];
92 }
93
94 selectorString = OOStringFromJSValue(context, argv[0]);
95
96 // Join all parameters together with spaces.
97 if (1 < argc && [selectorString hasSuffix:@":"])
98 {
99 haveParameter = YES;
100 paramString = [NSString concatenationOfStringsFromJavaScriptValues:argv + 1 count:argc - 1 separator:@" " inContext:context];
101 }
102
103 selector = NSSelectorFromString(selectorString);
104
105 if ([object respondsToSelector:selector])
106 {
107 // Validate signature.
108 type = GetMethodType(object, selector);
109
110 if (MethodExpectsParameter(type) && !haveParameter)
111 {
112 OOJSReportError(context, @"%@.callObjC(): method %@ requires a parameter.", oo_jsClassName, selectorString);
113 error = YES;
114 }
115 else
116 {
117 IMP method = [object methodForSelector:selector];
118 switch (type)
119 {
121 [object performSelector:selector withObject:paramString];
122 break;
123
125 result = [object performSelector:selector withObject:paramString];
126 break;
127
129 result = [object performSelector:selector];
130 if ([selectorString hasSuffix:@"_bool"]) result = [NSNumber numberWithBool:OOBooleanFromObject(result, NO)];
131 break;
132
134 [object performSelector:selector];
135 break;
136
144 result = [NSNumber numberWithLongLong:OOCallIntegerMethod(object, selector, method, (OOShaderUniformType)type)];
145 break;
146
148 result = [NSNumber numberWithUnsignedLongLong:OOCallIntegerMethod(object, selector, method, (OOShaderUniformType)type)];
149 break;
150
153 result = [NSNumber numberWithDouble:OOCallFloatMethod(object, selector, method, (OOShaderUniformType)type)];
154 break;
155
157 {
158 Vector v = ((VectorReturnMsgSend)method)(object, selector);
159 *outResult = OBJECT_TO_JSVAL(JSVectorWithVector(context, v));
160 break;
161 }
162
164 {
165 Quaternion q = ((QuaternionReturnMsgSend)method)(object, selector);
166 *outResult = OBJECT_TO_JSVAL(JSQuaternionWithQuaternion(context, q));
167 break;
168 }
169
173 OOJSReportError(context, @"%@.callObjC(): method %@ cannot be called from JavaScript.", oo_jsClassName, selectorString);
174 error = YES;
175 break;
176 }
177 if (result != nil)
178 {
179 *outResult = [result oo_jsValueInContext:context];
180 }
181 }
182 }
183 else
184 {
185 OOJSReportError(context, @"%@.callObjC(): %@ does not respond to method %@.", oo_jsClassName, [object shortDescription], selectorString);
186 error = YES;
187 }
188
189 return !error;
190
192}
193
194
195// Template class providing method signature strings for the four signatures we support.
197
198- (void)voidVoidMethod;
199- (void)voidObjectMethod:(id)object;
200- (id)objectObjectMethod:(id)object;
201
202@end
203
204
205static BOOL SignatureMatch(NSMethodSignature *sig, SEL selector)
206{
207 NSMethodSignature *template = nil;
208
209 template = [OOJSCallMethodSignatureTemplateClass instanceMethodSignatureForSelector:selector];
210 return [sig isEqual:template];
211}
212
213
214static MethodType GetMethodType(id object, SEL selector)
215{
216 NSMethodSignature *sig = [object methodSignatureForSelector:selector];
217
218 if (SignatureMatch(sig, @selector(voidVoidMethod))) return kMethodTypeVoidVoid;
219 if (SignatureMatch(sig, @selector(voidObjectMethod:))) return kMethodTypeVoidObject;
220 if (SignatureMatch(sig, @selector(objectObjectMethod:))) return kMethodTypeObjectObject;
221
223 if (type != kMethodTypeInvalid) return type;
224
225 return kMethodTypeInvalid;
226}
227
228
229@implementation OOJSCallMethodSignatureTemplateClass: NSObject
230
231- (void)voidVoidMethod {}
232
233
234- (void)voidObjectMethod:(id)object {}
235
236
237- (id)objectObjectMethod:(id)object { return nil; }
238
239@end
240
241#endif
BOOL OOBooleanFromObject(id object, BOOL defaultValue)
#define OOINLINE
MethodType
Definition OOJSCall.m:42
@ kMethodTypeVectorVoid
Definition OOJSCall.m:55
@ kMethodTypeFloatVoid
Definition OOJSCall.m:53
@ kMethodTypeUnsignedShortVoid
Definition OOJSCall.m:48
@ kMethodTypeVoidVoid
Definition OOJSCall.m:62
@ kMethodTypeObjectVoid
Definition OOJSCall.m:60
@ kMethodTypeDoubleVoid
Definition OOJSCall.m:54
@ kMethodTypeUnsignedIntVoid
Definition OOJSCall.m:50
@ kMethodTypeLongVoid
Definition OOJSCall.m:51
@ kMethodTypePointVoid
Definition OOJSCall.m:58
@ kMethodTypeVoidObject
Definition OOJSCall.m:63
@ kMethodTypeUnsignedLongVoid
Definition OOJSCall.m:52
@ kMethodTypeUnsignedCharVoid
Definition OOJSCall.m:46
@ kMethodTypeShortVoid
Definition OOJSCall.m:47
@ kMethodTypeQuaternionVoid
Definition OOJSCall.m:56
@ kMethodTypeCharVoid
Definition OOJSCall.m:45
@ kMethodTypeMatrixVoid
Definition OOJSCall.m:57
@ kMethodTypeIntVoid
Definition OOJSCall.m:49
@ kMethodTypeInvalid
Definition OOJSCall.m:43
@ kMethodTypeObjectObject
Definition OOJSCall.m:61
OOINLINE BOOL MethodExpectsParameter(MethodType type)
Definition OOJSCall.m:68
static BOOL SignatureMatch(NSMethodSignature *sig, SEL selector)
Definition OOJSCall.m:205
BOOL OOJSCallObjCObjectMethod(JSContext *context, id object, NSString *oo_jsClassName, uintN argc, jsval *argv, jsval *outResult)
Definition OOJSCall.m:71
static MethodType GetMethodType(id object, SEL selector)
Definition OOJSCall.m:214
#define OOJS_PROFILE_EXIT
#define OOJS_PROFILE_ENTER
JSObject * JSQuaternionWithQuaternion(JSContext *context, Quaternion quaternion) NONNULL_FUNC
JSObject * JSVectorWithVector(JSContext *context, Vector vector) NONNULL_FUNC
Definition OOJSVector.m:159
NSString * OOStringFromJSValue(JSContext *context, jsval value)
void OOJSReportError(JSContext *context, NSString *format,...)
return nil
OOShaderUniformType OOShaderUniformTypeFromMethodSignature(NSMethodSignature *signature)
Vector(* VectorReturnMsgSend)(id, SEL)
@ kOOShaderUniformTypeQuaternion
@ kOOShaderUniformTypeMatrix
@ kOOShaderUniformTypeVector
@ kOOShaderUniformTypeLong
@ kOOShaderUniformTypeUnsignedChar
@ kOOShaderUniformTypeShort
@ kOOShaderUniformTypePoint
@ kOOShaderUniformTypeUnsignedLong
@ kOOShaderUniformTypeFloat
@ kOOShaderUniformTypeUnsignedInt
@ kOOShaderUniformTypeUnsignedShort
@ kOOShaderUniformTypeDouble
@ kOOShaderUniformTypeObject
@ kOOShaderUniformTypeInt
@ kOOShaderUniformTypeChar
@ kOOShaderUniformTypeInvalid
Quaternion(* QuaternionReturnMsgSend)(id, SEL)