Object.freeze broken on latest Nightly
https://bugs.webkit.org/show_bug.cgi?id=80577
Reviewed by Oliver Hunt.
Source/JavaScriptCore:
* runtime/Arguments.cpp:
(JSC::Arguments::defineOwnProperty):
- defineOwnProperty was checking for correct behaviour, provided that length/callee hadn't
been overrridden. instead, just reify length/callee & rely on JSObject::defineOwnProperty.
* runtime/JSFunction.cpp:
(JSC::JSFunction::defineOwnProperty):
- for arguments/caller/length properties, defineOwnProperty was incorrectly asserting that
the object must be extensible; this is incorrect since these properties should already exist
on the object. In addition, it was asserting that the arguments/caller values must match the
corresponding magic data properties, but for strict mode function this is incorrect. Instead,
just reify the arguments/caller accessor & defer to JSObject::defineOwnProperty.
LayoutTests:
* fast/js/preventExtensions-expected.txt:
* fast/js/script-tests/preventExtensions.js:
(shouldBeTrue):
(shouldBeFalse.shouldBeFalse.preventExtensionsFreezeIsFrozen):
- Added test cases.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@111250 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index 81ee26c..25adda5 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,22 @@
+2012-03-19 Gavin Barraclough <barraclough@apple.com>
+
+ Object.freeze broken on latest Nightly
+ https://bugs.webkit.org/show_bug.cgi?id=80577
+
+ Reviewed by Oliver Hunt.
+
+ * runtime/Arguments.cpp:
+ (JSC::Arguments::defineOwnProperty):
+ - defineOwnProperty was checking for correct behaviour, provided that length/callee hadn't
+ been overrridden. instead, just reify length/callee & rely on JSObject::defineOwnProperty.
+ * runtime/JSFunction.cpp:
+ (JSC::JSFunction::defineOwnProperty):
+ - for arguments/caller/length properties, defineOwnProperty was incorrectly asserting that
+ the object must be extensible; this is incorrect since these properties should already exist
+ on the object. In addition, it was asserting that the arguments/caller values must match the
+ corresponding magic data properties, but for strict mode function this is incorrect. Instead,
+ just reify the arguments/caller accessor & defer to JSObject::defineOwnProperty.
+
2012-03-19 Filip Pizlo <fpizlo@apple.com>
LLInt get_by_pname slow path incorrectly assumes that the operands are not constants
diff --git a/Source/JavaScriptCore/runtime/Arguments.cpp b/Source/JavaScriptCore/runtime/Arguments.cpp
index 7a53ec1..e5f54c2 100644
--- a/Source/JavaScriptCore/runtime/Arguments.cpp
+++ b/Source/JavaScriptCore/runtime/Arguments.cpp
@@ -306,6 +306,7 @@
bool isArrayIndex;
unsigned i = propertyName.toArrayIndex(isArrayIndex);
if (isArrayIndex && i < thisObject->d->numArguments) {
+ object->putDirect(exec->globalData(), propertyName, thisObject->argument(i).get(), 0);
if (!Base::defineOwnProperty(object, exec, propertyName, descriptor, shouldThrow))
return false;
@@ -331,35 +332,16 @@
thisObject->d->deletedArguments[i] = true;
}
}
-
return true;
}
if (propertyName == exec->propertyNames().length && !thisObject->d->overrodeLength) {
+ thisObject->putDirect(exec->globalData(), propertyName, jsNumber(thisObject->d->numArguments), DontEnum);
thisObject->d->overrodeLength = true;
- if (!descriptor.isAccessorDescriptor()) {
- if (!descriptor.value())
- descriptor.setValue(jsNumber(thisObject->d->numArguments));
- if (!descriptor.configurablePresent())
- descriptor.setConfigurable(true);
- }
- if (!descriptor.configurablePresent())
- descriptor.setConfigurable(true);
- }
-
- if (propertyName == exec->propertyNames().callee && !thisObject->d->overrodeCallee) {
+ } else if (propertyName == exec->propertyNames().callee && !thisObject->d->overrodeCallee) {
+ thisObject->putDirect(exec->globalData(), propertyName, thisObject->d->callee.get(), DontEnum);
thisObject->d->overrodeCallee = true;
- if (!descriptor.isAccessorDescriptor()) {
- if (!descriptor.value())
- descriptor.setValue(thisObject->d->callee.get());
- if (!descriptor.configurablePresent())
- descriptor.setConfigurable(true);
- }
- if (!descriptor.configurablePresent())
- descriptor.setConfigurable(true);
- }
-
- if (propertyName == exec->propertyNames().caller && thisObject->d->isStrictMode)
+ } else if (propertyName == exec->propertyNames().caller && thisObject->d->isStrictMode)
thisObject->createStrictModeCallerIfNecessary(exec);
return Base::defineOwnProperty(object, exec, propertyName, descriptor, shouldThrow);
diff --git a/Source/JavaScriptCore/runtime/JSFunction.cpp b/Source/JavaScriptCore/runtime/JSFunction.cpp
index a588551..ecc9d31 100644
--- a/Source/JavaScriptCore/runtime/JSFunction.cpp
+++ b/Source/JavaScriptCore/runtime/JSFunction.cpp
@@ -370,46 +370,55 @@
// following the rules set out in ECMA-262 8.12.9.
PropertySlot slot;
thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, propertyName, slot);
- } else if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length || propertyName == exec->propertyNames().caller) {
- if (!object->isExtensible()) {
- if (throwException)
- throwError(exec, createTypeError(exec, "Attempting to define property on object that is not extensible."));
- return false;
+ return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
+ }
+
+ bool valueCheck;
+ if (propertyName == exec->propertyNames().arguments) {
+ if (thisObject->jsExecutable()->isStrictMode()) {
+ if (!Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor))
+ thisObject->putDirectAccessor(exec->globalData(), propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Accessor);
+ return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
}
- if (descriptor.configurablePresent() && descriptor.configurable()) {
- if (throwException)
- throwError(exec, createTypeError(exec, "Attempting to configurable attribute of unconfigurable property."));
- return false;
+ valueCheck = !descriptor.value() || sameValue(exec, descriptor.value(), exec->interpreter()->retrieveArgumentsFromVMCode(exec, thisObject));
+ } else if (propertyName == exec->propertyNames().caller) {
+ if (thisObject->jsExecutable()->isStrictMode()) {
+ if (!Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor))
+ thisObject->putDirectAccessor(exec->globalData(), propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Accessor);
+ return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
}
- if (descriptor.enumerablePresent() && descriptor.enumerable()) {
- if (throwException)
- throwError(exec, createTypeError(exec, "Attempting to change enumerable attribute of unconfigurable property."));
- return false;
- }
- if (descriptor.isAccessorDescriptor()) {
- if (throwException)
- throwError(exec, createTypeError(exec, "Attempting to change access mechanism for an unconfigurable property."));
- return false;
- }
- if (descriptor.writablePresent() && descriptor.writable()) {
- if (throwException)
- throwError(exec, createTypeError(exec, "Attempting to change writable attribute of unconfigurable property."));
- return false;
- }
- if (!descriptor.value())
- return true;
- if (propertyName == exec->propertyNames().arguments && sameValue(exec, descriptor.value(), exec->interpreter()->retrieveArgumentsFromVMCode(exec, thisObject)))
- return true;
- if (propertyName == exec->propertyNames().length && sameValue(exec, descriptor.value(), jsNumber(thisObject->jsExecutable()->parameterCount())))
- return true;
- if (propertyName == exec->propertyNames().caller && sameValue(exec, descriptor.value(), exec->interpreter()->retrieveCallerFromVMCode(exec, thisObject)))
- return true;
+ valueCheck = !descriptor.value() || sameValue(exec, descriptor.value(), exec->interpreter()->retrieveCallerFromVMCode(exec, thisObject));
+ } else if (propertyName == exec->propertyNames().length)
+ valueCheck = !descriptor.value() || sameValue(exec, descriptor.value(), jsNumber(thisObject->jsExecutable()->parameterCount()));
+ else
+ return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
+
+ if (descriptor.configurablePresent() && descriptor.configurable()) {
+ if (throwException)
+ throwError(exec, createTypeError(exec, "Attempting to configurable attribute of unconfigurable property."));
+ return false;
+ }
+ if (descriptor.enumerablePresent() && descriptor.enumerable()) {
+ if (throwException)
+ throwError(exec, createTypeError(exec, "Attempting to change enumerable attribute of unconfigurable property."));
+ return false;
+ }
+ if (descriptor.isAccessorDescriptor()) {
+ if (throwException)
+ throwError(exec, createTypeError(exec, "Attempting to change access mechanism for an unconfigurable property."));
+ return false;
+ }
+ if (descriptor.writablePresent() && descriptor.writable()) {
+ if (throwException)
+ throwError(exec, createTypeError(exec, "Attempting to change writable attribute of unconfigurable property."));
+ return false;
+ }
+ if (!valueCheck) {
if (throwException)
throwError(exec, createTypeError(exec, "Attempting to change value of a readonly property."));
return false;
}
-
- return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
+ return true;
}
// ECMA 13.2.2 [[Construct]]