#include "config.h"
#include "JSClassRef.h"
#include "APICast.h"
#include "JSCallbackObject.h"
#include "JSObjectRef.h"
#include <kjs/JSGlobalObject.h>
#include <kjs/identifier.h>
#include <kjs/object_object.h>
using namespace KJS;
const JSClassDefinition kJSClassDefinitionEmpty = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
OpaqueJSClass::OpaqueJSClass(const JSClassDefinition* definition, OpaqueJSClass* protoClass)
: className(definition->className)
, parentClass(definition->parentClass)
, prototypeClass(0)
, staticValues(0)
, staticFunctions(0)
, initialize(definition->initialize)
, finalize(definition->finalize)
, hasProperty(definition->hasProperty)
, getProperty(definition->getProperty)
, setProperty(definition->setProperty)
, deleteProperty(definition->deleteProperty)
, getPropertyNames(definition->getPropertyNames)
, callAsFunction(definition->callAsFunction)
, callAsConstructor(definition->callAsConstructor)
, hasInstance(definition->hasInstance)
, convertToType(definition->convertToType)
, cachedPrototype(0)
{
if (const JSStaticValue* staticValue = definition->staticValues) {
staticValues = new StaticValuesTable();
while (staticValue->name) {
staticValues->add(Identifier(staticValue->name).ustring().rep(),
new StaticValueEntry(staticValue->getProperty, staticValue->setProperty, staticValue->attributes));
++staticValue;
}
}
if (const JSStaticFunction* staticFunction = definition->staticFunctions) {
staticFunctions = new StaticFunctionsTable();
while (staticFunction->name) {
staticFunctions->add(Identifier(staticFunction->name).ustring().rep(),
new StaticFunctionEntry(staticFunction->callAsFunction, staticFunction->attributes));
++staticFunction;
}
}
if (protoClass)
prototypeClass = JSClassRetain(protoClass);
}
OpaqueJSClass::~OpaqueJSClass()
{
if (staticValues) {
deleteAllValues(*staticValues);
delete staticValues;
}
if (staticFunctions) {
deleteAllValues(*staticFunctions);
delete staticFunctions;
}
if (prototypeClass)
JSClassRelease(prototypeClass);
}
JSClassRef OpaqueJSClass::createNoAutomaticPrototype(const JSClassDefinition* definition)
{
return new OpaqueJSClass(definition, 0);
}
void clearReferenceToPrototype(JSObjectRef prototype)
{
OpaqueJSClass* jsClass = static_cast<OpaqueJSClass*>(JSObjectGetPrivate(prototype));
ASSERT(jsClass);
jsClass->cachedPrototype = 0;
}
JSClassRef OpaqueJSClass::create(const JSClassDefinition* definition)
{
if (const JSStaticFunction* staticFunctions = definition->staticFunctions) {
JSClassDefinition protoDefinition = kJSClassDefinitionEmpty;
protoDefinition.staticFunctions = staticFunctions;
protoDefinition.finalize = clearReferenceToPrototype;
OpaqueJSClass* protoClass = new OpaqueJSClass(&protoDefinition, 0);
JSClassDefinition objectDefinition = *definition;
objectDefinition.staticFunctions = 0;
return new OpaqueJSClass(&objectDefinition, protoClass);
}
return new OpaqueJSClass(definition, 0);
}
JSObject* OpaqueJSClass::prototype(JSContextRef ctx)
{
if (!prototypeClass)
return 0;
ExecState* exec = toJS(ctx);
if (!cachedPrototype) {
JSObject* parentPrototype = 0;
if (parentClass)
parentPrototype = parentClass->prototype(ctx); if (!parentPrototype)
parentPrototype = exec->dynamicGlobalObject()->objectPrototype();
cachedPrototype = new JSCallbackObject<JSObject>(exec, prototypeClass, parentPrototype, this); }
return cachedPrototype;
}