source: webkit/trunk/JavaScriptCore/API/JSClassRef.cpp@ 55833

Last change on this file since 55833 was 55833, checked in by [email protected], 15 years ago

Rubber stamped by Oliver Hunt.

Rename JSC::UStringImpl::data() to characters(), to match WebCore::StringImpl.

JavaScriptCore:

  • API/JSClassRef.cpp:

(OpaqueJSClassContextData::OpaqueJSClassContextData):

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::keyForCharacterSwitch):

  • bytecompiler/NodesCodegen.cpp:

(JSC::processClauseList):

  • interpreter/Interpreter.cpp:

(JSC::Interpreter::privateExecute):

  • jit/JITStubs.cpp:

(JSC::DEFINE_STUB_FUNCTION):

  • runtime/ArrayPrototype.cpp:

(JSC::arrayProtoFuncToString):

  • runtime/Identifier.cpp:

(JSC::Identifier::equal):
(JSC::Identifier::addSlowCase):

  • runtime/JSString.cpp:

(JSC::JSString::resolveRope):

  • runtime/UString.cpp:

(JSC::UString::toStrictUInt32):
(JSC::equal):

  • runtime/UString.h:

(JSC::UString::data):

  • runtime/UStringImpl.h:

(JSC::UStringImpl::characters):
(JSC::UStringImpl::hash):
(JSC::UStringImpl::setHash):

WebCore:

  • bridge/jni/jsc/JavaStringJSC.h:

(JSC::Bindings::JavaStringImpl::uchars):

  • platform/text/AtomicString.cpp:

(WebCore::AtomicString::add):
(WebCore::AtomicString::find):

  • Property svn:eol-style set to native
File size: 10.6 KB
Line 
1/*
2 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "JSClassRef.h"
28
29#include "APICast.h"
30#include "JSCallbackObject.h"
31#include "JSObjectRef.h"
32#include <runtime/InitializeThreading.h>
33#include <runtime/JSGlobalObject.h>
34#include <runtime/ObjectPrototype.h>
35#include <runtime/Identifier.h>
36#include <wtf/unicode/UTF8.h>
37
38using namespace std;
39using namespace JSC;
40using namespace WTF::Unicode;
41
42const JSClassDefinition kJSClassDefinitionEmpty = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
43
44static inline UString tryCreateStringFromUTF8(const char* string)
45{
46 if (!string)
47 return UString::null();
48
49 size_t length = strlen(string);
50 Vector<UChar, 1024> buffer(length);
51 UChar* p = buffer.data();
52 if (conversionOK != convertUTF8ToUTF16(&string, string + length, &p, p + length))
53 return UString::null();
54
55 return UString(buffer.data(), p - buffer.data());
56}
57
58OpaqueJSClass::OpaqueJSClass(const JSClassDefinition* definition, OpaqueJSClass* protoClass)
59 : parentClass(definition->parentClass)
60 , prototypeClass(0)
61 , initialize(definition->initialize)
62 , finalize(definition->finalize)
63 , hasProperty(definition->hasProperty)
64 , getProperty(definition->getProperty)
65 , setProperty(definition->setProperty)
66 , deleteProperty(definition->deleteProperty)
67 , getPropertyNames(definition->getPropertyNames)
68 , callAsFunction(definition->callAsFunction)
69 , callAsConstructor(definition->callAsConstructor)
70 , hasInstance(definition->hasInstance)
71 , convertToType(definition->convertToType)
72 , m_className(tryCreateStringFromUTF8(definition->className))
73 , m_staticValues(0)
74 , m_staticFunctions(0)
75{
76 initializeThreading();
77
78 if (const JSStaticValue* staticValue = definition->staticValues) {
79 m_staticValues = new OpaqueJSClassStaticValuesTable();
80 while (staticValue->name) {
81 UString valueName = tryCreateStringFromUTF8(staticValue->name);
82 if (!valueName.isNull()) {
83 // Use a local variable here to sidestep an RVCT compiler bug.
84 StaticValueEntry* entry = new StaticValueEntry(staticValue->getProperty, staticValue->setProperty, staticValue->attributes);
85 UStringImpl* impl = valueName.rep();
86 impl->ref();
87 m_staticValues->add(impl, entry);
88 }
89 ++staticValue;
90 }
91 }
92
93 if (const JSStaticFunction* staticFunction = definition->staticFunctions) {
94 m_staticFunctions = new OpaqueJSClassStaticFunctionsTable();
95 while (staticFunction->name) {
96 UString functionName = tryCreateStringFromUTF8(staticFunction->name);
97 if (!functionName.isNull()) {
98 // Use a local variable here to sidestep an RVCT compiler bug.
99 StaticFunctionEntry* entry = new StaticFunctionEntry(staticFunction->callAsFunction, staticFunction->attributes);
100 UStringImpl* impl = functionName.rep();
101 impl->ref();
102 m_staticFunctions->add(impl, entry);
103 }
104 ++staticFunction;
105 }
106 }
107
108 if (protoClass)
109 prototypeClass = JSClassRetain(protoClass);
110}
111
112OpaqueJSClass::~OpaqueJSClass()
113{
114 ASSERT(!m_className.rep()->isIdentifier());
115
116 if (m_staticValues) {
117 OpaqueJSClassStaticValuesTable::const_iterator end = m_staticValues->end();
118 for (OpaqueJSClassStaticValuesTable::const_iterator it = m_staticValues->begin(); it != end; ++it) {
119 ASSERT(!it->first->isIdentifier());
120 delete it->second;
121 }
122 delete m_staticValues;
123 }
124
125 if (m_staticFunctions) {
126 OpaqueJSClassStaticFunctionsTable::const_iterator end = m_staticFunctions->end();
127 for (OpaqueJSClassStaticFunctionsTable::const_iterator it = m_staticFunctions->begin(); it != end; ++it) {
128 ASSERT(!it->first->isIdentifier());
129 delete it->second;
130 }
131 delete m_staticFunctions;
132 }
133
134 if (prototypeClass)
135 JSClassRelease(prototypeClass);
136}
137
138PassRefPtr<OpaqueJSClass> OpaqueJSClass::createNoAutomaticPrototype(const JSClassDefinition* definition)
139{
140 return adoptRef(new OpaqueJSClass(definition, 0));
141}
142
143static void clearReferenceToPrototype(JSObjectRef prototype)
144{
145 OpaqueJSClassContextData* jsClassData = static_cast<OpaqueJSClassContextData*>(JSObjectGetPrivate(prototype));
146 ASSERT(jsClassData);
147 jsClassData->cachedPrototype.clear(toJS(prototype));
148}
149
150PassRefPtr<OpaqueJSClass> OpaqueJSClass::create(const JSClassDefinition* clientDefinition)
151{
152 JSClassDefinition definition = *clientDefinition; // Avoid modifying client copy.
153
154 JSClassDefinition protoDefinition = kJSClassDefinitionEmpty;
155 protoDefinition.finalize = clearReferenceToPrototype;
156 swap(definition.staticFunctions, protoDefinition.staticFunctions); // Move static functions to the prototype.
157
158 // We are supposed to use JSClassRetain/Release but since we know that we currently have
159 // the only reference to this class object we cheat and use a RefPtr instead.
160 RefPtr<OpaqueJSClass> protoClass = adoptRef(new OpaqueJSClass(&protoDefinition, 0));
161 return adoptRef(new OpaqueJSClass(&definition, protoClass.get()));
162}
163
164OpaqueJSClassContextData::OpaqueJSClassContextData(OpaqueJSClass* jsClass)
165 : m_class(jsClass)
166{
167 if (jsClass->m_staticValues) {
168 staticValues = new OpaqueJSClassStaticValuesTable;
169 OpaqueJSClassStaticValuesTable::const_iterator end = jsClass->m_staticValues->end();
170 for (OpaqueJSClassStaticValuesTable::const_iterator it = jsClass->m_staticValues->begin(); it != end; ++it) {
171 ASSERT(!it->first->isIdentifier());
172 // Use a local variable here to sidestep an RVCT compiler bug.
173 StaticValueEntry* entry = new StaticValueEntry(it->second->getProperty, it->second->setProperty, it->second->attributes);
174 staticValues->add(UString::Rep::create(it->first->characters(), it->first->length()), entry);
175 }
176 } else
177 staticValues = 0;
178
179 if (jsClass->m_staticFunctions) {
180 staticFunctions = new OpaqueJSClassStaticFunctionsTable;
181 OpaqueJSClassStaticFunctionsTable::const_iterator end = jsClass->m_staticFunctions->end();
182 for (OpaqueJSClassStaticFunctionsTable::const_iterator it = jsClass->m_staticFunctions->begin(); it != end; ++it) {
183 ASSERT(!it->first->isIdentifier());
184 // Use a local variable here to sidestep an RVCT compiler bug.
185 StaticFunctionEntry* entry = new StaticFunctionEntry(it->second->callAsFunction, it->second->attributes);
186 staticFunctions->add(UString::Rep::create(it->first->characters(), it->first->length()), entry);
187 }
188
189 } else
190 staticFunctions = 0;
191}
192
193OpaqueJSClassContextData::~OpaqueJSClassContextData()
194{
195 if (staticValues) {
196 deleteAllValues(*staticValues);
197 delete staticValues;
198 }
199
200 if (staticFunctions) {
201 deleteAllValues(*staticFunctions);
202 delete staticFunctions;
203 }
204}
205
206OpaqueJSClassContextData& OpaqueJSClass::contextData(ExecState* exec)
207{
208 OpaqueJSClassContextData*& contextData = exec->globalData().opaqueJSClassData.add(this, 0).first->second;
209 if (!contextData)
210 contextData = new OpaqueJSClassContextData(this);
211 return *contextData;
212}
213
214UString OpaqueJSClass::className()
215{
216 // Make a deep copy, so that the caller has no chance to put the original into IdentifierTable.
217 return UString(m_className.data(), m_className.size());
218}
219
220OpaqueJSClassStaticValuesTable* OpaqueJSClass::staticValues(JSC::ExecState* exec)
221{
222 OpaqueJSClassContextData& jsClassData = contextData(exec);
223 return jsClassData.staticValues;
224}
225
226OpaqueJSClassStaticFunctionsTable* OpaqueJSClass::staticFunctions(JSC::ExecState* exec)
227{
228 OpaqueJSClassContextData& jsClassData = contextData(exec);
229 return jsClassData.staticFunctions;
230}
231
232/*!
233// Doc here in case we make this public. (Hopefully we won't.)
234@function
235 @abstract Returns the prototype that will be used when constructing an object with a given class.
236 @param ctx The execution context to use.
237 @param jsClass A JSClass whose prototype you want to get.
238 @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.
239*/
240JSObject* OpaqueJSClass::prototype(ExecState* exec)
241{
242 /* Class (C++) and prototype (JS) inheritance are parallel, so:
243 * (C++) | (JS)
244 * ParentClass | ParentClassPrototype
245 * ^ | ^
246 * | | |
247 * DerivedClass | DerivedClassPrototype
248 */
249
250 if (!prototypeClass)
251 return 0;
252
253 OpaqueJSClassContextData& jsClassData = contextData(exec);
254
255 if (!jsClassData.cachedPrototype) {
256 // Recursive, but should be good enough for our purposes
257 jsClassData.cachedPrototype = new (exec) JSCallbackObject<JSObject>(exec, exec->lexicalGlobalObject()->callbackObjectStructure(), prototypeClass, &jsClassData); // set jsClassData as the object's private data, so it can clear our reference on destruction
258 if (parentClass) {
259 if (JSObject* prototype = parentClass->prototype(exec))
260 jsClassData.cachedPrototype->setPrototype(prototype);
261 }
262 }
263 return jsClassData.cachedPrototype.get();
264}
Note: See TracBrowser for help on using the repository browser.