Fix Object.freeze for objects with mixed accessors and data properties

The bug in the existing code was that it modified the |attributes|
local variable on its way through the loop in CopyUpToAddAttributes.
But that affected any properties updated after an accessor property.
The code now sets up a mask each time and applies that instead of
mutating |attributes|.

R=verwaest@chromium.org

Review URL: https://chromiumcodereview.appspot.com/16051002

Patch from Adam Klein <adamk@chromium.org>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14818 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
verwaest@chromium.org 2013-05-27 10:56:27 +00:00
parent 3e41834721
commit 9d3e7e5b81
2 changed files with 24 additions and 3 deletions

View File

@ -6744,11 +6744,14 @@ MaybeObject* DescriptorArray::CopyUpToAddAttributes(
for (int i = 0; i < size; ++i) {
Object* value = GetValue(i);
PropertyDetails details = GetDetails(i);
int mask = DONT_DELETE | DONT_ENUM;
// READ_ONLY is an invalid attribute for JS setters/getters.
if (details.type() == CALLBACKS && value->IsAccessorPair()) {
attributes = static_cast<PropertyAttributes>(attributes & ~READ_ONLY);
if (details.type() != CALLBACKS || !value->IsAccessorPair()) {
mask |= READ_ONLY;
}
Descriptor desc(GetKey(i), value, details.CopyAddAttributes(attributes));
details = details.CopyAddAttributes(
static_cast<PropertyAttributes>(attributes & mask));
Descriptor desc(GetKey(i), value, details);
descriptors->Set(i, &desc, witness);
}
} else {

View File

@ -296,3 +296,21 @@ assertEquals(42, obj.accessor);
accessorDidRun = false;
obj.accessor = 'ignored value';
assertTrue(accessorDidRun);
// Test for regression in mixed accessor/data property objects.
// The strict function is one such object.
assertTrue(Object.isFrozen(Object.freeze(function(){"use strict";})));
// Also test a simpler case
obj = {};
Object.defineProperty(obj, 'accessor', {
get: function() { return 42 },
set: function() { accessorDidRun = true },
configurable: true,
enumerable: true
});
obj.data = 'foo';
assertTrue(%HasFastProperties(obj));
Object.freeze(obj);
assertTrue(%HasFastProperties(obj));
assertTrue(Object.isFrozen(obj));