558bd7543c4c4021982bdfbb597d9d41369d5d17
[WebKit-https.git] / JavaScriptCore / bindings / objc / WebScriptObject.mm
1 /*
2  * Copyright (C) 2003 Apple Computer, Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25 #import <JavaScriptCore/WebScriptObjectPrivate.h>
26
27 #include <JavaScriptCore/internal.h>
28 #include <JavaScriptCore/list.h>
29 #include <JavaScriptCore/value.h>
30
31 #include <objc_jsobject.h>
32 #include <objc_instance.h>
33 #include <objc_utility.h>
34
35 #include <runtime_object.h>
36 #include <runtime_root.h>
37
38 using namespace KJS;
39 using namespace KJS::Bindings;
40
41 @interface WebScriptObjectPrivate : NSObject
42 {
43     KJS::ObjectImp *imp;
44     const Bindings::RootObject *root;
45 }
46 @end
47
48 @implementation WebScriptObjectPrivate
49 @end
50
51 @implementation WebScriptObject
52
53 static void _didExecute(WebScriptObject *obj)
54 {
55     ExecState *exec = obj->_private->root->interpreter()->globalExec();
56     KJSDidExecuteFunctionPtr func = Instance::didExecuteFunction();
57     if (func)
58         func (exec, static_cast<KJS::ObjectImp*>(obj->_private->root->rootObjectImp()));
59 }
60
61 - _initWithObjectImp:(KJS::ObjectImp *)imp root:(const Bindings::RootObject *)root
62 {
63     assert (imp != 0);
64     //assert (root != 0);
65
66     self = [super init];
67
68     _private = [[WebScriptObjectPrivate alloc] init];
69     _private->imp = imp;
70     _private->root = root;    
71
72     addNativeReference (root, imp);
73     
74     return self;
75 }
76
77 - (KJS::ObjectImp *)_imp
78 {
79     return _private->imp;
80 }
81
82 - (void)dealloc
83 {
84     if (_private)
85         removeNativeReference (_private->imp);
86     [_private release];
87     [super dealloc];
88 }
89
90 + (BOOL)throwException:(NSString *)exceptionMessage
91 {
92     NSLog (@"%s:%d:  not yet implemented", __PRETTY_FUNCTION__, __LINE__);
93     return NO;
94 }
95
96 static KJS::List listFromNSArray(ExecState *exec, NSArray *array)
97 {
98     long i, numObjects = array ? [array count] : 0;
99     KJS::List aList;
100     
101     for (i = 0; i < numObjects; i++) {
102         id anObject = [array objectAtIndex:i];
103         aList.append (convertObjcValueToValue(exec, &anObject, ObjcObjectType));
104     }
105     return aList;
106 }
107
108 - (id)callWebScriptMethod:(NSString *)name withArguments:(NSArray *)args
109 {
110     // Lookup the function object.
111     ExecState *exec = _private->root->interpreter()->globalExec();
112     Interpreter::lock();
113     
114     Value v = convertObjcValueToValue(exec, &name, ObjcObjectType);
115     Identifier identifier(v.toString(exec));
116     Value func = _private->imp->get (exec, identifier);
117     Interpreter::unlock();
118     if (func.isNull() || func.type() == UndefinedType) {
119         // Maybe throw an exception here?
120         return 0;
121     }
122
123     // Call the function object.    
124     Interpreter::lock();
125     ObjectImp *funcImp = static_cast<ObjectImp*>(func.imp());
126     Object thisObj = Object(const_cast<ObjectImp*>(_private->imp));
127     List argList = listFromNSArray(exec, args);
128     Value result = funcImp->call (exec, thisObj, argList);
129     Interpreter::unlock();
130
131     // Convert and return the result of the function call.
132     id resultObj = [WebScriptObject _convertValueToObjcValue:result root:_private->root];
133
134     _didExecute(self);
135         
136     return resultObj;
137 }
138
139 - (id)evaluateWebScript:(NSString *)script
140 {
141     ExecState *exec = _private->root->interpreter()->globalExec();
142     Object thisObj = Object(const_cast<ObjectImp*>(_private->imp));
143     Interpreter::lock();
144     Value v = convertObjcValueToValue(exec, &script, ObjcObjectType);
145     KJS::Value result = _private->root->interpreter()->evaluate(v.toString(exec)).value();
146     Interpreter::unlock();
147     
148     id resultObj = [WebScriptObject _convertValueToObjcValue:result root:_private->root];
149
150     _didExecute(self);
151     
152     return resultObj;
153 }
154
155 - (void)setValue:(id)value forKey:(NSString *)key
156 {
157     ExecState *exec = _private->root->interpreter()->globalExec();
158     Interpreter::lock();
159     Value v = convertObjcValueToValue(exec, &key, ObjcObjectType);
160    _private->imp->put (exec, Identifier (v.toString(exec)), (convertObjcValueToValue(exec, &value, ObjcObjectType)));
161     Interpreter::unlock();
162
163     _didExecute(self);
164 }
165
166 - (id)valueForKey:(NSString *)key
167 {
168     ExecState *exec = _private->root->interpreter()->globalExec();
169     Interpreter::lock();
170     Value v = convertObjcValueToValue(exec, &key, ObjcObjectType);
171     Value result = _private->imp->get (exec, Identifier (v.toString(exec)));
172     Interpreter::unlock();
173     
174     id resultObj = [WebScriptObject _convertValueToObjcValue:result root:_private->root];
175
176     _didExecute(self);
177     
178     return resultObj;
179 }
180
181 - (void)removeWebScriptKey:(NSString *)key;
182 {
183     ExecState *exec = _private->root->interpreter()->globalExec();
184     Interpreter::lock();
185     Value v = convertObjcValueToValue(exec, &key, ObjcObjectType);
186     _private->imp->deleteProperty (exec, Identifier (v.toString(exec)));
187     Interpreter::unlock();
188
189     _didExecute(self);
190 }
191
192 - (NSString *)stringRepresentation
193 {
194     Interpreter::lock();
195     Object thisObj = Object(const_cast<ObjectImp*>(_private->imp));
196     ExecState *exec = _private->root->interpreter()->globalExec();
197     
198     id result = convertValueToObjcValue(exec, thisObj, ObjcObjectType).objectValue;
199
200     Interpreter::unlock();
201     
202     id resultObj = [result description];
203
204     _didExecute(self);
205
206     return resultObj;
207 }
208
209 - (id)webScriptValueAtIndex:(unsigned int)index;
210 {
211     ExecState *exec = _private->root->interpreter()->globalExec();
212     Interpreter::lock();
213     Value result = _private->imp->get (exec, (unsigned)index);
214     Interpreter::unlock();
215
216     id resultObj = [WebScriptObject _convertValueToObjcValue:result root:_private->root];
217
218     _didExecute(self);
219
220     return resultObj;
221 }
222
223 - (void)setWebScriptValueAtIndex:(unsigned int)index value:(id)value;
224 {
225     ExecState *exec = _private->root->interpreter()->globalExec();
226     Interpreter::lock();
227     _private->imp->put (exec, (unsigned)index, (convertObjcValueToValue(exec, &value, ObjcObjectType)));
228     Interpreter::unlock();
229
230     _didExecute(self);
231 }
232
233 - (void)setException: (NSString *)description;
234 {
235     ExecState *exec = _private->root->interpreter()->globalExec();
236     Object err = Error::create(exec, GeneralError, [description UTF8String]);
237     exec->setException (err);
238 }
239
240 + (id)_convertValueToObjcValue:(KJS::Value)value root:(const Bindings::RootObject *)root
241 {
242     id result = 0;
243
244     // First see if we have a ObjC instance.
245     if (value.type() == KJS::ObjectType){
246         ObjectImp *objectImp = static_cast<ObjectImp*>(value.imp());
247         if (strcmp(objectImp->classInfo()->className, "RuntimeObject") == 0) {
248             RuntimeObjectImp *imp = static_cast<RuntimeObjectImp *>(value.imp());
249             ObjcInstance *instance = static_cast<ObjcInstance*>(imp->getInternalInstance());
250             if (instance)
251                 result = instance->getObject();
252         }
253         // Convert to a WebScriptObject
254         else {
255             result = [[[WebScriptObject alloc] _initWithObjectImp:objectImp root:root] autorelease];
256         }
257     }
258     
259     // Convert JavaScript String value to NSString?
260     else if (value.type() == KJS::StringType) {
261         StringImp *s = static_cast<KJS::StringImp*>(value.imp());
262         UString u = s->value();
263         
264         NSString *string = [NSString stringWithCharacters:(const unichar*)u.data() length:u.size()];
265         result = string;
266     }
267     
268     // Convert JavaScript Number value to NSNumber?
269     else if (value.type() == KJS::NumberType) {
270         Number n = Number::dynamicCast(value);
271         result = [NSNumber numberWithDouble:n.value()];
272     }
273     
274     // Boolean?
275     return result;
276 }
277
278 @end
279
280
281 @implementation WebUndefined
282
283 static WebUndefined *sharedUndefined = 0;
284
285 + (WebUndefined *)undefined
286 {
287     if (!sharedUndefined)
288         sharedUndefined = [[WebUndefined alloc] init];
289     return sharedUndefined;
290 }
291
292 - (id)initWithCoder:(NSCoder *)coder
293 {
294     return [WebUndefined undefined];
295 }
296
297 - (void)encodeWithCoder:(NSCoder *)encoder
298 {
299 }
300
301 - (id)copyWithZone:(NSZone *)zone
302 {
303     return [WebUndefined undefined];
304 }
305
306 - (id)retain {
307     return [WebUndefined undefined];
308 }
309
310 - (void)release {
311 }
312
313 - (unsigned)retainCount {
314     return 0xFFFFFFFF;
315 }
316
317 - (id)autorelease {
318     return [WebUndefined undefined];
319 }
320
321 - (void)dealloc {
322 }
323
324 - (id)copy {
325     return [WebUndefined undefined];
326 }
327
328 - (id)replacementObjectForPortCoder:(NSPortCoder *)encoder {
329     return [WebUndefined undefined];
330 }
331
332 @end