1324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver/*
2324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Copyright (C) 2006, 2007 Apple Inc.  All rights reserved.
3324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *
4324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Redistribution and use in source and binary forms, with or without
5324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * modification, are permitted provided that the following conditions
6324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * are met:
7324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 1. Redistributions of source code must retain the above copyright
8324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *    notice, this list of conditions and the following disclaimer.
9324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 2. Redistributions in binary form must reproduce the above copyright
10324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *    notice, this list of conditions and the following disclaimer in the
11324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *    documentation and/or other materials provided with the distribution.
12324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *
13324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */
25324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
26324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "config.h"
27324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "JSClassRef.h"
28324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
29324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "APICast.h"
30324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "JSCallbackObject.h"
31324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "JSObjectRef.h"
32324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include <runtime/InitializeThreading.h>
33324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include <runtime/JSGlobalObject.h>
34324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include <runtime/ObjectPrototype.h>
35324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include <runtime/Identifier.h>
36324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include <wtf/text/StringHash.h>
37324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include <wtf/unicode/UTF8.h>
38324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
39324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverusing namespace std;
40324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverusing namespace JSC;
41324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverusing namespace WTF::Unicode;
42324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
43324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverconst JSClassDefinition kJSClassDefinitionEmpty = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
44324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
45324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverstatic inline UString tryCreateStringFromUTF8(const char* string)
46324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver{
47324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if (!string)
48324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return UString();
49324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
50324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    size_t length = strlen(string);
51324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    Vector<UChar, 1024> buffer(length);
52324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    UChar* p = buffer.data();
53324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if (conversionOK != convertUTF8ToUTF16(&string, string + length, &p, p + length))
54324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return UString();
55324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
56324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return UString(buffer.data(), p - buffer.data());
57324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
58324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
59324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverOpaqueJSClass::OpaqueJSClass(const JSClassDefinition* definition, OpaqueJSClass* protoClass)
60324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    : parentClass(definition->parentClass)
61324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    , prototypeClass(0)
62324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    , initialize(definition->initialize)
63324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    , finalize(definition->finalize)
64324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    , hasProperty(definition->hasProperty)
65324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    , getProperty(definition->getProperty)
66324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    , setProperty(definition->setProperty)
67324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    , deleteProperty(definition->deleteProperty)
68324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    , getPropertyNames(definition->getPropertyNames)
69324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    , callAsFunction(definition->callAsFunction)
70324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    , callAsConstructor(definition->callAsConstructor)
71324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    , hasInstance(definition->hasInstance)
72324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    , convertToType(definition->convertToType)
73324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    , m_className(tryCreateStringFromUTF8(definition->className))
74324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    , m_staticValues(0)
75324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    , m_staticFunctions(0)
76324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver{
77324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    initializeThreading();
78324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
79324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if (const JSStaticValue* staticValue = definition->staticValues) {
80324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        m_staticValues = new OpaqueJSClassStaticValuesTable();
81324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        while (staticValue->name) {
82324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            UString valueName = tryCreateStringFromUTF8(staticValue->name);
83324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            if (!valueName.isNull()) {
84324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                // Use a local variable here to sidestep an RVCT compiler bug.
85324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                StaticValueEntry* entry = new StaticValueEntry(staticValue->getProperty, staticValue->setProperty, staticValue->attributes);
86324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                StringImpl* impl = valueName.impl();
87324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                StaticValueEntry* existingEntry = m_staticValues->get(impl);
88324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                m_staticValues->set(impl, entry);
89324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                delete existingEntry;
90324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            }
91324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            ++staticValue;
92324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
93324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
94324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
95324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if (const JSStaticFunction* staticFunction = definition->staticFunctions) {
96324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        m_staticFunctions = new OpaqueJSClassStaticFunctionsTable();
97324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        while (staticFunction->name) {
98324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            UString functionName = tryCreateStringFromUTF8(staticFunction->name);
99324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            if (!functionName.isNull()) {
100324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                // Use a local variable here to sidestep an RVCT compiler bug.
101324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                StaticFunctionEntry* entry = new StaticFunctionEntry(staticFunction->callAsFunction, staticFunction->attributes);
102324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                StringImpl* impl = functionName.impl();
103324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                StaticFunctionEntry* existingEntry = m_staticFunctions->get(impl);
104324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                m_staticFunctions->set(impl, entry);
105324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                delete existingEntry;
106324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            }
107324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            ++staticFunction;
108324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
109324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
110324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
111324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if (protoClass)
112324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        prototypeClass = JSClassRetain(protoClass);
113324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
114324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
115324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverOpaqueJSClass::~OpaqueJSClass()
116324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver{
117324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    // The empty string is shared across threads & is an identifier, in all other cases we should have done a deep copy in className(), below.
118324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    ASSERT(!m_className.length() || !m_className.impl()->isIdentifier());
119324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
120324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if (m_staticValues) {
121324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        OpaqueJSClassStaticValuesTable::const_iterator end = m_staticValues->end();
122324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        for (OpaqueJSClassStaticValuesTable::const_iterator it = m_staticValues->begin(); it != end; ++it) {
123324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            ASSERT(!it->first->isIdentifier());
124324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            delete it->second;
125324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
126324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        delete m_staticValues;
127324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
128324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
129324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if (m_staticFunctions) {
130324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        OpaqueJSClassStaticFunctionsTable::const_iterator end = m_staticFunctions->end();
131324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        for (OpaqueJSClassStaticFunctionsTable::const_iterator it = m_staticFunctions->begin(); it != end; ++it) {
132324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            ASSERT(!it->first->isIdentifier());
133324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            delete it->second;
134324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
135324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        delete m_staticFunctions;
136324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
137324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
138324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if (prototypeClass)
139324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        JSClassRelease(prototypeClass);
140324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
141324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
142324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverPassRefPtr<OpaqueJSClass> OpaqueJSClass::createNoAutomaticPrototype(const JSClassDefinition* definition)
143324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver{
144324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return adoptRef(new OpaqueJSClass(definition, 0));
145324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
146324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
147324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverPassRefPtr<OpaqueJSClass> OpaqueJSClass::create(const JSClassDefinition* clientDefinition)
148324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver{
149324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    JSClassDefinition definition = *clientDefinition; // Avoid modifying client copy.
150324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
151324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    JSClassDefinition protoDefinition = kJSClassDefinitionEmpty;
152324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    protoDefinition.finalize = 0;
153324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    swap(definition.staticFunctions, protoDefinition.staticFunctions); // Move static functions to the prototype.
154324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
155324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    // We are supposed to use JSClassRetain/Release but since we know that we currently have
156324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    // the only reference to this class object we cheat and use a RefPtr instead.
157324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    RefPtr<OpaqueJSClass> protoClass = adoptRef(new OpaqueJSClass(&protoDefinition, 0));
158324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return adoptRef(new OpaqueJSClass(&definition, protoClass.get()));
159324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
160324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
161324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverOpaqueJSClassContextData::OpaqueJSClassContextData(JSC::JSGlobalData&, OpaqueJSClass* jsClass)
162324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    : m_class(jsClass)
163324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver{
164324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if (jsClass->m_staticValues) {
165324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        staticValues = new OpaqueJSClassStaticValuesTable;
166324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        OpaqueJSClassStaticValuesTable::const_iterator end = jsClass->m_staticValues->end();
167324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        for (OpaqueJSClassStaticValuesTable::const_iterator it = jsClass->m_staticValues->begin(); it != end; ++it) {
168324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            ASSERT(!it->first->isIdentifier());
169324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            // Use a local variable here to sidestep an RVCT compiler bug.
170324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            StaticValueEntry* entry = new StaticValueEntry(it->second->getProperty, it->second->setProperty, it->second->attributes);
171324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            staticValues->add(StringImpl::create(it->first->characters(), it->first->length()), entry);
172324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
173324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    } else
174324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        staticValues = 0;
175324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
176324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if (jsClass->m_staticFunctions) {
177324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        staticFunctions = new OpaqueJSClassStaticFunctionsTable;
178324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        OpaqueJSClassStaticFunctionsTable::const_iterator end = jsClass->m_staticFunctions->end();
179324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        for (OpaqueJSClassStaticFunctionsTable::const_iterator it = jsClass->m_staticFunctions->begin(); it != end; ++it) {
180324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            ASSERT(!it->first->isIdentifier());
181324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            // Use a local variable here to sidestep an RVCT compiler bug.
182324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            StaticFunctionEntry* entry = new StaticFunctionEntry(it->second->callAsFunction, it->second->attributes);
183324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            staticFunctions->add(StringImpl::create(it->first->characters(), it->first->length()), entry);
184324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
185324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
186324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    } else
187324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        staticFunctions = 0;
188324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
189324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
190324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverOpaqueJSClassContextData::~OpaqueJSClassContextData()
191324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver{
192324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if (staticValues) {
193324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        deleteAllValues(*staticValues);
194324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        delete staticValues;
195324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
196324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
197324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if (staticFunctions) {
198324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        deleteAllValues(*staticFunctions);
199324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        delete staticFunctions;
200324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
201324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
202324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
203324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverOpaqueJSClassContextData& OpaqueJSClass::contextData(ExecState* exec)
204324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver{
205324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    OpaqueJSClassContextData*& contextData = exec->globalData().opaqueJSClassData.add(this, 0).first->second;
206324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if (!contextData)
207324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        contextData = new OpaqueJSClassContextData(exec->globalData(), this);
208324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return *contextData;
209324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
210324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
211324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverUString OpaqueJSClass::className()
212324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver{
213324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    // Make a deep copy, so that the caller has no chance to put the original into IdentifierTable.
214324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return UString(m_className.characters(), m_className.length());
215324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
216324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
217324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverOpaqueJSClassStaticValuesTable* OpaqueJSClass::staticValues(JSC::ExecState* exec)
218324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver{
219324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    OpaqueJSClassContextData& jsClassData = contextData(exec);
220324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return jsClassData.staticValues;
221324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
222324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
223324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverOpaqueJSClassStaticFunctionsTable* OpaqueJSClass::staticFunctions(JSC::ExecState* exec)
224324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver{
225324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    OpaqueJSClassContextData& jsClassData = contextData(exec);
226324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return jsClassData.staticFunctions;
227324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
228324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
229324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver/*!
230324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver// Doc here in case we make this public. (Hopefully we won't.)
231324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver@function
232324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver @abstract Returns the prototype that will be used when constructing an object with a given class.
233324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver @param ctx The execution context to use.
234324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver @param jsClass A JSClass whose prototype you want to get.
235324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver @result The JSObject prototype that was automatically generated for jsClass, or NULL if no prototype was automatically generated. This is the prototype that will be used when constructing an object using jsClass.
236324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver*/
237324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverJSObject* OpaqueJSClass::prototype(ExecState* exec)
238324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver{
239324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    /* Class (C++) and prototype (JS) inheritance are parallel, so:
240324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     *     (C++)      |        (JS)
241324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     *   ParentClass  |   ParentClassPrototype
242324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     *       ^        |          ^
243324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     *       |        |          |
244324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     *  DerivedClass  |  DerivedClassPrototype
245324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     */
246324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
247324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if (!prototypeClass)
248324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return 0;
249324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
250324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    OpaqueJSClassContextData& jsClassData = contextData(exec);
251324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
252324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if (!jsClassData.cachedPrototype) {
253324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        // Recursive, but should be good enough for our purposes
254324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        jsClassData.cachedPrototype.set(exec->globalData(), new (exec) JSCallbackObject<JSObjectWithGlobalObject>(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackObjectStructure(), prototypeClass, &jsClassData), 0); // set jsClassData as the object's private data, so it can clear our reference on destruction
255324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if (parentClass) {
256324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            if (JSObject* prototype = parentClass->prototype(exec))
257324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                jsClassData.cachedPrototype->setPrototype(exec->globalData(), prototype);
258324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
259324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
260324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return jsClassData.cachedPrototype.get();
261324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
262324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver