Diff
Modified: trunk/LayoutTests/ChangeLog (97904 => 97905)
--- trunk/LayoutTests/ChangeLog 2011-10-20 00:53:21 UTC (rev 97904)
+++ trunk/LayoutTests/ChangeLog 2011-10-20 01:18:03 UTC (rev 97905)
@@ -1,3 +1,14 @@
+2011-10-19 Gavin Barraclough <[email protected]>
+
+ Poisoning of strict caller,arguments inappropriately poisoning "in"
+ https://bugs.webkit.org/show_bug.cgi?id=63398
+
+ Reviewed by Oliver Hunt.
+
+ * fast/js/basic-strict-mode-expected.txt:
+ * fast/js/script-tests/basic-strict-mode.js:
+ - Add tests.
+
2011-10-19 Erik Arvidsson <[email protected]>
Fix test breakage after r97881
Modified: trunk/LayoutTests/fast/js/basic-strict-mode-expected.txt (97904 => 97905)
--- trunk/LayoutTests/fast/js/basic-strict-mode-expected.txt 2011-10-20 00:53:21 UTC (rev 97904)
+++ trunk/LayoutTests/fast/js/basic-strict-mode-expected.txt 2011-10-20 01:18:03 UTC (rev 97905)
@@ -56,16 +56,20 @@
PASS (function(){(function (){'use strict'; with(1){};})}) threw exception SyntaxError: 'with' statements are not valid in strict mode.
PASS (function (){'use strict'; arguments.callee; })() threw exception TypeError: Unable to access callee of strict mode function.
PASS (function (){'use strict'; arguments.caller; })() threw exception TypeError: Unable to access caller of strict mode function.
-PASS (function f(){'use strict'; f.arguments; })() threw exception TypeError: Cannot access arguments property of a strict mode function.
-PASS (function f(){'use strict'; f.caller; })() threw exception TypeError: Cannot access caller property of a strict mode function.
-PASS (function f(){'use strict'; f.arguments=5; })() threw exception TypeError: Cannot access arguments property of a strict mode function.
-PASS (function f(){'use strict'; f.caller=5; })() threw exception TypeError: Cannot access caller property of a strict mode function.
+PASS (function f(){'use strict'; f.arguments; })() threw exception TypeError: Type error.
+PASS (function f(){'use strict'; f.caller; })() threw exception TypeError: Type error.
+PASS (function f(){'use strict'; f.arguments=5; })() threw exception TypeError: Type error.
+PASS (function f(){'use strict'; f.caller=5; })() threw exception TypeError: Type error.
PASS (function (arg){'use strict'; arguments.callee; })() threw exception TypeError: Unable to access callee of strict mode function.
PASS (function (arg){'use strict'; arguments.caller; })() threw exception TypeError: Unable to access caller of strict mode function.
-PASS (function f(arg){'use strict'; f.arguments; })() threw exception TypeError: Cannot access arguments property of a strict mode function.
-PASS (function f(arg){'use strict'; f.caller; })() threw exception TypeError: Cannot access caller property of a strict mode function.
-PASS (function f(arg){'use strict'; f.arguments=5; })() threw exception TypeError: Cannot access arguments property of a strict mode function.
-PASS (function f(arg){'use strict'; f.caller=5; })() threw exception TypeError: Cannot access caller property of a strict mode function.
+PASS (function f(arg){'use strict'; f.arguments; })() threw exception TypeError: Type error.
+PASS (function f(arg){'use strict'; f.caller; })() threw exception TypeError: Type error.
+PASS (function f(arg){'use strict'; f.arguments=5; })() threw exception TypeError: Type error.
+PASS (function f(arg){'use strict'; f.caller=5; })() threw exception TypeError: Type error.
+PASS "caller" in function(){"use strict"} is true
+PASS (function(){"use strict";}).hasOwnProperty("caller") is true
+PASS "arguments" in function(){"use strict"} is true
+PASS (function(){"use strict";}).hasOwnProperty("arguments") is true
PASS 'use strict'; (function (){with(1){};}) threw exception SyntaxError: 'with' statements are not valid in strict mode.
PASS (function(){'use strict'; (function (){with(1){};})}) threw exception SyntaxError: 'with' statements are not valid in strict mode.
PASS 'use strict'; (function (){var a; delete a;}) threw exception SyntaxError: Cannot delete unqualified property 'a' in strict mode.
Modified: trunk/LayoutTests/fast/js/script-tests/basic-strict-mode.js (97904 => 97905)
--- trunk/LayoutTests/fast/js/script-tests/basic-strict-mode.js 2011-10-20 00:53:21 UTC (rev 97904)
+++ trunk/LayoutTests/fast/js/script-tests/basic-strict-mode.js 2011-10-20 01:18:03 UTC (rev 97905)
@@ -74,6 +74,13 @@
shouldThrow("(function f(arg){'use strict'; f.caller; })()");
shouldThrow("(function f(arg){'use strict'; f.arguments=5; })()");
shouldThrow("(function f(arg){'use strict'; f.caller=5; })()");
+
+// arguments/caller poisoning should be visible but not throw with 'in' & 'hasOwnProperty'.
+shouldBeTrue('"caller" in function(){"use strict"}');
+shouldBeTrue('(function(){"use strict";}).hasOwnProperty("caller")');
+shouldBeTrue('"arguments" in function(){"use strict"}');
+shouldBeTrue('(function(){"use strict";}).hasOwnProperty("arguments")');
+
shouldBeSyntaxError("'use strict'; (function (){with(1){};})");
shouldBeSyntaxError("'use strict'; (function (){var a; delete a;})");
shouldBeSyntaxError("'use strict'; var a; (function (){ delete a;})");
Modified: trunk/Source/_javascript_Core/ChangeLog (97904 => 97905)
--- trunk/Source/_javascript_Core/ChangeLog 2011-10-20 00:53:21 UTC (rev 97904)
+++ trunk/Source/_javascript_Core/ChangeLog 2011-10-20 01:18:03 UTC (rev 97905)
@@ -1,3 +1,41 @@
+2011-10-19 Gavin Barraclough <[email protected]>
+
+ Poisoning of strict caller,arguments inappropriately poisoning "in"
+ https://bugs.webkit.org/show_bug.cgi?id=63398
+
+ Reviewed by Oliver Hunt.
+
+ This fixes the problem by correctly implementing the spec -
+ the error should actually be being thrown from a standard JS getter/setter.
+ This implements spec correct behaviour for strict mode JS functions & bound
+ functions, I'll follow up with a patch to do the same for arguments.
+
+ * runtime/JSBoundFunction.cpp:
+ (JSC::JSBoundFunction::finishCreation):
+ - Add the poisoned caller/arguments properties.
+ * runtime/JSBoundFunction.h:
+ * runtime/JSFunction.cpp:
+ (JSC::JSFunction::finishCreation):
+ (JSC::JSFunction::getOwnPropertySlot):
+ (JSC::JSFunction::getOwnPropertyDescriptor):
+ (JSC::JSFunction::put):
+ - If the caller/arguments are accessed on a strict mode function, lazily add the ThrowTypeError getter.
+ * runtime/JSFunction.h:
+ * runtime/JSGlobalObject.cpp:
+ (JSC::JSGlobalObject::createThrowTypeError):
+ (JSC::JSGlobalObject::visitChildren):
+ * runtime/JSGlobalObject.h:
+ (JSC::JSGlobalObject::throwTypeErrorGetterSetter):
+ - Add a ThrowTypeError type, per ES5 13.2.3.
+ * runtime/JSGlobalObjectFunctions.cpp:
+ (JSC::globalFuncThrowTypeError):
+ * runtime/JSGlobalObjectFunctions.h:
+ - Implementation of ThrowTypeError.
+ * runtime/JSObject.cpp:
+ (JSC::JSObject::initializeGetterSetterProperty):
+ * runtime/JSObject.h:
+ - This function adds a new property (must not exist already) that is an initialized getter/setter.
+
2011-10-19 Yuqiang Xian <[email protected]>
DFG JIT 32_64 - improve double boxing/unboxing
Modified: trunk/Source/_javascript_Core/runtime/JSBoundFunction.cpp (97904 => 97905)
--- trunk/Source/_javascript_Core/runtime/JSBoundFunction.cpp 2011-10-20 00:53:21 UTC (rev 97904)
+++ trunk/Source/_javascript_Core/runtime/JSBoundFunction.cpp 2011-10-20 01:18:03 UTC (rev 97905)
@@ -96,43 +96,6 @@
return m_targetFunction->hasInstance(exec, value, proto);
}
-bool JSBoundFunction::getOwnPropertySlotVirtual(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
-{
- return getOwnPropertySlot(this, exec, propertyName, slot);
-}
-
-bool JSBoundFunction::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
-{
- if (propertyName == exec->propertyNames().arguments) {
- throwTypeError(exec, StrictModeArgumentsAccessError);
- slot.setValue(jsNull());
- return true;
- }
-
- if (propertyName == exec->propertyNames().caller) {
- throwTypeError(exec, StrictModeCallerAccessError);
- slot.setValue(jsNull());
- return true;
- }
-
- return Base::getOwnPropertySlot(cell, exec, propertyName, slot);
-}
-
-bool JSBoundFunction::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
-{
- if (propertyName == exec->propertyNames().arguments) {
- createDescriptorForThrowingProperty(exec, descriptor, StrictModeArgumentsAccessError);
- return true;
- }
-
- if (propertyName == exec->propertyNames().caller) {
- createDescriptorForThrowingProperty(exec, descriptor, StrictModeCallerAccessError);
- return true;
- }
-
- return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
-}
-
JSBoundFunction::JSBoundFunction(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, JSObject* targetFunction, JSValue boundThis, JSValue boundArgs)
: Base(exec, globalObject, structure)
, m_targetFunction(exec->globalData(), this, targetFunction)
@@ -145,6 +108,9 @@
{
Base::finishCreation(exec, executable, length, name);
ASSERT(inherits(&s_info));
+
+ initializeGetterSetterProperty(exec, exec->propertyNames().arguments, globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Getter | Setter);
+ initializeGetterSetterProperty(exec, exec->propertyNames().caller, globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Getter | Setter);
}
void JSBoundFunction::visitChildren(JSCell* cell, SlotVisitor& visitor)
Modified: trunk/Source/_javascript_Core/runtime/JSBoundFunction.h (97904 => 97905)
--- trunk/Source/_javascript_Core/runtime/JSBoundFunction.h 2011-10-20 00:53:21 UTC (rev 97904)
+++ trunk/Source/_javascript_Core/runtime/JSBoundFunction.h 2011-10-20 01:18:03 UTC (rev 97905)
@@ -39,10 +39,6 @@
static JSBoundFunction* create(ExecState*, JSGlobalObject*, JSObject* targetFunction, JSValue boundThis, JSValue boundArgs, int, const Identifier&);
- virtual bool getOwnPropertySlotVirtual(ExecState*, const Identifier&, PropertySlot&);
- static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&);
- virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
-
virtual bool hasInstance(ExecState*, JSValue value, JSValue proto);
JSObject* targetFunction() { return m_targetFunction.get(); }
Modified: trunk/Source/_javascript_Core/runtime/JSFunction.cpp (97904 => 97905)
--- trunk/Source/_javascript_Core/runtime/JSFunction.cpp 2011-10-20 00:53:21 UTC (rev 97904)
+++ trunk/Source/_javascript_Core/runtime/JSFunction.cpp 2011-10-20 01:18:03 UTC (rev 97905)
@@ -97,7 +97,8 @@
Base::finishCreation(exec->globalData());
ASSERT(inherits(&s_info));
m_executable.set(exec->globalData(), this, executable);
- putDirect(exec->globalData(), exec->globalData().propertyNames->name, jsString(exec, name.isNull() ? "" : name.ustring()), DontDelete | ReadOnly | DontEnum);
+ if (!name.isNull())
+ putDirect(exec->globalData(), exec->globalData().propertyNames->name, jsString(exec, name.ustring()), DontDelete | ReadOnly | DontEnum);
putDirect(exec->globalData(), exec->propertyNames().length, jsNumber(length), DontDelete | ReadOnly | DontEnum);
}
@@ -117,9 +118,6 @@
ASSERT(vptr() == JSGlobalData::jsFunctionVPtr);
}
-const char* StrictModeCallerAccessError = "Cannot access caller property of a strict mode function";
-const char* StrictModeArgumentsAccessError = "Cannot access arguments property of a strict mode function";
-
void createDescriptorForThrowingProperty(ExecState* exec, PropertyDescriptor& descriptor, const char* message)
{
JSValue thrower = createTypeErrorFunction(exec, message);
@@ -224,11 +222,14 @@
if (propertyName == exec->propertyNames().arguments) {
if (thisObject->jsExecutable()->isStrictMode()) {
- throwTypeError(exec, StrictModeArgumentsAccessError);
- slot.setValue(jsNull());
- return true;
+ bool result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
+ if (!result) {
+ thisObject->initializeGetterSetterProperty(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Getter | Setter);
+ result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
+ ASSERT(result);
+ }
+ return result;
}
-
slot.setCacheableCustom(thisObject, argumentsGetter);
return true;
}
@@ -240,9 +241,13 @@
if (propertyName == exec->propertyNames().caller) {
if (thisObject->jsExecutable()->isStrictMode()) {
- throwTypeError(exec, StrictModeCallerAccessError);
- slot.setValue(jsNull());
- return true;
+ bool result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
+ if (!result) {
+ thisObject->initializeGetterSetterProperty(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Getter | Setter);
+ result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
+ ASSERT(result);
+ }
+ return result;
}
slot.setCacheableCustom(thisObject, callerGetter);
return true;
@@ -263,10 +268,16 @@
}
if (propertyName == exec->propertyNames().arguments) {
- if (jsExecutable()->isStrictMode())
- createDescriptorForThrowingProperty(exec, descriptor, StrictModeArgumentsAccessError);
- else
- descriptor.setDescriptor(exec->interpreter()->retrieveArguments(exec, this), ReadOnly | DontEnum | DontDelete);
+ if (jsExecutable()->isStrictMode()) {
+ bool result = Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+ if (!result) {
+ initializeGetterSetterProperty(exec, propertyName, globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Getter | Setter);
+ result = Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+ ASSERT(result);
+ }
+ return result;
+ }
+ descriptor.setDescriptor(exec->interpreter()->retrieveArguments(exec, this), ReadOnly | DontEnum | DontDelete);
return true;
}
@@ -276,10 +287,16 @@
}
if (propertyName == exec->propertyNames().caller) {
- if (jsExecutable()->isStrictMode())
- createDescriptorForThrowingProperty(exec, descriptor, StrictModeCallerAccessError);
- else
- descriptor.setDescriptor(exec->interpreter()->retrieveCaller(exec, this), ReadOnly | DontEnum | DontDelete);
+ if (jsExecutable()->isStrictMode()) {
+ bool result = Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+ if (!result) {
+ initializeGetterSetterProperty(exec, propertyName, globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Getter | Setter);
+ result = Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+ ASSERT(result);
+ }
+ return result;
+ }
+ descriptor.setDescriptor(exec->interpreter()->retrieveCaller(exec, this), ReadOnly | DontEnum | DontDelete);
return true;
}
@@ -318,15 +335,12 @@
PropertySlot slot;
thisObject->getOwnPropertySlotVirtual(exec, propertyName, slot);
}
- if (thisObject->jsExecutable()->isStrictMode()) {
- if (propertyName == exec->propertyNames().arguments) {
- throwTypeError(exec, StrictModeArgumentsAccessError);
- return;
- }
- if (propertyName == exec->propertyNames().caller) {
- throwTypeError(exec, StrictModeCallerAccessError);
- return;
- }
+ if (thisObject->jsExecutable()->isStrictMode() && (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().caller)) {
+ // This will trigger the property to be reified, if this is not already the case!
+ bool okay = thisObject->hasProperty(exec, propertyName);
+ ASSERT_UNUSED(okay, okay);
+ Base::put(thisObject, exec, propertyName, value, slot);
+ return;
}
if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length)
return;
Modified: trunk/Source/_javascript_Core/runtime/JSFunction.h (97904 => 97905)
--- trunk/Source/_javascript_Core/runtime/JSFunction.h 2011-10-20 00:53:21 UTC (rev 97904)
+++ trunk/Source/_javascript_Core/runtime/JSFunction.h 2011-10-20 01:18:03 UTC (rev 97905)
@@ -41,9 +41,6 @@
EncodedJSValue JSC_HOST_CALL callHostFunctionAsConstructor(ExecState*);
- extern const char* StrictModeCallerAccessError;
- extern const char* StrictModeArgumentsAccessError;
-
void createDescriptorForThrowingProperty(ExecState*, PropertyDescriptor&, const char* message);
class JSFunction : public JSNonFinalObject {
Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp (97904 => 97905)
--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp 2011-10-20 00:53:21 UTC (rev 97904)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp 2011-10-20 01:18:03 UTC (rev 97905)
@@ -47,6 +47,7 @@
#include "ErrorPrototype.h"
#include "FunctionConstructor.h"
#include "FunctionPrototype.h"
+#include "GetterSetter.h"
#include "JSBoundFunction.h"
#include "JSFunction.h"
#include "JSGlobalObjectFunctions.h"
@@ -305,6 +306,15 @@
resetPrototype(exec->globalData(), prototype);
}
+void JSGlobalObject::createThrowTypeError(ExecState* exec)
+{
+ JSFunction* thrower = JSFunction::create(exec, this, 0, Identifier(), globalFuncThrowTypeError);
+ GetterSetter* getterSetter = GetterSetter::create(exec);
+ getterSetter->setGetter(exec->globalData(), thrower);
+ getterSetter->setSetter(exec->globalData(), thrower);
+ m_throwTypeErrorGetterSetter.set(exec->globalData(), this, getterSetter);
+}
+
// Set prototype, and also insert the object prototype at the end of the chain.
void JSGlobalObject::resetPrototype(JSGlobalData& globalData, JSValue prototype)
{
@@ -339,6 +349,7 @@
visitIfNeeded(visitor, &thisObject->m_evalFunction);
visitIfNeeded(visitor, &thisObject->m_callFunction);
visitIfNeeded(visitor, &thisObject->m_applyFunction);
+ visitIfNeeded(visitor, &thisObject->m_throwTypeErrorGetterSetter);
visitIfNeeded(visitor, &thisObject->m_objectPrototype);
visitIfNeeded(visitor, &thisObject->m_functionPrototype);
Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.h (97904 => 97905)
--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.h 2011-10-20 00:53:21 UTC (rev 97904)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.h 2011-10-20 01:18:03 UTC (rev 97905)
@@ -42,6 +42,7 @@
class Debugger;
class ErrorConstructor;
class FunctionPrototype;
+ class GetterSetter;
class GlobalCodeBlock;
class NativeErrorConstructor;
class ProgramCodeBlock;
@@ -90,6 +91,7 @@
WriteBarrier<JSFunction> m_evalFunction;
WriteBarrier<JSFunction> m_callFunction;
WriteBarrier<JSFunction> m_applyFunction;
+ WriteBarrier<GetterSetter> m_throwTypeErrorGetterSetter;
WriteBarrier<ObjectPrototype> m_objectPrototype;
WriteBarrier<FunctionPrototype> m_functionPrototype;
@@ -212,6 +214,12 @@
JSFunction* evalFunction() const { return m_evalFunction.get(); }
JSFunction* callFunction() const { return m_callFunction.get(); }
JSFunction* applyFunction() const { return m_applyFunction.get(); }
+ GetterSetter* throwTypeErrorGetterSetter(ExecState* exec)
+ {
+ if (!m_throwTypeErrorGetterSetter)
+ createThrowTypeError(exec);
+ return m_throwTypeErrorGetterSetter.get();
+ }
ObjectPrototype* objectPrototype() const { return m_objectPrototype.get(); }
FunctionPrototype* functionPrototype() const { return m_functionPrototype.get(); }
@@ -321,6 +329,8 @@
void init(JSObject* thisValue);
void reset(JSValue prototype);
+ void createThrowTypeError(ExecState*);
+
void setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray, size_t count);
static void clearRareData(JSCell*);
};
Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp (97904 => 97905)
--- trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp 2011-10-20 00:53:21 UTC (rev 97904)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp 2011-10-20 01:18:03 UTC (rev 97905)
@@ -594,4 +594,9 @@
return JSValue::encode(jsString(exec, builder.toUString()));
}
+EncodedJSValue JSC_HOST_CALL globalFuncThrowTypeError(ExecState* exec)
+{
+ return throwVMTypeError(exec);
+}
+
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.h (97904 => 97905)
--- trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.h 2011-10-20 00:53:21 UTC (rev 97904)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.h 2011-10-20 01:18:03 UTC (rev 97905)
@@ -47,6 +47,7 @@
EncodedJSValue JSC_HOST_CALL globalFuncEncodeURIComponent(ExecState*);
EncodedJSValue JSC_HOST_CALL globalFuncEscape(ExecState*);
EncodedJSValue JSC_HOST_CALL globalFuncUnescape(ExecState*);
+ EncodedJSValue JSC_HOST_CALL globalFuncThrowTypeError(ExecState*);
static const double mantissaOverflowLowerBound = 9007199254740992.0;
double parseIntOverflow(const char*, int length, int radix);
Modified: trunk/Source/_javascript_Core/runtime/JSObject.cpp (97904 => 97905)
--- trunk/Source/_javascript_Core/runtime/JSObject.cpp 2011-10-20 00:53:21 UTC (rev 97904)
+++ trunk/Source/_javascript_Core/runtime/JSObject.cpp 2011-10-20 01:18:03 UTC (rev 97905)
@@ -396,6 +396,28 @@
getterSetter->setGetter(globalData, getterFunction);
}
+void JSObject::initializeGetterSetterProperty(ExecState* exec, const Identifier& propertyName, GetterSetter* getterSetter, unsigned attributes)
+{
+ // Set an inital property on an object; the property must not already exist & the attribute flags must be set correctly.
+ ASSERT(structure()->get(exec->globalData(), propertyName) == WTF::notFound);
+ ASSERT(static_cast<bool>(getterSetter->getter()) == static_cast<bool>(attributes & Getter));
+ ASSERT(static_cast<bool>(getterSetter->setter()) == static_cast<bool>(attributes & Setter));
+
+ JSGlobalData& globalData = exec->globalData();
+ PutPropertySlot slot;
+ putDirectInternal(globalData, propertyName, getterSetter, attributes | Getter, true, slot, 0);
+
+ // putDirect will change our Structure if we add a new property. For
+ // getters and setters, though, we also need to change our Structure
+ // if we override an existing non-getter or non-setter.
+ if (slot.type() != PutPropertySlot::NewProperty) {
+ if (!structure()->isDictionary())
+ setStructure(exec->globalData(), Structure::getterSetterTransition(globalData, structure()));
+ }
+
+ structure()->setHasGetterSetterProperties(true);
+}
+
void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes)
{
if (propertyName == exec->propertyNames().underscoreProto) {
Modified: trunk/Source/_javascript_Core/runtime/JSObject.h (97904 => 97905)
--- trunk/Source/_javascript_Core/runtime/JSObject.h 2011-10-20 00:53:21 UTC (rev 97904)
+++ trunk/Source/_javascript_Core/runtime/JSObject.h 2011-10-20 01:18:03 UTC (rev 97905)
@@ -45,7 +45,8 @@
return value.asCell();
return 0;
}
-
+
+ class GetterSetter;
class HashEntry;
class InternalFunction;
class MarkedBlock;
@@ -190,6 +191,7 @@
void putUndefinedAtDirectOffset(size_t offset) { propertyStorage()[offset].setUndefined(); }
void fillGetterPropertySlot(PropertySlot&, WriteBarrierBase<Unknown>* location);
+ void initializeGetterSetterProperty(ExecState*, const Identifier&, GetterSetter*, unsigned attributes);
virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes = 0);
virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes = 0);