2 * Copyright (C) 2005, 2008 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
30 #include "UserObjectImp.h"
32 #include <JavaScriptCore/JSString.h>
33 #include <JavaScriptCore/PropertyNameArray.h>
35 const ClassInfo
UserObjectImp::info
= { "UserObject", 0, 0, 0 };
37 UserObjectImp::UserObjectImp(PassRefPtr
<StructureID
> structure
, JSUserObject
* userObject
)
39 , fJSUserObject((JSUserObject
*)userObject
->Retain())
43 UserObjectImp::~UserObjectImp()
46 fJSUserObject
->Release();
49 const ClassInfo
* UserObjectImp::classInfo() const
54 CallType
UserObjectImp::getCallData(CallData
& callData
)
56 return fJSUserObject
? fJSUserObject
->getCallData(callData
) : CallTypeNone
;
59 JSValue
* UserObjectImp::callAsFunction(ExecState
*exec
, JSObject
*thisObj
, const ArgList
&args
)
61 JSValue
* result
= jsUndefined();
62 JSUserObject
* jsThisObj
= KJSValueToJSObject(thisObj
, exec
);
64 CFIndex argCount
= args
.size();
65 CFArrayCallBacks arrayCallBacks
;
66 JSTypeGetCFArrayCallBacks(&arrayCallBacks
);
67 CFMutableArrayRef jsArgs
= CFArrayCreateMutable(0, 0, &arrayCallBacks
);
69 for (CFIndex i
= 0; i
< argCount
; i
++) {
70 JSUserObject
* jsArg
= KJSValueToJSObject(args
.at(exec
, i
), exec
);
71 CFArrayAppendValue(jsArgs
, (void*)jsArg
);
76 JSUserObject
* jsResult
;
78 JSLock::DropAllLocks
dropLocks(exec
);
80 // getCallData should have guarded against a NULL fJSUserObject.
81 assert(fJSUserObject
);
82 jsResult
= fJSUserObject
->CallFunction(jsThisObj
, jsArgs
);
86 result
= JSObjectKJSValue(jsResult
);
90 ReleaseCFType(jsArgs
);
97 void UserObjectImp::getPropertyNames(ExecState
*exec
, PropertyNameArray
& propertyNames
)
99 JSUserObject
* ptr
= GetJSUserObject();
101 CFArrayRef cfPropertyNames
= ptr
->CopyPropertyNames();
102 if (cfPropertyNames
) {
103 CFIndex count
= CFArrayGetCount(cfPropertyNames
);
105 for (i
= 0; i
< count
; i
++) {
106 CFStringRef propertyName
= (CFStringRef
)CFArrayGetValueAtIndex(cfPropertyNames
, i
);
107 propertyNames
.add(CFStringToIdentifier(propertyName
, exec
));
109 CFRelease(cfPropertyNames
);
112 JSObject::getPropertyNames(exec
, propertyNames
);
115 JSValue
* UserObjectImp::userObjectGetter(ExecState
*, const Identifier
& propertyName
, const PropertySlot
& slot
)
117 UserObjectImp
*thisObj
= static_cast<UserObjectImp
*>(asObject(slot
.slotBase()));
118 // getOwnPropertySlot should have guarded against a null fJSUserObject.
119 assert(thisObj
->fJSUserObject
);
121 CFStringRef cfPropName
= IdentifierToCFString(propertyName
);
122 JSUserObject
*jsResult
= thisObj
->fJSUserObject
->CopyProperty(cfPropName
);
123 ReleaseCFType(cfPropName
);
124 JSValue
* result
= JSObjectKJSValue(jsResult
);
130 bool UserObjectImp::getOwnPropertySlot(ExecState
*exec
, const Identifier
& propertyName
, PropertySlot
& slot
)
135 CFStringRef cfPropName
= IdentifierToCFString(propertyName
);
136 JSUserObject
*jsResult
= fJSUserObject
->CopyProperty(cfPropName
);
137 ReleaseCFType(cfPropName
);
139 slot
.setCustom(this, userObjectGetter
);
143 JSValue
* kjsValue
= toPrimitive(exec
);
144 if (!kjsValue
->isUndefinedOrNull()) {
145 JSObject
*kjsObject
= kjsValue
->toObject(exec
);
146 if (kjsObject
->getPropertySlot(exec
, propertyName
, slot
))
150 return JSObject::getOwnPropertySlot(exec
, propertyName
, slot
);
153 void UserObjectImp::put(ExecState
*exec
, const Identifier
&propertyName
, JSValue
* value
, int attr
)
158 CFStringRef cfPropName
= IdentifierToCFString(propertyName
);
159 JSUserObject
*jsValueObj
= KJSValueToJSObject(value
, exec
);
161 fJSUserObject
->SetProperty(cfPropName
, jsValueObj
);
163 if (jsValueObj
) jsValueObj
->Release();
164 ReleaseCFType(cfPropName
);
167 JSUserObject
* UserObjectImp::GetJSUserObject() const
169 return fJSUserObject
;
172 JSValue
* UserObjectImp::toPrimitive(ExecState
*exec
, JSType
) const
174 JSValue
* result
= jsUndefined();
175 JSUserObject
* jsObjPtr
= KJSValueToJSObject(toObject(exec
), exec
);
176 CFTypeRef cfValue
= jsObjPtr
? jsObjPtr
->CopyCFValue() : 0;
178 CFTypeID cfType
= CFGetTypeID(cfValue
); // toPrimitive
179 if (cfValue
== GetCFNull()) {
182 else if (cfType
== CFBooleanGetTypeID()) {
183 if (cfValue
== kCFBooleanTrue
) {
184 result
= jsBoolean(true);
186 result
= jsBoolean(false);
188 } else if (cfType
== CFStringGetTypeID()) {
189 result
= jsString(exec
, CFStringToUString((CFStringRef
)cfValue
));
190 } else if (cfType
== CFNumberGetTypeID()) {
192 CFNumberGetValue((CFNumberRef
)cfValue
, kCFNumberDoubleType
, &d
);
193 result
= jsNumber(exec
, d
);
194 } else if (cfType
== CFURLGetTypeID()) {
195 CFURLRef absURL
= CFURLCopyAbsoluteURL((CFURLRef
)cfValue
);
197 result
= jsString(exec
, CFStringToUString(CFURLGetString(absURL
)));
198 ReleaseCFType(absURL
);
201 ReleaseCFType(cfValue
);
209 bool UserObjectImp::toBoolean(ExecState
*exec
) const
212 JSUserObject
* jsObjPtr
= KJSValueToJSObject(toObject(exec
), exec
);
213 CFTypeRef cfValue
= jsObjPtr
? jsObjPtr
->CopyCFValue() : 0;
216 CFTypeID cfType
= CFGetTypeID(cfValue
); // toPrimitive
217 if (cfValue
== GetCFNull())
221 else if (cfType
== CFBooleanGetTypeID())
223 if (cfValue
== kCFBooleanTrue
)
228 else if (cfType
== CFStringGetTypeID())
230 if (CFStringGetLength((CFStringRef
)cfValue
))
235 else if (cfType
== CFNumberGetTypeID())
237 if (cfValue
!= kCFNumberNaN
)
240 if (CFNumberGetValue((CFNumberRef
)cfValue
, kCFNumberDoubleType
, &d
))
249 else if (cfType
== CFArrayGetTypeID())
251 if (CFArrayGetCount((CFArrayRef
)cfValue
))
256 else if (cfType
== CFDictionaryGetTypeID())
258 if (CFDictionaryGetCount((CFDictionaryRef
)cfValue
))
263 else if (cfType
== CFSetGetTypeID())
265 if (CFSetGetCount((CFSetRef
)cfValue
))
270 else if (cfType
== CFURLGetTypeID())
272 CFURLRef absURL
= CFURLCopyAbsoluteURL((CFURLRef
)cfValue
);
275 CFStringRef cfStr
= CFURLGetString(absURL
);
276 if (cfStr
&& CFStringGetLength(cfStr
))
280 ReleaseCFType(absURL
);
284 if (jsObjPtr
) jsObjPtr
->Release();
285 ReleaseCFType(cfValue
);
289 double UserObjectImp::toNumber(ExecState
*exec
) const
292 JSUserObject
* jsObjPtr
= KJSValueToJSObject(toObject(exec
), exec
);
293 CFTypeRef cfValue
= jsObjPtr
? jsObjPtr
->CopyCFValue() : 0;
296 CFTypeID cfType
= CFGetTypeID(cfValue
);
298 if (cfValue
== GetCFNull())
302 else if (cfType
== CFBooleanGetTypeID())
304 if (cfValue
== kCFBooleanTrue
)
309 else if (cfType
== CFStringGetTypeID())
311 result
= CFStringGetDoubleValue((CFStringRef
)cfValue
);
313 else if (cfType
== CFNumberGetTypeID())
315 CFNumberGetValue((CFNumberRef
)cfValue
, kCFNumberDoubleType
, &result
);
318 ReleaseCFType(cfValue
);
319 if (jsObjPtr
) jsObjPtr
->Release();
323 UString
UserObjectImp::toString(ExecState
*exec
) const
326 JSUserObject
* jsObjPtr
= KJSValueToJSObject(toObject(exec
), exec
);
327 CFTypeRef cfValue
= jsObjPtr
? jsObjPtr
->CopyCFValue() : 0;
330 CFTypeID cfType
= CFGetTypeID(cfValue
);
331 if (cfValue
== GetCFNull())
335 else if (cfType
== CFBooleanGetTypeID())
337 if (cfValue
== kCFBooleanTrue
)
346 else if (cfType
== CFStringGetTypeID())
348 result
= CFStringToUString((CFStringRef
)cfValue
);
350 else if (cfType
== CFNumberGetTypeID())
352 if (cfValue
== kCFNumberNaN
)
356 else if (CFNumberCompare(kCFNumberPositiveInfinity
, (CFNumberRef
)cfValue
, 0) == 0)
360 else if (CFNumberCompare(kCFNumberNegativeInfinity
, (CFNumberRef
)cfValue
, 0) == 0)
362 result
= "-Infinity";
366 CFStringRef cfNumStr
;
368 CFNumberGetValue((CFNumberRef
)cfValue
, kCFNumberDoubleType
, &d
);
369 if (CFNumberIsFloatType((CFNumberRef
)cfValue
))
371 cfNumStr
= CFStringCreateWithFormat(0, 0, CFSTR("%f"), d
);
375 cfNumStr
= CFStringCreateWithFormat(0, 0, CFSTR("%.0f"), d
);
377 result
= CFStringToUString(cfNumStr
);
378 ReleaseCFType(cfNumStr
);
381 else if (cfType
== CFArrayGetTypeID())
385 else if (cfType
== CFDictionaryGetTypeID())
389 else if (cfType
== CFSetGetTypeID())
393 else if (cfType
== CFURLGetTypeID())
395 CFURLRef absURL
= CFURLCopyAbsoluteURL((CFURLRef
)cfValue
);
398 CFStringRef cfStr
= CFURLGetString(absURL
);
401 result
= CFStringToUString(cfStr
);
403 ReleaseCFType(absURL
);
407 ReleaseCFType(cfValue
);
408 if (jsObjPtr
) jsObjPtr
->Release();
412 void UserObjectImp::mark()
416 fJSUserObject
->Mark();