JSObjectRef thisRef = toRef(this);
do {
- if (JSObjectInitializeCallback initialize = jsClass->callbacks.initialize)
+ if (JSObjectInitializeCallback initialize = jsClass->initialize)
initialize(context, thisRef, toRef(exec->exceptionSlot()));
- } while ((jsClass = jsClass->parent));
+ } while ((jsClass = jsClass->parentClass));
}
JSCallbackObject::~JSCallbackObject()
{
JSObjectRef thisRef = toRef(this);
- for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parent)
- if (JSObjectFinalizeCallback finalize = jsClass->callbacks.finalize)
+ for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
+ if (JSObjectFinalizeCallback finalize = jsClass->finalize)
finalize(thisRef);
JSClassRelease(m_class);
UString JSCallbackObject::className() const
{
- return classInfo()->className;
+ if (!m_class->className.isNull())
+ return m_class->className;
+
+ return JSObject::className();
}
bool JSCallbackObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
JSObjectRef thisRef = toRef(this);
JSStringRef propertyNameRef = toRef(propertyName.ustring().rep());
- for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parent) {
+ for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass) {
// optional optimization to bypass getProperty in cases when we only need to know if the property exists
- if (JSObjectHasPropertyCallback hasProperty = jsClass->callbacks.hasProperty) {
+ if (JSObjectHasPropertyCallback hasProperty = jsClass->hasProperty) {
if (hasProperty(context, thisRef, propertyNameRef)) {
slot.setCustom(this, callbackGetter);
return true;
}
- } else if (JSObjectGetPropertyCallback getProperty = jsClass->callbacks.getProperty) {
+ } else if (JSObjectGetPropertyCallback getProperty = jsClass->getProperty) {
if (JSValueRef value = getProperty(context, thisRef, propertyNameRef, toRef(exec->exceptionSlot()))) {
// cache the value so we don't have to compute it again
// FIXME: This violates the PropertySlot design a little bit.
JSStringRef propertyNameRef = toRef(propertyName.ustring().rep());
JSValueRef valueRef = toRef(value);
- for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parent) {
- if (JSObjectSetPropertyCallback setProperty = jsClass->callbacks.setProperty) {
+ for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass) {
+ if (JSObjectSetPropertyCallback setProperty = jsClass->setProperty) {
if (setProperty(context, thisRef, propertyNameRef, valueRef, toRef(exec->exceptionSlot())))
return;
}
JSObjectRef thisRef = toRef(this);
JSStringRef propertyNameRef = toRef(propertyName.ustring().rep());
- for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parent) {
- if (JSObjectDeletePropertyCallback deleteProperty = jsClass->callbacks.deleteProperty) {
+ for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass) {
+ if (JSObjectDeletePropertyCallback deleteProperty = jsClass->deleteProperty) {
if (deleteProperty(context, thisRef, propertyNameRef, toRef(exec->exceptionSlot())))
return true;
}
bool JSCallbackObject::implementsConstruct() const
{
- for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parent)
- if (jsClass->callbacks.callAsConstructor)
+ for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
+ if (jsClass->callAsConstructor)
return true;
return false;
JSContextRef execRef = toRef(exec);
JSObjectRef thisRef = toRef(this);
- for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parent) {
- if (JSObjectCallAsConstructorCallback callAsConstructor = jsClass->callbacks.callAsConstructor) {
+ for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass) {
+ if (JSObjectCallAsConstructorCallback callAsConstructor = jsClass->callAsConstructor) {
size_t argumentCount = args.size();
JSValueRef arguments[argumentCount];
for (size_t i = 0; i < argumentCount; i++)
bool JSCallbackObject::implementsHasInstance() const
{
- for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parent)
- if (jsClass->callbacks.hasInstance)
+ for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
+ if (jsClass->hasInstance)
return true;
return false;
JSContextRef execRef = toRef(exec);
JSObjectRef thisRef = toRef(this);
- for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parent)
- if (JSObjectHasInstanceCallback hasInstance = jsClass->callbacks.hasInstance)
+ for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
+ if (JSObjectHasInstanceCallback hasInstance = jsClass->hasInstance)
return hasInstance(execRef, thisRef, toRef(value), toRef(exec->exceptionSlot()));
ASSERT(0); // implementsHasInstance should prevent us from reaching here
bool JSCallbackObject::implementsCall() const
{
- for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parent)
- if (jsClass->callbacks.callAsFunction)
+ for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
+ if (jsClass->callAsFunction)
return true;
return false;
JSObjectRef thisRef = toRef(this);
JSObjectRef thisObjRef = toRef(thisObj);
- for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parent) {
- if (JSObjectCallAsFunctionCallback callAsFunction = jsClass->callbacks.callAsFunction) {
+ for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass) {
+ if (JSObjectCallAsFunctionCallback callAsFunction = jsClass->callAsFunction) {
size_t argumentCount = args.size();
JSValueRef arguments[argumentCount];
for (size_t i = 0; i < argumentCount; i++)
{
JSObjectRef thisRef = toRef(this);
- for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parent) {
- if (JSObjectAddPropertiesToListCallback addPropertiesToList = jsClass->callbacks.addPropertiesToList)
+ for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass) {
+ if (JSObjectAddPropertiesToListCallback addPropertiesToList = jsClass->addPropertiesToList)
addPropertiesToList(thisRef, toRef(&propertyList));
if (__JSClass::StaticValuesTable* staticValues = jsClass->staticValues) {
JSContextRef context = toRef(exec);
JSObjectRef thisRef = toRef(this);
- for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parent)
- if (JSObjectConvertToTypeCallback convertToType = jsClass->callbacks.convertToType)
+ for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
+ if (JSObjectConvertToTypeCallback convertToType = jsClass->convertToType)
if (JSValueRef value = convertToType(context, thisRef, kJSTypeNumber, toRef(exec->exceptionSlot())))
return toJS(value)->getNumber();
JSContextRef context = toRef(exec);
JSObjectRef thisRef = toRef(this);
- for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parent)
- if (JSObjectConvertToTypeCallback convertToType = jsClass->callbacks.convertToType)
+ for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
+ if (JSObjectConvertToTypeCallback convertToType = jsClass->convertToType)
if (JSValueRef value = convertToType(context, thisRef, kJSTypeString, toRef(exec->exceptionSlot())))
return toJS(value)->getString();
bool JSCallbackObject::inherits(JSClassRef c) const
{
- for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parent)
+ for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
if (jsClass == c)
return true;
JSObjectRef thisRef = toRef(thisObj);
JSStringRef propertyNameRef = toRef(propertyName.ustring().rep());
- for (JSClassRef jsClass = thisObj->m_class; jsClass; jsClass = jsClass->parent)
+ for (JSClassRef jsClass = thisObj->m_class; jsClass; jsClass = jsClass->parentClass)
if (__JSClass::StaticValuesTable* staticValues = jsClass->staticValues)
if (StaticValueEntry* entry = staticValues->get(propertyName.ustring().rep()))
if (JSObjectGetPropertyCallback getProperty = entry->getProperty)
if (JSValue* cachedOrOverrideValue = thisObj->getDirect(propertyName))
return cachedOrOverrideValue;
- for (JSClassRef jsClass = thisObj->m_class; jsClass; jsClass = jsClass->parent) {
+ for (JSClassRef jsClass = thisObj->m_class; jsClass; jsClass = jsClass->parentClass) {
if (__JSClass::StaticFunctionsTable* staticFunctions = jsClass->staticFunctions) {
if (StaticFunctionEntry* entry = staticFunctions->get(propertyName.ustring().rep())) {
JSValue* v = toJS(JSObjectMakeFunction(toRef(exec), entry->callAsFunction));
JSObjectRef thisRef = toRef(thisObj);
JSStringRef propertyNameRef = toRef(propertyName.ustring().rep());
- for (JSClassRef jsClass = thisObj->m_class; jsClass; jsClass = jsClass->parent)
- if (JSObjectGetPropertyCallback getProperty = jsClass->callbacks.getProperty)
+ for (JSClassRef jsClass = thisObj->m_class; jsClass; jsClass = jsClass->parentClass)
+ if (JSObjectGetPropertyCallback getProperty = jsClass->getProperty)
if (JSValueRef value = getProperty(toRef(exec), thisRef, propertyNameRef, toRef(exec->exceptionSlot())))
return toJS(value);
using namespace KJS;
-const JSObjectCallbacks kJSObjectCallbacksNone = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+const JSClassDefinition kJSClassDefinitionNull = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-JSClassRef JSClassCreate(JSStaticValue* staticValues, JSStaticFunction* staticFunctions, const JSObjectCallbacks* callbacks, JSClassRef parentClass)
+__JSClass::__JSClass(JSClassDefinition* definition)
+ : refCount(0)
+ , className(definition->className)
+ , parentClass(definition->parentClass)
+ , staticValues(0)
+ , staticFunctions(0)
+ , initialize(definition->initialize)
+ , finalize(definition->finalize)
+ , hasProperty(definition->hasProperty)
+ , getProperty(definition->getProperty)
+ , setProperty(definition->setProperty)
+ , deleteProperty(definition->deleteProperty)
+ , addPropertiesToList(definition->addPropertiesToList)
+ , callAsFunction(definition->callAsFunction)
+ , callAsConstructor(definition->callAsConstructor)
+ , hasInstance(definition->hasInstance)
+ , convertToType(definition->convertToType)
{
- JSClassRef jsClass = new __JSClass;
- if (staticValues) {
- jsClass->staticValues = new __JSClass::StaticValuesTable();
- while (staticValues->name) {
- jsClass->staticValues->add(Identifier(staticValues->name).ustring().rep(),
- new StaticValueEntry(staticValues->getProperty, staticValues->setProperty, staticValues->attributes));
- ++staticValues;
+ if (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 (staticFunctions) {
- jsClass->staticFunctions = new __JSClass::StaticFunctionsTable();
- while (staticFunctions->name) {
- jsClass->staticFunctions->add(Identifier(staticFunctions->name).ustring().rep(),
- new StaticFunctionEntry(staticFunctions->callAsFunction, staticFunctions->attributes));
- ++staticFunctions;
+ if (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 (callbacks)
- jsClass->callbacks = *callbacks;
- else
- jsClass->callbacks = kJSObjectCallbacksNone;
-
- jsClass->parent = parentClass;
-
- return JSClassRetain(jsClass);
-}
-
-JSClassRef JSClassRetain(JSClassRef jsClass)
-{
- ++jsClass->refCount;
- return jsClass;
}
-void JSClassRelease(JSClassRef jsClass)
+__JSClass::~__JSClass()
{
- if (--jsClass->refCount == 0) {
- if (jsClass->staticValues) {
- deleteAllValues(*jsClass->staticValues);
- delete jsClass->staticValues;
- }
-
- if (jsClass->staticFunctions) {
- deleteAllValues(*jsClass->staticFunctions);
- delete jsClass->staticFunctions;
- }
+ if (staticValues) {
+ deleteAllValues(*staticValues);
+ delete staticValues;
+ }
- delete jsClass;
+ if (staticFunctions) {
+ deleteAllValues(*staticFunctions);
+ delete staticFunctions;
}
}
};
struct __JSClass {
- __JSClass()
- : refCount(0), staticValues(0), staticFunctions(0)
- {
- }
-
- unsigned refCount;
+ __JSClass(JSClassDefinition*);
+ ~__JSClass();
typedef HashMap<RefPtr<KJS::UString::Rep>, StaticValueEntry*> StaticValuesTable;
- StaticValuesTable* staticValues;
-
typedef HashMap<RefPtr<KJS::UString::Rep>, StaticFunctionEntry*> StaticFunctionsTable;
- StaticFunctionsTable* staticFunctions;
- KJS::UString name; // FIXME: Not used yet
- JSObjectCallbacks callbacks;
- __JSClass* parent;
+ unsigned refCount;
+
+ KJS::UString className;
+ __JSClass* parentClass;
+
+ StaticValuesTable* staticValues;
+ StaticFunctionsTable* staticFunctions;
+
+ JSObjectInitializeCallback initialize;
+ JSObjectFinalizeCallback finalize;
+ JSObjectHasPropertyCallback hasProperty;
+ JSObjectGetPropertyCallback getProperty;
+ JSObjectSetPropertyCallback setProperty;
+ JSObjectDeletePropertyCallback deleteProperty;
+ JSObjectAddPropertiesToListCallback addPropertiesToList;
+ JSObjectCallAsFunctionCallback callAsFunction;
+ JSObjectCallAsConstructorCallback callAsConstructor;
+ JSObjectHasInstanceCallback hasInstance;
+ JSObjectConvertToTypeCallback convertToType;
};
#endif // JSClassRef_h
static JSClassRef JSNodePrototype_class(JSContextRef context)
{
- static JSClassRef nodePrototypeClass;
- if (!nodePrototypeClass)
- nodePrototypeClass = JSClassCreate(NULL, JSNodePrototype_staticFunctions, &kJSObjectCallbacksNone, NULL);
- return nodePrototypeClass;
+ static JSClassRef jsClass;
+ if (!jsClass) {
+ JSClassDefinition definition = kJSClassDefinitionNull;
+ definition.staticFunctions = JSNodePrototype_staticFunctions;
+ jsClass = JSClassCreate(&definition);
+ }
+ return jsClass;
}
static JSValueRef JSNode_getNodeType(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
static JSClassRef JSNode_class(JSContextRef context)
{
- static JSClassRef nodeClass;
- if (!nodeClass) {
- JSObjectCallbacks JSNode_callbacks = kJSObjectCallbacksNone;
- JSNode_callbacks.finalize = JSNode_finalize;
-
- nodeClass = JSClassCreate(JSNode_staticValues, NULL, &JSNode_callbacks, NULL);
+ static JSClassRef jsClass;
+ if (!jsClass) {
+ JSClassDefinition definition = kJSClassDefinitionNull;
+ definition.staticValues = JSNode_staticValues;
+ definition.finalize = JSNode_finalize;
+
+ jsClass = JSClassCreate(&definition);
}
- return nodeClass;
+ return jsClass;
}
static JSObjectRef JSNode_prototype(JSContextRef context)
{
static JSClassRef jsClass;
if (!jsClass) {
- jsClass = JSClassCreate(NULL, JSNodeListPrototype_staticFunctions, &kJSObjectCallbacksNone, NULL);
+ JSClassDefinition definition = kJSClassDefinitionNull;
+ definition.staticFunctions = JSNodeListPrototype_staticFunctions;
+ jsClass = JSClassCreate(&definition);
}
return jsClass;
{
static JSClassRef jsClass;
if (!jsClass) {
- JSObjectCallbacks callbacks = kJSObjectCallbacksNone;
- callbacks.getProperty = JSNodeList_getProperty;
- callbacks.finalize = JSNodeList_finalize;
-
- jsClass = JSClassCreate(JSNodeList_staticValues, NULL, &callbacks, NULL);
+ JSClassDefinition definition = kJSClassDefinitionNull;
+ definition.staticValues = JSNodeList_staticValues;
+ definition.getProperty = JSNodeList_getProperty;
+ definition.finalize = JSNodeList_finalize;
+
+ jsClass = JSClassCreate(&definition);
}
return jsClass;
#include "JSCallbackConstructor.h"
#include "JSCallbackFunction.h"
#include "JSCallbackObject.h"
+#include "JSClassRef.h"
#include "identifier.h"
#include "function.h"
using namespace KJS;
+JSClassRef JSClassCreate(JSClassDefinition* definition)
+{
+ JSClassRef jsClass = new __JSClass(definition);
+ return JSClassRetain(jsClass);
+}
+
+JSClassRef JSClassRetain(JSClassRef jsClass)
+{
+ ++jsClass->refCount;
+ return jsClass;
+}
+
+void JSClassRelease(JSClassRef jsClass)
+{
+ if (--jsClass->refCount == 0)
+ delete jsClass;
+}
+
JSObjectRef JSObjectMake(JSContextRef context, JSClassRef jsClass, JSValueRef prototype)
{
JSLock lock;
/*!
@typedef JSObjectHasPropertyCallback
-@abstract The callback invoked when determining whether an object has a given property.
+@abstract The callback invoked when determining whether an object has a property.
@param context The current execution context.
@param object The JSObject to search for the property.
@param propertyName A JSString containing the name of the property look up.
bool HasProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName);
-If this function returns false, the hasProperty request forwards to object's static property table, then its parent class chain (which includes the default object class), then its prototype chain.
+If this function returns false, the hasProperty request forwards to object's statically declared properties, then its parent class chain (which includes the default object class), then its prototype chain.
This callback enables optimization in cases where only a property's existence needs to be known, not its value, and computing its value would be expensive.
/*!
@typedef JSObjectGetPropertyCallback
-@abstract The callback invoked when getting a property from an object.
+@abstract The callback invoked when getting a property's value.
@param context The current execution context.
@param object The JSObject to search for the property.
@param propertyName A JSString containing the name of the property to get.
JSValueRef GetProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
-If this function returns NULL, the get request forwards to object's static property table, then its parent class chain (which includes the default object class), then its prototype chain.
+If this function returns NULL, the get request forwards to object's statically declared properties, then its parent class chain (which includes the default object class), then its prototype chain.
*/
typedef JSValueRef
(*JSObjectGetPropertyCallback) (JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
/*!
@typedef JSObjectSetPropertyCallback
-@abstract The callback invoked when setting the value of a given property.
+@abstract The callback invoked when setting a property's value.
@param context The current execution context.
@param object The JSObject on which to set the property's value.
@param propertyName A JSString containing the name of the property to set.
bool SetProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception);
-If this function returns false, the set request forwards to object's static property table, then its parent class chain (which includes the default object class).
+If this function returns false, the set request forwards to object's statically declared properties, then its parent class chain (which includes the default object class).
*/
typedef bool
(*JSObjectSetPropertyCallback) (JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception);
/*!
@typedef JSObjectDeletePropertyCallback
-@abstract The callback invoked when deleting a given property.
+@abstract The callback invoked when deleting a property.
@param context The current execution context.
@param object The JSObject in which to delete the property.
@param propertyName A JSString containing the name of the property to delete.
bool DeleteProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
-If this function returns false, the delete request forwards to object's static property table, then its parent class chain (which includes the default object class).
+If this function returns false, the delete request forwards to object's statically declared properties, then its parent class chain (which includes the default object class).
*/
typedef bool
(*JSObjectDeletePropertyCallback) (JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
typedef JSValueRef
(*JSObjectConvertToTypeCallback) (JSContextRef context, JSObjectRef object, JSType type, JSValueRef* exception);
+/*!
+@struct JSStaticValue
+@abstract This structure describes a statically declared value property.
+@field name A null-terminated UTF8 string containing the property's name.
+@field getProperty A JSObjectGetPropertyCallback to invoke when getting the property's value.
+@field setProperty A JSObjectSetPropertyCallback to invoke when setting the property's value.
+@field attributes A logically ORed set of JSPropertyAttributes to give to the property.
+*/
+typedef struct {
+ const char* const name; // FIXME: convert UTF8
+ JSObjectGetPropertyCallback getProperty;
+ JSObjectSetPropertyCallback setProperty;
+ JSPropertyAttributes attributes;
+} JSStaticValue;
+
+/*!
+@struct JSStaticFunction
+@abstract This structure describes a statically declared function property.
+@field name A null-terminated UTF8 string containing the property's name.
+@field callAsFunction A JSObjectCallAsFunctionCallback to invoke when the property is called as a function.
+@field attributes A logically ORed set of JSPropertyAttributes to give to the property.
+*/
+typedef struct {
+ const char* const name; // FIXME: convert UTF8
+ JSObjectCallAsFunctionCallback callAsFunction;
+ JSPropertyAttributes attributes;
+} JSStaticFunction;
+
/*!
-@struct JSObjectCallbacks
-@abstract This structure contains optional callbacks for supplementing default object behavior. Any callback field can be NULL.
+@struct JSClassDefinition
+@abstract This structure contains properties and callbacks that define a type of object. All fields are optional. Any field may be NULL.
@field version The version number of this structure. The current version is 0.
-@field initialize The callback invoked when an object is first created. Use this callback in conjunction with JSObjectSetPrivate to initialize private data in your object.
-@field finalize The callback invoked when an object is finalized (prepared for garbage collection). Use this callback to release resources allocated for your object, and perform other cleanup.
-@field hasProperty The callback invoked when determining whether an object has a given property. If this field is NULL, getProperty will be called instead. The hasProperty callback enables optimization in cases where only a property's existence needs to be known, not its value, and computing its value would be expensive.
-@field getProperty The callback invoked when getting the value of a given property.
-@field setProperty The callback invoked when setting the value of a given property.
-@field deleteProperty The callback invoked when deleting a given property.
+@field className A null-terminated UTF8 string containing the class's name.
+@field parentClass A JSClass to set as the class's parent class. Pass NULL use the default object class.
+@field staticValues A JSStaticValue array containing the class's statically declared value properties. Pass NULL to specify no statically declared value properties. The array must be terminated by a JSStaticValue whose name field is NULL.
+@field staticFunctions A JSStaticFunction array containing the class's statically declared function properties. Pass NULL to specify no statically declared function properties. The array must be terminated by a JSStaticFunction whose name field is NULL.
+@field initialize The callback invoked when an object is first created. Use this callback to initialize the object.
+@field finalize The callback invoked when an object is finalized (prepared for garbage collection). Use this callback to release resources allocated for the object, and perform other cleanup.
+@field hasProperty The callback invoked when determining whether an object has a property. If this field is NULL, getProperty is called instead. The hasProperty callback enables optimization in cases where only a property's existence needs to be known, not its value, and computing its value is expensive.
+@field getProperty The callback invoked when getting a property's value.
+@field setProperty The callback invoked when setting a property's value.
+@field deleteProperty The callback invoked when deleting a property.
@field addPropertiesToList The callback invoked when adding an object's properties to a property list.
@field callAsFunction The callback invoked when an object is called as a function.
@field hasInstance The callback invoked when an object is used as the target of an 'instanceof' expression.
@field callAsConstructor The callback invoked when an object is used as a constructor in a 'new' expression.
@field convertToType The callback invoked when converting an object to a particular JavaScript type.
+@discussion The staticValues and staticFunctions arrays are the simplest and most efficient means for vending custom properties. Statically declared properties autmatically service requests like get, set, and enumerate. Property access callbacks are required only to implement unusual properties, like array indexes, whose names are not known at compile-time.
+
+If you named your getter function "GetX" and your setter function "SetX", you would declare a JSStaticValue array containing "X" like this:
+
+JSStaticValue StaticValueArray[] = {
+ { "X", GetX, SetX, kJSPropertyAttributeNone },
+ { 0, 0, 0, 0 }
+};
+
+Standard JavaScript practice calls for storing functions in prototype objects, so derived objects can share them. Therefore, it is common for prototype classes to have function properties but no value properties, and for object classes to have value properties but no function properties.
+
+A NULL callback specifies that the default object callback should substitute, except in the case of hasProperty, where it specifies that getProperty should substitute.
*/
typedef struct {
int version; // current (and only) version is 0
+
+ const char* className;
+ JSClassRef parentClass;
+
+ JSStaticValue* staticValues;
+ JSStaticFunction* staticFunctions;
+
JSObjectInitializeCallback initialize;
JSObjectFinalizeCallback finalize;
JSObjectHasPropertyCallback hasProperty;
JSObjectCallAsConstructorCallback callAsConstructor;
JSObjectHasInstanceCallback hasInstance;
JSObjectConvertToTypeCallback convertToType;
-} JSObjectCallbacks;
+} JSClassDefinition;
/*!
-@const kJSObjectCallbacksNone
-@abstract A JSObjectCallbacks structure of the current version, filled with NULL callbacks.
-@discussion Use this constant as a convenience when creating callback structures. For example, to create a callback structure that has only a finalize method:
-
-JSObjectCallbacks callbacks = kJSObjectCallbacksNone;
-
-callbacks.finalize = Finalize;
-*/
-extern const JSObjectCallbacks kJSObjectCallbacksNone;
+@const kJSClassDefinitionNull
+@abstract A JSClassDefinition structure of the current version, filled with NULL pointers.
+@discussion Use this constant as a convenience when creating class definitions. For example, to create a class definition with only a finalize method:
-/*!
-@struct JSStaticValue
-@abstract This structure describes a static value property.
-@field name A null-terminated UTF8 string containing the property's name.
-@field getProperty A JSObjectGetPropertyCallback to invoke when getting the property's value.
-@field setProperty A JSObjectSetPropertyCallback to invoke when setting the property's value.
-@field attributes A logically ORed set of JSPropertyAttributes to give to the property.
-*/
-typedef struct {
- const char* const name; // FIXME: convert UTF8
- JSObjectGetPropertyCallback getProperty;
- JSObjectSetPropertyCallback setProperty;
- JSPropertyAttributes attributes;
-} JSStaticValue;
+JSClassDefinition definition = kJSClassDefinitionNull;
-/*!
-@struct JSStaticFunction
-@abstract This structure describes a static function property.
-@field name A null-terminated UTF8 string containing the property's name.
-@field callAsFunction A JSObjectCallAsFunctionCallback to invoke when the property is called as a function.
-@field attributes A logically ORed set of JSPropertyAttributes to give to the property.
+definition.finalize = Finalize;
*/
-typedef struct {
- const char* const name; // FIXME: convert UTF8
- JSObjectCallAsFunctionCallback callAsFunction;
- JSPropertyAttributes attributes;
-} JSStaticFunction;
+extern const JSClassDefinition kJSClassDefinitionNull;
/*!
@function
-@abstract Creates a JavaScript class suitable for use with JSObjectMake
-@param staticValues A JSStaticValue array representing the class's static value properties. Pass NULL to specify no static value properties. The array must be terminated by a JSStaticValue whose name field is NULL.
-@param staticFunctions A JSStaticFunction array representing the class's static function properties. Pass NULL to specify no static function properties. The array must be terminated by a JSStaticFunction whose name field is NULL.
-@param callbacks A pointer to a JSObjectCallbacks structure holding custom callbacks for supplementing default object behavior. Pass NULL to specify no custom behavior.
-@param parentClass A JSClass to set as the class's parent class. Pass NULL use the default object class.
-@result A JSClass with the given properties, callbacks, and parent class. Ownership follows the Create Rule.
-@discussion The simplest and most efficient way to add custom properties to a class is by specifying static values and functions. Standard JavaScript practice calls for functions to be placed in prototype objects, so that they can be shared among objects.
-*/
-JSClassRef JSClassCreate(JSStaticValue* staticValues, JSStaticFunction* staticFunctions, const JSObjectCallbacks* callbacks, JSClassRef parentClass);
+@abstract Creates a JavaScript class suitable for use with JSObjectMake.
+@param definition A JSClassDefinition that defines the class.
+@result A JSClass with the given definition's name, properties, callbacks, and parent class. Ownership follows the Create Rule.
+*/
+JSClassRef JSClassCreate(JSClassDefinition* definition);
+
/*!
@function
@abstract Retains a JavaScript class.
/*!
@function
-@abstract Tests whether an object has a certain property.
+@abstract Tests whether an object has a given property.
@param object The JSObject to test.
@param propertyName A JSString containing the property's name.
@result true if the object has a property whose name matches propertyName, otherwise false.
@abstract Gets a pointer to private data from an object.
@param object A JSObject whose private data you want to get.
@result A void* that points to the object's private data, if the object has private data, otherwise NULL.
-@discussion JSObjectGetPrivate and JSObjectSetPrivate only work on custom objects created by JSObjectMake, JSObjectMakeFunction, and JSObjectMakeConstructor.
+@discussion JSObjectGetPrivate and JSObjectSetPrivate only work on objects created by JSObjectMake, JSObjectMakeFunction, and JSObjectMakeConstructor.
*/
void* JSObjectGetPrivate(JSObjectRef object);
@param object A JSObject whose private data you want to set.
@param data A void* that points to the object's private data.
@result true if the set operation succeeds, otherwise false.
-@discussion JSObjectGetPrivate and JSObjectSetPrivate only work on custom objects created by JSObjectMake, JSObjectMakeFunction, and JSObjectMakeConstructor.
+@discussion JSObjectGetPrivate and JSObjectSetPrivate only work on objects created by JSObjectMake, JSObjectMakeFunction, and JSObjectMakeConstructor.
*/
bool JSObjectSetPrivate(JSObjectRef object, void* data);
/*!
@function
@abstract Adds a property to a property list.
-@discussion Use this method inside a JSObjectAddPropertiesToListCallback to add a custom property to an object's property list.
+@discussion Use this method inside a JSObjectAddPropertiesToListCallback to add a property to an object's property list.
@param propertyList The JSPropertyList to which you want to add a property.
@param thisObject The JSObject to which the property belongs.
@param propertyName A JSString specifying the property's name.
didFinalize = true;
}
-JSObjectCallbacks MyObject_callbacks = {
+JSClassDefinition MyObject_definition = {
0,
+
+ "MyObject",
+ NULL,
+
+ NULL,
+ NULL,
+
MyObject_initialize,
MyObject_finalize,
MyObject_hasProperty,
static JSClassRef MyObject_class(JSContextRef context)
{
static JSClassRef jsClass;
- if (!jsClass) {
- jsClass = JSClassCreate(NULL, NULL, &MyObject_callbacks, NULL);
- }
+ if (!jsClass)
+ jsClass = JSClassCreate(&MyObject_definition);
return jsClass;
}
JSPropertyEnumeratorRelease(enumerator);
assert(count == 1); // jsCFString should not be enumerated
- JSClassRef nullCallbacksClass = JSClassCreate(NULL, NULL, NULL, NULL);
- JSClassRelease(nullCallbacksClass);
+ JSClassDefinition nullDefinition = kJSClassDefinitionNull;
+ JSClassRef nullClass = JSClassCreate(&nullDefinition);
+ JSClassRelease(nullClass);
functionBody = JSStringCreateWithUTF8CString("return this;");
function = JSObjectMakeFunctionWithBody(context, functionBody, NULL, 1, NULL);
shouldBe("typeof new MyObject()", "object");
shouldBe("MyObject ? 1 : 0", true); // toBoolean
shouldBe("+MyObject", 1); // toNumber
-shouldBe("(MyObject.toString())", "[object CallbackObject]"); // toString
+shouldBe("(MyObject.toString())", "[object MyObject]"); // toString
shouldBe("MyObject - 0", NaN); // toPrimitive
shouldBe("typeof MyConstructor", "object");
+2006-07-15 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej.
+
+ - Moved the arguments passed to JSClassCreate into a single structure,
+ called JSClassDefinition. This will enable easier structure
+ migration/versioning in the future, if necessary.
+
+ - Added support for class names.
+
+ - kJSClassDefinitionNull replaces kJSObjectCallbacksNone.
+
+ - JSClass is becoming a fairly complex struct, so I migrated all of its
+ implementation other than reference counting to the sruct.
+
+ - Also moved JSClass* functions in the API to JSObjectRef.cpp, since they're
+ declared in JSObjectRef.h
+
+ - Also added some more informative explanation to the class structure doc.
+
2006-07-15 Darin Adler <darin@apple.com>
Reviewed by Geoff.
__ZNK3KJS9Reference15getPropertyNameEv
__ZTVN3KJS19InternalFunctionImpE
__ZTVN3KJS8JSObjectE
-_kJSObjectCallbacksNone
+_kJSClassDefinitionNull
_kjs_pcre_compile
_kjs_pcre_exec
_kjs_pcre_free