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

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

JavaScriptCore: Make naming & behaviour of UString[Impl] methods more consistent.
https://bugs.webkit.org/show_bug.cgi?id=33702

Reviewed by Sam Weinig.

UString::create() creates a copy of the UChar* passed, but UStringImpl::create() assumes
that it should assume ownership of the provided buffer (with UString::createNonCopying()
and UStringImpl::createCopying() providing the alternate behaviours). Unify on create()
taking a copy of the provided buffer. For non-copying cases, use the name 'adopt', and
make this method take a Vector<UChar>&. For cases where non-copying construction was being
used, other than from a Vector<UChar>, change the code to allocate the storage along with
the UStringImpl using UStringImpl::createUninitialized(). (The adopt() method also more
closely matches that of WebCore::StringImpl).

Also, UString::createUninitialized() and UStringImpl::createUninitialized() have incompatible
behaviours, in that the UString form sets the provided UChar* to a null or non-null value to
indicate success or failure, but UStringImpl uses the returned PassRefPtr<UStringImpl> to
indicate when allocation has failed (potentially leaving the output Char* uninitialized).
This is also incompatible with WebCore::StringImpl's behaviour, in that
StringImpl::createUninitialized() will CRASH() if unable to allocate. Some uses of
createUninitialized() in JSC are unsafe, since they do not test the result for null.
UStringImpl's indication is preferable, since we may want a successful call to set the result
buffer to 0 (specifically, StringImpl returns 0 for the buffer where createUninitialized()
returns the empty string, which seems reasonable to catch bugs early). UString's method
cannot support UStringImpl's behaviour directly, since it returns an object rather than a
pointer.

  • remove UString::createUninitialized(), replace with calls to UStringImpl::createUninitialized()
  • create a UStringImpl::tryCreateUninitialized() form UStringImpl::createUninitialized(), with current behaviour, make createUninitialized() crash on failure to allocate.
  • make cases in JSC that do not check the result call createUninitialized(), and cases that do check call tryCreateUninitialized().

Rename computedHash() to existingHash(), to bring this in line wih WebCore::StringImpl.

  • API/JSClassRef.cpp:

(OpaqueJSClassContextData::OpaqueJSClassContextData):

(JSC::arrayProtoFuncToString):

  • runtime/Identifier.cpp:

(JSC::CStringTranslator::translate):
(JSC::UCharBufferTranslator::translate):

  • runtime/JSString.cpp:

(JSC::JSString::resolveRope):

  • runtime/Lookup.cpp:

(JSC::HashTable::createTable):

  • runtime/Lookup.h:

(JSC::HashTable::entry):

  • runtime/StringBuilder.h:

(JSC::StringBuilder::release):

  • runtime/StringConstructor.cpp:

(JSC::stringFromCharCodeSlowCase):

  • runtime/StringPrototype.cpp:

(JSC::substituteBackreferencesSlow):
(JSC::stringProtoFuncToLowerCase):
(JSC::stringProtoFuncToUpperCase):
(JSC::stringProtoFuncFontsize):
(JSC::stringProtoFuncLink):

  • runtime/Structure.cpp:

(JSC::Structure::despecifyDictionaryFunction):
(JSC::Structure::get):
(JSC::Structure::despecifyFunction):
(JSC::Structure::put):
(JSC::Structure::remove):
(JSC::Structure::insertIntoPropertyMapHashTable):
(JSC::Structure::checkConsistency):

  • runtime/Structure.h:

(JSC::Structure::get):

  • runtime/StructureTransitionTable.h:

(JSC::StructureTransitionTableHash::hash):

  • runtime/UString.cpp:

(JSC::createRep):
(JSC::UString::UString):
(JSC::UString::spliceSubstringsWithSeparators):
(JSC::UString::replaceRange):
(JSC::UString::operator=):

  • runtime/UString.h:

(JSC::UString::adopt):
(JSC::IdentifierRepHash::hash):
(JSC::makeString):

  • runtime/UStringImpl.h:

(JSC::UStringImpl::adopt):
(JSC::UStringImpl::create):
(JSC::UStringImpl::createUninitialized):
(JSC::UStringImpl::tryCreateUninitialized):
(JSC::UStringImpl::existingHash):

WebCore: Rubber stamped by Sam Weinig.

Make naming & behaviour of UString[Impl] methods more consistent.
https://bugs.webkit.org/show_bug.cgi?id=33702

WebCore change reflecting UString method name change computedHash() -> existingHash().

  • platform/text/AtomicString.cpp:

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

  • Property svn:eol-style set to native
File size: 10.0 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
37using namespace JSC;
38
39const JSClassDefinition kJSClassDefinitionEmpty = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
40
41OpaqueJSClass::OpaqueJSClass(const JSClassDefinition* definition, OpaqueJSClass* protoClass)
42 : parentClass(definition->parentClass)
43 , prototypeClass(0)
44 , initialize(definition->initialize)
45 , finalize(definition->finalize)
46 , hasProperty(definition->hasProperty)
47 , getProperty(definition->getProperty)
48 , setProperty(definition->setProperty)
49 , deleteProperty(definition->deleteProperty)
50 , getPropertyNames(definition->getPropertyNames)
51 , callAsFunction(definition->callAsFunction)
52 , callAsConstructor(definition->callAsConstructor)
53 , hasInstance(definition->hasInstance)
54 , convertToType(definition->convertToType)
55 , m_className(UString::createFromUTF8(definition->className).rep()->ref())
56 , m_staticValues(0)
57 , m_staticFunctions(0)
58{
59 initializeThreading();
60
61 if (const JSStaticValue* staticValue = definition->staticValues) {
62 m_staticValues = new OpaqueJSClassStaticValuesTable();
63 while (staticValue->name) {
64 // Use a local variable here to sidestep an RVCT compiler bug.
65 StaticValueEntry* entry = new StaticValueEntry(staticValue->getProperty, staticValue->setProperty, staticValue->attributes);
66 m_staticValues->add(UString::createFromUTF8(staticValue->name).rep()->ref(), entry);
67 ++staticValue;
68 }
69 }
70
71 if (const JSStaticFunction* staticFunction = definition->staticFunctions) {
72 m_staticFunctions = new OpaqueJSClassStaticFunctionsTable();
73 while (staticFunction->name) {
74 // Use a local variable here to sidestep an RVCT compiler bug.
75 StaticFunctionEntry* entry = new StaticFunctionEntry(staticFunction->callAsFunction, staticFunction->attributes);
76 m_staticFunctions->add(UString::createFromUTF8(staticFunction->name).rep()->ref(), entry);
77 ++staticFunction;
78 }
79 }
80
81 if (protoClass)
82 prototypeClass = JSClassRetain(protoClass);
83}
84
85OpaqueJSClass::~OpaqueJSClass()
86{
87 ASSERT(!m_className.rep()->isIdentifier());
88
89 if (m_staticValues) {
90 OpaqueJSClassStaticValuesTable::const_iterator end = m_staticValues->end();
91 for (OpaqueJSClassStaticValuesTable::const_iterator it = m_staticValues->begin(); it != end; ++it) {
92 ASSERT(!it->first->isIdentifier());
93 delete it->second;
94 }
95 delete m_staticValues;
96 }
97
98 if (m_staticFunctions) {
99 OpaqueJSClassStaticFunctionsTable::const_iterator end = m_staticFunctions->end();
100 for (OpaqueJSClassStaticFunctionsTable::const_iterator it = m_staticFunctions->begin(); it != end; ++it) {
101 ASSERT(!it->first->isIdentifier());
102 delete it->second;
103 }
104 delete m_staticFunctions;
105 }
106
107 if (prototypeClass)
108 JSClassRelease(prototypeClass);
109}
110
111PassRefPtr<OpaqueJSClass> OpaqueJSClass::createNoAutomaticPrototype(const JSClassDefinition* definition)
112{
113 return adoptRef(new OpaqueJSClass(definition, 0));
114}
115
116static void clearReferenceToPrototype(JSObjectRef prototype)
117{
118 OpaqueJSClassContextData* jsClassData = static_cast<OpaqueJSClassContextData*>(JSObjectGetPrivate(prototype));
119 ASSERT(jsClassData);
120 jsClassData->cachedPrototype = 0;
121}
122
123PassRefPtr<OpaqueJSClass> OpaqueJSClass::create(const JSClassDefinition* definition)
124{
125 if (const JSStaticFunction* staticFunctions = definition->staticFunctions) {
126 // copy functions into a prototype class
127 JSClassDefinition protoDefinition = kJSClassDefinitionEmpty;
128 protoDefinition.staticFunctions = staticFunctions;
129 protoDefinition.finalize = clearReferenceToPrototype;
130
131 // We are supposed to use JSClassRetain/Release but since we know that we currently have
132 // the only reference to this class object we cheat and use a RefPtr instead.
133 RefPtr<OpaqueJSClass> protoClass = adoptRef(new OpaqueJSClass(&protoDefinition, 0));
134
135 // remove functions from the original class
136 JSClassDefinition objectDefinition = *definition;
137 objectDefinition.staticFunctions = 0;
138
139 return adoptRef(new OpaqueJSClass(&objectDefinition, protoClass.get()));
140 }
141
142 return adoptRef(new OpaqueJSClass(definition, 0));
143}
144
145OpaqueJSClassContextData::OpaqueJSClassContextData(OpaqueJSClass* jsClass)
146 : m_class(jsClass)
147{
148 if (jsClass->m_staticValues) {
149 staticValues = new OpaqueJSClassStaticValuesTable;
150 OpaqueJSClassStaticValuesTable::const_iterator end = jsClass->m_staticValues->end();
151 for (OpaqueJSClassStaticValuesTable::const_iterator it = jsClass->m_staticValues->begin(); it != end; ++it) {
152 ASSERT(!it->first->isIdentifier());
153 // Use a local variable here to sidestep an RVCT compiler bug.
154 StaticValueEntry* entry = new StaticValueEntry(it->second->getProperty, it->second->setProperty, it->second->attributes);
155 staticValues->add(UString::Rep::create(it->first->data(), it->first->size()), entry);
156
157 }
158
159 } else
160 staticValues = 0;
161
162
163 if (jsClass->m_staticFunctions) {
164 staticFunctions = new OpaqueJSClassStaticFunctionsTable;
165 OpaqueJSClassStaticFunctionsTable::const_iterator end = jsClass->m_staticFunctions->end();
166 for (OpaqueJSClassStaticFunctionsTable::const_iterator it = jsClass->m_staticFunctions->begin(); it != end; ++it) {
167 ASSERT(!it->first->isIdentifier());
168 // Use a local variable here to sidestep an RVCT compiler bug.
169 StaticFunctionEntry* entry = new StaticFunctionEntry(it->second->callAsFunction, it->second->attributes);
170 staticFunctions->add(UString::Rep::create(it->first->data(), it->first->size()), entry);
171 }
172
173 } else
174 staticFunctions = 0;
175}
176
177OpaqueJSClassContextData::~OpaqueJSClassContextData()
178{
179 if (staticValues) {
180 deleteAllValues(*staticValues);
181 delete staticValues;
182 }
183
184 if (staticFunctions) {
185 deleteAllValues(*staticFunctions);
186 delete staticFunctions;
187 }
188}
189
190OpaqueJSClassContextData& OpaqueJSClass::contextData(ExecState* exec)
191{
192 OpaqueJSClassContextData*& contextData = exec->globalData().opaqueJSClassData.add(this, 0).first->second;
193 if (!contextData)
194 contextData = new OpaqueJSClassContextData(this);
195 return *contextData;
196}
197
198UString OpaqueJSClass::className()
199{
200 // Make a deep copy, so that the caller has no chance to put the original into IdentifierTable.
201 return UString(m_className.data(), m_className.size());
202}
203
204OpaqueJSClassStaticValuesTable* OpaqueJSClass::staticValues(JSC::ExecState* exec)
205{
206 OpaqueJSClassContextData& jsClassData = contextData(exec);
207 return jsClassData.staticValues;
208}
209
210OpaqueJSClassStaticFunctionsTable* OpaqueJSClass::staticFunctions(JSC::ExecState* exec)
211{
212 OpaqueJSClassContextData& jsClassData = contextData(exec);
213 return jsClassData.staticFunctions;
214}
215
216/*!
217// Doc here in case we make this public. (Hopefully we won't.)
218@function
219 @abstract Returns the prototype that will be used when constructing an object with a given class.
220 @param ctx The execution context to use.
221 @param jsClass A JSClass whose prototype you want to get.
222 @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.
223*/
224JSObject* OpaqueJSClass::prototype(ExecState* exec)
225{
226 /* Class (C++) and prototype (JS) inheritance are parallel, so:
227 * (C++) | (JS)
228 * ParentClass | ParentClassPrototype
229 * ^ | ^
230 * | | |
231 * DerivedClass | DerivedClassPrototype
232 */
233
234 if (!prototypeClass)
235 return 0;
236
237 OpaqueJSClassContextData& jsClassData = contextData(exec);
238
239 if (!jsClassData.cachedPrototype) {
240 // Recursive, but should be good enough for our purposes
241 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
242 if (parentClass) {
243 if (JSObject* prototype = parentClass->prototype(exec))
244 jsClassData.cachedPrototype->setPrototype(prototype);
245 }
246 }
247 return jsClassData.cachedPrototype.get();
248}
Note: See TracBrowser for help on using the repository browser.