class ExecState;
class JSValue;
class JSObject;
- class ReferenceList;
+ class PropertyNameArray;
}
/* Opaque typing convenience methods */
return reinterpret_cast<KJS::JSObject*>(o);
}
-inline KJS::ReferenceList* toJS(JSPropertyListRef l)
+inline KJS::PropertyNameArray* toJS(JSPropertyNameAccumulatorRef a)
{
- return reinterpret_cast<KJS::ReferenceList*>(l);
+ return reinterpret_cast<KJS::PropertyNameArray*>(a);
}
inline JSValueRef toRef(KJS::JSValue* v)
return reinterpret_cast<JSObjectRef>(const_cast<KJS::JSObject*>(o));
}
-inline JSPropertyListRef toRef(KJS::ReferenceList* l)
+inline JSContextRef toRef(KJS::ExecState* e)
{
- return reinterpret_cast<JSPropertyListRef>(l);
+ return reinterpret_cast<JSContextRef>(e);
}
-inline JSContextRef toRef(KJS::ExecState* e)
+inline JSPropertyNameAccumulatorRef toRef(KJS::PropertyNameArray* l)
{
- return reinterpret_cast<JSContextRef>(e);
+ return reinterpret_cast<JSPropertyNameAccumulatorRef>(l);
}
#endif // APICast_h
/*! @typedef JSClassRef A JavaScript class. Used with JSObjectMake to construct objects with custom behavior. */
typedef struct __JSClass* JSClassRef;
-/*! @typedef JSPropertyListRef A JavaScript property list. Used for listing the properties in an object so they can be enumerated. */
-typedef struct __JSPropertyList* JSPropertyListRef;
+/*! @typedef JSPropertyNameArrayRef An array of JavaScript property names. */
+typedef struct __JSPropertyNameArray* JSPropertyNameArrayRef;
-/*! @typedef JSPropertyEnumeratorRef A JavaScript property enumerator. Used for enumerating the properties in an object. */
-typedef struct __JSPropertyEnumerator* JSPropertyEnumeratorRef;
+/*! @typedef JSPropertyNameAccumulatorRef A data type used to collect a JavaScript object's property names. */
+typedef struct __JSPropertyNameAccumulator* JSPropertyNameAccumulatorRef;
/* JavaScript data types */
#include "JSClassRef.h"
#include "JSObjectRef.h"
#include "internal.h"
-#include "reference.h"
-#include "reference_list.h"
+#include "PropertyNameArray.h"
namespace KJS {
return 0;
}
-void JSCallbackObject::getPropertyList(ReferenceList& propertyList, bool recursive)
+void JSCallbackObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
{
+ JSContextRef execRef = toRef(exec);
JSObjectRef thisRef = toRef(this);
for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass) {
- if (JSObjectAddPropertiesToListCallback addPropertiesToList = jsClass->addPropertiesToList)
- addPropertiesToList(thisRef, toRef(&propertyList));
+ if (JSObjectGetPropertyNamesCallback getPropertyNames = jsClass->getPropertyNames)
+ getPropertyNames(execRef, thisRef, toRef(&propertyNames));
if (__JSClass::StaticValuesTable* staticValues = jsClass->staticValues) {
typedef __JSClass::StaticValuesTable::const_iterator iterator;
UString::Rep* name = it->first.get();
StaticValueEntry* entry = it->second;
if (entry->getProperty && !(entry->attributes & kJSPropertyAttributeDontEnum))
- propertyList.append(Reference(this, Identifier(name)));
+ propertyNames.add(Identifier(name));
}
}
UString::Rep* name = it->first.get();
StaticFunctionEntry* entry = it->second;
if (!(entry->attributes & kJSPropertyAttributeDontEnum))
- propertyList.append(Reference(this, Identifier(name)));
+ propertyNames.add(Identifier(name));
}
}
}
- JSObject::getPropertyList(propertyList, recursive);
+ JSObject::getPropertyNames(exec, propertyNames);
}
double JSCallbackObject::toNumber(ExecState* exec) const
virtual bool implementsCall() const;
virtual JSValue* callAsFunction(ExecState*, JSObject* thisObj, const List &args);
- virtual void getPropertyList(ReferenceList& propertyList, bool recursive);
+ virtual void getPropertyNames(ExecState*, PropertyNameArray&);
virtual double toNumber(ExecState*) const;
virtual UString toString(ExecState*) const;
, getProperty(definition->getProperty)
, setProperty(definition->setProperty)
, deleteProperty(definition->deleteProperty)
- , addPropertiesToList(definition->addPropertiesToList)
+ , getPropertyNames(definition->getPropertyNames)
, callAsFunction(definition->callAsFunction)
, callAsConstructor(definition->callAsConstructor)
, hasInstance(definition->hasInstance)
JSObjectGetPropertyCallback getProperty;
JSObjectSetPropertyCallback setProperty;
JSObjectDeletePropertyCallback deleteProperty;
- JSObjectAddPropertiesToListCallback addPropertiesToList;
+ JSObjectGetPropertyNamesCallback getPropertyNames;
JSObjectCallAsFunctionCallback callAsFunction;
JSObjectCallAsConstructorCallback callAsConstructor;
JSObjectHasInstanceCallback hasInstance;
#include "nodes.h"
#include "internal.h"
#include "object.h"
-#include "reference_list.h"
+#include "PropertyNameArray.h"
using namespace KJS;
return result;
}
-struct __JSPropertyEnumerator
+struct __JSPropertyNameArray
{
- __JSPropertyEnumerator() : refCount(0), iterator(list.end())
+ __JSPropertyNameArray() : refCount(0)
{
}
unsigned refCount;
- ReferenceList list;
- ReferenceListIterator iterator;
+ PropertyNameArray array;
};
-JSPropertyEnumeratorRef JSObjectCreatePropertyEnumerator(JSObjectRef object)
+JSPropertyNameArrayRef JSObjectCopyPropertyNames(JSContextRef context, JSObjectRef object)
{
JSLock lock;
JSObject* jsObject = toJS(object);
+ ExecState* exec = toJS(context);
- JSPropertyEnumeratorRef enumerator = new __JSPropertyEnumerator();
- jsObject->getPropertyList(enumerator->list);
- enumerator->iterator = enumerator->list.begin();
+ JSPropertyNameArrayRef propertyNames = new __JSPropertyNameArray();
+ jsObject->getPropertyNames(exec, propertyNames->array);
- return JSPropertyEnumeratorRetain(enumerator);
+ return JSPropertyNameArrayRetain(propertyNames);
}
-JSStringRef JSPropertyEnumeratorGetNextName(JSPropertyEnumeratorRef enumerator)
+JSPropertyNameArrayRef JSPropertyNameArrayRetain(JSPropertyNameArrayRef array)
{
- ReferenceListIterator& iterator = enumerator->iterator;
- if (iterator != enumerator->list.end()) {
- JSStringRef result = toRef(iterator->getPropertyName().ustring().rep());
- iterator++;
- return result;
- }
- return 0;
+ ++array->refCount;
+ return array;
+}
+
+void JSPropertyNameArrayRelease(JSPropertyNameArrayRef array)
+{
+ if (--array->refCount == 0)
+ delete array;
}
-JSPropertyEnumeratorRef JSPropertyEnumeratorRetain(JSPropertyEnumeratorRef enumerator)
+size_t JSPropertyNameArrayGetCount(JSPropertyNameArrayRef array)
{
- ++enumerator->refCount;
- return enumerator;
+ return array->array.size();
}
-void JSPropertyEnumeratorRelease(JSPropertyEnumeratorRef enumerator)
+JSStringRef JSPropertyNameArrayGetNameAtIndex(JSPropertyNameArrayRef array, size_t index)
{
- if (--enumerator->refCount == 0)
- delete enumerator;
+ return toRef(array->array[index].ustring().rep());
}
-void JSPropertyListAdd(JSPropertyListRef propertyList, JSObjectRef thisObject, JSStringRef propertyName)
+void JSPropertyNameAccumulatorAddName(JSPropertyNameAccumulatorRef array, JSStringRef propertyName)
{
JSLock lock;
- ReferenceList* jsPropertyList = toJS(propertyList);
- JSObject* jsObject = toJS(thisObject);
+ PropertyNameArray* propertyNames = toJS(array);
UString::Rep* rep = toJS(propertyName);
- jsPropertyList->append(Reference(jsObject, Identifier(rep)));
+ propertyNames->add(Identifier(rep));
}
(*JSObjectDeletePropertyCallback) (JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
/*!
-@typedef JSObjectAddPropertiesToListCallback
-@abstract The callback invoked when adding an object's properties to a property list.
-@param object The JSObject whose properties need to be added to propertyList.
-@param propertyList A JavaScript property list that will be used to enumerate object's properties.
-@discussion If you named your function GetPropertyList, you would declare it like this:
+@typedef JSObjectGetPropertyNamesCallback
+@abstract The callback invoked to get the names of an object's properties.
+@param context The current execution context.
+@param object The JSObject whose property names need to be appended to propertyNames.
+@param accumulator A JavaScript property name accumulator, to which the object should add the names of its properties.
+@discussion If you named your function GetPropertyNames, you would declare it like this:
+
+void GetPropertyNames(JSContextRef context, JSObjectRef object, JSPropertyNameAccumulatorRef accumulator);
-void AddPropertiesToList(JSObjectRef object, JSPropertyListRef propertyList);
+Use JSPropertyNameAccumulatorAddName to add property names to accumulator.
-Use JSPropertyListAdd to add properties to propertyList.
+Property lists are used by JSPropertyEnumerators and JavaScript for...in loops.
-Property lists are used by JSPropertyEnumerators and JavaScript for...in loops.
+It's only necessary to add names of properties that you handle
+specially in your own get / set callbacks. Static property names,
+names of standard JS properties, and properties from the prototype
+will be added automatically.
*/
typedef void
-(*JSObjectAddPropertiesToListCallback) (JSObjectRef object, JSPropertyListRef propertyList);
+(*JSObjectGetPropertyNamesCallback) (JSContextRef context, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames);
/*!
@typedef JSObjectCallAsFunctionCallback
JSObjectGetPropertyCallback getProperty;
JSObjectSetPropertyCallback setProperty;
JSObjectDeletePropertyCallback deleteProperty;
- JSObjectAddPropertiesToListCallback addPropertiesToList;
+ JSObjectGetPropertyNamesCallback getPropertyNames;
JSObjectCallAsFunctionCallback callAsFunction;
JSObjectCallAsConstructorCallback callAsConstructor;
JSObjectHasInstanceCallback hasInstance;
@param object The JSObject whose property you want to set.
@param propertyIndex The property's name as a number
@param value A JSValue to use as the property's value.
-@param attributes A logically ORed set of JSPropertyAttributes to give to the property.
@discussion This is equivalent to setting a property by a string name containing the number, but allows faster access to JS arrays.
*/
-void JSObjectSetPropertyAtIndex(JSContextRef context, JSObjectRef object, unsigned propertyIndex, JSValueRef value, JSPropertyAttributes attributes);
+void JSObjectSetPropertyAtIndex(JSContextRef context, JSObjectRef object, unsigned propertyIndex, JSValueRef value);
/*!
@function
/*!
@function
-@abstract Creates an enumerator for an object's properties.
-@param object The object whose properties you want to enumerate.
-@result A JSPropertyEnumerator with a list of object's properties. Ownership follows the Create Rule.
+@abstract Get the names of all enumerable properties of an object.
+@param context The execution context to use.
+@param object The object from which to get property names.
+@result A JSPropertyNameArray containing the names of all the object's enumerable properties.
*/
-JSPropertyEnumeratorRef JSObjectCreatePropertyEnumerator(JSObjectRef object);
+JSPropertyNameArrayRef JSObjectCopyPropertyNames(JSContextRef context, JSObjectRef object);
+
/*!
@function
-@abstract Retains a property enumerator.
-@param enumerator The JSPropertyEnumerator to retain.
-@result A JSPropertyEnumerator that is the same as enumerator.
+@abstract Retains a JavaScript property name array.
+@param array The JSPropertyNameArray to retain.
+@result A JSPropertyNameArray that is the same as array.
*/
-JSPropertyEnumeratorRef JSPropertyEnumeratorRetain(JSPropertyEnumeratorRef enumerator);
+JSPropertyNameArrayRef JSPropertyNameArrayRetain(JSPropertyNameArrayRef array);
+
/*!
@function
-@abstract Releases a property enumerator.
-@param enumerator The JSPropertyEnumerator to release.
+@abstract Releases a JavaScript property name array.
+@param array The JSPropetyNameArray to release.
*/
-void JSPropertyEnumeratorRelease(JSPropertyEnumeratorRef enumerator);
+void JSPropertyNameArrayRelease(JSPropertyNameArrayRef array);
+
+/*!
+@function
+@abstract Get the number of items in a JavaScript property name array.
+@param array The array from which to retrieve the count.
+@result The count of items in the array.
+*/
+size_t JSPropertyNameArrayGetCount(JSPropertyNameArrayRef array);
+
/*!
@function
-@abstract Gets a property enumerator's next property.
-@param enumerator The JSPropertyEnumerator whose next property you want to get.
-@result A JSString containing the property's name, or NULL if all properties have been enumerated.
+@abstract Get a single item from a JavaScript property name array.
+@param array The array from which to retrieve a property name.
+@param index The index of the property name to retrieve.
+@result A JSStringRef containing the name of the property.
*/
-JSStringRef JSPropertyEnumeratorGetNextName(JSPropertyEnumeratorRef enumerator);
+JSStringRef JSPropertyNameArrayGetNameAtIndex(JSPropertyNameArrayRef array, size_t index);
/*!
@function
-@abstract Adds a property to a 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.
+@abstract Add a property name - useful while getting the property names for an object.
+@param accumulator The accumulator object to which to add the property.
+@param propertyName The new property to add.
*/
-void JSPropertyListAdd(JSPropertyListRef propertyList, JSObjectRef thisObject, JSStringRef propertyName);
+void JSPropertyNameAccumulatorAddName(JSPropertyNameAccumulatorRef accumulator, JSStringRef propertyName);
#ifdef __cplusplus
}
return false;
}
-static void MyObject_addPropertiesToList(JSObjectRef object, JSPropertyListRef propertyList)
+static void MyObject_getPropertyNames(JSContextRef context, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames)
{
UNUSED_PARAM(context);
JSStringRef propertyName;
propertyName = JSStringCreateWithUTF8CString("alwaysOne");
- JSPropertyListAdd(propertyList, object, propertyName);
+ JSPropertyNameAccumulatorAddName(propertyNames, propertyName);
JSStringRelease(propertyName);
propertyName = JSStringCreateWithUTF8CString("myPropertyName");
- JSPropertyListAdd(propertyList, object, propertyName);
+ JSPropertyNameAccumulatorAddName(propertyNames, propertyName);
JSStringRelease(propertyName);
}
MyObject_getProperty,
MyObject_setProperty,
MyObject_deleteProperty,
- MyObject_addPropertiesToList,
+ MyObject_getPropertyNames,
MyObject_callAsFunction,
MyObject_callAsConstructor,
MyObject_hasInstance,
o = JSObjectMake(context, NULL, NULL);
JSObjectSetProperty(context, o, jsOneIString, JSValueMakeNumber(1), kJSPropertyAttributeNone, NULL);
JSObjectSetProperty(context, o, jsCFIString, JSValueMakeNumber(1), kJSPropertyAttributeDontEnum, NULL);
- JSPropertyEnumeratorRef enumerator = JSObjectCreatePropertyEnumerator(o);
- int count = 0;
- while (JSPropertyEnumeratorGetNextName(enumerator))
- ++count;
- JSPropertyEnumeratorRelease(enumerator);
+ JSPropertyNameArrayRef nameArray = JSObjectCopyPropertyNames(context, o);
+ size_t expectedCount = JSPropertyNameArrayGetCount(nameArray);
+ size_t count;
+ for (count = 0; count < expectedCount; ++count)
+ JSPropertyNameArrayGetNameAtIndex(nameArray, count);
+ JSPropertyNameArrayRelease(nameArray);
assert(count == 1); // jsCFString should not be enumerated
JSClassDefinition nullDefinition = kJSClassDefinitionNull;
+2006-07-15 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Darin.
+
+ - switch property lists to be vector+set of Identifiers instead of list of References
+
+ This has the following benefits:
+
+ - no duplicates in property lists
+ - simplifies API calls
+ - probably more efficient, since linked list is gone
+ - entirely removed Reference, ReferenceList and ProtectedReference types from the API
+
+ * kjs/PropertyNameArray.cpp: Added.
+ (KJS::PropertyNameArray::add): Check set, if not already there, add to
+ vector.
+ * kjs/PropertyNameArray.h: Added.
+ (KJS::PropertyNameArray::PropertyNameArray): Newly added type, combines
+ a set and a vector to make a unique but ordered list of identifiers.
+ (KJS::PropertyNameArray::begin): ditto
+ (KJS::PropertyNameArray::end): ditto
+ (KJS::PropertyNameArray::size): ditto
+ (KJS::PropertyNameArray::operator[]): ditto
+ * kjs/array_instance.h:
+ * kjs/array_object.cpp:
+ (ArrayInstance::getPropertyNames): renamed from getPropertyList, updated
+ for PropertyNameArray
+ (ArrayInstance::setLength): updated for PropertyNameArray
+ (ArrayInstance::pushUndefinedObjectsToEnd): ditto
+ * kjs/nodes.cpp:
+ (ForInNode::execute): updated for PropertyNameArray
+ * kjs/nodes.h:
+ * kjs/object.cpp:
+ (KJS::JSObject::getPropertyNames): renamed from getPropertyList, updated
+ for PropertyNameArray
+ * kjs/object.h:
+ * kjs/property_map.cpp:
+ (KJS::PropertyMap::getEnumerablePropertyNames): updated for PropertyNameArray
+ (KJS::PropertyMap::getSparseArrayPropertyNames): ditto
+ * kjs/property_map.h:
+ * kjs/protected_reference.h: Removed.
+ * kjs/reference.cpp: Removed.
+ * kjs/reference.h: Removed.
+ * kjs/reference_list.cpp: Removed.
+ * kjs/reference_list.h: Removed.
+ * kjs/scope_chain.cpp:
+ (KJS::ScopeChain::print): Use PropertyNamesArray instead of ReferenceList.
+ * kjs/string_object.cpp:
+ (StringInstance::getPropertyNames): Updated for new approach.
+ * kjs/string_object.h:
+ * kjs/ustring.h:
+ * API/APICast.h:
+ (toJS): Added overload for PropertyNameAccumulatorRef / PropertyNameArray*
+ (toRef): ditto
+ * API/JSBase.h:
+ * API/JSCallbackObject.cpp:
+ (KJS::JSCallbackObject::getPropertyNames): Fixed for new API.
+ * API/JSCallbackObject.h:
+ * API/JSObjectRef.cpp:
+ (__JSPropertyNameArray::__JSPropertyNameArray): Type used for a publicly vended
+ JSPropertyNameArrayRef.
+ (JSObjectCopyPropertyNames): New API call - renamed / refactored from
+ JSObjectCreatePropertyList
+ (JSPropertyNameArrayRetain): new retain call for JSPropertyNameArray.
+ (JSPropertyNameArrayRelease): new release call for - " -.
+ (JSPropertyNameArrayGetCount): Instead of having to use a stateful enumerator you
+ can now get the count and items in any order.
+ (JSPropertyNameArrayGetNameAtIndex): See above.
+ (JSPropertyNameAccumulatorAddName): What you add properties to is now an opaque
+ accumulator object.
+ * API/JSObjectRef.h: Prototyped new functions, removed old ones
+ * JavaScriptCore.exp: Updated exported symbols.
+ * JavaScriptCore.xcodeproj/project.pbxproj: Added new files, removed old.
+ * API/testapi.c:
+ (MyObject_getPropertyNames): Renamed / fixed callback to fit new paradigm.
+ (main): Updated for new API.
+
2006-07-15 Darin Adler <darin@apple.com>
- oops, missed a few more arrays that had to be const
_JSGlobalContextRetain
_JSObjectCallAsConstructor
_JSObjectCallAsFunction
-_JSObjectCreatePropertyEnumerator
+_JSObjectCopyPropertyNames
_JSObjectDeleteProperty
_JSObjectGetPrivate
_JSObjectGetProperty
+_JSObjectGetPropertyAtIndex
_JSObjectGetPrototype
_JSObjectHasProperty
_JSObjectIsConstructor
_JSObjectMakeFunctionWithBody
_JSObjectSetPrivate
_JSObjectSetProperty
+_JSObjectSetPropertyAtIndex
_JSObjectSetPrototype
-_JSPropertyEnumeratorGetNextName
-_JSPropertyEnumeratorRelease
-_JSPropertyEnumeratorRetain
-_JSPropertyListAdd
+_JSPropertyNameAccumulatorAddName
+_JSPropertyNameArrayGetCount
+_JSPropertyNameArrayGetNameAtIndex
+_JSPropertyNameArrayRelease
+_JSPropertyNameArrayRetain
_JSStringCopyCFString
_JSStringCreateWithCFString
_JSStringCreateWithCharacters
__ZN3KJS12DateInstance4infoE
__ZN3KJS12PropertySlot15undefinedGetterEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERKS0_
__ZN3KJS12jsNumberCellEd
-__ZN3KJS13ReferenceList6appendERKNS_9ReferenceE
-__ZN3KJS13ReferenceListC1Ev
-__ZN3KJS13ReferenceListD1Ev
__ZN3KJS13SavedBuiltinsC1Ev
__ZN3KJS13SavedBuiltinsD1Ev
__ZN3KJS15SavedPropertiesC1Ev
__ZN3KJS15SavedPropertiesD1Ev
__ZN3KJS16RuntimeObjectImpC1EPNS_8Bindings8InstanceE
+__ZN3KJS17PropertyNameArray3addERKNS_10IdentifierE
__ZN3KJS18lengthPropertyNameE
__ZN3KJS19InternalFunctionImp11hasInstanceEPNS_9ExecStateEPNS_7JSValueE
__ZN3KJS19InternalFunctionImp4infoE
__ZN3KJS19InternalFunctionImpC2EPNS_17FunctionPrototypeERKNS_10IdentifierE
__ZN3KJS19messagePropertyNameE
-__ZN3KJS21ReferenceListIteratorppEi
__ZN3KJS21prototypePropertyNameE
__ZN3KJS4List6appendEPNS_7JSValueE
__ZN3KJS4List7releaseEv
__ZN3KJS8JSObject14callAsFunctionEPNS_9ExecStateEPS0_RKNS_4ListE
__ZN3KJS8JSObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
__ZN3KJS8JSObject14deletePropertyEPNS_9ExecStateEj
-__ZN3KJS8JSObject15getPropertyListERNS_13ReferenceListEb
+__ZN3KJS8JSObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
__ZN3KJS8JSObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
__ZN3KJS8JSObject22fillGetterPropertySlotERNS_12PropertySlotEPPNS_7JSValueE
__ZN3KJS8JSObject3putEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueEi
__ZN3KJS9Collector7collectEv
__ZN3KJS9Collector7protectEPNS_7JSValueE
__ZN3KJS9Collector9unprotectEPNS_7JSValueE
-__ZN3KJS9ReferenceC1EPNS_8JSObjectERKNS_10IdentifierE
__ZN3KJSeqERKNS_7UStringEPKc
__ZN3WTF10fastCallocEmm
__ZN3WTF10fastMallocEm
__ZNK3KJS11PropertyMap3getERKNS_10IdentifierE
__ZNK3KJS11PropertyMap4saveERNS_15SavedPropertiesE
__ZNK3KJS12DateInstance7getTimeERdRi
-__ZNK3KJS13ReferenceList3endEv
-__ZNK3KJS13ReferenceList5beginEv
__ZNK3KJS19InternalFunctionImp14implementsCallEv
__ZNK3KJS19InternalFunctionImp21implementsHasInstanceEv
-__ZNK3KJS21ReferenceListIteratorneERKS0_
-__ZNK3KJS21ReferenceListIteratorptEv
__ZNK3KJS4List2atEi
__ZNK3KJS4List8copyTailEv
__ZNK3KJS6JSCell9getNumberERd
__ZNK3KJS8JSObject9classNameEv
__ZNK3KJS8JSObject9toBooleanEPNS_9ExecStateE
__ZNK3KJS9ExecState18lexicalInterpreterEv
-__ZNK3KJS9Reference15getPropertyNameEv
__ZTVN3KJS19InternalFunctionImpE
__ZTVN3KJS8JSObjectE
_kJSClassDefinitionNull
14BD5A360A3E91F600BAF59C /* JavaScriptCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 14BD5A2F0A3E91F600BAF59C /* JavaScriptCore.h */; settings = {ATTRIBUTES = (Private, ); }; };
14F137590A3A727E00F26F90 /* Context.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14F137580A3A727E00F26F90 /* Context.cpp */; };
14F137830A3A765B00F26F90 /* context.h in Headers */ = {isa = PBXBuildFile; fileRef = 14F137820A3A765B00F26F90 /* context.h */; settings = {ATTRIBUTES = (Private, ); }; };
- 652C107F08DA7B1E0020887D /* protected_reference.h in Headers */ = {isa = PBXBuildFile; fileRef = 652C107E08DA7B1E0020887D /* protected_reference.h */; };
+ 65400C110A69BAF200509887 /* PropertyNameArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65400C0F0A69BAF200509887 /* PropertyNameArray.cpp */; };
+ 65400C120A69BAF200509887 /* PropertyNameArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 65400C100A69BAF200509887 /* PropertyNameArray.h */; settings = {ATTRIBUTES = (Private, ); }; };
6541BD7208E80A17002CBEE7 /* TCPageMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 6541BD6E08E80A17002CBEE7 /* TCPageMap.h */; };
6541BD7308E80A17002CBEE7 /* TCSpinLock.h in Headers */ = {isa = PBXBuildFile; fileRef = 6541BD6F08E80A17002CBEE7 /* TCSpinLock.h */; };
6541BD7408E80A17002CBEE7 /* TCSystemAlloc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6541BD7008E80A17002CBEE7 /* TCSystemAlloc.cpp */; };
932F5B5C0822A1C700736975 /* ustring.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A8860255597D01FF60F7 /* ustring.h */; settings = {ATTRIBUTES = (Private, ); }; };
932F5B600822A1C700736975 /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = F68EBB8C0255D4C601FF60F7 /* config.h */; settings = {ATTRIBUTES = (Private, ); }; };
932F5B610822A1C700736975 /* JavaScriptCorePrefix.h in Headers */ = {isa = PBXBuildFile; fileRef = F5C290E60284F98E018635CA /* JavaScriptCorePrefix.h */; };
- 932F5B630822A1C700736975 /* reference_list.h in Headers */ = {isa = PBXBuildFile; fileRef = F54F0800030CD22001B5C2EB /* reference_list.h */; settings = {ATTRIBUTES = (Private, ); }; };
- 932F5B640822A1C700736975 /* reference.h in Headers */ = {isa = PBXBuildFile; fileRef = F5341391030CEEB1018BE7F3 /* reference.h */; settings = {ATTRIBUTES = (Private, ); }; };
932F5B650822A1C700736975 /* completion.h in Headers */ = {isa = PBXBuildFile; fileRef = F5BB2BC5030F772101FCFE1D /* completion.h */; settings = {ATTRIBUTES = (Private, ); }; };
932F5B660822A1C700736975 /* identifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 933A349A038AE7C6008635CE /* identifier.h */; settings = {ATTRIBUTES = (Private, ); }; };
932F5B670822A1C700736975 /* array_instance.h in Headers */ = {isa = PBXBuildFile; fileRef = 938772E5038BFE19008635CE /* array_instance.h */; settings = {ATTRIBUTES = (Private, ); }; };
932F5BA80822A1C700736975 /* ustring.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F692A8850255597D01FF60F7 /* ustring.cpp */; };
932F5BA90822A1C700736975 /* value.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F692A8870255597D01FF60F7 /* value.cpp */; };
932F5BAB0822A1C700736975 /* nodes2string.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5FFE656026B47A6018635CA /* nodes2string.cpp */; };
- 932F5BAC0822A1C700736975 /* reference.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5341390030CEEB1018BE7F3 /* reference.cpp */; settings = {ATTRIBUTES = (Private, ); }; };
- 932F5BAD0822A1C700736975 /* reference_list.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5341394030CF5F8018BE7F3 /* reference_list.cpp */; settings = {ATTRIBUTES = (Private, ); }; };
932F5BAE0822A1C700736975 /* identifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 933A349D038AE80F008635CE /* identifier.cpp */; };
932F5BAF0822A1C700736975 /* scope_chain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9374D3A8038D9D74008635CE /* scope_chain.cpp */; };
932F5BB00822A1C700736975 /* list.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 931C6CF0038EE8DE008635CE /* list.cpp */; };
51F0EC9705C88DC700E6DF1B /* objc_utility.mm */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = objc_utility.mm; path = bindings/objc/objc_utility.mm; sourceTree = "<group>"; tabWidth = 8; };
651F6412039D5B5F0078395C /* dtoa.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dtoa.cpp; sourceTree = "<group>"; tabWidth = 8; };
651F6413039D5B5F0078395C /* dtoa.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = dtoa.h; sourceTree = "<group>"; tabWidth = 8; };
- 652C107E08DA7B1E0020887D /* protected_reference.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = protected_reference.h; sourceTree = "<group>"; tabWidth = 8; };
+ 65400C0F0A69BAF200509887 /* PropertyNameArray.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = PropertyNameArray.cpp; sourceTree = "<group>"; };
+ 65400C100A69BAF200509887 /* PropertyNameArray.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PropertyNameArray.h; sourceTree = "<group>"; };
6541720E039E08B90058BFEB /* dftables.c */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.c; name = dftables.c; path = pcre/dftables.c; sourceTree = "<group>"; tabWidth = 8; };
6541720F039E08B90058BFEB /* pcre.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; name = pcre.h; path = pcre/pcre.h; sourceTree = "<group>"; tabWidth = 8; };
65417217039E0B280058BFEB /* pcre-config.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; name = "pcre-config.h"; path = "pcre/pcre-config.h"; sourceTree = "<group>"; tabWidth = 8; };
E195678F09E7CF1200B89D13 /* UnicodeIcu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnicodeIcu.h; sourceTree = "<group>"; };
E195679409E7CF1200B89D13 /* Unicode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Unicode.h; sourceTree = "<group>"; };
E195679509E7CF1200B89D13 /* UnicodeCategory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnicodeCategory.h; sourceTree = "<group>"; };
- F5341390030CEEB1018BE7F3 /* reference.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = reference.cpp; sourceTree = "<group>"; tabWidth = 8; };
- F5341391030CEEB1018BE7F3 /* reference.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = reference.h; sourceTree = "<group>"; tabWidth = 8; };
- F5341394030CF5F8018BE7F3 /* reference_list.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = reference_list.cpp; sourceTree = "<group>"; tabWidth = 8; };
- F54F0800030CD22001B5C2EB /* reference_list.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = reference_list.h; sourceTree = "<group>"; tabWidth = 8; };
F5BB2BC5030F772101FCFE1D /* completion.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = completion.h; sourceTree = "<group>"; tabWidth = 8; };
F5C290E60284F98E018635CA /* JavaScriptCorePrefix.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; name = JavaScriptCorePrefix.h; path = ../JavaScriptCorePrefix.h; sourceTree = "<group>"; tabWidth = 8; };
F5FFE656026B47A6018635CA /* nodes2string.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = nodes2string.cpp; sourceTree = "<group>"; tabWidth = 8; };
65417200039E01BA0058BFEB /* kjs */ = {
isa = PBXGroup;
children = (
+ 65400C0F0A69BAF200509887 /* PropertyNameArray.cpp */,
+ 65400C100A69BAF200509887 /* PropertyNameArray.h */,
938772E5038BFE19008635CE /* array_instance.h */,
F692A84D0255597D01FF60F7 /* array_object.cpp */,
F692A84E0255597D01FF60F7 /* array_object.h */,
65621E6B089E859700760F35 /* property_slot.cpp */,
65621E6C089E859700760F35 /* property_slot.h */,
65C02FBB0637462A003E7EE6 /* protect.h */,
- 652C107E08DA7B1E0020887D /* protected_reference.h */,
- F5341390030CEEB1018BE7F3 /* reference.cpp */,
- F5341391030CEEB1018BE7F3 /* reference.h */,
- F5341394030CF5F8018BE7F3 /* reference_list.cpp */,
- F54F0800030CD22001B5C2EB /* reference_list.h */,
F692A87D0255597D01FF60F7 /* regexp.cpp */,
F692A87E0255597D01FF60F7 /* regexp.h */,
F692A87B0255597D01FF60F7 /* regexp_object.cpp */,
932F5B5C0822A1C700736975 /* ustring.h in Headers */,
932F5B600822A1C700736975 /* config.h in Headers */,
932F5B610822A1C700736975 /* JavaScriptCorePrefix.h in Headers */,
- 932F5B630822A1C700736975 /* reference_list.h in Headers */,
- 932F5B640822A1C700736975 /* reference.h in Headers */,
932F5B650822A1C700736975 /* completion.h in Headers */,
932F5B660822A1C700736975 /* identifier.h in Headers */,
932F5B670822A1C700736975 /* array_instance.h in Headers */,
93E26BFD08B151D400F85226 /* ucp.h in Headers */,
93E26BFE08B151D400F85226 /* ucpinternal.h in Headers */,
93E26C1308B1523D00F85226 /* ucptable.c in Headers */,
- 652C107F08DA7B1E0020887D /* protected_reference.h in Headers */,
65E217BD08E7EECC0023E5F6 /* Assertions.h in Headers */,
65E217C008E7EECC0023E5F6 /* FastMalloc.h in Headers */,
6541BD7208E80A17002CBEE7 /* TCPageMap.h in Headers */,
1440F8910A508B100005F061 /* JSCallbackFunction.h in Headers */,
1440F8AE0A508D200005F061 /* JSCallbackConstructor.h in Headers */,
1440FCE30A51E46B0005F061 /* JSClassRef.h in Headers */,
+ 65400C120A69BAF200509887 /* PropertyNameArray.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
932F5BA80822A1C700736975 /* ustring.cpp in Sources */,
932F5BA90822A1C700736975 /* value.cpp in Sources */,
932F5BAB0822A1C700736975 /* nodes2string.cpp in Sources */,
- 932F5BAC0822A1C700736975 /* reference.cpp in Sources */,
- 932F5BAD0822A1C700736975 /* reference_list.cpp in Sources */,
932F5BAE0822A1C700736975 /* identifier.cpp in Sources */,
932F5BAF0822A1C700736975 /* scope_chain.cpp in Sources */,
932F5BB00822A1C700736975 /* list.cpp in Sources */,
1440F8AF0A508D200005F061 /* JSCallbackConstructor.cpp in Sources */,
1440FCE40A51E46B0005F061 /* JSClassRef.cpp in Sources */,
1421359B0A677F4F00A8195E /* JSBase.cpp in Sources */,
+ 65400C110A69BAF200509887 /* PropertyNameArray.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
--- /dev/null
+// -*- mode: c++; c-basic-offset: 4 -*-
+/*
+ * Copyright (C) 2006 Apple Computer, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "PropertyNameArray.h"
+
+namespace KJS {
+
+void PropertyNameArray::add(const Identifier& ident)
+{
+ if (!m_set.add(ident.ustring().rep()).second)
+ return;
+
+ m_vector.append(ident);
+}
+
+} // namespace KJS
+
--- /dev/null
+// -*- mode: c++; c-basic-offset: 4 -*-
+/*
+ * Copyright (C) 2006 Apple Computer, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef KJS_PROPERTY_NAME_ARRAY_H
+#define KJS_PROPERTY_NAME_ARRAY_H
+
+#include "identifier.h"
+
+#include <wtf/HashSet.h>
+#include <wtf/Vector.h>
+
+namespace KJS {
+
+ class PropertyNameArray;
+
+ typedef Vector<Identifier>::const_iterator PropertyNameArrayIterator;
+
+ class PropertyNameArray {
+ public:
+ typedef PropertyNameArrayIterator iterator;
+
+ void add(const Identifier&);
+ iterator begin() const { return m_vector.begin(); }
+ iterator end() const { return m_vector.end(); }
+ int size() const { return m_vector.size(); }
+
+ Identifier& operator[](unsigned i) { return m_vector[i]; }
+ const Identifier& operator[](unsigned i) const { return m_vector[i]; }
+
+ private:
+ typedef HashSet<UString::Rep*, PtrHash<UString::Rep*> > IdentifierSet;
+ IdentifierSet m_set;
+ Vector<Identifier> m_vector;
+ };
+
+
+} // namespace KJS
+
+
+#endif // KJS_PROPERTY_NAME_ARRAY_H
virtual void put(ExecState *exec, unsigned propertyName, JSValue *value, int attr = None);
virtual bool deleteProperty(ExecState *exec, const Identifier &propertyName);
virtual bool deleteProperty(ExecState *exec, unsigned propertyName);
- virtual void getPropertyList(ReferenceList& propertyList, bool recursive);
+ virtual void getPropertyNames(ExecState*, PropertyNameArray&);
virtual void mark();
#include "error_object.h"
#include "lookup.h"
#include "operations.h"
-#include "reference_list.h"
+#include "PropertyNameArray.h"
#include <wtf/HashSet.h>
#include <stdio.h>
return JSObject::deleteProperty(exec, Identifier::from(index));
}
-void ArrayInstance::getPropertyList(ReferenceList& propertyList, bool recursive)
+void ArrayInstance::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
{
// avoid fetching this every time through the loop
- JSValue *undefined = jsUndefined();
-
- //### FIXME: should avoid duplicates with prototype
+ JSValue* undefined = jsUndefined();
+
for (unsigned i = 0; i < storageLength; ++i) {
- JSValue *imp = storage[i];
- if (imp && imp != undefined) {
- propertyList.append(Reference(this, i));
- }
+ JSValue* value = storage[i];
+ if (value && value != undefined)
+ propertyNames.add(Identifier::from(i));
}
- return JSObject::getPropertyList(propertyList, recursive);
+
+ JSObject::getPropertyNames(exec, propertyNames);
}
void ArrayInstance::resizeStorage(unsigned newLength)
}
if (newLength < length) {
- ReferenceList sparseProperties;
+ PropertyNameArray sparseProperties;
- _prop.addSparseArrayPropertiesToReferenceList(sparseProperties, this);
+ _prop.getSparseArrayPropertyNames(sparseProperties);
- ReferenceListIterator it = sparseProperties.begin();
- while (it != sparseProperties.end()) {
- Reference ref = it++;
+ PropertyNameArrayIterator end = sparseProperties.end();
+
+ for (PropertyNameArrayIterator it = sparseProperties.begin(); it != end; ++it) {
+ Identifier name = *it;
bool ok;
- unsigned index = ref.getPropertyName().toArrayIndex(&ok);
- if (ok && index > newLength) {
- ref.deleteValue(exec);
- }
+ unsigned index = name.toArrayIndex(&ok);
+ if (ok && index > newLength)
+ deleteProperty(exec, name);
}
}
o++;
}
}
+
+ PropertyNameArray sparseProperties;
+ _prop.getSparseArrayPropertyNames(sparseProperties);
+ unsigned newLength = o + sparseProperties.size();
+
+ if (newLength > storageLength)
+ resizeStorage(newLength);
- ReferenceList sparseProperties;
- _prop.addSparseArrayPropertiesToReferenceList(sparseProperties, this);
- unsigned newLength = o + sparseProperties.length();
-
- if (newLength > storageLength) {
- resizeStorage(newLength);
- }
-
- ReferenceListIterator it = sparseProperties.begin();
- while (it != sparseProperties.end()) {
- Reference ref = it++;
- storage[o] = ref.getValue(exec);
- JSObject::deleteProperty(exec, ref.getPropertyName());
- o++;
+ PropertyNameArrayIterator end = sparseProperties.end();
+ for (PropertyNameArrayIterator it = sparseProperties.begin(); it != end; ++it) {
+ Identifier name = *it;
+ storage[o] = get(exec, name);
+ JSObject::deleteProperty(exec, name);
+ o++;
}
if (newLength != storageLength)
#include "function_object.h"
#include "lexer.h"
#include "operations.h"
-#include "reference_list.h"
+#include "PropertyNameArray.h"
#include <wtf/HashSet.h>
#include <wtf/HashCountedSet.h>
#include <wtf/MathExtras.h>
JSValue *retval = 0;
JSObject *v;
Completion c;
- ReferenceList propertyList;
+ PropertyNameArray propertyNames;
if (varDecl) {
varDecl->evaluate(exec);
KJS_CHECKEXCEPTION
v = e->toObject(exec);
- v->getPropertyList(propertyList);
-
- ReferenceListIterator propIt = propertyList.begin();
-
- while (propIt != propertyList.end()) {
- Identifier name = propIt->getPropertyName();
- if (!v->hasProperty(exec, name)) {
- propIt++;
- continue;
- }
+ v->getPropertyNames(exec, propertyNames);
+
+ PropertyNameArrayIterator end = propertyNames.end();
+ for (PropertyNameArrayIterator it = propertyNames.begin(); it != end; ++it) {
+ const Identifier &name = *it;
+ if (!v->hasProperty(exec, name))
+ continue;
- JSValue *str = jsString(name.ustring());
+ JSValue *str = jsString(name.ustring());
- if (lexpr->isResolveNode()) {
+ if (lexpr->isResolveNode()) {
const Identifier &ident = static_cast<ResolveNode *>(lexpr.get())->identifier();
const ScopeChain& chain = exec->context()->scopeChain();
return c;
}
}
-
- propIt++;
}
// bail out on error
class ProgramNode;
class PropertyNameNode;
class PropertyListNode;
- class Reference;
class RegExp;
class SourceElementsNode;
class SourceStream;
#include "lookup.h"
#include "nodes.h"
#include "operations.h"
-#include "reference_list.h"
+#include "PropertyNameArray.h"
#include <math.h>
// maximum global call stack size. Protects against accidental or
return false;
}
-void JSObject::getPropertyList(ReferenceList& propertyList, bool recursive)
+void JSObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
{
- _prop.addEnumerablesToReferenceList(propertyList, this);
+ _prop.getEnumerablePropertyNames(propertyNames);
// Add properties from the static hashtable of properties
const ClassInfo *info = classInfo();
int size = info->propHashTable->size;
const HashEntry *e = info->propHashTable->entries;
for (int i = 0; i < size; ++i, ++e) {
- if ( e->s && !(e->attr & DontEnum) )
- propertyList.append(Reference(this, e->s)); /// ######### check for duplicates with the propertymap
+ if (e->s && !(e->attr & DontEnum))
+ propertyNames.add(e->s);
}
}
info = info->parentClass;
}
- if (_proto->isObject() && recursive)
- static_cast<JSObject*>(_proto)->getPropertyList(propertyList, recursive);
+ if (_proto->isObject())
+ static_cast<JSObject*>(_proto)->getPropertyNames(exec, propertyNames);
}
bool JSObject::toBoolean(ExecState */*exec*/) const
class HashEntry;
class ListImp;
class InternalFunctionImp;
+ class PropertyNameArray;
// ECMA 262-3 8.6.1
// Property attributes
const ScopeChain &scope() const { return _scope; }
void setScope(const ScopeChain &s) { _scope = s; }
- /**
- * Returns a List of References to all the properties of the object. Used
- * in "for x in y" statements. The list is created new, so it can be freely
- * modified without affecting the object's properties. It should be deleted
- * by the caller.
- *
- * Subclasses can override this method in ObjectImpl to provide the
- * appearance of
- * having extra properties other than those set specifically with put().
- *
- * @param exec The current execution state
- * @param recursive Whether or not properties in the object's prototype
- * chain should be
- * included in the list.
- * @return A List of References to properties of the object.
- **/
- virtual void getPropertyList(ReferenceList& propertyList, bool recursive = true);
+ virtual void getPropertyNames(ExecState*, PropertyNameArray&);
/**
* Returns the internal value of the object. This is used for objects such
#include "object.h"
#include "protect.h"
-#include "reference_list.h"
+#include "PropertyNameArray.h"
#include <algorithm>
#include <wtf/FastMalloc.h>
#include <wtf/Vector.h>
#endif
// lastIndexUsed is an ever-increasing index used to identify the order items
-// were inserted into the property map. It's vital that addEnumerablesToReferenceList
+// were inserted into the property map. It's vital that getEnumerablePropertyNames
// return the properties in the order they were added for compatibility with other
// browsers' JavaScript implementations.
struct PropertyMapHashTable
return false;
}
-void PropertyMap::addEnumerablesToReferenceList(ReferenceList &list, JSObject *base) const
+void PropertyMap::getEnumerablePropertyNames(PropertyNameArray& propertyNames) const
{
if (!_table) {
#if USE_SINGLE_ENTRY
UString::Rep *key = _singleEntry.key;
if (key && !(_singleEntry.attributes & DontEnum))
- list.append(Reference(base, Identifier(key)));
+ propertyNames.add(Identifier(key));
#endif
return;
}
// Sort the entries by index.
qsort(sortedEnumerables.data(), p - sortedEnumerables.data(), sizeof(Entry*), comparePropertyMapEntryIndices);
- // Put the keys of the sorted entries into the reference list.
+ // Put the keys of the sorted entries into the list.
for (Entry** q = sortedEnumerables.data(); q != p; ++q)
- list.append(Reference(base, Identifier((*q)->key)));
+ propertyNames.add(Identifier(q[0]->key));
}
-void PropertyMap::addSparseArrayPropertiesToReferenceList(ReferenceList &list, JSObject *base) const
+void PropertyMap::getSparseArrayPropertyNames(PropertyNameArray& propertyNames) const
{
if (!_table) {
#if USE_SINGLE_ENTRY
bool fitsInUInt32;
k.toUInt32(&fitsInUInt32);
if (fitsInUInt32)
- list.append(Reference(base, Identifier(key)));
+ propertyNames.add(Identifier(key));
}
#endif
return;
bool fitsInUInt32;
k.toUInt32(&fitsInUInt32);
if (fitsInUInt32)
- list.append(Reference(base, Identifier(key)));
+ propertyNames.add(Identifier(key));
}
}
}
namespace KJS {
+ class PropertyNameArray;
class JSObject;
- class ReferenceList;
class JSValue;
class SavedProperty;
JSValue **getLocation(const Identifier &name);
void mark() const;
- void addEnumerablesToReferenceList(ReferenceList &, JSObject *) const;
- void addSparseArrayPropertiesToReferenceList(ReferenceList &, JSObject *) const;
+ void getEnumerablePropertyNames(PropertyNameArray&) const;
+ void getSparseArrayPropertyNames(PropertyNameArray&) const;
void save(SavedProperties &) const;
void restore(const SavedProperties &p);
+++ /dev/null
-// -*- c-basic-offset: 4 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 2005 Apple Computer, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef KJS_PROTECTED_REFERENCE_H
-#define KJS_PROTECTED_REFERENCE_H
-
-#include "protect.h"
-
-namespace KJS {
-
- class ProtectedReference : public Reference {
- public:
- ProtectedReference(const Reference& r)
- : Reference(r)
- {
- JSLock lock;
- gcProtectNullTolerant(base);
- }
-
- ~ProtectedReference()
- {
- JSLock lock;
- gcUnprotectNullTolerant(base);
- }
-
- ProtectedReference& operator=(const Reference &r)
- {
- JSLock lock;
- JSValue *old = base;
- Reference::operator=(r);
- gcProtectNullTolerant(base);
- gcUnprotectNullTolerant(old);
- return *this;
- }
-
- private:
- ProtectedReference();
- ProtectedReference(JSObject *b, const Identifier& p);
- ProtectedReference(JSObject *b, unsigned p);
- ProtectedReference(const Identifier& p);
- ProtectedReference(unsigned p);
- };
-
-} // namespace
-
-#endif
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 2004 Apple Computer, Inc
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "JSType.h"
-#include "config.h"
-#include "internal.h"
-#include "reference.h"
-
-namespace KJS {
-
-// ------------------------------ Reference ------------------------------------
-
-Reference::Reference(JSObject *b, const Identifier& p)
- : base(b),
- propertyNameIsNumber(false),
- prop(p)
-{
-}
-
-Reference::Reference(JSObject *b, unsigned p)
- : base(b),
- propertyNameAsNumber(p),
- propertyNameIsNumber(true)
-{
-}
-
-Identifier Reference::getPropertyName() const
-{
- if (propertyNameIsNumber && prop.isNull())
- prop = Identifier::from(propertyNameAsNumber);
- return prop;
-}
-
-JSValue *Reference::getValue(ExecState *exec) const
-{
- JSValue *o = base;
- if (!o || !o->isObject()) {
- if (!o || o->isNull())
- return throwError(exec, ReferenceError, "Can't find variable: " + getPropertyName().ustring());
- return throwError(exec, ReferenceError, "Base is not an object");
- }
-
- if (propertyNameIsNumber)
- return static_cast<JSObject*>(o)->get(exec, propertyNameAsNumber);
- return static_cast<JSObject*>(o)->get(exec, prop);
-}
-
-bool Reference::deleteValue(ExecState *exec)
-{
- JSValue *o = base;
- JSType t = o ? o->type() : NullType;
-
- // The spec doesn't mention what to do if the base is null... just return true
- if (t != ObjectType) {
- assert(t == NullType);
- return true;
- }
-
- if (propertyNameIsNumber)
- return static_cast<JSObject*>(o)->deleteProperty(exec,propertyNameAsNumber);
- return static_cast<JSObject*>(o)->deleteProperty(exec,prop);
-}
-
-}
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 2003 Apple Computer, Inc
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef KJS_REFERENCE_H_
-#define KJS_REFERENCE_H_
-
-#include "object.h"
-
-namespace KJS {
-
- class JSObject;
-
- class Reference {
- friend class ReferenceList;
- friend class ReferenceListIterator;
- public:
- Reference(JSObject *b, const Identifier& p);
- Reference(JSObject *b, unsigned p);
-
- /**
- * Performs the GetPropertyName type conversion operation on this value
- * (ECMA 8.7)
- */
- Identifier getPropertyName() const;
-
- /**
- * Performs the GetValue type conversion operation on this value
- * (ECMA 8.7.1)
- */
- JSValue *getValue(ExecState *exec) const;
-
- /**
- * Performs the PutValue type conversion operation on this value
- * (ECMA 8.7.1)
- */
- bool deleteValue(ExecState *exec);
-
- protected:
- JSValue *base;
-
- private:
- Reference() { }
-
- unsigned propertyNameAsNumber;
- bool propertyNameIsNumber;
- mutable Identifier prop;
- };
-
-}
-
-#endif
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 2003 Apple Computer, Inc
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "reference_list.h"
-
-#include "protected_reference.h"
-
-namespace KJS {
- class ReferenceListNode {
- friend class ReferenceList;
- friend class ReferenceListIterator;
-
- protected:
- ReferenceListNode(const Reference &ref) : reference(ref), next(NULL) {}
-
- private:
- ProtectedReference reference;
- ReferenceListNode *next;
- };
-
- class ReferenceListHeadNode : ReferenceListNode {
- friend class ReferenceList;
- friend class ReferenceListIterator;
-
- ReferenceListHeadNode(const Reference &ref) : ReferenceListNode(ref), refcount(1) {}
- int refcount;
- int length;
- };
-
-}
-
-using namespace KJS;
-
-// ReferenceList
-
-ReferenceList::ReferenceList() :
- head(NULL),
- tail(NULL)
-{
-}
-
-ReferenceList::ReferenceList(const ReferenceList &list)
-{
- head = list.head;
- tail = list.tail;
- if (head != NULL) {
- head->refcount++;
- }
-}
-
-ReferenceList &ReferenceList::operator=(const ReferenceList &list)
-{
- ReferenceList tmp(list);
- tmp.swap(*this);
-
- return *this;
-}
-
-void ReferenceList::swap(ReferenceList &list)
-{
- ReferenceListHeadNode *tmpHead = list.head;
- list.head = head;
- head = tmpHead;
-
- ReferenceListNode *tmpTail = list.tail;
- list.tail = tail;
- tail = tmpTail;
-}
-
-
-void ReferenceList::append(const Reference& ref)
-{
- if (tail == NULL) {
- tail = head = new ReferenceListHeadNode(ref);
- } else {
- tail->next = new ReferenceListNode(ref);
- tail = tail->next;
- }
- head->length++;
-}
-
-int ReferenceList::length()
-{
- return head ? head->length : 0;
-}
-
-ReferenceList::~ReferenceList()
-{
- if (head != NULL && --(head->refcount) == 0) {
- ReferenceListNode *next;
-
- for (ReferenceListNode *p = head; p != NULL; p = next) {
- next = p->next;
- if (p == head) {
- delete (ReferenceListHeadNode *)p;
- } else {
- delete p;
- }
- }
- }
-}
-
-ReferenceListIterator ReferenceList::begin() const
-{
- return ReferenceListIterator(head);
-}
-
-ReferenceListIterator ReferenceList::end() const
-{
- return ReferenceListIterator(NULL);
-}
-
-
-// ReferenceListIterator
-
-
-ReferenceListIterator::ReferenceListIterator(ReferenceListNode *n) :
- node(n)
-{
-}
-
-bool ReferenceListIterator::operator!=(const ReferenceListIterator &it) const
-{
- return node != it.node;
-}
-
-const Reference *ReferenceListIterator::operator->() const
-{
- return &node->reference;
-}
-
-const Reference &ReferenceListIterator::operator++(int)
-{
- const Reference &ref = node->reference;
- node = node->next;
- return ref;
-}
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 2003 Apple Computer, Inc
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef KJS_REFERENCE_LIST_H_
-#define KJS_REFERENCE_LIST_H_
-
-#include "reference.h"
-
-namespace KJS {
-
- class ReferenceListNode;
- class ReferenceListHeadNode;
-
- class ReferenceListIterator {
- friend class ReferenceList;
-
- public:
- bool operator!=(const ReferenceListIterator &it) const;
- const Reference *operator->() const;
- const Reference &operator++(int i);
-
- private:
- ReferenceListIterator(ReferenceListNode *n);
- ReferenceListIterator();
- ReferenceListNode *node;
- };
-
- class ReferenceList {
- public:
- ReferenceList();
- ReferenceList(const ReferenceList &list);
- ReferenceList &operator=(const ReferenceList &list);
- ~ReferenceList();
-
- void append(const Reference& val);
- int length();
-
- ReferenceListIterator begin() const;
- ReferenceListIterator end() const;
-
- private:
- void swap(ReferenceList &list);
- ReferenceListHeadNode *head;
- ReferenceListNode *tail;
- };
-
-}
-
-#endif
#include "config.h"
#include "scope_chain.h"
-#include "reference_list.h"
+#include "PropertyNameArray.h"
+#include "object.h"
namespace KJS {
ScopeChainIterator scopeEnd = end();
for (ScopeChainIterator scopeIter = begin(); scopeIter != scopeEnd; ++scopeIter) {
JSObject* o = *scopeIter;
- ReferenceList propertyList;
- o->getPropertyList(propertyList, false);
- ReferenceListIterator propEnd = propertyList.end();
+ PropertyNameArray propertyNames;
+ // FIXME: should pass ExecState here!
+ o->getPropertyNames(0, propertyNames);
+ PropertyNameArrayIterator propEnd = propertyNames.end();
fprintf(stderr, "----- [scope %p] -----\n", o);
- for (ReferenceListIterator propIter = propertyList.begin(); propIter != propEnd; propIter++) {
- Identifier name = propIter->getPropertyName();
+ for (PropertyNameArrayIterator propIter = propertyNames.begin(); propIter != propEnd; propIter++) {
+ Identifier name = *propIter;
fprintf(stderr, "%s, ", name.ascii());
}
fprintf(stderr, "\n");
#include "error_object.h"
#include "operations.h"
-#include "reference_list.h"
+#include "PropertyNameArray.h"
#include "regexp_object.h"
#include <wtf/unicode/Unicode.h>
return JSObject::deleteProperty(exec, propertyName);
}
-void StringInstance::getPropertyList(ReferenceList& propertyList, bool recursive)
+void StringInstance::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
{
- //### FIXME: should avoid duplicates with prototype
int size = internalValue()->getString().size();
for (int i = 0; i < size; i++)
- propertyList.append(Reference(this, i));
- return JSObject::getPropertyList(propertyList, recursive);
+ propertyNames.add(Identifier(UString(i)));
+ return JSObject::getPropertyNames(exec, propertyNames);
}
// ------------------------------ StringPrototype ---------------------------
StringInstance(JSObject *proto);
StringInstance(JSObject *proto, const UString &string);
- virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
- virtual void put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr = None);
- virtual bool deleteProperty(ExecState *exec, const Identifier &propertyName);
- virtual void getPropertyList(ReferenceList& propertyList, bool recursive);
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+ virtual void put(ExecState* exec, const Identifier& propertyName, JSValue* value, int attr = None);
+ virtual bool deleteProperty(ExecState* exec, const Identifier& propertyName);
+ virtual void getPropertyNames(ExecState*, PropertyNameArray&);
virtual const ClassInfo *classInfo() const { return &info; }
static const ClassInfo info;
* @return Higher byte.
*/
unsigned char high() const { return ref().uc >> 8; }
+
private:
// not implemented, can only be constructed from UString
UCharReference();
};
public:
+
/**
* Constructs a null string.
*/
+2006-07-15 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Darin.
+
+ - switch property lists to be vector+set of Identifiers instead of list of References
+
+ * JSUtils.cpp:
+ (KJSValueToCFTypeInternal): updated for JSC SPI changes
+ * JSValueWrapper.cpp:
+ (JSValueWrapper::JSObjectCopyPropertyNames): ditto
+ * UserObjectImp.cpp:
+ (UserObjectImp::getPropertyNames): ditto
+ * UserObjectImp.h:
+
=== Safari-521.17 ===
2006-07-14 Geoffrey Garen <ggaren@apple.com>
#include "UserObjectImp.h"
#include "JSValueWrapper.h"
#include "JSObject.h"
-#include <JavaScriptCore/reference_list.h>
+#include <JavaScriptCore/PropertyNameArray.h>
struct ObjectImpList {
JSObject* imp;
isArray = true;
JSInterpreter* intrepreter = (JSInterpreter*)exec->dynamicInterpreter();
if (intrepreter && (intrepreter->Flags() & kJSFlagConvertAssociativeArray)) {
- ReferenceList propList;
- object->getPropertyList(propList);
- ReferenceListIterator iter = propList.begin();
- ReferenceListIterator end = propList.end();
+ PropertyNameArray propNames;
+ object->getPropertyNames(exec, propNames);
+ PropertyNameArrayIterator iter = propNames.begin();
+ PropertyNameArrayIterator end = propNames.end();
while(iter != end && isArray)
{
- Identifier propName = iter->getPropertyName();
+ Identifier propName = *iter;
UString ustr = propName.ustring();
const UniChar* uniChars = (const UniChar*)ustr.data();
int size = ustr.size();
else
{
// Not an array, just treat it like a dictionary which contains (property name, property value) pairs
- ReferenceList propList;
- object->getPropertyList(propList);
+ PropertyNameArray propNames;
+ object->getPropertyNames(exec, propNames);
{
result = CFDictionaryCreateMutable(0,
0,
&kCFTypeDictionaryValueCallBacks);
if (result)
{
- ReferenceListIterator iter = propList.begin();
- ReferenceListIterator end = propList.end();
+ PropertyNameArrayIterator iter = propNames.begin();
+ PropertyNameArrayIterator end = propNames.end();
while(iter != end)
{
- Identifier propName = iter->getPropertyName();
+ Identifier propName = *iter;
if (object->hasProperty(exec, propName))
{
CFStringRef cfKey = IdentifierToCFString(propName);
#include "config.h"
#include "JSValueWrapper.h"
-#include "JavaScriptCore/reference_list.h"
+#include <JavaScriptCore/PropertyNameArray.h>
#include <pthread.h>
JSValueWrapper::JSValueWrapper(JSValue *inValue)
{
ExecState* exec = getThreadGlobalExecState();
JSObject *object = ptr->GetValue()->toObject(exec);
- ReferenceList propList;
- object->getPropertyList(propList);
- ReferenceListIterator iterator = propList.begin();
+ PropertyNameArray propNames;
+ object->getPropertyNames(exec, propNames);
+ PropertyNameArrayIterator iterator = propNames.begin();
- while (iterator != propList.end()) {
- Identifier name = iterator->getPropertyName();
+ while (iterator != propNames.end()) {
+ Identifier name = *iterator;
CFStringRef nameStr = IdentifierToCFString(name);
if (!result)
#include "config.h"
#include "UserObjectImp.h"
-#include <JavaScriptCore/reference_list.h>
+#include <JavaScriptCore/PropertyNameArray.h>
const ClassInfo UserObjectImp::info = {"UserObject", 0, 0, 0};
}
-void UserObjectImp::getPropertyList(ExecState *exec, ReferenceList& propertyList, bool recursive)
+void UserObjectImp::getPropertyNames(ExecState *exec, PropertyNameArray& propertyNames)
{
JSUserObject* ptr = GetJSUserObject();
if (ptr) {
CFIndex i;
for (i = 0; i < count; i++) {
CFStringRef propertyName = (CFStringRef)CFArrayGetValueAtIndex(cfPropertyNames, i);
- propertyList.append(Reference(this, CFStringToIdentifier(propertyName)));
+ propertyNames.add(CFStringToIdentifier(propertyName));
}
CFRelease(cfPropertyNames);
}
}
- JSObject::getPropertyList(propertyList, recursive);
+ JSObject::getPropertyNames(exec, propertyNames);
}
JSValue *UserObjectImp::userObjectGetter(ExecState *, JSObject *, const Identifier& propertyName, const PropertySlot& slot)
virtual bool implementsCall() const;
- virtual void getPropertyList(ExecState *exec, ReferenceList& propertyList, bool recursive = true);
+ virtual void getPropertyNames(ExecState*, PropertyNameArray&);
virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args);
virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
+2006-07-16 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Darin.
+
+ - new test case and updated results for property list changes
+
+ * fast/js/for-in-avoid-duplicates-expected.txt: Added.
+ * fast/js/for-in-avoid-duplicates.html: Added.
+ * fast/js/kde/Array-expected.txt:
+ * fast/js/resources/for-in-avoid-duplicates.js: Added.
+
2006-07-15 Darin Adler <darin@apple.com>
Reviewed by John Sullivan.
--- /dev/null
+This tests that for/in statements don't report properties that are in both an object ant its prototype more than once.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS i is 2
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="resources/js-test-style.css">
+<script src="resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="resources/for-in-avoid-duplicates.js"></script>
+<script src="resources/js-test-post.js"></script>
+</body>
+</html>
PASS arr[maxint] is undefined
PASS arr.length is maxint
PASS arr[maxint-1] is "test2"
-FAIL propnames.length should be 3 (of type number). Was 4 (of type number).
+PASS propnames.length is 3
PASS propnames[0] is '0'
PASS propnames[1] is '1'
-FAIL propnames[2] should be 2 (of type string). Was 1 (of type string).
+PASS propnames[2] is '2'
PASS successfullyParsed is true
TEST COMPLETE
--- /dev/null
+description(
+"This tests that for/in statements don't report properties that are in both an object and its prototype more than once."
+);
+
+
+function constr() {
+ this.xxx = "foo";
+ this.yyy = "bar";
+}
+
+constructor.prototype = { xxx: "baz", yyy: "quux" };
+
+var obj = new constr();
+
+var i = 0;
+for (var prop in obj) {
+ ++i;
+}
+
+shouldBe("i", "2");
+
+var successfullyParsed = true;