Diff
Modified: trunk/LayoutTests/ChangeLog (133545 => 133546)
--- trunk/LayoutTests/ChangeLog 2012-11-06 01:48:19 UTC (rev 133545)
+++ trunk/LayoutTests/ChangeLog 2012-11-06 01:53:09 UTC (rev 133546)
@@ -1,3 +1,16 @@
+2012-11-05 Filip Pizlo <[email protected]>
+
+ Prototype chain caching should check that the path from the base object to the slot base involves prototype hops only
+ https://bugs.webkit.org/show_bug.cgi?id=101276
+
+ Reviewed by Gavin Barraclough.
+
+ This test already covered this case, but only for method_check. Modified it to
+ also cover the get_by_id case.
+
+ * fast/js/toString-and-valueOf-override-expected.txt:
+ * fast/js/toString-and-valueOf-override.html:
+
2012-11-05 Mark Lam <[email protected]>
Fixed flaky fast/xmlhttprequest/xmlhttprequest-recursive-sync-event.html.
Modified: trunk/LayoutTests/fast/js/toString-and-valueOf-override-expected.txt (133545 => 133546)
--- trunk/LayoutTests/fast/js/toString-and-valueOf-override-expected.txt 2012-11-06 01:48:19 UTC (rev 133545)
+++ trunk/LayoutTests/fast/js/toString-and-valueOf-override-expected.txt 2012-11-06 01:53:09 UTC (rev 133546)
@@ -3,6 +3,8 @@
[span] : [object HTMLSpanElement]
String(span) : [object HTMLSpanElement]
String([span]) : [object HTMLSpanElement]
+span.toString : function toString() { [native code] }
+span.toString() (cached in variable) : [object Undefined]
span.toString() : [object HTMLSpanElement]
[span].toString() : [object HTMLSpanElement]
span.valueOf() : [object HTMLSpanElement]
@@ -13,6 +15,8 @@
[span] : toString
String(span) : toString
String([span]) : toString
+span.toString : function () { return "toString"; }
+span.toString() (cached in variable) : toString
span.toString() : toString
[span].toString() : toString
span.valueOf() : valueOf
@@ -23,6 +27,8 @@
[span] : valueOf
String(span) : valueOf
String([span]) : valueOf
+span.toString : function () { return new Object(); }
+span.toString() (cached in variable) : [object Object]
span.toString() : [object Object]
[span].toString() : valueOf
span.valueOf() : valueOf
@@ -33,6 +39,8 @@
[span] : toString
String(span) : toString
String([span]) : toString
+span.toString : function () { return 'toString'; }
+span.toString() (cached in variable) : toString
span.toString() : toString
[span].toString() : toString
span.valueOf() : [object Object]
@@ -43,6 +51,8 @@
TypeError: No default value
TypeError: No default value
TypeError: No default value
+span.toString : function () { return new Object(); }
+span.toString() (cached in variable) : [object Object]
span.toString() : [object Object]
TypeError: No default value
span.valueOf() : [object Object]
@@ -53,8 +63,10 @@
Exception
Exception
Exception
+span.toString : function () { throw "Exception"; }
Exception
Exception
+Exception
span.valueOf() : valueOf
Exception
@@ -63,6 +75,8 @@
[span] : toString
String(span) : toString
String([span]) : toString
+span.toString : function () { return 'toString'; }
+span.toString() (cached in variable) : toString
span.toString() : toString
[span].toString() : toString
Exception
@@ -73,10 +87,12 @@
Exception
Exception
Exception
+span.toString : function () { throw "Exception"; }
Exception
Exception
Exception
Exception
+Exception
Unmodified window
@@ -84,6 +100,8 @@
[window] : [object Window]
String(window) : [object Window]
String([window]) : [object Window]
+window.toString : function toString() { [native code] }
+window.toString() (cached in variable) : [object Undefined]
window.toString() : [object Window]
[window].toString() : [object Window]
window.valueOf() : [object Window]
@@ -94,6 +112,8 @@
[window] : toString
String(window) : toString
String([window]) : toString
+window.toString : function () { return "toString"; }
+window.toString() (cached in variable) : toString
window.toString() : toString
[window].toString() : toString
window.valueOf() : valueOf
@@ -104,6 +124,8 @@
[window] : valueOf
String(window) : valueOf
String([window]) : valueOf
+window.toString : function () { return new Object(); }
+window.toString() (cached in variable) : [object Object]
window.toString() : [object Object]
[window].toString() : valueOf
window.valueOf() : valueOf
@@ -114,6 +136,8 @@
[window] : toString
String(window) : toString
String([window]) : toString
+window.toString : function () { return 'toString'; }
+window.toString() (cached in variable) : toString
window.toString() : toString
[window].toString() : toString
window.valueOf() : [object Object]
@@ -124,6 +148,8 @@
TypeError: No default value
TypeError: No default value
TypeError: No default value
+window.toString : function () { return new Object(); }
+window.toString() (cached in variable) : [object Object]
window.toString() : [object Object]
TypeError: No default value
window.valueOf() : [object Object]
@@ -134,8 +160,10 @@
Exception
Exception
Exception
+window.toString : function () { throw "Exception"; }
Exception
Exception
+Exception
window.valueOf() : valueOf
Exception
@@ -144,6 +172,8 @@
[window] : toString
String(window) : toString
String([window]) : toString
+window.toString : function () { return 'toString'; }
+window.toString() (cached in variable) : toString
window.toString() : toString
[window].toString() : toString
Exception
@@ -154,10 +184,12 @@
Exception
Exception
Exception
+window.toString : function () { throw "Exception"; }
Exception
Exception
Exception
Exception
+Exception
Unmodified Navigator
@@ -165,6 +197,8 @@
[Navigator] : [object Navigator]
String(Navigator) : [object Navigator]
String([Navigator]) : [object Navigator]
+Navigator.toString : function toString() { [native code] }
+Navigator.toString() (cached in variable) : [object Undefined]
Navigator.toString() : [object Navigator]
[Navigator].toString() : [object Navigator]
Navigator.valueOf() : [object Navigator]
@@ -175,6 +209,8 @@
[Navigator] : toString
String(Navigator) : toString
String([Navigator]) : toString
+Navigator.toString : function () { return "toString"; }
+Navigator.toString() (cached in variable) : toString
Navigator.toString() : toString
[Navigator].toString() : toString
Navigator.valueOf() : valueOf
@@ -185,6 +221,8 @@
[Navigator] : valueOf
String(Navigator) : valueOf
String([Navigator]) : valueOf
+Navigator.toString : function () { return new Object(); }
+Navigator.toString() (cached in variable) : [object Object]
Navigator.toString() : [object Object]
[Navigator].toString() : valueOf
Navigator.valueOf() : valueOf
@@ -195,6 +233,8 @@
[Navigator] : toString
String(Navigator) : toString
String([Navigator]) : toString
+Navigator.toString : function () { return 'toString'; }
+Navigator.toString() (cached in variable) : toString
Navigator.toString() : toString
[Navigator].toString() : toString
Navigator.valueOf() : [object Object]
@@ -205,6 +245,8 @@
TypeError: No default value
TypeError: No default value
TypeError: No default value
+Navigator.toString : function () { return new Object(); }
+Navigator.toString() (cached in variable) : [object Object]
Navigator.toString() : [object Object]
TypeError: No default value
Navigator.valueOf() : [object Object]
@@ -215,8 +257,10 @@
Exception
Exception
Exception
+Navigator.toString : function () { throw "Exception"; }
Exception
Exception
+Exception
Navigator.valueOf() : valueOf
Exception
@@ -225,6 +269,8 @@
[Navigator] : toString
String(Navigator) : toString
String([Navigator]) : toString
+Navigator.toString : function () { return 'toString'; }
+Navigator.toString() (cached in variable) : toString
Navigator.toString() : toString
[Navigator].toString() : toString
Exception
@@ -235,10 +281,12 @@
Exception
Exception
Exception
+Navigator.toString : function () { throw "Exception"; }
Exception
Exception
Exception
Exception
+Exception
Unmodified History
@@ -246,6 +294,8 @@
[History] : [object History]
String(History) : [object History]
String([History]) : [object History]
+History.toString : function toString() { [native code] }
+History.toString() (cached in variable) : [object Undefined]
History.toString() : [object History]
[History].toString() : [object History]
History.valueOf() : [object History]
@@ -256,6 +306,8 @@
[History] : toString
String(History) : toString
String([History]) : toString
+History.toString : function () { return "toString"; }
+History.toString() (cached in variable) : toString
History.toString() : toString
[History].toString() : toString
History.valueOf() : valueOf
@@ -266,6 +318,8 @@
[History] : valueOf
String(History) : valueOf
String([History]) : valueOf
+History.toString : function () { return new Object(); }
+History.toString() (cached in variable) : [object Object]
History.toString() : [object Object]
[History].toString() : valueOf
History.valueOf() : valueOf
@@ -276,6 +330,8 @@
[History] : toString
String(History) : toString
String([History]) : toString
+History.toString : function () { return 'toString'; }
+History.toString() (cached in variable) : toString
History.toString() : toString
[History].toString() : toString
History.valueOf() : [object Object]
@@ -286,6 +342,8 @@
TypeError: No default value
TypeError: No default value
TypeError: No default value
+History.toString : function () { return new Object(); }
+History.toString() (cached in variable) : [object Object]
History.toString() : [object Object]
TypeError: No default value
History.valueOf() : [object Object]
@@ -296,8 +354,10 @@
Exception
Exception
Exception
+History.toString : function () { throw "Exception"; }
Exception
Exception
+Exception
History.valueOf() : valueOf
Exception
@@ -306,6 +366,8 @@
[History] : toString
String(History) : toString
String([History]) : toString
+History.toString : function () { return 'toString'; }
+History.toString() (cached in variable) : toString
History.toString() : toString
[History].toString() : toString
Exception
@@ -316,10 +378,12 @@
Exception
Exception
Exception
+History.toString : function () { throw "Exception"; }
Exception
Exception
Exception
Exception
+Exception
Unmodified Selection
@@ -327,6 +391,8 @@
[Selection] :
String(Selection) :
String([Selection]) :
+Selection.toString : function toString() { [native code] }
+TypeError: Type error
Selection.toString() :
[Selection].toString() :
Selection.valueOf() :
@@ -337,6 +403,8 @@
[Selection] : toString
String(Selection) : toString
String([Selection]) : toString
+Selection.toString : function () { return "toString"; }
+Selection.toString() (cached in variable) : toString
Selection.toString() : toString
[Selection].toString() : toString
Selection.valueOf() : valueOf
@@ -347,6 +415,8 @@
[Selection] : valueOf
String(Selection) : valueOf
String([Selection]) : valueOf
+Selection.toString : function () { return new Object(); }
+Selection.toString() (cached in variable) : [object Object]
Selection.toString() : [object Object]
[Selection].toString() : valueOf
Selection.valueOf() : valueOf
@@ -357,6 +427,8 @@
[Selection] : toString
String(Selection) : toString
String([Selection]) : toString
+Selection.toString : function () { return 'toString'; }
+Selection.toString() (cached in variable) : toString
Selection.toString() : toString
[Selection].toString() : toString
Selection.valueOf() : [object Object]
@@ -367,6 +439,8 @@
TypeError: No default value
TypeError: No default value
TypeError: No default value
+Selection.toString : function () { return new Object(); }
+Selection.toString() (cached in variable) : [object Object]
Selection.toString() : [object Object]
TypeError: No default value
Selection.valueOf() : [object Object]
@@ -377,8 +451,10 @@
Exception
Exception
Exception
+Selection.toString : function () { throw "Exception"; }
Exception
Exception
+Exception
Selection.valueOf() : valueOf
Exception
@@ -387,6 +463,8 @@
[Selection] : toString
String(Selection) : toString
String([Selection]) : toString
+Selection.toString : function () { return 'toString'; }
+Selection.toString() (cached in variable) : toString
Selection.toString() : toString
[Selection].toString() : toString
Exception
@@ -397,10 +475,12 @@
Exception
Exception
Exception
+Selection.toString : function () { throw "Exception"; }
Exception
Exception
Exception
Exception
+Exception
Modified: trunk/LayoutTests/fast/js/toString-and-valueOf-override.html (133545 => 133546)
--- trunk/LayoutTests/fast/js/toString-and-valueOf-override.html 2012-11-06 01:48:19 UTC (rev 133545)
+++ trunk/LayoutTests/fast/js/toString-and-valueOf-override.html 2012-11-06 01:53:09 UTC (rev 133546)
@@ -12,6 +12,8 @@
try { print('[' + type + '] : ' + [object]); } catch(e) { print(e); }
try { print('String(' + type + ') : ' + String(object)); } catch(e) { print(e); }
try { print('String([' + type + ']) : ' + String([object])); } catch(e) { print(e); }
+ try { print(type + '.toString : ' + object.toString); } catch(e) { print(e); }
+ try { var toString = object.toString; print(type + '.toString() (cached in variable) : ' + toString()); } catch(e) { print(e); }
try { print(type + '.toString() : ' + object.toString()); } catch(e) { print(e); }
try { print('[' + type + '].toString() : ' + [object].toString()); } catch(e) { print(e); }
try { print(type + '.valueOf() : ' + object.valueOf()); } catch(e) { print(e); }
Modified: trunk/Source/_javascript_Core/ChangeLog (133545 => 133546)
--- trunk/Source/_javascript_Core/ChangeLog 2012-11-06 01:48:19 UTC (rev 133545)
+++ trunk/Source/_javascript_Core/ChangeLog 2012-11-06 01:53:09 UTC (rev 133546)
@@ -1,3 +1,30 @@
+2012-11-05 Filip Pizlo <[email protected]>
+
+ Prototype chain caching should check that the path from the base object to the slot base involves prototype hops only
+ https://bugs.webkit.org/show_bug.cgi?id=101276
+
+ Reviewed by Gavin Barraclough.
+
+ Changed normalizePrototypeChain() to report an invalid prototype chain if any object is a proxy.
+ This catches cases where our prototype chain checks would have been insufficient to guard against
+ newly introduced properties, despecialized properties, or deleted properties in the chain of
+ objects involved in the access.
+
+ * dfg/DFGRepatch.cpp:
+ (JSC::DFG::tryCacheGetByID):
+ (JSC::DFG::tryBuildGetByIDProtoList):
+ (JSC::DFG::tryCachePutByID):
+ (JSC::DFG::tryBuildPutByIdList):
+ * jit/JITStubs.cpp:
+ (JSC::JITThunks::tryCachePutByID):
+ (JSC::JITThunks::tryCacheGetByID):
+ (JSC::DEFINE_STUB_FUNCTION):
+ * llint/LLIntSlowPaths.cpp:
+ (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+ * runtime/Operations.h:
+ (JSC):
+ (JSC::normalizePrototypeChain):
+
2012-11-05 Dima Gorbik <[email protected]>
Back out controversial changes from Bug 98665.
Modified: trunk/Source/_javascript_Core/dfg/DFGRepatch.cpp (133545 => 133546)
--- trunk/Source/_javascript_Core/dfg/DFGRepatch.cpp 2012-11-06 01:48:19 UTC (rev 133545)
+++ trunk/Source/_javascript_Core/dfg/DFGRepatch.cpp 2012-11-06 01:53:09 UTC (rev 133546)
@@ -324,7 +324,7 @@
PropertyOffset offset = slot.cachedOffset();
size_t count = normalizePrototypeChain(exec, baseValue, slot.slotBase(), propertyName, offset);
- if (!count)
+ if (count == InvalidPrototypeChain)
return false;
StructureChain* prototypeChain = structure->prototypeChain(exec);
@@ -550,7 +550,7 @@
PropertyOffset offset = slot.cachedOffset();
size_t count = normalizePrototypeChain(exec, baseValue, slot.slotBase(), propertyName, offset);
- if (!count)
+ if (count == InvalidPrototypeChain)
return false;
Structure* structure = baseValue.asCell()->structure();
@@ -964,7 +964,8 @@
if (hasIndexingHeader(oldStructure->indexingType()))
return false;
- normalizePrototypeChain(exec, baseCell);
+ if (normalizePrototypeChain(exec, baseCell) == InvalidPrototypeChain)
+ return false;
StructureChain* prototypeChain = structure->prototypeChain(exec);
@@ -1035,7 +1036,8 @@
if (hasIndexingHeader(oldStructure->indexingType()))
return false;
- normalizePrototypeChain(exec, baseCell);
+ if (normalizePrototypeChain(exec, baseCell) == InvalidPrototypeChain)
+ return false;
StructureChain* prototypeChain = structure->prototypeChain(exec);
Modified: trunk/Source/_javascript_Core/jit/JITStubs.cpp (133545 => 133546)
--- trunk/Source/_javascript_Core/jit/JITStubs.cpp 2012-11-06 01:48:19 UTC (rev 133545)
+++ trunk/Source/_javascript_Core/jit/JITStubs.cpp 2012-11-06 01:53:09 UTC (rev 133546)
@@ -864,7 +864,10 @@
}
// put_by_id_transition checks the prototype chain for setters.
- normalizePrototypeChain(callFrame, baseCell);
+ if (normalizePrototypeChain(callFrame, baseCell) == InvalidPrototypeChain) {
+ ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
+ return;
+ }
StructureChain* prototypeChain = structure->prototypeChain(callFrame);
ASSERT(structure->previousID()->transitionWatchpointSetHasBeenInvalidated());
@@ -937,7 +940,7 @@
if (slot.slotBase() == structure->prototypeForLookup(callFrame)) {
ASSERT(slot.slotBase().isObject());
-
+
JSObject* slotBaseObject = asObject(slot.slotBase());
size_t offset = slot.cachedOffset();
@@ -958,7 +961,7 @@
PropertyOffset offset = slot.cachedOffset();
size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset);
- if (!count) {
+ if (count == InvalidPrototypeChain) {
stubInfo->accessType = access_get_by_id_generic;
return;
}
@@ -1873,7 +1876,13 @@
if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full));
}
- } else if (size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset)) {
+ } else {
+ size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset);
+ if (count == InvalidPrototypeChain) {
+ ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
+ return JSValue::encode(result);
+ }
+
ASSERT(!baseValue.asCell()->structure()->isDictionary());
int listIndex;
PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(callFrame->globalData(), codeBlock->ownerExecutable(), stubInfo, listIndex);
@@ -1885,8 +1894,7 @@
if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full));
}
- } else
- ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
+ }
return JSValue::encode(result);
}
Modified: trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp (133545 => 133546)
--- trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp 2012-11-06 01:48:19 UTC (rev 133545)
+++ trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp 2012-11-06 01:53:09 UTC (rev 133546)
@@ -1001,32 +1001,32 @@
// below may GC.
pc[0].u.opcode = LLInt::getOpcode(llint_op_put_by_id);
- normalizePrototypeChain(exec, baseCell);
-
- ASSERT(structure->previousID()->isObject());
- pc[4].u.structure.set(
- globalData, codeBlock->ownerExecutable(), structure->previousID());
- if (isInlineOffset(slot.cachedOffset()))
- pc[5].u.operand = offsetInInlineStorage(slot.cachedOffset()) * sizeof(JSValue) + JSObject::offsetOfInlineStorage();
- else
- pc[5].u.operand = offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue);
- pc[6].u.structure.set(
- globalData, codeBlock->ownerExecutable(), structure);
- StructureChain* chain = structure->prototypeChain(exec);
- ASSERT(chain);
- pc[7].u.structureChain.set(
- globalData, codeBlock->ownerExecutable(), chain);
-
- if (pc[8].u.operand) {
+ if (normalizePrototypeChain(exec, baseCell) != InvalidPrototypeChain) {
+ ASSERT(structure->previousID()->isObject());
+ pc[4].u.structure.set(
+ globalData, codeBlock->ownerExecutable(), structure->previousID());
if (isInlineOffset(slot.cachedOffset()))
- pc[0].u.opcode = LLInt::getOpcode(llint_op_put_by_id_transition_direct);
+ pc[5].u.operand = offsetInInlineStorage(slot.cachedOffset()) * sizeof(JSValue) + JSObject::offsetOfInlineStorage();
else
- pc[0].u.opcode = LLInt::getOpcode(llint_op_put_by_id_transition_direct_out_of_line);
- } else {
- if (isInlineOffset(slot.cachedOffset()))
- pc[0].u.opcode = LLInt::getOpcode(llint_op_put_by_id_transition_normal);
- else
- pc[0].u.opcode = LLInt::getOpcode(llint_op_put_by_id_transition_normal_out_of_line);
+ pc[5].u.operand = offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue);
+ pc[6].u.structure.set(
+ globalData, codeBlock->ownerExecutable(), structure);
+ StructureChain* chain = structure->prototypeChain(exec);
+ ASSERT(chain);
+ pc[7].u.structureChain.set(
+ globalData, codeBlock->ownerExecutable(), chain);
+
+ if (pc[8].u.operand) {
+ if (isInlineOffset(slot.cachedOffset()))
+ pc[0].u.opcode = LLInt::getOpcode(llint_op_put_by_id_transition_direct);
+ else
+ pc[0].u.opcode = LLInt::getOpcode(llint_op_put_by_id_transition_direct_out_of_line);
+ } else {
+ if (isInlineOffset(slot.cachedOffset()))
+ pc[0].u.opcode = LLInt::getOpcode(llint_op_put_by_id_transition_normal);
+ else
+ pc[0].u.opcode = LLInt::getOpcode(llint_op_put_by_id_transition_normal_out_of_line);
+ }
}
}
} else {
Modified: trunk/Source/_javascript_Core/runtime/JSCell.h (133545 => 133546)
--- trunk/Source/_javascript_Core/runtime/JSCell.h 2012-11-06 01:48:19 UTC (rev 133545)
+++ trunk/Source/_javascript_Core/runtime/JSCell.h 2012-11-06 01:53:09 UTC (rev 133546)
@@ -75,6 +75,7 @@
bool isString() const;
bool isObject() const;
bool isGetterSetter() const;
+ bool isProxy() const;
bool inherits(const ClassInfo*) const;
bool isAPIValueWrapper() const;
Modified: trunk/Source/_javascript_Core/runtime/JSObject.h (133545 => 133546)
--- trunk/Source/_javascript_Core/runtime/JSObject.h 2012-11-06 01:48:19 UTC (rev 133545)
+++ trunk/Source/_javascript_Core/runtime/JSObject.h 2012-11-06 01:53:09 UTC (rev 133546)
@@ -525,7 +525,6 @@
bool isNameScopeObject() const;
bool isActivationObject() const;
bool isErrorInstance() const;
- bool isProxy() const;
void seal(JSGlobalData&);
void freeze(JSGlobalData&);
@@ -934,11 +933,6 @@
return structure()->typeInfo().type() == ErrorInstanceType;
}
-inline bool JSObject::isProxy() const
-{
- return structure()->typeInfo().type() == ProxyType;
-}
-
inline void JSObject::setButterfly(JSGlobalData& globalData, Butterfly* butterfly, Structure* structure)
{
ASSERT(structure);
Modified: trunk/Source/_javascript_Core/runtime/Operations.h (133545 => 133546)
--- trunk/Source/_javascript_Core/runtime/Operations.h 2012-11-06 01:48:19 UTC (rev 133545)
+++ trunk/Source/_javascript_Core/runtime/Operations.h 2012-11-06 01:53:09 UTC (rev 133546)
@@ -24,6 +24,7 @@
#include "ExceptionHelpers.h"
#include "Interpreter.h"
+#include "JSProxy.h"
#include "JSString.h"
#include "JSValueInlineMethods.h"
@@ -297,19 +298,24 @@
return jsAddSlowCase(callFrame, v1, v2);
}
+#define InvalidPrototypeChain (std::numeric_limits<size_t>::max())
+
inline size_t normalizePrototypeChain(CallFrame* callFrame, JSValue base, JSValue slotBase, const Identifier& propertyName, PropertyOffset& slotOffset)
{
JSCell* cell = base.asCell();
size_t count = 0;
while (slotBase != cell) {
+ if (cell->isProxy())
+ return InvalidPrototypeChain;
+
JSValue v = cell->structure()->prototypeForLookup(callFrame);
// If we didn't find slotBase in base's prototype chain, then base
// must be a proxy for another object.
if (v.isNull())
- return 0;
+ return InvalidPrototypeChain;
cell = v.asCell();
@@ -332,6 +338,9 @@
{
size_t count = 0;
while (1) {
+ if (base->isProxy())
+ return InvalidPrototypeChain;
+
JSValue v = base->structure()->prototypeForLookup(callFrame);
if (v.isNull())
return count;
Modified: trunk/Source/_javascript_Core/runtime/Structure.h (133545 => 133546)
--- trunk/Source/_javascript_Core/runtime/Structure.h 2012-11-06 01:48:19 UTC (rev 133545)
+++ trunk/Source/_javascript_Core/runtime/Structure.h 2012-11-06 01:53:09 UTC (rev 133546)
@@ -521,6 +521,11 @@
return m_structure->typeInfo().type() == GetterSetterType;
}
+ inline bool JSCell::isProxy() const
+ {
+ return structure()->typeInfo().type() == ProxyType;
+ }
+
inline bool JSCell::isAPIValueWrapper() const
{
return m_structure->typeInfo().type() == APIValueWrapperType;