Changeset 27022 in webkit for trunk/JavaScriptCore/API


Ignore:
Timestamp:
Oct 24, 2007, 11:38:35 PM (18 years ago)
Author:
eseidel
Message:

2007-10-24 Eric Seidel <[email protected]>

Reviewed by Maciej.


Add a JSGlobalObject class and remove the InterpreterMap
http://bugs.webkit.org/show_bug.cgi?id=15681


This required making JSCallbackObject a template class to allow for
JSGlobalObjects with JSCallbackObject functionality.


SunSpider claims this was a 0.5% speedup.

  • API/JSCallbackObject.cpp: (KJS::):
  • API/JSCallbackObject.h:
  • API/JSCallbackObjectFunctions.h: Copied from API/JSCallbackObject.cpp. (KJS::::JSCallbackObject): (KJS::::init): (KJS::::~JSCallbackObject): (KJS::::initializeIfNeeded): (KJS::::className): (KJS::::getOwnPropertySlot): (KJS::::put): (KJS::::deleteProperty): (KJS::::implementsConstruct): (KJS::::construct): (KJS::::implementsHasInstance): (KJS::::hasInstance): (KJS::::implementsCall): (KJS::::callAsFunction): (KJS::::getPropertyNames): (KJS::::toNumber): (KJS::::toString): (KJS::::setPrivate): (KJS::::getPrivate): (KJS::::inherits): (KJS::::cachedValueGetter): (KJS::::staticValueGetter): (KJS::::staticFunctionGetter): (KJS::::callbackGetter):
  • API/JSClassRef.cpp: (OpaqueJSClass::prototype):
  • API/JSContextRef.cpp: (JSGlobalContextCreate):
  • API/JSObjectRef.cpp: (JSObjectMake): (JSObjectGetPrivate): (JSObjectSetPrivate):
  • API/JSValueRef.cpp: (JSValueIsObjectOfClass):
  • JavaScriptCore.exp:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • bindings/c/c_utility.cpp: (KJS::Bindings::convertValueToNPVariant):
  • bindings/jni/jni_jsobject.cpp:
  • bindings/objc/objc_utility.mm: (KJS::Bindings::convertValueToObjcValue):
  • kjs/Context.cpp: (KJS::Context::Context):
  • kjs/ExecState.cpp: (KJS::ExecState::lexicalInterpreter):
  • kjs/JSGlobalObject.h: Added. (KJS::JSGlobalObject::JSGlobalObject): (KJS::JSGlobalObject::isGlobalObject): (KJS::JSGlobalObject::interpreter): (KJS::JSGlobalObject::setInterpreter):
  • kjs/array_instance.cpp:
  • kjs/context.h:
  • kjs/function.cpp: (KJS::FunctionImp::callAsFunction): (KJS::GlobalFuncImp::callAsFunction):
  • kjs/interpreter.cpp: (KJS::Interpreter::Interpreter): (KJS::Interpreter::init): (KJS::Interpreter::~Interpreter): (KJS::Interpreter::globalObject): (KJS::Interpreter::initGlobalObject): (KJS::Interpreter::evaluate):
  • kjs/interpreter.h:
  • kjs/lookup.h: (KJS::cacheGlobalObject):
  • kjs/object.h: (KJS::JSObject::isGlobalObject):
  • kjs/testkjs.cpp:
Location:
trunk/JavaScriptCore/API
Files:
6 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/API/JSCallbackObject.cpp

    r25258 r27022  
    22/*
    33 * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
     4 * Copyright (C) 2007 Eric Seidel <[email protected]>
    45 *
    56 * Redistribution and use in source and binary forms, with or without
     
    2526 */
    2627
    27 #include <wtf/Platform.h>
    2828#include "JSCallbackObject.h"
    29 
    30 #include "APICast.h"
    31 #include "JSCallbackFunction.h"
    32 #include "JSClassRef.h"
    33 #include "JSObjectRef.h"
    34 #include "JSStringRef.h"
    35 #include "PropertyNameArray.h"
    36 #include "internal.h"
    37 #include <wtf/Vector.h>
    3829
    3930namespace KJS {
    4031
    41 const ClassInfo JSCallbackObject::info = { "CallbackObject", 0, 0, 0 };
    42 
    43 JSCallbackObject::JSCallbackObject(ExecState* exec, JSClassRef jsClass, JSValue* prototype, void* data)
    44     : JSObject(prototype)
    45     , m_class(0)
    46     , m_isInitialized(false)
    47 {
    48     init(exec, jsClass, data);
    49 }
    50 
    51 void JSCallbackObject::init(ExecState* exec, JSClassRef jsClass, void* data)
    52 {
    53     m_privateData = data;
    54     JSClassRef oldClass = m_class;
    55     m_class = JSClassRetain(jsClass);
    56     if (oldClass)
    57         JSClassRelease(oldClass);
    58 
    59     if (!exec)
    60         return;
    61 
    62     Vector<JSObjectInitializeCallback, 16> initRoutines;
    63     do {
    64         if (JSObjectInitializeCallback initialize = jsClass->initialize)
    65             initRoutines.append(initialize);
    66     } while ((jsClass = jsClass->parentClass));
    67    
    68     // initialize from base to derived
    69     for (int i = static_cast<int>(initRoutines.size()) - 1; i >= 0; i--) {
    70         JSLock::DropAllLocks dropAllLocks;
    71         JSObjectInitializeCallback initialize = initRoutines[i];
    72         initialize(toRef(exec), toRef(this));
    73     }
    74     m_isInitialized = true;
    75 }
    76 
    77 JSCallbackObject::~JSCallbackObject()
    78 {
    79     JSObjectRef thisRef = toRef(this);
    80    
    81     for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
    82         if (JSObjectFinalizeCallback finalize = jsClass->finalize) {
    83             finalize(thisRef);
    84         }
    85    
    86     JSClassRelease(m_class);
    87 }
    88 
    89 void JSCallbackObject::initializeIfNeeded(ExecState* exec)
    90 {
    91     if (m_isInitialized)
    92         return;
    93     init(exec, m_class, m_privateData);
    94 }
    95 
    96 UString JSCallbackObject::className() const
    97 {
    98     if (!m_class->className.isNull())
    99         return m_class->className;
    100    
    101     return JSObject::className();
    102 }
    103 
    104 bool JSCallbackObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
    105 {
    106     JSContextRef ctx = toRef(exec);
    107     JSObjectRef thisRef = toRef(this);
    108     JSStringRef propertyNameRef = toRef(propertyName.ustring().rep());
    109 
    110     for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass) {
    111         // optional optimization to bypass getProperty in cases when we only need to know if the property exists
    112         if (JSObjectHasPropertyCallback hasProperty = jsClass->hasProperty) {
    113             JSLock::DropAllLocks dropAllLocks;
    114             if (hasProperty(ctx, thisRef, propertyNameRef)) {
    115                 slot.setCustom(this, callbackGetter);
    116                 return true;
    117             }
    118         } else if (JSObjectGetPropertyCallback getProperty = jsClass->getProperty) {
    119             JSLock::DropAllLocks dropAllLocks;
    120             if (JSValueRef value = getProperty(ctx, thisRef, propertyNameRef, toRef(exec->exceptionSlot()))) {
    121                 // cache the value so we don't have to compute it again
    122                 // FIXME: This violates the PropertySlot design a little bit.
    123                 // We should either use this optimization everywhere, or nowhere.
    124                 slot.setCustom(reinterpret_cast<JSObject*>(toJS(value)), cachedValueGetter);
    125                 return true;
    126             }
    127         }
    128 
    129         if (OpaqueJSClass::StaticValuesTable* staticValues = jsClass->staticValues) {
    130             if (staticValues->contains(propertyName.ustring().rep())) {
    131                 slot.setCustom(this, staticValueGetter);
    132                 return true;
    133             }
    134         }
    135        
    136         if (OpaqueJSClass::StaticFunctionsTable* staticFunctions = jsClass->staticFunctions) {
    137             if (staticFunctions->contains(propertyName.ustring().rep())) {
    138                 slot.setCustom(this, staticFunctionGetter);
    139                 return true;
    140             }
    141         }
    142     }
    143 
    144     return JSObject::getOwnPropertySlot(exec, propertyName, slot);
    145 }
    146 
    147 bool JSCallbackObject::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
    148 {
    149     return getOwnPropertySlot(exec, Identifier::from(propertyName), slot);
    150 }
    151 
    152 void JSCallbackObject::put(ExecState* exec, const Identifier& propertyName, JSValue* value, int attr)
    153 {
    154     JSContextRef ctx = toRef(exec);
    155     JSObjectRef thisRef = toRef(this);
    156     JSStringRef propertyNameRef = toRef(propertyName.ustring().rep());
    157     JSValueRef valueRef = toRef(value);
    158 
    159     for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass) {
    160         if (JSObjectSetPropertyCallback setProperty = jsClass->setProperty) {
    161             JSLock::DropAllLocks dropAllLocks;
    162             if (setProperty(ctx, thisRef, propertyNameRef, valueRef, toRef(exec->exceptionSlot())))
    163                 return;
    164         }
    165    
    166         if (OpaqueJSClass::StaticValuesTable* staticValues = jsClass->staticValues) {
    167             if (StaticValueEntry* entry = staticValues->get(propertyName.ustring().rep())) {
    168                 if (entry->attributes & kJSPropertyAttributeReadOnly)
    169                     return;
    170                 if (JSObjectSetPropertyCallback setProperty = entry->setProperty) {
    171                     JSLock::DropAllLocks dropAllLocks;
    172                     if (setProperty(ctx, thisRef, propertyNameRef, valueRef, toRef(exec->exceptionSlot())))
    173                         return;
    174                 } else
    175                     throwError(exec, ReferenceError, "Attempt to set a property that is not settable.");
    176             }
    177         }
    178        
    179         if (OpaqueJSClass::StaticFunctionsTable* staticFunctions = jsClass->staticFunctions) {
    180             if (StaticFunctionEntry* entry = staticFunctions->get(propertyName.ustring().rep())) {
    181                 if (entry->attributes & kJSPropertyAttributeReadOnly)
    182                     return;
    183                 putDirect(propertyName, value, attr); // put as override property
    184                 return;
    185             }
    186         }
    187     }
    188 
    189     return JSObject::put(exec, propertyName, value, attr);
    190 }
    191 
    192 void JSCallbackObject::put(ExecState* exec, unsigned propertyName, JSValue* value, int attr)
    193 {
    194     return put(exec, Identifier::from(propertyName), value, attr);
    195 }
    196 
    197 bool JSCallbackObject::deleteProperty(ExecState* exec, const Identifier& propertyName)
    198 {
    199     JSContextRef ctx = toRef(exec);
    200     JSObjectRef thisRef = toRef(this);
    201     JSStringRef propertyNameRef = toRef(propertyName.ustring().rep());
    202    
    203     for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass) {
    204         if (JSObjectDeletePropertyCallback deleteProperty = jsClass->deleteProperty) {
    205             JSLock::DropAllLocks dropAllLocks;
    206             if (deleteProperty(ctx, thisRef, propertyNameRef, toRef(exec->exceptionSlot())))
    207                 return true;
    208         }
    209 
    210         if (OpaqueJSClass::StaticValuesTable* staticValues = jsClass->staticValues) {
    211             if (StaticValueEntry* entry = staticValues->get(propertyName.ustring().rep())) {
    212                 if (entry->attributes & kJSPropertyAttributeDontDelete)
    213                     return false;
    214                 return true;
    215             }
    216         }
    217        
    218         if (OpaqueJSClass::StaticFunctionsTable* staticFunctions = jsClass->staticFunctions) {
    219             if (StaticFunctionEntry* entry = staticFunctions->get(propertyName.ustring().rep())) {
    220                 if (entry->attributes & kJSPropertyAttributeDontDelete)
    221                     return false;
    222                 return true;
    223             }
    224         }
    225     }
    226 
    227     return JSObject::deleteProperty(exec, propertyName);
    228 }
    229 
    230 bool JSCallbackObject::deleteProperty(ExecState* exec, unsigned propertyName)
    231 {
    232     return deleteProperty(exec, Identifier::from(propertyName));
    233 }
    234 
    235 bool JSCallbackObject::implementsConstruct() const
    236 {
    237     for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
    238         if (jsClass->callAsConstructor)
    239             return true;
    240 
    241     return false;
    242 }
    243 
    244 JSObject* JSCallbackObject::construct(ExecState* exec, const List& args)
    245 {
    246     JSContextRef execRef = toRef(exec);
    247     JSObjectRef thisRef = toRef(this);
    248    
    249     for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass) {
    250         if (JSObjectCallAsConstructorCallback callAsConstructor = jsClass->callAsConstructor) {
    251             int argumentCount = static_cast<int>(args.size());
    252             Vector<JSValueRef, 16> arguments(argumentCount);
    253             for (int i = 0; i < argumentCount; i++)
    254                 arguments[i] = toRef(args[i]);
    255             JSLock::DropAllLocks dropAllLocks;
    256             return toJS(callAsConstructor(execRef, thisRef, argumentCount, arguments.data(), toRef(exec->exceptionSlot())));
    257         }
    258     }
    259    
    260     ASSERT(0); // implementsConstruct should prevent us from reaching here
    261     return 0;
    262 }
    263 
    264 bool JSCallbackObject::implementsHasInstance() const
    265 {
    266     for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
    267         if (jsClass->hasInstance)
    268             return true;
    269 
    270     return false;
    271 }
    272 
    273 bool JSCallbackObject::hasInstance(ExecState *exec, JSValue *value)
    274 {
    275     JSContextRef execRef = toRef(exec);
    276     JSObjectRef thisRef = toRef(this);
    277 
    278     for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
    279         if (JSObjectHasInstanceCallback hasInstance = jsClass->hasInstance) {
    280             JSLock::DropAllLocks dropAllLocks;
    281             return hasInstance(execRef, thisRef, toRef(value), toRef(exec->exceptionSlot()));
    282         }
    283 
    284     ASSERT(0); // implementsHasInstance should prevent us from reaching here
    285     return 0;
    286 }
    287 
    288 
    289 bool JSCallbackObject::implementsCall() const
    290 {
    291     for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
    292         if (jsClass->callAsFunction)
    293             return true;
    294    
    295     return false;
    296 }
    297 
    298 JSValue* JSCallbackObject::callAsFunction(ExecState* exec, JSObject* thisObj, const List &args)
    299 {
    300     JSContextRef execRef = toRef(exec);
    301     JSObjectRef thisRef = toRef(this);
    302     JSObjectRef thisObjRef = toRef(thisObj);
    303 
    304     for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass) {
    305         if (JSObjectCallAsFunctionCallback callAsFunction = jsClass->callAsFunction) {
    306             int argumentCount = static_cast<int>(args.size());
    307             Vector<JSValueRef, 16> arguments(argumentCount);
    308             for (int i = 0; i < argumentCount; i++)
    309                 arguments[i] = toRef(args[i]);
    310             JSLock::DropAllLocks dropAllLocks;
    311             return toJS(callAsFunction(execRef, thisRef, thisObjRef, argumentCount, arguments.data(), toRef(exec->exceptionSlot())));
    312         }
    313     }
    314 
    315     ASSERT(0); // implementsCall should prevent us from reaching here
    316     return 0;
    317 }
    318 
    319 void JSCallbackObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
    320 {
    321     JSContextRef execRef = toRef(exec);
    322     JSObjectRef thisRef = toRef(this);
    323 
    324     for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass) {
    325         if (JSObjectGetPropertyNamesCallback getPropertyNames = jsClass->getPropertyNames) {
    326             JSLock::DropAllLocks dropAllLocks;
    327             getPropertyNames(execRef, thisRef, toRef(&propertyNames));
    328         }
    329 
    330         if (OpaqueJSClass::StaticValuesTable* staticValues = jsClass->staticValues) {
    331             typedef OpaqueJSClass::StaticValuesTable::const_iterator iterator;
    332             iterator end = staticValues->end();
    333             for (iterator it = staticValues->begin(); it != end; ++it) {
    334                 UString::Rep* name = it->first.get();
    335                 StaticValueEntry* entry = it->second;
    336                 if (entry->getProperty && !(entry->attributes & kJSPropertyAttributeDontEnum))
    337                     propertyNames.add(Identifier(name));
    338             }
    339         }
    340 
    341         if (OpaqueJSClass::StaticFunctionsTable* staticFunctions = jsClass->staticFunctions) {
    342             typedef OpaqueJSClass::StaticFunctionsTable::const_iterator iterator;
    343             iterator end = staticFunctions->end();
    344             for (iterator it = staticFunctions->begin(); it != end; ++it) {
    345                 UString::Rep* name = it->first.get();
    346                 StaticFunctionEntry* entry = it->second;
    347                 if (!(entry->attributes & kJSPropertyAttributeDontEnum))
    348                     propertyNames.add(Identifier(name));
    349             }
    350         }
    351     }
    352 
    353     JSObject::getPropertyNames(exec, propertyNames);
    354 }
    355 
    356 double JSCallbackObject::toNumber(ExecState* exec) const
    357 {
    358     JSContextRef ctx = toRef(exec);
    359     JSObjectRef thisRef = toRef(this);
    360 
    361     for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
    362         if (JSObjectConvertToTypeCallback convertToType = jsClass->convertToType) {
    363             JSLock::DropAllLocks dropAllLocks;
    364             if (JSValueRef value = convertToType(ctx, thisRef, kJSTypeNumber, toRef(exec->exceptionSlot())))
    365                 return toJS(value)->getNumber();
    366         }
    367 
    368     return JSObject::toNumber(exec);
    369 }
    370 
    371 UString JSCallbackObject::toString(ExecState* exec) const
    372 {
    373     JSContextRef ctx = toRef(exec);
    374     JSObjectRef thisRef = toRef(this);
    375 
    376     for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
    377         if (JSObjectConvertToTypeCallback convertToType = jsClass->convertToType) {
    378             JSLock::DropAllLocks dropAllLocks;
    379             if (JSValueRef value = convertToType(ctx, thisRef, kJSTypeString, toRef(exec->exceptionSlot())))
    380                 return toJS(value)->getString();
    381         }
    382 
    383     return JSObject::toString(exec);
    384 }
    385 
    386 void JSCallbackObject::setPrivate(void* data)
    387 {
    388     m_privateData = data;
    389 }
    390 
    391 void* JSCallbackObject::getPrivate()
    392 {
    393     return m_privateData;
    394 }
    395 
    396 bool JSCallbackObject::inherits(JSClassRef c) const
    397 {
    398     for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
    399         if (jsClass == c)
    400             return true;
    401 
    402     return false;
    403 }
    404 
    405 JSValue* JSCallbackObject::cachedValueGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot& slot)
    406 {
    407     JSValue* v = slot.slotBase();
    408     ASSERT(v);
    409     return v;
    410 }
    411 
    412 JSValue* JSCallbackObject::staticValueGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
    413 {
    414     ASSERT(slot.slotBase()->inherits(&JSCallbackObject::info));
    415     JSCallbackObject* thisObj = static_cast<JSCallbackObject*>(slot.slotBase());
    416 
    417     JSObjectRef thisRef = toRef(thisObj);
    418     JSStringRef propertyNameRef = toRef(propertyName.ustring().rep());
    419 
    420     for (JSClassRef jsClass = thisObj->m_class; jsClass; jsClass = jsClass->parentClass)
    421         if (OpaqueJSClass::StaticValuesTable* staticValues = jsClass->staticValues)
    422             if (StaticValueEntry* entry = staticValues->get(propertyName.ustring().rep()))
    423                 if (JSObjectGetPropertyCallback getProperty = entry->getProperty) {
    424                     JSLock::DropAllLocks dropAllLocks;
    425                     if (JSValueRef value = getProperty(toRef(exec), thisRef, propertyNameRef, toRef(exec->exceptionSlot())))
    426                         return toJS(value);
    427                 }
    428 
    429     return throwError(exec, ReferenceError, "Static value property defined with NULL getProperty callback.");
    430 }
    431 
    432 JSValue* JSCallbackObject::staticFunctionGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
    433 {
    434     ASSERT(slot.slotBase()->inherits(&JSCallbackObject::info));
    435     JSCallbackObject* thisObj = static_cast<JSCallbackObject*>(slot.slotBase());
    436 
    437     if (JSValue* cachedOrOverrideValue = thisObj->getDirect(propertyName))
    438         return cachedOrOverrideValue;
    439 
    440     for (JSClassRef jsClass = thisObj->m_class; jsClass; jsClass = jsClass->parentClass) {
    441         if (OpaqueJSClass::StaticFunctionsTable* staticFunctions = jsClass->staticFunctions) {
    442             if (StaticFunctionEntry* entry = staticFunctions->get(propertyName.ustring().rep())) {
    443                 if (JSObjectCallAsFunctionCallback callAsFunction = entry->callAsFunction) {
    444                     JSObject* o = new JSCallbackFunction(exec, callAsFunction, propertyName);
    445                     thisObj->putDirect(propertyName, o, entry->attributes);
    446                     return o;
    447                 }
    448             }
    449         }
    450     }
    451 
    452     return throwError(exec, ReferenceError, "Static function property defined with NULL callAsFunction callback.");
    453 }
    454 
    455 JSValue* JSCallbackObject::callbackGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
    456 {
    457     ASSERT(slot.slotBase()->inherits(&JSCallbackObject::info));
    458     JSCallbackObject* thisObj = static_cast<JSCallbackObject*>(slot.slotBase());
    459 
    460     JSObjectRef thisRef = toRef(thisObj);
    461     JSStringRef propertyNameRef = toRef(propertyName.ustring().rep());
    462 
    463     for (JSClassRef jsClass = thisObj->m_class; jsClass; jsClass = jsClass->parentClass)
    464         if (JSObjectGetPropertyCallback getProperty = jsClass->getProperty) {
    465             JSLock::DropAllLocks dropAllLocks;
    466             if (JSValueRef value = getProperty(toRef(exec), thisRef, propertyNameRef, toRef(exec->exceptionSlot())))
    467                 return toJS(value);
    468         }
    469 
    470     return throwError(exec, ReferenceError, "hasProperty callback returned true for a property that doesn't exist.");
    471 }
     32// Define the two types of JSCallbackObjects we support.
     33template <> const ClassInfo JSCallbackObject<JSObject>::info = { "CallbackObject", 0, 0, 0 };
     34template <> const ClassInfo JSCallbackObject<JSGlobalObject>::info = { "CallbackGlobalObject", 0, 0, 0 };
    47235
    47336} // namespace KJS
  • trunk/JavaScriptCore/API/JSCallbackObject.h

    r25257 r27022  
    22/*
    33 * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
     4 * Copyright (C) 2007 Eric Seidel <[email protected]>
    45 *
    56 * Redistribution and use in source and binary forms, with or without
     
    3435namespace KJS {
    3536
    36 class JSCallbackObject : public JSObject
     37template <class Base>
     38class JSCallbackObject : public Base
    3739{
    3840public:
     
    9395} // namespace KJS
    9496
     97// include the actual template class implementation
     98#include "JSCallbackObjectFunctions.h"
     99
    95100#endif // JSCallbackObject_h
  • trunk/JavaScriptCore/API/JSCallbackObjectFunctions.h

    r27021 r27022  
    22/*
    33 * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
     4 * Copyright (C) 2007 Eric Seidel <[email protected]>
    45 *
    56 * Redistribution and use in source and binary forms, with or without
     
    2627
    2728#include <wtf/Platform.h>
    28 #include "JSCallbackObject.h"
    29 
    3029#include "APICast.h"
    3130#include "JSCallbackFunction.h"
    3231#include "JSClassRef.h"
    3332#include "JSObjectRef.h"
     33#include "JSGlobalObject.h"
    3434#include "JSStringRef.h"
    3535#include "PropertyNameArray.h"
     
    3939namespace KJS {
    4040
    41 const ClassInfo JSCallbackObject::info = { "CallbackObject", 0, 0, 0 };
    42 
    43 JSCallbackObject::JSCallbackObject(ExecState* exec, JSClassRef jsClass, JSValue* prototype, void* data)
    44     : JSObject(prototype)
     41template <class Base>
     42JSCallbackObject<Base>::JSCallbackObject(ExecState* exec, JSClassRef jsClass, JSValue* prototype, void* data)
     43    : Base(prototype)
    4544    , m_class(0)
    4645    , m_isInitialized(false)
     
    4948}
    5049
    51 void JSCallbackObject::init(ExecState* exec, JSClassRef jsClass, void* data)
     50template <class Base>
     51void JSCallbackObject<Base>::init(ExecState* exec, JSClassRef jsClass, void* data)
    5252{
    5353    m_privateData = data;
     
    5656    if (oldClass)
    5757        JSClassRelease(oldClass);
    58 
     58   
    5959    if (!exec)
    6060        return;
    61 
     61   
    6262    Vector<JSObjectInitializeCallback, 16> initRoutines;
    6363    do {
     
    7575}
    7676
    77 JSCallbackObject::~JSCallbackObject()
     77template <class Base>
     78JSCallbackObject<Base>::~JSCallbackObject()
    7879{
    7980    JSObjectRef thisRef = toRef(this);
     
    8384            finalize(thisRef);
    8485        }
    85    
     86           
    8687    JSClassRelease(m_class);
    8788}
    8889
    89 void JSCallbackObject::initializeIfNeeded(ExecState* exec)
     90template <class Base>
     91void JSCallbackObject<Base>::initializeIfNeeded(ExecState* exec)
    9092{
    9193    if (m_isInitialized)
     
    9496}
    9597
    96 UString JSCallbackObject::className() const
     98template <class Base>
     99UString JSCallbackObject<Base>::className() const
    97100{
    98101    if (!m_class->className.isNull())
     
    102105}
    103106
    104 bool JSCallbackObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
     107template <class Base>
     108bool JSCallbackObject<Base>::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
    105109{
    106110    JSContextRef ctx = toRef(exec);
    107111    JSObjectRef thisRef = toRef(this);
    108112    JSStringRef propertyNameRef = toRef(propertyName.ustring().rep());
    109 
     113   
    110114    for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass) {
    111115        // optional optimization to bypass getProperty in cases when we only need to know if the property exists
     
    126130            }
    127131        }
    128 
     132       
    129133        if (OpaqueJSClass::StaticValuesTable* staticValues = jsClass->staticValues) {
    130134            if (staticValues->contains(propertyName.ustring().rep())) {
     
    141145        }
    142146    }
    143 
     147   
    144148    return JSObject::getOwnPropertySlot(exec, propertyName, slot);
    145149}
    146150
    147 bool JSCallbackObject::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
     151template <class Base>
     152bool JSCallbackObject<Base>::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
    148153{
    149154    return getOwnPropertySlot(exec, Identifier::from(propertyName), slot);
    150155}
    151156
    152 void JSCallbackObject::put(ExecState* exec, const Identifier& propertyName, JSValue* value, int attr)
     157template <class Base>
     158void JSCallbackObject<Base>::put(ExecState* exec, const Identifier& propertyName, JSValue* value, int attr)
    153159{
    154160    JSContextRef ctx = toRef(exec);
     
    156162    JSStringRef propertyNameRef = toRef(propertyName.ustring().rep());
    157163    JSValueRef valueRef = toRef(value);
    158 
     164   
    159165    for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass) {
    160166        if (JSObjectSetPropertyCallback setProperty = jsClass->setProperty) {
     
    163169                return;
    164170        }
    165    
     171       
    166172        if (OpaqueJSClass::StaticValuesTable* staticValues = jsClass->staticValues) {
    167173            if (StaticValueEntry* entry = staticValues->get(propertyName.ustring().rep())) {
     
    181187                if (entry->attributes & kJSPropertyAttributeReadOnly)
    182188                    return;
    183                 putDirect(propertyName, value, attr); // put as override property
     189                JSCallbackObject<Base>::putDirect(propertyName, value, attr); // put as override property
    184190                return;
    185191            }
    186192        }
    187193    }
    188 
     194   
    189195    return JSObject::put(exec, propertyName, value, attr);
    190196}
    191197
    192 void JSCallbackObject::put(ExecState* exec, unsigned propertyName, JSValue* value, int attr)
     198template <class Base>
     199void JSCallbackObject<Base>::put(ExecState* exec, unsigned propertyName, JSValue* value, int attr)
    193200{
    194201    return put(exec, Identifier::from(propertyName), value, attr);
    195202}
    196203
    197 bool JSCallbackObject::deleteProperty(ExecState* exec, const Identifier& propertyName)
     204template <class Base>
     205bool JSCallbackObject<Base>::deleteProperty(ExecState* exec, const Identifier& propertyName)
    198206{
    199207    JSContextRef ctx = toRef(exec);
     
    207215                return true;
    208216        }
    209 
     217       
    210218        if (OpaqueJSClass::StaticValuesTable* staticValues = jsClass->staticValues) {
    211219            if (StaticValueEntry* entry = staticValues->get(propertyName.ustring().rep())) {
     
    224232        }
    225233    }
    226 
     234   
    227235    return JSObject::deleteProperty(exec, propertyName);
    228236}
    229237
    230 bool JSCallbackObject::deleteProperty(ExecState* exec, unsigned propertyName)
     238template <class Base>
     239bool JSCallbackObject<Base>::deleteProperty(ExecState* exec, unsigned propertyName)
    231240{
    232241    return deleteProperty(exec, Identifier::from(propertyName));
    233242}
    234243
    235 bool JSCallbackObject::implementsConstruct() const
     244template <class Base>
     245bool JSCallbackObject<Base>::implementsConstruct() const
    236246{
    237247    for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
    238248        if (jsClass->callAsConstructor)
    239249            return true;
    240 
     250   
    241251    return false;
    242252}
    243253
    244 JSObject* JSCallbackObject::construct(ExecState* exec, const List& args)
     254template <class Base>
     255JSObject* JSCallbackObject<Base>::construct(ExecState* exec, const List& args)
    245256{
    246257    JSContextRef execRef = toRef(exec);
     
    262273}
    263274
    264 bool JSCallbackObject::implementsHasInstance() const
     275template <class Base>
     276bool JSCallbackObject<Base>::implementsHasInstance() const
    265277{
    266278    for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
    267279        if (jsClass->hasInstance)
    268280            return true;
    269 
     281   
    270282    return false;
    271283}
    272284
    273 bool JSCallbackObject::hasInstance(ExecState *exec, JSValue *value)
     285template <class Base>
     286bool JSCallbackObject<Base>::hasInstance(ExecState *exec, JSValue *value)
    274287{
    275288    JSContextRef execRef = toRef(exec);
    276289    JSObjectRef thisRef = toRef(this);
    277 
     290   
    278291    for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
    279292        if (JSObjectHasInstanceCallback hasInstance = jsClass->hasInstance) {
     
    281294            return hasInstance(execRef, thisRef, toRef(value), toRef(exec->exceptionSlot()));
    282295        }
    283 
    284     ASSERT(0); // implementsHasInstance should prevent us from reaching here
     296           
     297    ASSERT_NOT_REACHED(); // implementsHasInstance should prevent us from reaching here
    285298    return 0;
    286299}
    287300
    288301
    289 bool JSCallbackObject::implementsCall() const
     302template <class Base>
     303bool JSCallbackObject<Base>::implementsCall() const
    290304{
    291305    for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
     
    296310}
    297311
    298 JSValue* JSCallbackObject::callAsFunction(ExecState* exec, JSObject* thisObj, const List &args)
     312template <class Base>
     313JSValue* JSCallbackObject<Base>::callAsFunction(ExecState* exec, JSObject* thisObj, const List &args)
    299314{
    300315    JSContextRef execRef = toRef(exec);
    301316    JSObjectRef thisRef = toRef(this);
    302317    JSObjectRef thisObjRef = toRef(thisObj);
    303 
     318   
    304319    for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass) {
    305320        if (JSObjectCallAsFunctionCallback callAsFunction = jsClass->callAsFunction) {
     
    312327        }
    313328    }
    314 
    315     ASSERT(0); // implementsCall should prevent us from reaching here
     329   
     330    ASSERT_NOT_REACHED(); // implementsCall should prevent us from reaching here
    316331    return 0;
    317332}
    318333
    319 void JSCallbackObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
     334template <class Base>
     335void JSCallbackObject<Base>::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
    320336{
    321337    JSContextRef execRef = toRef(exec);
    322338    JSObjectRef thisRef = toRef(this);
    323 
     339   
    324340    for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass) {
    325341        if (JSObjectGetPropertyNamesCallback getPropertyNames = jsClass->getPropertyNames) {
     
    327343            getPropertyNames(execRef, thisRef, toRef(&propertyNames));
    328344        }
    329 
     345       
    330346        if (OpaqueJSClass::StaticValuesTable* staticValues = jsClass->staticValues) {
    331347            typedef OpaqueJSClass::StaticValuesTable::const_iterator iterator;
     
    338354            }
    339355        }
    340 
     356       
    341357        if (OpaqueJSClass::StaticFunctionsTable* staticFunctions = jsClass->staticFunctions) {
    342358            typedef OpaqueJSClass::StaticFunctionsTable::const_iterator iterator;
     
    350366        }
    351367    }
    352 
     368   
    353369    JSObject::getPropertyNames(exec, propertyNames);
    354370}
    355371
    356 double JSCallbackObject::toNumber(ExecState* exec) const
     372template <class Base>
     373double JSCallbackObject<Base>::toNumber(ExecState* exec) const
    357374{
    358375    JSContextRef ctx = toRef(exec);
    359376    JSObjectRef thisRef = toRef(this);
    360 
     377   
    361378    for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
    362379        if (JSObjectConvertToTypeCallback convertToType = jsClass->convertToType) {
     
    365382                return toJS(value)->getNumber();
    366383        }
    367 
     384           
    368385    return JSObject::toNumber(exec);
    369386}
    370387
    371 UString JSCallbackObject::toString(ExecState* exec) const
     388template <class Base>
     389UString JSCallbackObject<Base>::toString(ExecState* exec) const
    372390{
    373391    JSContextRef ctx = toRef(exec);
    374392    JSObjectRef thisRef = toRef(this);
    375 
     393   
    376394    for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
    377395        if (JSObjectConvertToTypeCallback convertToType = jsClass->convertToType) {
     
    380398                return toJS(value)->getString();
    381399        }
    382 
     400           
    383401    return JSObject::toString(exec);
    384402}
    385403
    386 void JSCallbackObject::setPrivate(void* data)
     404template <class Base>
     405void JSCallbackObject<Base>::setPrivate(void* data)
    387406{
    388407    m_privateData = data;
    389408}
    390409
    391 void* JSCallbackObject::getPrivate()
     410template <class Base>
     411void* JSCallbackObject<Base>::getPrivate()
    392412{
    393413    return m_privateData;
    394414}
    395415
    396 bool JSCallbackObject::inherits(JSClassRef c) const
     416template <class Base>
     417bool JSCallbackObject<Base>::inherits(JSClassRef c) const
    397418{
    398419    for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
    399420        if (jsClass == c)
    400421            return true;
    401 
     422   
    402423    return false;
    403424}
    404425
    405 JSValue* JSCallbackObject::cachedValueGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot& slot)
     426template <class Base>
     427JSValue* JSCallbackObject<Base>::cachedValueGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot& slot)
    406428{
    407429    JSValue* v = slot.slotBase();
     
    410432}
    411433
    412 JSValue* JSCallbackObject::staticValueGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
     434template <class Base>
     435JSValue* JSCallbackObject<Base>::staticValueGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
    413436{
    414437    ASSERT(slot.slotBase()->inherits(&JSCallbackObject::info));
    415438    JSCallbackObject* thisObj = static_cast<JSCallbackObject*>(slot.slotBase());
    416 
     439   
    417440    JSObjectRef thisRef = toRef(thisObj);
    418441    JSStringRef propertyNameRef = toRef(propertyName.ustring().rep());
    419 
     442   
    420443    for (JSClassRef jsClass = thisObj->m_class; jsClass; jsClass = jsClass->parentClass)
    421444        if (OpaqueJSClass::StaticValuesTable* staticValues = jsClass->staticValues)
     
    426449                        return toJS(value);
    427450                }
    428 
     451                   
    429452    return throwError(exec, ReferenceError, "Static value property defined with NULL getProperty callback.");
    430453}
    431454
    432 JSValue* JSCallbackObject::staticFunctionGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
     455template <class Base>
     456JSValue* JSCallbackObject<Base>::staticFunctionGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
    433457{
    434458    ASSERT(slot.slotBase()->inherits(&JSCallbackObject::info));
    435459    JSCallbackObject* thisObj = static_cast<JSCallbackObject*>(slot.slotBase());
    436 
     460   
    437461    if (JSValue* cachedOrOverrideValue = thisObj->getDirect(propertyName))
    438462        return cachedOrOverrideValue;
    439 
     463   
    440464    for (JSClassRef jsClass = thisObj->m_class; jsClass; jsClass = jsClass->parentClass) {
    441465        if (OpaqueJSClass::StaticFunctionsTable* staticFunctions = jsClass->staticFunctions) {
     
    449473        }
    450474    }
    451 
     475   
    452476    return throwError(exec, ReferenceError, "Static function property defined with NULL callAsFunction callback.");
    453477}
    454478
    455 JSValue* JSCallbackObject::callbackGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
     479template <class Base>
     480JSValue* JSCallbackObject<Base>::callbackGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
    456481{
    457482    ASSERT(slot.slotBase()->inherits(&JSCallbackObject::info));
    458483    JSCallbackObject* thisObj = static_cast<JSCallbackObject*>(slot.slotBase());
    459 
     484   
    460485    JSObjectRef thisRef = toRef(thisObj);
    461486    JSStringRef propertyNameRef = toRef(propertyName.ustring().rep());
    462 
     487   
    463488    for (JSClassRef jsClass = thisObj->m_class; jsClass; jsClass = jsClass->parentClass)
    464489        if (JSObjectGetPropertyCallback getProperty = jsClass->getProperty) {
     
    467492                return toJS(value);
    468493        }
    469 
     494           
    470495    return throwError(exec, ReferenceError, "hasProperty callback returned true for a property that doesn't exist.");
    471496}
  • trunk/JavaScriptCore/API/JSClassRef.cpp

    r24809 r27022  
    157157        if (!parentPrototype)
    158158            parentPrototype = exec->dynamicInterpreter()->builtinObjectPrototype();
    159         cachedPrototype = new JSCallbackObject(exec, prototypeClass, parentPrototype, this); // set ourself as the object's private data, so it can clear our reference on destruction
     159        cachedPrototype = new JSCallbackObject<JSObject>(exec, prototypeClass, parentPrototype, this); // set ourself as the object's private data, so it can clear our reference on destruction
    160160    }
    161161    return cachedPrototype;
  • trunk/JavaScriptCore/API/JSContextRef.cpp

    r25257 r27022  
    3030
    3131#include "JSCallbackObject.h"
     32#include "JSGlobalObject.h"
    3233#include "completion.h"
    3334#include "interpreter.h"
     
    4041    JSLock lock;
    4142
    42     JSObject* globalObject;
     43    JSGlobalObject* globalObject;
    4344    if (globalObjectClass)
    4445        // Specify jsNull() as the prototype.  Interpreter will fix it up to point at builtinObjectPrototype() in its constructor
    45         globalObject = new JSCallbackObject(0, globalObjectClass, jsNull(), 0);
     46        globalObject = new JSCallbackObject<JSGlobalObject>(0, globalObjectClass, jsNull(), 0);
    4647    else
    47         globalObject = new JSObject();
     48        globalObject = new JSGlobalObject();
    4849
    4950    Interpreter* interpreter = new Interpreter(globalObject); // adds the built-in object prototype to the global object
    5051    if (globalObjectClass)
    51         static_cast<JSCallbackObject*>(globalObject)->initializeIfNeeded(interpreter->globalExec());
     52        static_cast<JSCallbackObject<JSGlobalObject>*>(globalObject)->initializeIfNeeded(interpreter->globalExec());
    5253    JSGlobalContextRef ctx = reinterpret_cast<JSGlobalContextRef>(interpreter->globalExec());
    5354    return JSGlobalContextRetain(ctx);
  • trunk/JavaScriptCore/API/JSObjectRef.cpp

    r26625 r27022  
    3333#include "JSCallbackObject.h"
    3434#include "JSClassRef.h"
     35#include "JSGlobalObject.h"
    3536
    3637#include "identifier.h"
     
    7879        jsPrototype = exec->lexicalInterpreter()->builtinObjectPrototype();
    7980
    80     return toRef(new JSCallbackObject(exec, jsClass, jsPrototype, data));
     81    return toRef(new JSCallbackObject<JSObject>(exec, jsClass, jsPrototype, data));
    8182}
    8283
     
    236237    JSObject* jsObject = toJS(object);
    237238   
    238     if (jsObject->inherits(&JSCallbackObject::info))
    239         return static_cast<JSCallbackObject*>(jsObject)->getPrivate();
     239    if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::info))
     240        return static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivate();
     241    else if (jsObject->inherits(&JSCallbackObject<JSObject>::info))
     242        return static_cast<JSCallbackObject<JSObject>*>(jsObject)->getPrivate();
    240243   
    241244    return 0;
     
    246249    JSObject* jsObject = toJS(object);
    247250   
    248     if (jsObject->inherits(&JSCallbackObject::info)) {
    249         static_cast<JSCallbackObject*>(jsObject)->setPrivate(data);
     251    if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::info)) {
     252        static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivate(data);
     253        return true;
     254    } else if (jsObject->inherits(&JSCallbackObject<JSObject>::info)) {
     255        static_cast<JSCallbackObject<JSObject>*>(jsObject)->setPrivate(data);
    250256        return true;
    251257    }
  • trunk/JavaScriptCore/API/JSValueRef.cpp

    r19193 r27022  
    3131
    3232#include <kjs/JSType.h>
     33#include <kjs/JSGlobalObject.h>
    3334#include <kjs/internal.h>
    3435#include <kjs/operations.h>
     
    105106    JSValue* jsValue = toJS(value);
    106107   
    107     if (JSObject* o = jsValue->getObject())
    108         if (o->inherits(&JSCallbackObject::info))
    109             return static_cast<JSCallbackObject*>(o)->inherits(jsClass);
     108    if (JSObject* o = jsValue->getObject()) {
     109        if (o->inherits(&JSCallbackObject<JSGlobalObject>::info))
     110            return static_cast<JSCallbackObject<JSGlobalObject>*>(o)->inherits(jsClass);
     111        else if (o->inherits(&JSCallbackObject<JSObject>::info))
     112            return static_cast<JSCallbackObject<JSObject>*>(o)->inherits(jsClass);
     113    }
    110114    return false;
    111115}
Note: See TracChangeset for help on using the changeset viewer.