Title: [271873] trunk/Source
Revision
271873
Author
shvaikal...@gmail.com
Date
2021-01-25 18:13:11 -0800 (Mon, 25 Jan 2021)

Log Message

REGRESSION (r270874): Some React Native apps are reported broken on iOS
https://bugs.webkit.org/show_bug.cgi?id=220809

Reviewed by Saam Barati.

Source/_javascript_Core:

r270874 fixed for/in shadowing issue by introducing an invariant: a property
returned by getOwn*PropertyNames() in DontEnumPropertiesMode::Exclude should be
reported as [[Enumerable]] by getOwnPropertySlot(). Otherwise, for/in skips the
property, which causes RN apps to break.

Since there is no way to enforce this invariant for opaque API objects like
JSCallbackObject, this change skips [[Enumerable]] check for them by introducing
GetOwnPropertySlotMayBeWrongAboutDontEnum out of line type info flag.

Also, this patch reverts JSCallbackObject::getOwnPropertySlot() changes of r270874
that are no longer necessary and observable (via Object.getOwnPropertyDescriptor).

* API/JSCallbackObject.h:
* API/JSCallbackObjectFunctions.h:
(JSC::JSCallbackObject<Parent>::getOwnPropertySlot):
* API/tests/testapiScripts/testapi.js:
* runtime/JSObject.cpp:
(JSC::JSObject::hasEnumerableProperty const):
* runtime/JSTypeInfo.h:
(JSC::TypeInfo::getOwnPropertySlotMayBeWrongAboutDontEnum const):

Source/WebCore:

* bridge/runtime_object.h:

Source/WebKit:

* WebProcess/Plugins/Netscape/JSNPObject.h:

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/API/JSCallbackObject.h (271872 => 271873)


--- trunk/Source/_javascript_Core/API/JSCallbackObject.h	2021-01-26 01:33:45 UTC (rev 271872)
+++ trunk/Source/_javascript_Core/API/JSCallbackObject.h	2021-01-26 02:13:11 UTC (rev 271873)
@@ -125,7 +125,7 @@
 class JSCallbackObject final : public Parent {
 public:
     using Base = Parent;
-    static constexpr unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | OverridesGetOwnSpecialPropertyNames | OverridesGetCallData | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | ImplementsHasInstance | ProhibitsPropertyCaching;
+    static constexpr unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | OverridesGetOwnSpecialPropertyNames | OverridesGetCallData | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | ImplementsHasInstance | ProhibitsPropertyCaching | GetOwnPropertySlotMayBeWrongAboutDontEnum;
     static_assert(!(StructureFlags & ImplementsDefaultHasInstance), "using customHasInstance");
 
     ~JSCallbackObject();

Modified: trunk/Source/_javascript_Core/API/JSCallbackObjectFunctions.h (271872 => 271873)


--- trunk/Source/_javascript_Core/API/JSCallbackObjectFunctions.h	2021-01-26 01:33:45 UTC (rev 271872)
+++ trunk/Source/_javascript_Core/API/JSCallbackObjectFunctions.h	2021-01-26 02:13:11 UTC (rev 271873)
@@ -162,9 +162,7 @@
     RefPtr<OpaqueJSString> propertyNameRef;
     
     if (StringImpl* name = propertyName.uid()) {
-        // FIXME: Set ReadOnly conditionally, based on setProperty presence in class inheritance chain.
-        // https://bugs.webkit.org/show_bug.cgi?id=219924
-        unsigned attributes = static_cast<unsigned>(PropertyAttribute::ReadOnly);
+        unsigned attributes = PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum;
         for (JSClassRef jsClass = thisObject->classRef(); jsClass; jsClass = jsClass->parentClass) {
             // optional optimization to bypass getProperty in cases when we only need to know if the property exists
             if (JSObjectHasPropertyCallback hasProperty = jsClass->hasProperty) {
@@ -196,13 +194,11 @@
             }
             
             if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(globalObject)) {
-                if (StaticValueEntry* entry = staticValues->get(name)) {
-                    // FIXME: getStaticValue() performs the same loop & checks just to acquire `entry`.
-                    // https://bugs.webkit.org/show_bug.cgi?id=219925
+                if (staticValues->contains(name)) {
                     JSValue value = thisObject->getStaticValue(globalObject, propertyName);
                     RETURN_IF_EXCEPTION(scope, false);
                     if (value) {
-                        slot.setValue(thisObject, entry->attributes, value);
+                        slot.setValue(thisObject, attributes, value);
                         return true;
                     }
                 }
@@ -209,8 +205,8 @@
             }
             
             if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(globalObject)) {
-                if (StaticFunctionEntry* entry = staticFunctions->get(name)) {
-                    slot.setCustom(thisObject, entry->attributes, getStaticFunctionGetter());
+                if (staticFunctions->contains(name)) {
+                    slot.setCustom(thisObject, attributes, getStaticFunctionGetter());
                     return true;
                 }
             }

Modified: trunk/Source/_javascript_Core/API/tests/testapiScripts/testapi.js (271872 => 271873)


--- trunk/Source/_javascript_Core/API/tests/testapiScripts/testapi.js	2021-01-26 01:33:45 UTC (rev 271872)
+++ trunk/Source/_javascript_Core/API/tests/testapiScripts/testapi.js	2021-01-26 02:13:11 UTC (rev 271873)
@@ -144,12 +144,12 @@
 shouldBe('typeof alwaysOneDescriptor', "object");
 shouldBe('alwaysOneDescriptor.value', MyObject.alwaysOne);
 shouldBe('alwaysOneDescriptor.configurable', true);
-shouldBe('alwaysOneDescriptor.enumerable', true);
+shouldBe('alwaysOneDescriptor.enumerable', false); // Actually it is.
 var cantFindDescriptor = Object.getOwnPropertyDescriptor(MyObject, "cantFind");
 shouldBe('typeof cantFindDescriptor', "object");
 shouldBe('cantFindDescriptor.value', MyObject.cantFind);
 shouldBe('cantFindDescriptor.configurable', true);
-shouldBe('cantFindDescriptor.enumerable', true);
+shouldBe('cantFindDescriptor.enumerable', false);
 try {
     // If getOwnPropertyDescriptor() returned an access descriptor, this wouldn't throw.
     Object.getOwnPropertyDescriptor(MyObject, "throwOnGet");
@@ -160,7 +160,7 @@
 shouldBe('typeof myPropertyNameDescriptor', "object");
 shouldBe('myPropertyNameDescriptor.value', MyObject.myPropertyName);
 shouldBe('myPropertyNameDescriptor.configurable', true);
-shouldBe('myPropertyNameDescriptor.enumerable', true);
+shouldBe('myPropertyNameDescriptor.enumerable', false); // Actually it is.
 try {
     // if getOwnPropertyDescriptor() returned an access descriptor, this wouldn't throw.
     Object.getOwnPropertyDescriptor(MyObject, "hasPropertyLie");
@@ -247,23 +247,23 @@
 shouldBe('typeof baseDupDescriptor', "object");
 shouldBe('baseDupDescriptor.value', derived.baseDup);
 shouldBe('baseDupDescriptor.configurable', true);
-shouldBe('baseDupDescriptor.enumerable', true);
+shouldBe('baseDupDescriptor.enumerable', false);
 var baseOnlyDescriptor = Object.getOwnPropertyDescriptor(derived, "baseOnly");
 shouldBe('typeof baseOnlyDescriptor', "object");
 shouldBe('baseOnlyDescriptor.value', derived.baseOnly);
 shouldBe('baseOnlyDescriptor.configurable', true);
-shouldBe('baseOnlyDescriptor.enumerable', true);
+shouldBe('baseOnlyDescriptor.enumerable', false);
 shouldBe('Object.getOwnPropertyDescriptor(derived, "protoOnly")', undefined);
 var protoDupDescriptor = Object.getOwnPropertyDescriptor(derived, "protoDup");
 shouldBe('typeof protoDupDescriptor', "object");
 shouldBe('protoDupDescriptor.value', derived.protoDup);
 shouldBe('protoDupDescriptor.configurable', true);
-shouldBe('protoDupDescriptor.enumerable', true);
+shouldBe('protoDupDescriptor.enumerable', false);
 var derivedOnlyDescriptor = Object.getOwnPropertyDescriptor(derived, "derivedOnly");
 shouldBe('typeof derivedOnlyDescriptor', "object");
 shouldBe('derivedOnlyDescriptor.value', derived.derivedOnly);
 shouldBe('derivedOnlyDescriptor.configurable', true);
-shouldBe('derivedOnlyDescriptor.enumerable', true);
+shouldBe('derivedOnlyDescriptor.enumerable', false);
 
 shouldBe("undefined instanceof MyObject", false);
 EvilExceptionObject.hasInstance = function f() { return f(); };

Modified: trunk/Source/_javascript_Core/ChangeLog (271872 => 271873)


--- trunk/Source/_javascript_Core/ChangeLog	2021-01-26 01:33:45 UTC (rev 271872)
+++ trunk/Source/_javascript_Core/ChangeLog	2021-01-26 02:13:11 UTC (rev 271873)
@@ -1,3 +1,31 @@
+2021-01-25  Alexey Shvayka  <shvaikal...@gmail.com>
+
+        REGRESSION (r270874): Some React Native apps are reported broken on iOS
+        https://bugs.webkit.org/show_bug.cgi?id=220809
+
+        Reviewed by Saam Barati.
+
+        r270874 fixed for/in shadowing issue by introducing an invariant: a property
+        returned by getOwn*PropertyNames() in DontEnumPropertiesMode::Exclude should be
+        reported as [[Enumerable]] by getOwnPropertySlot(). Otherwise, for/in skips the
+        property, which causes RN apps to break.
+
+        Since there is no way to enforce this invariant for opaque API objects like
+        JSCallbackObject, this change skips [[Enumerable]] check for them by introducing
+        GetOwnPropertySlotMayBeWrongAboutDontEnum out of line type info flag.
+
+        Also, this patch reverts JSCallbackObject::getOwnPropertySlot() changes of r270874
+        that are no longer necessary and observable (via Object.getOwnPropertyDescriptor).
+
+        * API/JSCallbackObject.h:
+        * API/JSCallbackObjectFunctions.h:
+        (JSC::JSCallbackObject<Parent>::getOwnPropertySlot):
+        * API/tests/testapiScripts/testapi.js:
+        * runtime/JSObject.cpp:
+        (JSC::JSObject::hasEnumerableProperty const):
+        * runtime/JSTypeInfo.h:
+        (JSC::TypeInfo::getOwnPropertySlotMayBeWrongAboutDontEnum const):
+
 2021-01-25  Chris Dumez  <cdu...@apple.com>
 
         Update availability annotations to match the macOS 11.0 and iOS 14.0 GM SDKs

Modified: trunk/Source/_javascript_Core/runtime/JSObject.cpp (271872 => 271873)


--- trunk/Source/_javascript_Core/runtime/JSObject.cpp	2021-01-26 01:33:45 UTC (rev 271872)
+++ trunk/Source/_javascript_Core/runtime/JSObject.cpp	2021-01-26 02:13:11 UTC (rev 271873)
@@ -1998,7 +1998,9 @@
     PropertySlot slot(this, PropertySlot::InternalMethodType::GetOwnProperty);
     bool hasProperty = const_cast<JSObject*>(this)->getPropertySlot(globalObject, propertyName, slot);
     RETURN_IF_EXCEPTION(scope, false);
-    return hasProperty && !(slot.attributes() & PropertyAttribute::DontEnum);
+    if (!hasProperty)
+        return false;
+    return !(slot.attributes() & PropertyAttribute::DontEnum) || (slot.slotBase() && slot.slotBase()->structure(vm)->typeInfo().getOwnPropertySlotMayBeWrongAboutDontEnum());
 }
 
 bool JSObject::hasEnumerableProperty(JSGlobalObject* globalObject, unsigned propertyName) const
@@ -2008,7 +2010,9 @@
     PropertySlot slot(this, PropertySlot::InternalMethodType::GetOwnProperty);
     bool hasProperty = const_cast<JSObject*>(this)->getPropertySlot(globalObject, propertyName, slot);
     RETURN_IF_EXCEPTION(scope, false);
-    return hasProperty && !(slot.attributes() & PropertyAttribute::DontEnum);
+    if (!hasProperty)
+        return false;
+    return !(slot.attributes() & PropertyAttribute::DontEnum) || (slot.slotBase() && slot.slotBase()->structure(vm)->typeInfo().getOwnPropertySlotMayBeWrongAboutDontEnum());
 }
 
 // ECMA 8.6.2.5

Modified: trunk/Source/_javascript_Core/runtime/JSTypeInfo.h (271872 => 271873)


--- trunk/Source/_javascript_Core/runtime/JSTypeInfo.h	2021-01-26 01:33:45 UTC (rev 271872)
+++ trunk/Source/_javascript_Core/runtime/JSTypeInfo.h	2021-01-26 02:13:11 UTC (rev 271873)
@@ -59,6 +59,7 @@
 static constexpr unsigned StructureIsImmortal = 1 << 17;
 static constexpr unsigned HasPutPropertySecurityCheck = 1 << 18;
 static constexpr unsigned OverridesGetPrototype = 1 << 19;
+static constexpr unsigned GetOwnPropertySlotMayBeWrongAboutDontEnum = 1 << 20;
 
 static constexpr unsigned numberOfInlineBits = 8;
 static constexpr unsigned OverridesGetPrototypeOutOfLine = OverridesGetPrototype >> numberOfInlineBits;
@@ -105,6 +106,7 @@
     bool prohibitsPropertyCaching() const { return isSetOnFlags2<ProhibitsPropertyCaching>(); }
     bool getOwnPropertySlotIsImpure() const { return isSetOnFlags2<GetOwnPropertySlotIsImpure>(); }
     bool getOwnPropertySlotIsImpureForPropertyAbsence() const { return isSetOnFlags2<GetOwnPropertySlotIsImpureForPropertyAbsence>(); }
+    bool getOwnPropertySlotMayBeWrongAboutDontEnum() const { return isSetOnFlags2<GetOwnPropertySlotMayBeWrongAboutDontEnum>(); }
     bool hasPutPropertySecurityCheck() const { return isSetOnFlags2<HasPutPropertySecurityCheck>(); }
     bool newImpurePropertyFiresWatchpoints() const { return isSetOnFlags2<NewImpurePropertyFiresWatchpoints>(); }
     bool isImmutablePrototypeExoticObject() const { return isSetOnFlags2<IsImmutablePrototypeExoticObject>(); }

Modified: trunk/Source/WebCore/ChangeLog (271872 => 271873)


--- trunk/Source/WebCore/ChangeLog	2021-01-26 01:33:45 UTC (rev 271872)
+++ trunk/Source/WebCore/ChangeLog	2021-01-26 02:13:11 UTC (rev 271873)
@@ -1,3 +1,12 @@
+2021-01-25  Alexey Shvayka  <shvaikal...@gmail.com>
+
+        REGRESSION (r270874): Some React Native apps are reported broken on iOS
+        https://bugs.webkit.org/show_bug.cgi?id=220809
+
+        Reviewed by Saam Barati.
+
+        * bridge/runtime_object.h:
+
 2021-01-25  Chris Dumez  <cdu...@apple.com>
 
         Unreviewed, add missing header includes to address build issues.

Modified: trunk/Source/WebCore/bridge/runtime_object.h (271872 => 271873)


--- trunk/Source/WebCore/bridge/runtime_object.h	2021-01-26 01:33:45 UTC (rev 271872)
+++ trunk/Source/WebCore/bridge/runtime_object.h	2021-01-26 02:13:11 UTC (rev 271873)
@@ -37,7 +37,7 @@
 class WEBCORE_EXPORT RuntimeObject : public JSNonFinalObject {
 public:
     using Base = JSNonFinalObject;
-    static constexpr unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | OverridesGetOwnPropertyNames | OverridesGetCallData;
+    static constexpr unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | OverridesGetOwnPropertyNames | OverridesGetCallData | GetOwnPropertySlotMayBeWrongAboutDontEnum;
     static constexpr bool needsDestruction = true;
 
     template<typename CellType, JSC::SubspaceAccess>

Modified: trunk/Source/WebKit/ChangeLog (271872 => 271873)


--- trunk/Source/WebKit/ChangeLog	2021-01-26 01:33:45 UTC (rev 271872)
+++ trunk/Source/WebKit/ChangeLog	2021-01-26 02:13:11 UTC (rev 271873)
@@ -1,3 +1,12 @@
+2021-01-25  Alexey Shvayka  <shvaikal...@gmail.com>
+
+        REGRESSION (r270874): Some React Native apps are reported broken on iOS
+        https://bugs.webkit.org/show_bug.cgi?id=220809
+
+        Reviewed by Saam Barati.
+
+        * WebProcess/Plugins/Netscape/JSNPObject.h:
+
 2021-01-25  Chris Dumez  <cdu...@apple.com>
 
         Unreviewed, add missing header includes to address build issues.

Modified: trunk/Source/WebKit/WebProcess/Plugins/Netscape/JSNPObject.h (271872 => 271873)


--- trunk/Source/WebKit/WebProcess/Plugins/Netscape/JSNPObject.h	2021-01-26 01:33:45 UTC (rev 271872)
+++ trunk/Source/WebKit/WebProcess/Plugins/Netscape/JSNPObject.h	2021-01-26 02:13:11 UTC (rev 271873)
@@ -44,7 +44,7 @@
 class JSNPObject final : public JSC::JSDestructibleObject {
 public:
     using Base = JSC::JSDestructibleObject;
-    static constexpr unsigned StructureFlags = Base::StructureFlags | JSC::OverridesGetOwnPropertySlot | JSC::OverridesGetOwnPropertyNames | JSC::OverridesGetCallData;
+    static constexpr unsigned StructureFlags = Base::StructureFlags | JSC::OverridesGetOwnPropertySlot | JSC::OverridesGetOwnPropertyNames | JSC::OverridesGetCallData | JSC::GetOwnPropertySlotMayBeWrongAboutDontEnum;
 
     template<typename CellType, JSC::SubspaceAccess>
     static JSC::IsoSubspace* subspaceFor(JSC::VM& vm)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to