Commit d1f19755 authored by oliver@apple.com's avatar oliver@apple.com
Browse files

[ES5] Implement Object.keys

https://bugs.webkit.org/show_bug.cgi?id=29170

Reviewed by Maciej Stachowiak.

This patch basically requires two separate steps, the first is to split getPropertyNames
into two functions -- getOwnPropertyNames and getPropertyNames, basically making them behave
in the same way as getOwnPropertySlot and getPropertySlot.  In essence getOwnPropertyNames
produces the list of properties on an object excluding its prototype chain and getPropertyNames
just iterates the the object and its prototype chain calling getOwnPropertyNames at each level.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@48336 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent de099dea
......@@ -66,7 +66,7 @@ private:
virtual bool hasInstance(ExecState* exec, JSValue value, JSValue proto);
virtual void getPropertyNames(ExecState*, PropertyNameArray&);
virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&);
virtual double toNumber(ExecState*) const;
virtual UString toString(ExecState*) const;
......
......@@ -373,7 +373,7 @@ JSValue JSCallbackObject<Base>::call(ExecState* exec, JSObject* functionObject,
}
template <class Base>
void JSCallbackObject<Base>::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
void JSCallbackObject<Base>::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
{
JSContextRef execRef = toRef(exec);
JSObjectRef thisRef = toRef(this);
......@@ -407,7 +407,7 @@ void JSCallbackObject<Base>::getPropertyNames(ExecState* exec, PropertyNameArray
}
}
Base::getPropertyNames(exec, propertyNames);
Base::getOwnPropertyNames(exec, propertyNames);
}
template <class Base>
......
2009-09-12 Oliver Hunt <oliver@apple.com>
Reviewed by Maciej Stachowiak.
[ES5] Implement Object.keys
https://bugs.webkit.org/show_bug.cgi?id=29170
This patch basically requires two separate steps, the first is to split getPropertyNames
into two functions -- getOwnPropertyNames and getPropertyNames, basically making them behave
in the same way as getOwnPropertySlot and getPropertySlot. In essence getOwnPropertyNames
produces the list of properties on an object excluding its prototype chain and getPropertyNames
just iterates the the object and its prototype chain calling getOwnPropertyNames at each level.
* API/JSCallbackObject.h:
* API/JSCallbackObjectFunctions.h:
(JSC::::getOwnPropertyNames):
* JavaScriptCore.exp:
* debugger/DebuggerActivation.cpp:
(JSC::DebuggerActivation::getOwnPropertyNames):
* debugger/DebuggerActivation.h:
* runtime/CommonIdentifiers.h:
* runtime/JSArray.cpp:
(JSC::JSArray::getOwnPropertyNames):
* runtime/JSArray.h:
* runtime/JSByteArray.cpp:
(JSC::JSByteArray::getOwnPropertyNames):
* runtime/JSByteArray.h:
* runtime/JSNotAnObject.cpp:
(JSC::JSNotAnObject::getOwnPropertyNames):
* runtime/JSNotAnObject.h:
* runtime/JSObject.cpp:
(JSC::JSObject::getOwnPropertyNames):
* runtime/JSObject.h:
* runtime/JSVariableObject.cpp:
(JSC::JSVariableObject::getOwnPropertyNames):
* runtime/JSVariableObject.h:
* runtime/ObjectConstructor.cpp:
(JSC::ObjectConstructor::ObjectConstructor):
(JSC::objectConstructorKeys):
* runtime/RegExpMatchesArray.h:
(JSC::RegExpMatchesArray::getOwnPropertyNames):
* runtime/StringObject.cpp:
(JSC::StringObject::getOwnPropertyNames):
* runtime/StringObject.h:
* runtime/Structure.cpp:
(JSC::Structure::getOwnEnumerablePropertyNames):
(JSC::Structure::getEnumerablePropertyNames):
* runtime/Structure.h:
2009-09-11 Oliver Hunt <oliver@apple.com>
Reviewed by Sam Weinig.
......
......@@ -113,9 +113,9 @@ __ZN3JSC12SamplingTool4dumpEPNS_9ExecStateE
__ZN3JSC12SamplingTool5setupEv
__ZN3JSC12SmallStrings17createEmptyStringEPNS_12JSGlobalDataE
__ZN3JSC12StringObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
__ZN3JSC12StringObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
__ZN3JSC12StringObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
__ZN3JSC12StringObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
__ZN3JSC12StringObject19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
__ZN3JSC12StringObject24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
__ZN3JSC12StringObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
__ZN3JSC12StringObject4infoE
......@@ -147,7 +147,7 @@ __ZN3JSC16InternalFunction4nameEPNS_12JSGlobalDataE
__ZN3JSC16InternalFunctionC2EPNS_12JSGlobalDataEN3WTF10PassRefPtrINS_9StructureEEERKNS_10IdentifierE
__ZN3JSC16JSVariableObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
__ZN3JSC16JSVariableObject14symbolTableGetERKNS_10IdentifierERNS_18PropertyDescriptorE
__ZN3JSC16JSVariableObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
__ZN3JSC16JSVariableObject19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
__ZN3JSC16toUInt32SlowCaseEdRb
__ZN3JSC17BytecodeGenerator21setDumpsGeneratedCodeEb
__ZN3JSC17PropertyNameArray3addEPNS_7UString3RepE
......@@ -250,6 +250,7 @@ __ZN3JSC8JSObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_7JSValu
__ZN3JSC8JSObject17putWithAttributesEPNS_9ExecStateEjNS_7JSValueEj
__ZN3JSC8JSObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
__ZN3JSC8JSObject18getPrimitiveNumberEPNS_9ExecStateERdRNS_7JSValueE
__ZN3JSC8JSObject19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
__ZN3JSC8JSObject21getPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
__ZN3JSC8JSObject22fillGetterPropertySlotERNS_12PropertySlotEPNS_7JSValueE
__ZN3JSC8JSObject23allocatePropertyStorageEmm
......
......@@ -71,7 +71,7 @@ bool DebuggerActivation::deleteProperty(ExecState* exec, const Identifier& prope
return m_activation->deleteProperty(exec, propertyName);
}
void DebuggerActivation::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
void DebuggerActivation::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
{
m_activation->getPropertyNames(exec, propertyNames);
}
......
......@@ -42,7 +42,7 @@ namespace JSC {
virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValue, unsigned attributes);
virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
virtual void getPropertyNames(ExecState*, PropertyNameArray&);
virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&);
virtual bool getPropertyAttributes(ExecState*, const Identifier& propertyName, unsigned& attributes) const;
virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunction);
virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunction);
......
......@@ -53,6 +53,7 @@
macro(input) \
macro(isArray) \
macro(isPrototypeOf) \
macro(keys) \
macro(length) \
macro(message) \
macro(multiline) \
......
......@@ -464,7 +464,7 @@ bool JSArray::deleteProperty(ExecState* exec, unsigned i)
return false;
}
void JSArray::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
void JSArray::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
{
// FIXME: Filling PropertyNameArray with an identifier for every integer
// is incredibly inefficient for large arrays. We need a different approach,
......@@ -484,7 +484,7 @@ void JSArray::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames
propertyNames.add(Identifier::from(exec, it->first));
}
JSObject::getPropertyNames(exec, propertyNames);
JSObject::getOwnPropertyNames(exec, propertyNames);
}
bool JSArray::increaseVectorLength(unsigned newLength)
......
......@@ -91,7 +91,7 @@ namespace JSC {
virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
virtual bool deleteProperty(ExecState*, unsigned propertyName);
virtual void getPropertyNames(ExecState*, PropertyNameArray&);
virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&);
virtual void markChildren(MarkStack&);
void* lazyCreationData();
......
......@@ -96,12 +96,12 @@ void JSByteArray::put(ExecState* exec, unsigned propertyName, JSValue value)
setIndex(exec, propertyName, value);
}
void JSByteArray::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
void JSByteArray::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
{
unsigned length = m_storage->length();
for (unsigned i = 0; i < length; ++i)
propertyNames.add(Identifier::from(exec, i));
JSObject::getPropertyNames(exec, propertyNames);
JSObject::getOwnPropertyNames(exec, propertyNames);
}
}
......
......@@ -82,7 +82,7 @@ namespace JSC {
virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&);
virtual void put(JSC::ExecState*, unsigned propertyName, JSC::JSValue);
virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&);
virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&);
virtual const ClassInfo* classInfo() const { return m_classInfo; }
static const ClassInfo s_defaultInfo;
......
......@@ -121,7 +121,7 @@ bool JSNotAnObject::deleteProperty(ExecState* exec, unsigned)
return false;
}
void JSNotAnObject::getPropertyNames(ExecState* exec, PropertyNameArray&)
void JSNotAnObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray&)
{
ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
}
......
......@@ -88,7 +88,7 @@ namespace JSC {
virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
virtual bool deleteProperty(ExecState*, unsigned propertyName);
virtual void getPropertyNames(ExecState*, PropertyNameArray&);
virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&);
JSNotAnObjectErrorStub* m_exception;
};
......
......@@ -427,6 +427,11 @@ void JSObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyName
m_structure->getEnumerablePropertyNames(exec, propertyNames, this);
}
void JSObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
{
m_structure->getOwnEnumerablePropertyNames(exec, propertyNames, this);
}
bool JSObject::toBoolean(ExecState*) const
{
return true;
......
......@@ -123,6 +123,7 @@ namespace JSC {
virtual bool hasInstance(ExecState*, JSValue, JSValue prototypeProperty);
virtual void getPropertyNames(ExecState*, PropertyNameArray&);
virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&);
virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const;
virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue& value);
......
......@@ -42,7 +42,7 @@ bool JSVariableObject::deleteProperty(ExecState* exec, const Identifier& propert
return JSObject::deleteProperty(exec, propertyName);
}
void JSVariableObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
void JSVariableObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
{
SymbolTable::const_iterator end = symbolTable().end();
for (SymbolTable::const_iterator it = symbolTable().begin(); it != end; ++it) {
......@@ -50,7 +50,7 @@ void JSVariableObject::getPropertyNames(ExecState* exec, PropertyNameArray& prop
propertyNames.add(Identifier(exec, it->first.get()));
}
JSObject::getPropertyNames(exec, propertyNames);
JSObject::getOwnPropertyNames(exec, propertyNames);
}
bool JSVariableObject::getPropertyAttributes(ExecState* exec, const Identifier& propertyName, unsigned& attributes) const
......
......@@ -49,7 +49,7 @@ namespace JSC {
virtual void putWithAttributes(ExecState*, const Identifier&, JSValue, unsigned attributes) = 0;
virtual bool deleteProperty(ExecState*, const Identifier&);
virtual void getPropertyNames(ExecState*, PropertyNameArray&);
virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&);
virtual bool isVariableObject() const;
virtual bool isDynamicScope() const = 0;
......
......@@ -34,6 +34,7 @@ ASSERT_CLASS_FITS_IN_CELL(ObjectConstructor);
static JSValue JSC_HOST_CALL objectConstructorGetPrototypeOf(ExecState*, JSObject*, JSValue, const ArgList&);
static JSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState*, JSObject*, JSValue, const ArgList&);
static JSValue JSC_HOST_CALL objectConstructorKeys(ExecState*, JSObject*, JSValue, const ArgList&);
ObjectConstructor::ObjectConstructor(ExecState* exec, PassRefPtr<Structure> structure, ObjectPrototype* objectPrototype, Structure* prototypeFunctionStructure)
: InternalFunction(&exec->globalData(), structure, Identifier(exec, "Object"))
......@@ -46,6 +47,7 @@ ObjectConstructor::ObjectConstructor(ExecState* exec, PassRefPtr<Structure> stru
putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().getPrototypeOf, objectConstructorGetPrototypeOf), DontEnum);
putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 2, exec->propertyNames().getOwnPropertyDescriptor, objectConstructorGetOwnPropertyDescriptor), DontEnum);
putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().keys, objectConstructorKeys), DontEnum);
}
// ECMA 15.2.2
......@@ -116,4 +118,17 @@ JSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState* exec,
return description;
}
JSValue JSC_HOST_CALL objectConstructorKeys(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
if (!args.at(0).isObject())
return throwError(exec, TypeError, "Requested keys of a value that is not an object.");
PropertyNameArray properties(exec);
asObject(args.at(0))->getOwnPropertyNames(exec, properties);
JSArray* keys = constructEmptyArray(exec);
size_t numProperties = properties.size();
for (size_t i = 0; i < numProperties; i++)
keys->push(exec, jsOwnedString(exec, properties[i].ustring()));
return keys;
}
} // namespace JSC
......@@ -79,11 +79,11 @@ namespace JSC {
return JSArray::deleteProperty(exec, propertyName);
}
virtual void getPropertyNames(ExecState* exec, PropertyNameArray& arr)
virtual void getOwnPropertyNames(ExecState* exec, PropertyNameArray& arr)
{
if (lazyCreationData())
fillArrayInstance(exec);
JSArray::getPropertyNames(exec, arr);
JSArray::getOwnPropertyNames(exec, arr);
}
void fillArrayInstance(ExecState*);
......
......@@ -82,12 +82,12 @@ bool StringObject::deleteProperty(ExecState* exec, const Identifier& propertyNam
return JSObject::deleteProperty(exec, propertyName);
}
void StringObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
void StringObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
{
int size = internalValue()->value().size();
for (int i = 0; i < size; ++i)
propertyNames.add(Identifier(exec, UString::from(i)));
return JSObject::getPropertyNames(exec, propertyNames);
return JSObject::getOwnPropertyNames(exec, propertyNames);
}
} // namespace JSC
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment