Rubber stamped by hyatt.
[WebKit-https.git] / JavaScriptGlue / UserObjectImp.cpp
1 #include "UserObjectImp.h"
2
3 const ClassInfo UserObjectImp::info = {"UserObject", 0, 0, 0};
4
5 class UserObjectPrototypeImp : public UserObjectImp {
6   public:
7     UserObjectPrototypeImp();
8         static UserObjectPrototypeImp* GlobalUserObjectPrototypeImp();
9   private:
10         static UserObjectPrototypeImp* sUserObjectPrototypeImp;
11 };
12
13 UserObjectPrototypeImp* UserObjectPrototypeImp::sUserObjectPrototypeImp = NULL;
14
15 UserObjectPrototypeImp::UserObjectPrototypeImp()
16   : UserObjectImp()
17 {
18 }
19
20 UserObjectPrototypeImp* UserObjectPrototypeImp::GlobalUserObjectPrototypeImp()
21 {
22         if (!sUserObjectPrototypeImp)
23         {
24                 sUserObjectPrototypeImp = new UserObjectPrototypeImp();
25                 static ProtectedValue protectPrototype = Value(sUserObjectPrototypeImp);
26         }
27         return sUserObjectPrototypeImp;
28 }
29
30
31 UserObjectImp::UserObjectImp(): ObjectImp(), fJSUserObject(NULL)
32 {
33 }
34
35 UserObjectImp::UserObjectImp(JSUserObject* userObject) : 
36         ObjectImp(Object(UserObjectPrototypeImp::GlobalUserObjectPrototypeImp())), 
37         fJSUserObject((JSUserObject*)userObject->Retain()) 
38
39 }
40
41 UserObjectImp::~UserObjectImp() 
42 {
43         if (fJSUserObject)
44         {
45                 fJSUserObject->Release(); 
46         }
47 }
48     
49 const ClassInfo * UserObjectImp::classInfo() const 
50 {
51         return &info; 
52 }
53         
54 bool    UserObjectImp::implementsCall() const 
55 {
56         return fJSUserObject ? fJSUserObject->ImplementsCall() : false; 
57 }
58
59 Value   UserObjectImp::call(ExecState *exec, Object &thisObj, const List &args)
60 {
61         Value result = Undefined();
62         JSUserObject* jsThisObj = KJSValueToJSObject(thisObj, exec);
63         if (jsThisObj)
64         {
65                 CFIndex argCount = args.size();
66                 CFArrayCallBacks arrayCallBacks;
67                 JSTypeGetCFArrayCallBacks(&arrayCallBacks);
68                 CFMutableArrayRef jsArgs = CFArrayCreateMutable(NULL, 0, &arrayCallBacks);
69                 if (jsArgs)
70                 {
71                         for (CFIndex i = 0; i < argCount;  i++)
72                         {
73                                 JSUserObject* jsArg = KJSValueToJSObject(args[i], exec);
74                                 CFArrayAppendValue(jsArgs, (void*)jsArg);
75                                 jsArg->Release();
76                         }
77                 }
78
79 #if 0
80                 JSUserObject* jsResult = fJSUserObject->CallFunction(jsThisObj, jsArgs);
81 #else
82                 int lockCount = Interpreter::lockCount();
83                 int i;
84                 for (i = 0; i < lockCount; i++)
85                 {
86                         Interpreter::unlock();
87                 }
88
89                 JSUserObject* jsResult = fJSUserObject->CallFunction(jsThisObj, jsArgs);
90
91                 for (i = 0; i < lockCount; i++)
92                 {
93                         Interpreter::lock();
94                 }
95 #endif
96                 if (jsResult)
97                 {
98                         result = JSObjectKJSValue(jsResult);
99                         jsResult->Release();
100                 }
101
102                 ReleaseCFType(jsArgs);
103                 jsThisObj->Release();
104         }
105         return result;
106 }
107
108
109 ReferenceList UserObjectImp::propList(ExecState *exec, bool recursive)
110 {
111         ReferenceList propList;
112         JSUserObject* ptr = GetJSUserObject();
113         if (ptr)
114         {
115                 Object theObject = toObject(exec);
116                 CFArrayRef propertyNames = ptr->CopyPropertyNames();
117                 if (propertyNames)
118                 {
119                         CFIndex count = CFArrayGetCount(propertyNames);
120                         CFIndex i;
121                         for (i = 0; i < count; i++)
122                         {
123                                 CFStringRef propertyName = (CFStringRef)CFArrayGetValueAtIndex(propertyNames, i);
124                                 propList.append(Reference(theObject, CFStringToIdentifier(propertyName)));
125                         }
126                         CFRelease(propertyNames);
127                 }
128         }
129         return propList;
130 }
131
132 bool UserObjectImp::hasProperty(ExecState *exec, const Identifier &propertyName) const
133 {
134         Value prop = get(exec, propertyName);
135         if (prop.type() != UndefinedType)
136         {
137                 return true;
138         }
139         return ObjectImp::hasProperty(exec, propertyName);
140 }
141
142 #if JAG_PINK_OR_LATER
143 Value   UserObjectImp::get(ExecState *exec, const Identifier &propertyName) const
144 {
145         Value result = Undefined();
146         CFStringRef     cfPropName = IdentifierToCFString(propertyName);
147         JSUserObject* jsResult = fJSUserObject->CopyProperty(cfPropName);
148         if (jsResult)
149         {
150                 result = JSObjectKJSValue(jsResult);
151                 jsResult->Release();
152         }
153         else
154         {
155                 Value kjsValue = toPrimitive(exec);
156                 if (kjsValue.type() != NullType && kjsValue.type() != UndefinedType)
157                 {
158                         Object kjsObject = kjsValue.toObject(exec);
159                         Value kjsObjectProp = kjsObject.get(exec, propertyName);
160                         result = kjsObjectProp;
161                 }
162         }
163         ReleaseCFType(cfPropName);
164         return result;
165
166 }
167
168 void    UserObjectImp::put(ExecState *exec, const Identifier &propertyName, const Value &value, int attr)
169 {
170         CFStringRef     cfPropName = IdentifierToCFString(propertyName);
171         JSUserObject* jsValueObj = KJSValueToJSObject(value, exec);
172
173         fJSUserObject->SetProperty(cfPropName, jsValueObj);
174
175         if (jsValueObj) jsValueObj->Release();  
176         ReleaseCFType(cfPropName);
177 }
178 #else   //JAG_PINK_OR_LATER
179 Value   UserObjectImp::get(ExecState* exec, const UString& propertyName) const
180 {
181         Value result = Undefined();
182         CFStringRef     cfPropName = UStringToCFString(propertyName);
183         JSUserObject* jsResult = fJSUserObject->CopyProperty(cfPropName);
184         if (jsResult)
185         {
186                 result = JSObjectKJSValue(jsResult);
187                 jsResult->Release();
188         }
189         else
190         {
191                 Value kjsValue = toPrimitive(exec);
192                 if (kjsValue != Null() && kjsValue != Undefined())
193                 {
194                         Object kjsObject = kjsValue.toObject(exec);
195                         Value kjsObjectProp = kjsObject.get(exec, propertyName);
196                         result = kjsObjectProp;
197                 }
198         }
199         ReleaseCFType(cfPropName);
200         return result;
201
202 }
203
204 void    UserObjectImp::put(ExecState* exec, const UString& propertyName, const Value& value, int attr)
205 {
206         CFStringRef     cfPropName = UStringToCFString(propertyName);
207         JSUserObject* jsValueObj = KJSValueToJSObject(value, exec);
208
209         fJSUserObject->SetProperty(cfPropName, jsValueObj);
210
211         if (jsValueObj) jsValueObj->Release();  
212         ReleaseCFType(cfPropName);
213 }
214 #endif  //JAG_PINK_OR_LATER
215         
216 JSUserObject* UserObjectImp::GetJSUserObject() const 
217
218         return fJSUserObject; 
219 }
220
221
222
223 Value UserObjectImp::toPrimitive(ExecState *exec, Type preferredType) const
224 {
225         Value result = Undefined();
226         JSUserObject* jsObjPtr = KJSValueToJSObject(toObject(exec), exec);
227         CFTypeRef cfValue = jsObjPtr ? jsObjPtr->CopyCFValue() : NULL;
228         if (cfValue)
229         {
230                 CFTypeID cfType = CFGetTypeID(cfValue);  // toPrimitive
231                 if (cfValue == GetCFNull())
232                 {
233                         result = Null();
234                 }
235                 else if (cfType == CFBooleanGetTypeID())
236                 {
237                         if (cfValue == kCFBooleanTrue)
238                         {
239                                 result = KJS::Boolean(true);
240                         }
241                         else 
242                         {
243                                 result = KJS::Boolean(false);
244                         }
245                 }
246                 else if (cfType == CFStringGetTypeID())
247                 {
248                         result = KJS::String(CFStringToUString((CFStringRef)cfValue));
249                 }
250                 else if (cfType == CFNumberGetTypeID())
251                 {
252                         double d = 0.0;
253                         CFNumberGetValue((CFNumberRef)cfValue, kCFNumberDoubleType, &d);
254                         result = KJS::Number(d);
255                 }
256                 else if (cfType == CFURLGetTypeID())
257                 {
258                         CFURLRef absURL = CFURLCopyAbsoluteURL((CFURLRef)cfValue);
259                         if (absURL)
260                         {
261                                 result = KJS::String(CFStringToUString(CFURLGetString(absURL)));
262                                 ReleaseCFType(absURL);
263                         }
264                 }               
265                 ReleaseCFType(cfValue);
266         }
267         if (jsObjPtr) jsObjPtr->Release();
268         return result;
269 }
270
271
272 bool UserObjectImp::toBoolean(ExecState *exec) const
273 {
274         bool result = false;
275         JSUserObject* jsObjPtr = KJSValueToJSObject(toObject(exec), exec);
276         CFTypeRef cfValue = jsObjPtr ? jsObjPtr->CopyCFValue() : NULL;
277         if (cfValue)
278         {
279                 CFTypeID cfType = CFGetTypeID(cfValue);  // toPrimitive
280                 if (cfValue == GetCFNull())
281                 {
282                         //
283                 }
284                 else if (cfType == CFBooleanGetTypeID())
285                 {
286                         if (cfValue == kCFBooleanTrue)
287                         {
288                                 result = true;
289                         }
290                 }
291                 else if (cfType == CFStringGetTypeID())
292                 {
293                         if (CFStringGetLength((CFStringRef)cfValue))
294                         {
295                                 result = true;
296                         }
297                 }
298                 else if (cfType == CFNumberGetTypeID())
299                 {
300                         if (cfValue != kCFNumberNaN)
301                         {
302                                 double d;
303                                 if (CFNumberGetValue((CFNumberRef)cfValue, kCFNumberDoubleType, &d))
304                                 {
305                                         if (d != 0)
306                                         {
307                                                 result = true;
308                                         }
309                                 }
310                         }
311                 }
312                 else if (cfType == CFArrayGetTypeID())
313                 {
314                         if (CFArrayGetCount((CFArrayRef)cfValue))
315                         {
316                                 result = true;
317                         }
318                 }
319                 else if (cfType == CFDictionaryGetTypeID())
320                 {
321                         if (CFDictionaryGetCount((CFDictionaryRef)cfValue))
322                         {
323                                 result = true;
324                         }
325                 }
326                 else if (cfType == CFSetGetTypeID())
327                 {
328                         if (CFSetGetCount((CFSetRef)cfValue))
329                         {
330                                 result = true;
331                         }
332                 }
333                 else if (cfType == CFURLGetTypeID())
334                 {
335                         CFURLRef absURL = CFURLCopyAbsoluteURL((CFURLRef)cfValue);
336                         if (absURL)
337                         {
338                                 CFStringRef cfStr = CFURLGetString(absURL);
339                                 if (cfStr && CFStringGetLength(cfStr))
340                                 {
341                                         result = true;
342                                 }
343                                 ReleaseCFType(absURL);
344                         }
345                 }
346         }
347         if (jsObjPtr) jsObjPtr->Release();
348         ReleaseCFType(cfValue);
349         return result;
350 }
351
352 double UserObjectImp::toNumber(ExecState *exec) const
353 {
354         double result = 0;
355         JSUserObject* jsObjPtr = KJSValueToJSObject(toObject(exec), exec);
356         CFTypeRef cfValue = jsObjPtr ? jsObjPtr->CopyCFValue() : NULL;
357         if (cfValue)
358         {
359                 CFTypeID cfType = CFGetTypeID(cfValue);
360                 
361                 if (cfValue == GetCFNull())
362                 {
363                         //
364                 }
365                 else if (cfType == CFBooleanGetTypeID())
366                 {
367                         if (cfValue == kCFBooleanTrue)
368                         {
369                                 result = 1;
370                         }
371                 }
372                 else if (cfType == CFStringGetTypeID())
373                 {
374                         result = CFStringGetDoubleValue((CFStringRef)cfValue);
375                 }
376                 else if (cfType == CFNumberGetTypeID())
377                 {
378                         CFNumberGetValue((CFNumberRef)cfValue, kCFNumberDoubleType, &result);           
379                 }
380         }
381         ReleaseCFType(cfValue);
382         if (jsObjPtr) jsObjPtr->Release();
383         return result;
384 }
385
386 UString UserObjectImp::toString(ExecState *exec) const
387 {
388         UString result;
389         JSUserObject* jsObjPtr = KJSValueToJSObject(toObject(exec), exec);
390         CFTypeRef cfValue = jsObjPtr ? jsObjPtr->CopyCFValue() : NULL;
391         if (cfValue)
392         {
393                 CFTypeID cfType = CFGetTypeID(cfValue);
394                 if (cfValue == GetCFNull())
395                 {
396                         //
397                 }
398                 else if (cfType == CFBooleanGetTypeID())
399                 {
400                         if (cfValue == kCFBooleanTrue)
401                         {
402                                 result = "true";
403                         }
404                         else
405                         {
406                                 result = "false";
407                         }
408                 }
409                 else if (cfType == CFStringGetTypeID())
410                 {
411                         result = CFStringToUString((CFStringRef)cfValue);
412                 }
413                 else if (cfType == CFNumberGetTypeID())
414                 {
415                         if (cfValue == kCFNumberNaN)
416                         {
417                                 result = "Nan";
418                         }
419                         else if (CFNumberCompare(kCFNumberPositiveInfinity, (CFNumberRef)cfValue, NULL) == 0)
420                         {
421                                 result = "Infinity";
422                         }
423                         else if (CFNumberCompare(kCFNumberNegativeInfinity, (CFNumberRef)cfValue, NULL) == 0)
424                         {
425                                 result = "-Infinity";
426                         }
427                         else
428                         {
429                                 CFStringRef cfNumStr = NULL;
430                                 if (CFNumberIsFloatType((CFNumberRef)cfValue))
431                                 {
432                                         double d = 0;
433                                         CFNumberGetValue((CFNumberRef)cfValue, kCFNumberDoubleType, &d);
434                                         cfNumStr = CFStringCreateWithFormat(NULL, NULL, CFSTR("%f"), (float)d);
435                                 }
436                                 else
437                                 {
438                                         int i = 0;
439                                         CFNumberGetValue((CFNumberRef)cfValue, kCFNumberIntType, &i);
440                                         cfNumStr = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), (int)i);
441                                 }
442                                 
443                                 if (cfNumStr)
444                                 {
445                                         result = CFStringToUString(cfNumStr);
446                                         ReleaseCFType(cfNumStr);
447                                 }                               
448                         }
449                 }
450                 else if (cfType == CFArrayGetTypeID())
451                 {
452                         //
453                 }
454                 else if (cfType == CFDictionaryGetTypeID())
455                 {
456                         //
457                 }
458                 else if (cfType == CFSetGetTypeID())
459                 {
460                         //
461                 }
462                 else if (cfType == CFURLGetTypeID())
463                 {
464                         CFURLRef absURL = CFURLCopyAbsoluteURL((CFURLRef)cfValue);
465                         if (absURL)
466                         {
467                                 CFStringRef cfStr = CFURLGetString(absURL);
468                                 if (cfStr)
469                                 {
470                                         result = CFStringToUString(cfStr);
471                                 }
472                                 ReleaseCFType(absURL);
473                         }
474                 }               
475         }
476         ReleaseCFType(cfValue);
477         if (jsObjPtr) jsObjPtr->Release();
478         return result;
479 }
480
481 void UserObjectImp::mark()
482 {
483         ObjectImp::mark(); // call parent to mark self
484         if (fJSUserObject)
485         {
486                 fJSUserObject->Mark(); // mark child
487         }
488 }