Ignore:
Timestamp:
Jan 15, 2011, 3:39:36 PM (14 years ago)
Author:
[email protected]
Message:

2011-01-15 Oliver Hunt <[email protected]>

Reviewed by Maciej Stachowiak.

Incorrect behavior changing attributes of an accessor
https://bugs.webkit.org/show_bug.cgi?id=52515

defineProperty doesn't correctly handle changing attributes of an accessor
property. This is because we don't pass the full descriptor to the
putDescriptor helper function, which means we have insufficient information
to do the right thing. Once that's passed the correct behavior is relatively
simple to implement.

  • runtime/JSObject.cpp: (JSC::putDescriptor): (JSC::JSObject::defineOwnProperty):
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/runtime/JSObject.cpp

    r69516 r75884  
    589589}
    590590
    591 static bool putDescriptor(ExecState* exec, JSObject* target, const Identifier& propertyName, PropertyDescriptor& descriptor, unsigned attributes, JSValue oldValue)
     591static bool putDescriptor(ExecState* exec, JSObject* target, const Identifier& propertyName, PropertyDescriptor& descriptor, unsigned attributes, const PropertyDescriptor& oldDescriptor)
    592592{
    593593    if (descriptor.isGenericDescriptor() || descriptor.isDataDescriptor()) {
    594         target->putWithAttributes(exec, propertyName, descriptor.value() ? descriptor.value() : oldValue, attributes & ~(Getter | Setter));
     594        if (descriptor.isGenericDescriptor() && oldDescriptor.isAccessorDescriptor()) {
     595            GetterSetter* accessor = new (exec) GetterSetter(exec);
     596            if (oldDescriptor.getter()) {
     597                attributes |= Getter;
     598                accessor->setGetter(asObject(oldDescriptor.getter()));
     599            }
     600            if (oldDescriptor.setter()) {
     601                attributes |= Setter;
     602                accessor->setSetter(asObject(oldDescriptor.setter()));
     603            }
     604            target->putWithAttributes(exec, propertyName, accessor, attributes);
     605            return true;
     606        }
     607        JSValue newValue = jsUndefined();
     608        if (descriptor.value())
     609            newValue = descriptor.value();
     610        else if (oldDescriptor.value())
     611            newValue = oldDescriptor.value();
     612        target->putWithAttributes(exec, propertyName, newValue, attributes & ~(Getter | Setter));
    595613        return true;
    596614    }
     
    609627    // If we have a new property we can just put it on normally
    610628    PropertyDescriptor current;
    611     if (!getOwnPropertyDescriptor(exec, propertyName, current))
    612         return putDescriptor(exec, this, propertyName, descriptor, descriptor.attributes(), jsUndefined());
     629    if (!getOwnPropertyDescriptor(exec, propertyName, current)) {
     630        PropertyDescriptor oldDescriptor;
     631        oldDescriptor.setValue(jsUndefined());
     632        return putDescriptor(exec, this, propertyName, descriptor, descriptor.attributes(), oldDescriptor);
     633    }
    613634
    614635    if (descriptor.isEmpty())
     
    636657        if (!current.attributesEqual(descriptor)) {
    637658            deleteProperty(exec, propertyName);
    638             putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current.value());
     659            putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current);
    639660        }
    640661        return true;
     
    649670        }
    650671        deleteProperty(exec, propertyName);
    651         return putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current.value() ? current.value() : jsUndefined());
     672        return putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current);
    652673    }
    653674
     
    677698        }
    678699        deleteProperty(exec, propertyName);
    679         return putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current.value());
     700        return putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current);
    680701    }
    681702
Note: See TracChangeset for help on using the changeset viewer.