Modified: trunk/Source/_javascript_Core/API/tests/testapi.c (87585 => 87586)
--- trunk/Source/_javascript_Core/API/tests/testapi.c 2011-05-27 23:34:03 UTC (rev 87585)
+++ trunk/Source/_javascript_Core/API/tests/testapi.c 2011-05-27 23:53:36 UTC (rev 87586)
@@ -355,6 +355,111 @@
return jsClass;
}
+static JSValueRef PropertyCatchalls_getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
+{
+ UNUSED_PARAM(context);
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(propertyName);
+ UNUSED_PARAM(exception);
+
+ if (JSStringIsEqualToUTF8CString(propertyName, "x")) {
+ static size_t count;
+ if (count++ < 5)
+ return NULL;
+
+ // Swallow all .x gets after 5, returning null.
+ return JSValueMakeNull(context);
+ }
+
+ if (JSStringIsEqualToUTF8CString(propertyName, "y")) {
+ static size_t count;
+ if (count++ < 5)
+ return NULL;
+
+ // Swallow all .y gets after 5, returning null.
+ return JSValueMakeNull(context);
+ }
+
+ if (JSStringIsEqualToUTF8CString(propertyName, "z")) {
+ static size_t count;
+ if (count++ < 5)
+ return NULL;
+
+ // Swallow all .y gets after 5, returning null.
+ return JSValueMakeNull(context);
+ }
+
+ return NULL;
+}
+
+static bool PropertyCatchalls_setProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
+{
+ UNUSED_PARAM(context);
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(propertyName);
+ UNUSED_PARAM(value);
+ UNUSED_PARAM(exception);
+
+ if (JSStringIsEqualToUTF8CString(propertyName, "x")) {
+ static size_t count;
+ if (count++ < 5)
+ return false;
+
+ // Swallow all .x sets after 4.
+ return true;
+ }
+
+ return false;
+}
+
+static void PropertyCatchalls_getPropertyNames(JSContextRef context, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames)
+{
+ UNUSED_PARAM(context);
+ UNUSED_PARAM(object);
+
+ static size_t count;
+ static const char* numbers[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
+
+ // Provide a property of a different name every time.
+ JSStringRef propertyName = JSStringCreateWithUTF8CString(numbers[count++ % 10]);
+ JSPropertyNameAccumulatorAddName(propertyNames, propertyName);
+ JSStringRelease(propertyName);
+}
+
+JSClassDefinition PropertyCatchalls_definition = {
+ 0,
+ kJSClassAttributeNone,
+
+ "PropertyCatchalls",
+ NULL,
+
+ NULL,
+ NULL,
+
+ NULL,
+ NULL,
+ NULL,
+ PropertyCatchalls_getProperty,
+ PropertyCatchalls_setProperty,
+ NULL,
+ PropertyCatchalls_getPropertyNames,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+};
+
+static JSClassRef PropertyCatchalls_class(JSContextRef context)
+{
+ UNUSED_PARAM(context);
+
+ static JSClassRef jsClass;
+ if (!jsClass)
+ jsClass = JSClassCreate(&PropertyCatchalls_definition);
+
+ return jsClass;
+}
+
static bool EvilExceptionObject_hasInstance(JSContextRef context, JSObjectRef constructor, JSValueRef possibleValue, JSValueRef* exception)
{
UNUSED_PARAM(context);
@@ -922,6 +1027,11 @@
ASSERT(JSValueGetType(context, jsCFEmptyString) == kJSTypeString);
ASSERT(JSValueGetType(context, jsCFEmptyStringWithCharacters) == kJSTypeString);
+ JSObjectRef propertyCatchalls = JSObjectMake(context, PropertyCatchalls_class(context), NULL);
+ JSStringRef propertyCatchallsString = JSStringCreateWithUTF8CString("PropertyCatchalls");
+ JSObjectSetProperty(context, globalObject, propertyCatchallsString, propertyCatchalls, kJSPropertyAttributeNone, NULL);
+ JSStringRelease(propertyCatchallsString);
+
JSObjectRef myObject = JSObjectMake(context, MyObject_class(context), NULL);
JSStringRef myObjectIString = JSStringCreateWithUTF8CString("MyObject");
JSObjectSetProperty(context, globalObject, myObjectIString, myObject, kJSPropertyAttributeNone, NULL);
Modified: trunk/Source/_javascript_Core/API/tests/testapi.js (87585 => 87586)
--- trunk/Source/_javascript_Core/API/tests/testapi.js 2011-05-27 23:34:03 UTC (rev 87585)
+++ trunk/Source/_javascript_Core/API/tests/testapi.js 2011-05-27 23:53:36 UTC (rev 87586)
@@ -246,6 +246,32 @@
shouldBe("EmptyObject", "[object CallbackObject]");
+for (var i = 0; i < 6; ++i)
+ PropertyCatchalls.x = i;
+shouldBe("PropertyCatchalls.x", 4);
+
+for (var i = 0; i < 6; ++i)
+ var x = PropertyCatchalls.x;
+shouldBe("x", null);
+
+for (var i = 0; i < 10; ++i) {
+ for (var p in PropertyCatchalls) {
+ if (p == "x")
+ continue;
+ shouldBe("p", i % 10);
+ break;
+ }
+}
+
+PropertyCatchalls.__proto__ = { y: 1 };
+for (var i = 0; i < 6; ++i)
+ var y = PropertyCatchalls.y;
+shouldBe("y", null);
+
+var o = { __proto__: PropertyCatchalls };
+for (var i = 0; i < 6; ++i)
+ var z = PropertyCatchalls.z;
+shouldBe("z", null);
+
if (failed)
throw "Some tests failed";
-
Modified: trunk/Source/_javascript_Core/jit/JITStubs.cpp (87585 => 87586)
--- trunk/Source/_javascript_Core/jit/JITStubs.cpp 2011-05-27 23:34:03 UTC (rev 87585)
+++ trunk/Source/_javascript_Core/jit/JITStubs.cpp 2011-05-27 23:53:36 UTC (rev 87586)
@@ -819,7 +819,7 @@
JSCell* baseCell = baseValue.asCell();
Structure* structure = baseCell->structure();
- if (structure->isUncacheableDictionary()) {
+ if (structure->isUncacheableDictionary() || structure->typeInfo().prohibitsPropertyCaching()) {
ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
return;
}
@@ -887,7 +887,7 @@
JSCell* baseCell = baseValue.asCell();
Structure* structure = baseCell->structure();
- if (structure->isUncacheableDictionary()) {
+ if (structure->isUncacheableDictionary() || structure->typeInfo().prohibitsPropertyCaching()) {
ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
return;
}
@@ -1722,7 +1722,7 @@
CHECK_FOR_EXCEPTION();
- if (!baseValue.isCell() || !slot.isCacheable() || baseValue.asCell()->structure()->isDictionary()) {
+ if (!baseValue.isCell() || !slot.isCacheable() || baseValue.asCell()->structure()->isDictionary() || baseValue.asCell()->structure()->typeInfo().prohibitsPropertyCaching()) {
ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
return JSValue::encode(result);
}
Modified: trunk/Source/_javascript_Core/runtime/JSTypeInfo.h (87585 => 87586)
--- trunk/Source/_javascript_Core/runtime/JSTypeInfo.h 2011-05-27 23:34:03 UTC (rev 87585)
+++ trunk/Source/_javascript_Core/runtime/JSTypeInfo.h 2011-05-27 23:53:36 UTC (rev 87586)
@@ -34,8 +34,7 @@
namespace JSC {
- // WebCore uses MasqueradesAsUndefined to make document.all and style.filter undetectable.
- static const unsigned MasqueradesAsUndefined = 1;
+ static const unsigned MasqueradesAsUndefined = 1; // WebCore uses MasqueradesAsUndefined to make document.all and style.filter undetectable.
static const unsigned ImplementsHasInstance = 1 << 1;
static const unsigned OverridesHasInstance = 1 << 2;
static const unsigned ImplementsDefaultHasInstance = 1 << 3;
@@ -44,16 +43,17 @@
static const unsigned OverridesVisitChildren = 1 << 6;
static const unsigned OverridesGetPropertyNames = 1 << 7;
static const unsigned IsJSFinalObject = 1 << 8;
+ static const unsigned ProhibitsPropertyCaching = 1 << 9;
class TypeInfo {
public:
TypeInfo(JSType type, unsigned flags = 0)
: m_type(type)
- , m_flags(flags & 0xFF)
+ , m_flags(flags & 0xff)
, m_flags2(flags >> 8)
{
- ASSERT(flags <= 0x1FF);
- ASSERT(type <= 0xFF);
+ ASSERT(flags <= 0x3ff);
+ ASSERT(type <= 0xff);
ASSERT(type >= CompoundType || !(flags & OverridesVisitChildren));
// ImplementsDefaultHasInstance means (ImplementsHasInstance & !OverridesHasInstance)
if ((m_flags & (ImplementsHasInstance | OverridesHasInstance)) == ImplementsHasInstance)
@@ -69,8 +69,9 @@
bool overridesGetOwnPropertySlot() const { return m_flags & OverridesGetOwnPropertySlot; }
bool overridesVisitChildren() const { return m_flags & OverridesVisitChildren; }
bool overridesGetPropertyNames() const { return m_flags & OverridesGetPropertyNames; }
+ unsigned isFinal() const { return m_flags2 & (IsJSFinalObject >> 8); }
+ unsigned prohibitsPropertyCaching() const { return m_flags2 & (ProhibitsPropertyCaching >> 8); }
unsigned flags() const { return m_flags; }
- unsigned isFinal() const { return m_flags2 && (IsJSFinalObject >> 8); }
static ptrdiff_t flagsOffset()
{