+{
+ // The empty string is shared across threads & is an identifier, in all other cases we should have done a deep copy in className(), below.
+ ASSERT(!m_className.size() || !m_className.rep()->isIdentifier());
+
+ if (m_staticValues) {
+ OpaqueJSClassStaticValuesTable::const_iterator end = m_staticValues->end();
+ for (OpaqueJSClassStaticValuesTable::const_iterator it = m_staticValues->begin(); it != end; ++it) {
+ ASSERT(!it->first->isIdentifier());
+ delete it->second;
+ }
+ delete m_staticValues;
+ }
+
+ if (m_staticFunctions) {
+ OpaqueJSClassStaticFunctionsTable::const_iterator end = m_staticFunctions->end();
+ for (OpaqueJSClassStaticFunctionsTable::const_iterator it = m_staticFunctions->begin(); it != end; ++it) {
+ ASSERT(!it->first->isIdentifier());
+ delete it->second;
+ }
+ delete m_staticFunctions;
+ }
+
+ if (prototypeClass)
+ JSClassRelease(prototypeClass);
+}
+
+PassRefPtr<OpaqueJSClass> OpaqueJSClass::createNoAutomaticPrototype(const JSClassDefinition* definition)
+{
+ return adoptRef(new OpaqueJSClass(definition, 0));
+}
+
+static void clearReferenceToPrototype(JSObjectRef prototype)
+{
+ OpaqueJSClassContextData* jsClassData = static_cast<OpaqueJSClassContextData*>(JSObjectGetPrivate(prototype));
+ ASSERT(jsClassData);
+ jsClassData->cachedPrototype.clear(toJS(prototype));
+}
+
+PassRefPtr<OpaqueJSClass> OpaqueJSClass::create(const JSClassDefinition* clientDefinition)
+{
+ JSClassDefinition definition = *clientDefinition; // Avoid modifying client copy.
+
+ JSClassDefinition protoDefinition = kJSClassDefinitionEmpty;
+ protoDefinition.finalize = clearReferenceToPrototype;
+ swap(definition.staticFunctions, protoDefinition.staticFunctions); // Move static functions to the prototype.
+
+ // We are supposed to use JSClassRetain/Release but since we know that we currently have
+ // the only reference to this class object we cheat and use a RefPtr instead.
+ RefPtr<OpaqueJSClass> protoClass = adoptRef(new OpaqueJSClass(&protoDefinition, 0));
+ return adoptRef(new OpaqueJSClass(&definition, protoClass.get()));
+}
+
+OpaqueJSClassContextData::OpaqueJSClassContextData(OpaqueJSClass* jsClass)
+ : m_class(jsClass)
+{
+ if (jsClass->m_staticValues) {
+ staticValues = new OpaqueJSClassStaticValuesTable;
+ OpaqueJSClassStaticValuesTable::const_iterator end = jsClass->m_staticValues->end();
+ for (OpaqueJSClassStaticValuesTable::const_iterator it = jsClass->m_staticValues->begin(); it != end; ++it) {
+ ASSERT(!it->first->isIdentifier());
+ // Use a local variable here to sidestep an RVCT compiler bug.
+ StaticValueEntry* entry = new StaticValueEntry(it->second->getProperty, it->second->setProperty, it->second->attributes);
+ staticValues->add(UString::Rep::create(it->first->characters(), it->first->length()), entry);
+ }
+ } else
+ staticValues = 0;
+
+ if (jsClass->m_staticFunctions) {
+ staticFunctions = new OpaqueJSClassStaticFunctionsTable;
+ OpaqueJSClassStaticFunctionsTable::const_iterator end = jsClass->m_staticFunctions->end();
+ for (OpaqueJSClassStaticFunctionsTable::const_iterator it = jsClass->m_staticFunctions->begin(); it != end; ++it) {
+ ASSERT(!it->first->isIdentifier());
+ // Use a local variable here to sidestep an RVCT compiler bug.
+ StaticFunctionEntry* entry = new StaticFunctionEntry(it->second->callAsFunction, it->second->attributes);
+ staticFunctions->add(UString::Rep::create(it->first->characters(), it->first->length()), entry);
+ }
+
+ } else
+ staticFunctions = 0;
+}
+
+OpaqueJSClassContextData::~OpaqueJSClassContextData()