Title: [280463] trunk
Revision
280463
Author
tzaga...@apple.com
Date
2021-07-29 19:00:36 -0700 (Thu, 29 Jul 2021)

Log Message

definePropertyOnReceiver should check if receiver canPerformFastPutInline
https://bugs.webkit.org/show_bug.cgi?id=227963
<rdar://80259710>

Reviewed by Alexey Shvayka.

JSTests:

* stress/reflect-set-custom-value.js: Added.

Source/_javascript_Core:

definePropertyOnReceiver has a fast path if the slot is not opaque and the receiver doesn't
have a custom defineOwnProperty implementation, in which case it calls putInlineFast (and
transitively putDirectInternal<PutModePut>). The issue is that putDirectInternal does not
handle customValues correctly: it just overwrites the property without changing the attributes.
To fix that, we should first check if the property might be a custom value, and if that's the case
we now call `definePropertyOnReceiverSlow`, which has been updated to handle custom values correctly.
I also added assertions to putInlineFastReplacingStaticPropertyIfNeeded and putDirectInternal
to make sure we don't accidentally overwrite custom values in the future.

* runtime/JSObject.cpp:
(JSC::definePropertyOnReceiverSlow):
(JSC::JSObject::definePropertyOnReceiver):
(JSC::JSObject::putInlineFastReplacingStaticPropertyIfNeeded):
* runtime/JSObjectInlines.h:
(JSC::JSObject::putDirectInternal):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (280462 => 280463)


--- trunk/JSTests/ChangeLog	2021-07-30 01:51:18 UTC (rev 280462)
+++ trunk/JSTests/ChangeLog	2021-07-30 02:00:36 UTC (rev 280463)
@@ -1,3 +1,13 @@
+2021-07-29  Tadeu Zagallo  <tzaga...@apple.com>
+
+        definePropertyOnReceiver should check if receiver canPerformFastPutInline
+        https://bugs.webkit.org/show_bug.cgi?id=227963
+        <rdar://80259710>
+
+        Reviewed by Alexey Shvayka.
+
+        * stress/reflect-set-custom-value.js: Added.
+
 2021-07-29  Yusuke Suzuki  <ysuz...@apple.com> and Alexey Shvayka  <shvaikal...@gmail.com>
 
         [JSC] Legacy RegExp fields should be accessors

Added: trunk/JSTests/stress/reflect-set-custom-value.js (0 => 280463)


--- trunk/JSTests/stress/reflect-set-custom-value.js	                        (rev 0)
+++ trunk/JSTests/stress/reflect-set-custom-value.js	2021-07-30 02:00:36 UTC (rev 280463)
@@ -0,0 +1,3 @@
+const testGetterSetter = $vm.createCustomTestGetterSetter();
+Reflect.set({}, 'customValue', 'foo', testGetterSetter);
+testGetterSetter.customValue = 42;

Modified: trunk/Source/_javascript_Core/ChangeLog (280462 => 280463)


--- trunk/Source/_javascript_Core/ChangeLog	2021-07-30 01:51:18 UTC (rev 280462)
+++ trunk/Source/_javascript_Core/ChangeLog	2021-07-30 02:00:36 UTC (rev 280463)
@@ -1,3 +1,27 @@
+2021-07-29  Tadeu Zagallo  <tzaga...@apple.com>
+
+        definePropertyOnReceiver should check if receiver canPerformFastPutInline
+        https://bugs.webkit.org/show_bug.cgi?id=227963
+        <rdar://80259710>
+
+        Reviewed by Alexey Shvayka.
+
+        definePropertyOnReceiver has a fast path if the slot is not opaque and the receiver doesn't
+        have a custom defineOwnProperty implementation, in which case it calls putInlineFast (and
+        transitively putDirectInternal<PutModePut>). The issue is that putDirectInternal does not
+        handle customValues correctly: it just overwrites the property without changing the attributes.
+        To fix that, we should first check if the property might be a custom value, and if that's the case
+        we now call `definePropertyOnReceiverSlow`, which has been updated to handle custom values correctly.
+        I also added assertions to putInlineFastReplacingStaticPropertyIfNeeded and putDirectInternal
+        to make sure we don't accidentally overwrite custom values in the future.
+
+        * runtime/JSObject.cpp:
+        (JSC::definePropertyOnReceiverSlow):
+        (JSC::JSObject::definePropertyOnReceiver):
+        (JSC::JSObject::putInlineFastReplacingStaticPropertyIfNeeded):
+        * runtime/JSObjectInlines.h:
+        (JSC::JSObject::putDirectInternal):
+
 2021-07-29  Yusuke Suzuki  <ysuz...@apple.com> and Alexey Shvayka  <shvaikal...@gmail.com>
 
         [JSC] Legacy RegExp fields should be accessors

Modified: trunk/Source/_javascript_Core/runtime/JSObject.cpp (280462 => 280463)


--- trunk/Source/_javascript_Core/runtime/JSObject.cpp	2021-07-30 01:51:18 UTC (rev 280462)
+++ trunk/Source/_javascript_Core/runtime/JSObject.cpp	2021-07-30 02:00:36 UTC (rev 280463)
@@ -874,6 +874,12 @@
         if (slot.attributes() & PropertyAttribute::ReadOnlyOrAccessorOrCustomAccessor)
             return typeError(globalObject, scope, shouldThrow, ReadonlyPropertyWriteError);
 
+        if (slot.attributes() & PropertyAttribute::CustomValue) {
+            PutPropertySlot::PutValueFunc customSetter = slot.customSetter();
+            if (customSetter)
+                RELEASE_AND_RETURN(scope, customSetter(receiver->globalObject(vm), JSValue::encode(receiver), JSValue::encode(value), propertyName));
+        }
+
         PropertyDescriptor descriptor;
         descriptor.setValue(value);
         RELEASE_AND_RETURN(scope, receiver->methodTable(vm)->defineOwnProperty(receiver, globalObject, propertyName, descriptor, shouldThrow));
@@ -903,6 +909,12 @@
             return definePropertyOnReceiverSlow(globalObject, propertyName, value, receiver, slot.isStrictMode());
     }
 
+    if (receiver->structure(vm)->hasCustomGetterSetterProperties()) {
+        unsigned attributes;
+        if (receiver->getDirectOffset(vm, propertyName, attributes) != invalidOffset && (attributes & PropertyAttribute::CustomValue))
+            return definePropertyOnReceiverSlow(globalObject, propertyName, value, receiver, slot.isStrictMode());
+    }
+
     if (UNLIKELY(receiver->hasNonReifiedStaticProperties(vm)))
         return receiver->putInlineFastReplacingStaticPropertyIfNeeded(globalObject, propertyName, value, slot);
     return receiver->putInlineFast(globalObject, propertyName, value, slot);
@@ -925,7 +937,8 @@
                 return typeError(globalObject, scope, slot.isStrictMode(), ReadonlyPropertyWriteError);
             }
             // Avoid PutModePut because it fails for non-extensible structures.
-            putDirect(vm, propertyName, value, attributesForStructure(entry->value->attributes()) & ~PropertyAttribute::CustomValue, slot);
+            ASSERT(!(entry->value->attributes() & PropertyAttribute::CustomValue));
+            putDirect(vm, propertyName, value, attributesForStructure(entry->value->attributes()), slot);
             return true;
         }
     }

Modified: trunk/Source/_javascript_Core/runtime/JSObjectInlines.h (280462 => 280463)


--- trunk/Source/_javascript_Core/runtime/JSObjectInlines.h	2021-07-30 01:51:18 UTC (rev 280462)
+++ trunk/Source/_javascript_Core/runtime/JSObjectInlines.h	2021-07-30 02:00:36 UTC (rev 280463)
@@ -282,7 +282,7 @@
     VM& vm = getVM(globalObject);
     auto scope = DECLARE_THROW_SCOPE(vm);
 
-    // FIXME: For a failure due to non-extensible structure, the error message is misleading.
+    // FIXME: For a failure due to non-extensible structure, the error message is misleading
     if (!putDirectInternal<PutModePut>(vm, propertyName, value, 0, slot))
         return typeError(globalObject, scope, slot.isStrictMode(), ReadonlyPropertyWriteError);
     return true;
@@ -345,8 +345,10 @@
             // https://bugs.webkit.org/show_bug.cgi?id=214342
             if (mode == PutModeDefineOwnProperty && (attributes != currentAttributes || (attributes & PropertyAttribute::AccessorOrCustomAccessorOrValue)))
                 setStructure(vm, Structure::attributeChangeTransition(vm, structure, propertyName, attributes));
-            else
+            else {
+                ASSERT(!(currentAttributes & PropertyAttribute::AccessorOrCustomAccessorOrValue));
                 slot.setExistingProperty(this, offset);
+            }
 
             return true;
         }
@@ -403,8 +405,10 @@
             // This allows adaptive watchpoints to observe if the new structure is the one we want.
             DeferredStructureTransitionWatchpointFire deferredWatchpointFire(vm, structure);
             setStructure(vm, Structure::attributeChangeTransition(vm, structure, propertyName, attributes, &deferredWatchpointFire));
-        } else
+        } else {
+            ASSERT(!(currentAttributes & PropertyAttribute::AccessorOrCustomAccessorOrValue));
             slot.setExistingProperty(this, offset);
+        }
 
         return true;
     }
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to