webengine/osswebengine/JavaScriptGlue/UserObjectImp.cpp
changeset 0 dd21522fd290
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     1 /*
       
     2  * Copyright (C) 2005 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  *
       
     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 #include <JavaScriptCore/PropertyNameArray.h>
       
    32 
       
    33 const ClassInfo UserObjectImp::info = {"UserObject", 0, 0, 0};
       
    34 
       
    35 UserObjectImp::UserObjectImp(JSUserObject* userObject)
       
    36     : fJSUserObject((JSUserObject*)userObject->Retain())
       
    37 {
       
    38 }
       
    39 
       
    40 UserObjectImp::~UserObjectImp()
       
    41 {
       
    42     if (fJSUserObject)
       
    43         fJSUserObject->Release();
       
    44 }
       
    45 
       
    46 const ClassInfo * UserObjectImp::classInfo() const
       
    47 {
       
    48     return &info;
       
    49 }
       
    50 
       
    51 bool UserObjectImp::implementsCall() const
       
    52 {
       
    53     return fJSUserObject ? fJSUserObject->ImplementsCall() : false;
       
    54 }
       
    55 
       
    56 JSValue *UserObjectImp::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
       
    57 {
       
    58     JSValue *result = jsUndefined();
       
    59     JSUserObject* jsThisObj = KJSValueToJSObject(thisObj, exec);
       
    60     if (jsThisObj) {
       
    61         CFIndex argCount = args.size();
       
    62         CFArrayCallBacks arrayCallBacks;
       
    63         JSTypeGetCFArrayCallBacks(&arrayCallBacks);
       
    64         CFMutableArrayRef jsArgs = CFArrayCreateMutable(0, 0, &arrayCallBacks);
       
    65         if (jsArgs) {
       
    66             for (CFIndex i = 0; i < argCount; i++) {
       
    67                 JSUserObject* jsArg = KJSValueToJSObject(args[i], exec);
       
    68                 CFArrayAppendValue(jsArgs, (void*)jsArg);
       
    69                 jsArg->Release();
       
    70             }
       
    71         }
       
    72 
       
    73         JSUserObject* jsResult;
       
    74         { // scope
       
    75             JSLock::DropAllLocks dropLocks;
       
    76 
       
    77             // implementsCall should have guarded against a NULL fJSUserObject.
       
    78             assert(fJSUserObject);
       
    79             jsResult = fJSUserObject->CallFunction(jsThisObj, jsArgs);
       
    80         }
       
    81 
       
    82         if (jsResult) {
       
    83             result = JSObjectKJSValue(jsResult);
       
    84             jsResult->Release();
       
    85         }
       
    86 
       
    87         ReleaseCFType(jsArgs);
       
    88         jsThisObj->Release();
       
    89     }
       
    90     return result;
       
    91 }
       
    92 
       
    93 
       
    94 void UserObjectImp::getPropertyNames(ExecState *exec, PropertyNameArray& propertyNames)
       
    95 {
       
    96     JSUserObject* ptr = 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));
       
   105             }
       
   106             CFRelease(cfPropertyNames);
       
   107         }
       
   108     }
       
   109     JSObject::getPropertyNames(exec, propertyNames);
       
   110 }
       
   111 
       
   112 JSValue *UserObjectImp::userObjectGetter(ExecState *, JSObject *, const Identifier& propertyName, const PropertySlot& slot)
       
   113 {
       
   114     UserObjectImp *thisObj = static_cast<UserObjectImp *>(slot.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(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
       
   128 {
       
   129     if (!fJSUserObject)
       
   130         return false;
       
   131 
       
   132     CFStringRef cfPropName = IdentifierToCFString(propertyName);
       
   133     JSUserObject *jsResult = fJSUserObject->CopyProperty(cfPropName);
       
   134     ReleaseCFType(cfPropName);
       
   135     if (jsResult) {
       
   136         slot.setCustom(this, userObjectGetter);
       
   137         jsResult->Release();
       
   138         return true;
       
   139     } else {
       
   140         JSValue *kjsValue = toPrimitive(exec);
       
   141         if (kjsValue->type() != NullType && kjsValue->type() != UndefinedType) {
       
   142             JSObject *kjsObject = kjsValue->toObject(exec);
       
   143             if (kjsObject->getPropertySlot(exec, propertyName, slot))
       
   144                 return true;
       
   145         }
       
   146     }
       
   147     return JSObject::getOwnPropertySlot(exec, propertyName, slot);
       
   148 }
       
   149 
       
   150 void UserObjectImp::put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr)
       
   151 {
       
   152     if (!fJSUserObject)
       
   153         return;
       
   154     
       
   155     CFStringRef cfPropName = IdentifierToCFString(propertyName);
       
   156     JSUserObject *jsValueObj = KJSValueToJSObject(value, exec);
       
   157 
       
   158     fJSUserObject->SetProperty(cfPropName, jsValueObj);
       
   159 
       
   160     if (jsValueObj) jsValueObj->Release();
       
   161     ReleaseCFType(cfPropName);
       
   162 }
       
   163 
       
   164 JSUserObject* UserObjectImp::GetJSUserObject() const
       
   165 {
       
   166     return fJSUserObject;
       
   167 }
       
   168 
       
   169 JSValue *UserObjectImp::toPrimitive(ExecState *exec, JSType preferredType) const
       
   170 {
       
   171     JSValue *result = jsUndefined();
       
   172     JSUserObject* jsObjPtr = KJSValueToJSObject(toObject(exec), exec);
       
   173     CFTypeRef cfValue = jsObjPtr ? jsObjPtr->CopyCFValue() : 0;
       
   174     if (cfValue) {
       
   175         CFTypeID cfType = CFGetTypeID(cfValue);  // toPrimitive
       
   176         if (cfValue == GetCFNull()) {
       
   177             result = jsNull();
       
   178         }
       
   179         else if (cfType == CFBooleanGetTypeID()) {
       
   180             if (cfValue == kCFBooleanTrue) {
       
   181                 result = jsBoolean(true);
       
   182             } else {
       
   183                 result = jsBoolean(false);
       
   184             }
       
   185         } else if (cfType == CFStringGetTypeID()) {
       
   186             result = jsString(CFStringToUString((CFStringRef)cfValue));
       
   187         } else if (cfType == CFNumberGetTypeID()) {
       
   188             double d = 0.0;
       
   189             CFNumberGetValue((CFNumberRef)cfValue, kCFNumberDoubleType, &d);
       
   190             result = jsNumber(d);
       
   191         } else if (cfType == CFURLGetTypeID()) {
       
   192             CFURLRef absURL = CFURLCopyAbsoluteURL((CFURLRef)cfValue);
       
   193             if (absURL) {
       
   194                 result = jsString(CFStringToUString(CFURLGetString(absURL)));
       
   195                 ReleaseCFType(absURL);
       
   196             }
       
   197         }
       
   198         ReleaseCFType(cfValue);
       
   199     }
       
   200     if (jsObjPtr)
       
   201         jsObjPtr->Release();
       
   202     return result;
       
   203 }
       
   204 
       
   205 
       
   206 bool UserObjectImp::toBoolean(ExecState *exec) const
       
   207 {
       
   208     bool result = false;
       
   209     JSUserObject* jsObjPtr = KJSValueToJSObject(toObject(exec), exec);
       
   210     CFTypeRef cfValue = jsObjPtr ? jsObjPtr->CopyCFValue() : 0;
       
   211     if (cfValue)
       
   212     {
       
   213         CFTypeID cfType = CFGetTypeID(cfValue);  // toPrimitive
       
   214         if (cfValue == GetCFNull())
       
   215         {
       
   216             //
       
   217         }
       
   218         else if (cfType == CFBooleanGetTypeID())
       
   219         {
       
   220             if (cfValue == kCFBooleanTrue)
       
   221             {
       
   222                 result = true;
       
   223             }
       
   224         }
       
   225         else if (cfType == CFStringGetTypeID())
       
   226         {
       
   227             if (CFStringGetLength((CFStringRef)cfValue))
       
   228             {
       
   229                 result = true;
       
   230             }
       
   231         }
       
   232         else if (cfType == CFNumberGetTypeID())
       
   233         {
       
   234             if (cfValue != kCFNumberNaN)
       
   235             {
       
   236                 double d;
       
   237                 if (CFNumberGetValue((CFNumberRef)cfValue, kCFNumberDoubleType, &d))
       
   238                 {
       
   239                     if (d != 0)
       
   240                     {
       
   241                         result = true;
       
   242                     }
       
   243                 }
       
   244             }
       
   245         }
       
   246         else if (cfType == CFArrayGetTypeID())
       
   247         {
       
   248             if (CFArrayGetCount((CFArrayRef)cfValue))
       
   249             {
       
   250                 result = true;
       
   251             }
       
   252         }
       
   253         else if (cfType == CFDictionaryGetTypeID())
       
   254         {
       
   255             if (CFDictionaryGetCount((CFDictionaryRef)cfValue))
       
   256             {
       
   257                 result = true;
       
   258             }
       
   259         }
       
   260         else if (cfType == CFSetGetTypeID())
       
   261         {
       
   262             if (CFSetGetCount((CFSetRef)cfValue))
       
   263             {
       
   264                 result = true;
       
   265             }
       
   266         }
       
   267         else if (cfType == CFURLGetTypeID())
       
   268         {
       
   269             CFURLRef absURL = CFURLCopyAbsoluteURL((CFURLRef)cfValue);
       
   270             if (absURL)
       
   271             {
       
   272                 CFStringRef cfStr = CFURLGetString(absURL);
       
   273                 if (cfStr && CFStringGetLength(cfStr))
       
   274                 {
       
   275                     result = true;
       
   276                 }
       
   277                 ReleaseCFType(absURL);
       
   278             }
       
   279         }
       
   280     }
       
   281     if (jsObjPtr) jsObjPtr->Release();
       
   282     ReleaseCFType(cfValue);
       
   283     return result;
       
   284 }
       
   285 
       
   286 double UserObjectImp::toNumber(ExecState *exec) const
       
   287 {
       
   288     double result = 0;
       
   289     JSUserObject* jsObjPtr = KJSValueToJSObject(toObject(exec), exec);
       
   290     CFTypeRef cfValue = jsObjPtr ? jsObjPtr->CopyCFValue() : 0;
       
   291     if (cfValue)
       
   292     {
       
   293         CFTypeID cfType = CFGetTypeID(cfValue);
       
   294 
       
   295         if (cfValue == GetCFNull())
       
   296         {
       
   297             //
       
   298         }
       
   299         else if (cfType == CFBooleanGetTypeID())
       
   300         {
       
   301             if (cfValue == kCFBooleanTrue)
       
   302             {
       
   303                 result = 1;
       
   304             }
       
   305         }
       
   306         else if (cfType == CFStringGetTypeID())
       
   307         {
       
   308             result = CFStringGetDoubleValue((CFStringRef)cfValue);
       
   309         }
       
   310         else if (cfType == CFNumberGetTypeID())
       
   311         {
       
   312             CFNumberGetValue((CFNumberRef)cfValue, kCFNumberDoubleType, &result);
       
   313         }
       
   314     }
       
   315     ReleaseCFType(cfValue);
       
   316     if (jsObjPtr) jsObjPtr->Release();
       
   317     return result;
       
   318 }
       
   319 
       
   320 UString UserObjectImp::toString(ExecState *exec) const
       
   321 {
       
   322     UString result;
       
   323     JSUserObject* jsObjPtr = KJSValueToJSObject(toObject(exec), exec);
       
   324     CFTypeRef cfValue = jsObjPtr ? jsObjPtr->CopyCFValue() : 0;
       
   325     if (cfValue)
       
   326     {
       
   327         CFTypeID cfType = CFGetTypeID(cfValue);
       
   328         if (cfValue == GetCFNull())
       
   329         {
       
   330             //
       
   331         }
       
   332         else if (cfType == CFBooleanGetTypeID())
       
   333         {
       
   334             if (cfValue == kCFBooleanTrue)
       
   335             {
       
   336                 result = "true";
       
   337             }
       
   338             else
       
   339             {
       
   340                 result = "false";
       
   341             }
       
   342         }
       
   343         else if (cfType == CFStringGetTypeID())
       
   344         {
       
   345             result = CFStringToUString((CFStringRef)cfValue);
       
   346         }
       
   347         else if (cfType == CFNumberGetTypeID())
       
   348         {
       
   349             if (cfValue == kCFNumberNaN)
       
   350             {
       
   351                 result = "Nan";
       
   352             }
       
   353             else if (CFNumberCompare(kCFNumberPositiveInfinity, (CFNumberRef)cfValue, 0) == 0)
       
   354             {
       
   355                 result = "Infinity";
       
   356             }
       
   357             else if (CFNumberCompare(kCFNumberNegativeInfinity, (CFNumberRef)cfValue, 0) == 0)
       
   358             {
       
   359                 result = "-Infinity";
       
   360             }
       
   361             else
       
   362             {
       
   363                 CFStringRef cfNumStr;
       
   364                 double d = 0;
       
   365                 CFNumberGetValue((CFNumberRef)cfValue, kCFNumberDoubleType, &d);
       
   366                 if (CFNumberIsFloatType((CFNumberRef)cfValue))
       
   367                 {
       
   368                     cfNumStr = CFStringCreateWithFormat(0, 0, CFSTR("%f"), d);
       
   369                 }
       
   370                 else
       
   371                 {
       
   372                     cfNumStr = CFStringCreateWithFormat(0, 0, CFSTR("%.0f"), d);
       
   373                 }
       
   374                 result = CFStringToUString(cfNumStr);
       
   375                 ReleaseCFType(cfNumStr);
       
   376             }
       
   377         }
       
   378         else if (cfType == CFArrayGetTypeID())
       
   379         {
       
   380             //
       
   381         }
       
   382         else if (cfType == CFDictionaryGetTypeID())
       
   383         {
       
   384             //
       
   385         }
       
   386         else if (cfType == CFSetGetTypeID())
       
   387         {
       
   388             //
       
   389         }
       
   390         else if (cfType == CFURLGetTypeID())
       
   391         {
       
   392             CFURLRef absURL = CFURLCopyAbsoluteURL((CFURLRef)cfValue);
       
   393             if (absURL)
       
   394             {
       
   395                 CFStringRef cfStr = CFURLGetString(absURL);
       
   396                 if (cfStr)
       
   397                 {
       
   398                     result = CFStringToUString(cfStr);
       
   399                 }
       
   400                 ReleaseCFType(absURL);
       
   401             }
       
   402         }
       
   403     }
       
   404     ReleaseCFType(cfValue);
       
   405     if (jsObjPtr) jsObjPtr->Release();
       
   406     return result;
       
   407 }
       
   408 
       
   409 void UserObjectImp::mark()
       
   410 {
       
   411     JSObject::mark();
       
   412     if (fJSUserObject)
       
   413         fJSUserObject->Mark();
       
   414 }