Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (198571 => 198572)
--- trunk/Source/_javascript_Core/ChangeLog 2016-03-23 01:39:36 UTC (rev 198571)
+++ trunk/Source/_javascript_Core/ChangeLog 2016-03-23 02:12:17 UTC (rev 198572)
@@ -1,3 +1,15 @@
+2016-03-22 Caitlin Potter <[email protected]>
+
+ [JSC] correctly handle indexed properties in Object.getOwnPropertyDescriptors
+ https://bugs.webkit.org/show_bug.cgi?id=155563
+
+ Reviewed by Saam Barati.
+
+ * runtime/JSObject.h:
+ (JSC::JSObject::putOwnDataPropertyMayBeIndex):
+ * runtime/ObjectConstructor.cpp:
+ (JSC::objectConstructorGetOwnPropertyDescriptors):
+
2016-03-22 Saam Barati <[email protected]>
We should FTL compile code when the debugger is enabled
Modified: trunk/Source/_javascript_Core/runtime/JSObject.h (198571 => 198572)
--- trunk/Source/_javascript_Core/runtime/JSObject.h 2016-03-23 01:39:36 UTC (rev 198571)
+++ trunk/Source/_javascript_Core/runtime/JSObject.h 2016-03-23 02:12:17 UTC (rev 198572)
@@ -627,6 +627,7 @@
// - does not walk the prototype chain (to check for accessors or non-writable properties).
// This is used by JSLexicalEnvironment.
bool putOwnDataProperty(VM&, PropertyName, JSValue, PutPropertySlot&);
+ bool putOwnDataPropertyMayBeIndex(ExecState*, PropertyName, JSValue, PutPropertySlot&);
// Fast access to known property offsets.
JSValue getDirect(PropertyOffset offset) const { return locationForOffset(offset)->get(); }
@@ -1482,6 +1483,19 @@
return putDirectInternal<PutModePut>(vm, propertyName, value, 0, slot);
}
+inline bool JSObject::putOwnDataPropertyMayBeIndex(ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
+{
+ ASSERT(value);
+ ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
+ ASSERT(!structure()->hasGetterSetterProperties());
+ ASSERT(!structure()->hasCustomGetterSetterProperties());
+
+ if (Optional<uint32_t> index = parseIndex(propertyName))
+ return putDirectIndex(exec, index.value(), value, 0, PutDirectIndexLikePutDirect);
+
+ return putDirectInternal<PutModePut>(exec->vm(), propertyName, value, 0, slot);
+}
+
inline bool JSObject::putDirect(VM& vm, PropertyName propertyName, JSValue value, unsigned attributes)
{
ASSERT(!value.isGetterSetter() && !(attributes & Accessor));
Modified: trunk/Source/_javascript_Core/runtime/ObjectConstructor.cpp (198571 => 198572)
--- trunk/Source/_javascript_Core/runtime/ObjectConstructor.cpp 2016-03-23 01:39:36 UTC (rev 198571)
+++ trunk/Source/_javascript_Core/runtime/ObjectConstructor.cpp 2016-03-23 02:12:17 UTC (rev 198572)
@@ -243,13 +243,17 @@
return jsUndefined();
JSObject* descriptors = constructEmptyObject(exec);
+ if (exec->hadException())
+ return jsUndefined();
for (auto& propertyName : properties) {
JSValue fromDescriptor = objectConstructorGetOwnPropertyDescriptor(exec, object, propertyName);
if (exec->hadException())
return jsUndefined();
- descriptors->putDirect(exec->vm(), propertyName, fromDescriptor, 0);
+ PutPropertySlot slot(descriptors);
+ descriptors->putOwnDataPropertyMayBeIndex(exec, propertyName, fromDescriptor, slot);
+ ASSERT(!exec->hadException());
}
return descriptors;
Modified: trunk/Source/_javascript_Core/tests/es6/Object_static_methods_Object.getOwnPropertyDescriptors.js (198571 => 198572)
--- trunk/Source/_javascript_Core/tests/es6/Object_static_methods_Object.getOwnPropertyDescriptors.js 2016-03-23 01:39:36 UTC (rev 198571)
+++ trunk/Source/_javascript_Core/tests/es6/Object_static_methods_Object.getOwnPropertyDescriptors.js 2016-03-23 02:12:17 UTC (rev 198572)
@@ -51,6 +51,8 @@
function F() {};
F.prototype.a = 'A';
F.prototype.b = 'B';
+ F.prototype[9999] = '0';
+ F.prototype[0] = '0';
var F2 = new F();
Object.defineProperties(F2, {
@@ -65,10 +67,26 @@
configurable: true,
writable: false,
value: 'C'
+ },
+ 9998: {
+ enumerable: true,
+ configurable: true,
+ writable: true,
+ value: 'X'
}
});
var result = Object.getOwnPropertyDescriptors(F2);
+
+ shouldBe(undefined, result[0]);
+
+ shouldBe(result[9998].enumerable, true);
+ shouldBe(result[9998].configurable, true);
+ shouldBe(result[9998].writable, true);
+ shouldBe(result[9998].value, 'X')
+
+ shouldBe(undefined, result[9999]);
+
shouldBe(undefined, result.a);
shouldBe(result.b.enumerable, false);
@@ -91,3 +109,40 @@
shouldBeDataProperty(result[symbol], 'Symbol(test)', 'global[Symbol(test)]');
delete global[symbol];
})(this);
+
+(function testIndexedProperties() {
+ var object = { 0: 'test' };
+ var result = Object.getOwnPropertyDescriptors(object);
+ shouldBeDataProperty(result[0], 'test', 'result[0]');
+ shouldBeDataProperty(result['0'], 'test', 'result["0"]');
+ shouldBe(result[0], result['0']);
+})();
+
+
+(function testPropertiesIndexedSetterOnPrototypeThrows() {
+ var symbol = Symbol('test');
+ Object.defineProperties(Object.prototype, {
+ 0: {
+ configurable: true,
+ get() { return; },
+ set(v) { throw new Error("Setter on prototype should be unreachable!"); }
+ },
+ a: {
+ configurable: true,
+ get() { return; },
+ set(v) { throw new Error("Setter on prototype should be unreachable!"); }
+ },
+ [symbol]: {
+ configurable: true,
+ get() { return; },
+ set(v) { throw new Error("Setter on prototype should be unreachable!"); }
+ }
+ });
+ var result = Object.getOwnPropertyDescriptors({ 0: 1, a: 2, [symbol]: 3 })
+ delete Object.prototype[0];
+ delete Object.prototype.a;
+ delete Object.prototype[symbol];
+ shouldBeDataProperty(result[0], 1, 'result[0]');
+ shouldBeDataProperty(result.a, 2, 'result["a"]');
+ shouldBeDataProperty(result[symbol], 3, 'result[symbol]');
+})();