tizen beta release
[profile/ivi/webkit-efl.git] / Source / JavaScriptGlue / UserObjectImp.cpp
1 /*
2  * Copyright (C) 2005, 2008, 2009 Apple 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  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer. 
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution. 
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission. 
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include "config.h"
30 #include "UserObjectImp.h"
31
32 #include <JavaScriptCore/JSString.h>
33 #include <JavaScriptCore/PropertyNameArray.h>
34
35 const ClassInfo UserObjectImp::s_info = { "UserObject", &JSNonFinalObject::s_info, 0, 0, CREATE_METHOD_TABLE(UserObjectImp) };
36
37 UserObjectImp::UserObjectImp(JSGlobalData& globalData, Structure* structure, JSUserObject* userObject)
38     : JSNonFinalObject(globalData, structure)
39     , fJSUserObject((JSUserObject*)userObject->Retain())
40 {
41 }
42
43 UserObjectImp::~UserObjectImp()
44 {
45     if (fJSUserObject)
46         fJSUserObject->Release();
47 }
48
49 CallType UserObjectImp::getCallData(JSCell* cell, CallData& callData)
50 {
51     UserObjectImp* thisObject = jsCast<UserObjectImp*>(cell);
52     return thisObject->fJSUserObject ? thisObject->fJSUserObject->getCallData(callData) : CallTypeNone;
53 }
54
55 JSValue UserObjectImp::callAsFunction(ExecState *exec)
56 {
57     JSValue result = jsUndefined();
58     JSUserObject* jsThisObj = KJSValueToJSObject(exec->hostThisValue().toThisObject(exec), exec);
59     if (jsThisObj) {
60         CFIndex argCount = exec->argumentCount();
61         CFArrayCallBacks arrayCallBacks;
62         JSTypeGetCFArrayCallBacks(&arrayCallBacks);
63         CFMutableArrayRef jsArgs = CFArrayCreateMutable(0, 0, &arrayCallBacks);
64         if (jsArgs) {
65             for (CFIndex i = 0; i < argCount; i++) {
66                 JSUserObject* jsArg = KJSValueToJSObject(exec->argument(i), exec);
67                 CFArrayAppendValue(jsArgs, (void*)jsArg);
68                 jsArg->Release();
69             }
70         }
71
72         JSUserObject* jsResult;
73         { // scope
74             JSGlueAPICallback apiCallback(exec);
75
76             // getCallData should have guarded against a NULL fJSUserObject.
77             assert(fJSUserObject);
78             jsResult = fJSUserObject->CallFunction(jsThisObj, jsArgs);
79         }
80
81         if (jsResult) {
82             result = JSObjectKJSValue(jsResult);
83             jsResult->Release();
84         }
85
86         ReleaseCFType(jsArgs);
87         jsThisObj->Release();
88     }
89     return result;
90 }
91
92
93 void UserObjectImp::getOwnPropertyNames(JSObject* object, ExecState *exec, PropertyNameArray& propertyNames, EnumerationMode mode)
94 {
95     UserObjectImp* thisObject = jsCast<UserObjectImp*>(object);
96     JSUserObject* ptr = thisObject->GetJSUserObject();
97     if (ptr) {
98         CFArrayRef cfPropertyNames = ptr->CopyPropertyNames();
99         if (cfPropertyNames) {
100             CFIndex count = CFArrayGetCount(cfPropertyNames);
101             CFIndex i;
102             for (i = 0; i < count; i++) {
103                 CFStringRef propertyName = (CFStringRef)CFArrayGetValueAtIndex(cfPropertyNames, i);
104                 propertyNames.add(CFStringToIdentifier(propertyName, exec));
105             }
106             CFRelease(cfPropertyNames);
107         }
108     }
109     JSObject::getOwnPropertyNames(thisObject, exec, propertyNames, mode);
110 }
111
112 JSValue UserObjectImp::userObjectGetter(ExecState*, JSValue slotBase, const Identifier& propertyName)
113 {
114     UserObjectImp *thisObj = static_cast<UserObjectImp *>(asObject(slotBase));
115     // getOwnPropertySlot should have guarded against a null fJSUserObject.
116     assert(thisObj->fJSUserObject);
117     
118     CFStringRef cfPropName = IdentifierToCFString(propertyName);
119     JSUserObject *jsResult = thisObj->fJSUserObject->CopyProperty(cfPropName);
120     ReleaseCFType(cfPropName);
121     JSValue result = JSObjectKJSValue(jsResult);
122     jsResult->Release();
123
124     return result;
125 }
126
127 bool UserObjectImp::getOwnPropertySlot(JSCell* cell, ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
128 {
129     UserObjectImp* thisObject = jsCast<UserObjectImp*>(cell);
130     if (!thisObject->fJSUserObject)
131         return false;
132
133     CFStringRef cfPropName = IdentifierToCFString(propertyName);
134     JSUserObject* jsResult = thisObject->fJSUserObject->CopyProperty(cfPropName);
135     ReleaseCFType(cfPropName);
136     if (jsResult) {
137         slot.setCustom(thisObject, userObjectGetter);
138         jsResult->Release();
139         return true;
140     } else {
141         JSValue kjsValue = thisObject->toPrimitive(exec);
142         if (!kjsValue.isUndefinedOrNull()) {
143             JSObject* kjsObject = kjsValue.toObject(exec);
144             if (kjsObject->getPropertySlot(exec, propertyName, slot))
145                 return true;
146         }
147     }
148     return JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot);
149 }
150
151 void UserObjectImp::put(JSCell* cell, ExecState *exec, const Identifier &propertyName, JSValue value, PutPropertySlot&)
152 {
153     UserObjectImp* thisObject = jsCast<UserObjectImp*>(cell);
154     if (!thisObject->fJSUserObject)
155         return;
156     
157     CFStringRef cfPropName = IdentifierToCFString(propertyName);
158     JSUserObject *jsValueObj = KJSValueToJSObject(value, exec);
159
160     thisObject->fJSUserObject->SetProperty(cfPropName, jsValueObj);
161
162     if (jsValueObj) jsValueObj->Release();
163     ReleaseCFType(cfPropName);
164 }
165
166 JSUserObject* UserObjectImp::GetJSUserObject() const
167 {
168     return fJSUserObject;
169 }
170
171 JSValue UserObjectImp::toPrimitive(ExecState *exec, PreferredPrimitiveType) const
172 {
173     JSValue result = jsUndefined();
174     JSUserObject* jsObjPtr = KJSValueToJSObject(toObject(exec, exec->lexicalGlobalObject()), exec);
175     CFTypeRef cfValue = jsObjPtr ? jsObjPtr->CopyCFValue() : 0;
176     if (cfValue) {
177         CFTypeID cfType = CFGetTypeID(cfValue);  // toPrimitive
178         if (cfValue == GetCFNull()) {
179             result = jsNull();
180         }
181         else if (cfType == CFBooleanGetTypeID()) {
182             if (cfValue == kCFBooleanTrue) {
183                 result = jsBoolean(true);
184             } else {
185                 result = jsBoolean(false);
186             }
187         } else if (cfType == CFStringGetTypeID()) {
188             result = jsString(exec, CFStringToUString((CFStringRef)cfValue));
189         } else if (cfType == CFNumberGetTypeID()) {
190             double d = 0.0;
191             CFNumberGetValue((CFNumberRef)cfValue, kCFNumberDoubleType, &d);
192             result = jsNumber(d);
193         } else if (cfType == CFURLGetTypeID()) {
194             CFURLRef absURL = CFURLCopyAbsoluteURL((CFURLRef)cfValue);
195             if (absURL) {
196                 result = jsString(exec, CFStringToUString(CFURLGetString(absURL)));
197                 ReleaseCFType(absURL);
198             }
199         }
200         ReleaseCFType(cfValue);
201     }
202     if (jsObjPtr)
203         jsObjPtr->Release();
204     return result;
205 }
206
207
208 bool UserObjectImp::toBoolean(ExecState *exec) const
209 {
210     bool result = false;
211     JSUserObject* jsObjPtr = KJSValueToJSObject(toObject(exec, exec->lexicalGlobalObject()), exec);
212     CFTypeRef cfValue = jsObjPtr ? jsObjPtr->CopyCFValue() : 0;
213     if (cfValue)
214     {
215         CFTypeID cfType = CFGetTypeID(cfValue);  // toPrimitive
216         if (cfValue == GetCFNull())
217         {
218             //
219         }
220         else if (cfType == CFBooleanGetTypeID())
221         {
222             if (cfValue == kCFBooleanTrue)
223             {
224                 result = true;
225             }
226         }
227         else if (cfType == CFStringGetTypeID())
228         {
229             if (CFStringGetLength((CFStringRef)cfValue))
230             {
231                 result = true;
232             }
233         }
234         else if (cfType == CFNumberGetTypeID())
235         {
236             if (cfValue != kCFNumberNaN)
237             {
238                 double d;
239                 if (CFNumberGetValue((CFNumberRef)cfValue, kCFNumberDoubleType, &d))
240                 {
241                     if (d != 0)
242                     {
243                         result = true;
244                     }
245                 }
246             }
247         }
248         else if (cfType == CFArrayGetTypeID())
249         {
250             if (CFArrayGetCount((CFArrayRef)cfValue))
251             {
252                 result = true;
253             }
254         }
255         else if (cfType == CFDictionaryGetTypeID())
256         {
257             if (CFDictionaryGetCount((CFDictionaryRef)cfValue))
258             {
259                 result = true;
260             }
261         }
262         else if (cfType == CFSetGetTypeID())
263         {
264             if (CFSetGetCount((CFSetRef)cfValue))
265             {
266                 result = true;
267             }
268         }
269         else if (cfType == CFURLGetTypeID())
270         {
271             CFURLRef absURL = CFURLCopyAbsoluteURL((CFURLRef)cfValue);
272             if (absURL)
273             {
274                 CFStringRef cfStr = CFURLGetString(absURL);
275                 if (cfStr && CFStringGetLength(cfStr))
276                 {
277                     result = true;
278                 }
279                 ReleaseCFType(absURL);
280             }
281         }
282     }
283     if (jsObjPtr) jsObjPtr->Release();
284     ReleaseCFType(cfValue);
285     return result;
286 }
287
288 void UserObjectImp::visitChildren(JSCell* cell, SlotVisitor& visitor)
289 {
290     UserObjectImp* thisObject = jsCast<UserObjectImp*>(cell);
291     JSObject::visitChildren(thisObject, visitor);
292     if (thisObject->fJSUserObject)
293         thisObject->fJSUserObject->Mark();
294 }