Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (277223 => 277224)
--- trunk/Source/_javascript_Core/ChangeLog 2021-05-08 04:32:51 UTC (rev 277223)
+++ trunk/Source/_javascript_Core/ChangeLog 2021-05-08 07:32:45 UTC (rev 277224)
@@ -1,3 +1,21 @@
+2021-05-08 Ross Kirsling <[email protected]>
+
+ Introduce JSObject::getIfPropertyExists helper
+ https://bugs.webkit.org/show_bug.cgi?id=225553
+
+ Reviewed by Alexey Shvayka.
+
+ Suggested by Alexey during review of r277221.
+ ArrayPrototype also has a "Has-guarded Get", so it's helpful for JSObject to house this functionality.
+
+ * runtime/ArrayPrototype.cpp:
+ (JSC::getProperty):
+ * runtime/ErrorInstance.cpp:
+ (JSC::ErrorInstance::finishCreation):
+ * runtime/JSObject.h:
+ * runtime/JSObjectInlines.h:
+ (JSC::JSObject::getIfPropertyExists):
+
2021-05-07 Ross Kirsling <[email protected]>
[JSC] Error#cause must recognize explicit undefined
Modified: trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp (277223 => 277224)
--- trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp 2021-05-08 04:32:51 UTC (rev 277223)
+++ trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp 2021-05-08 07:32:45 UTC (rev 277224)
@@ -147,22 +147,14 @@
{
VM& vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
-
+
if (JSValue result = object->tryGetIndexQuickly(index))
return result;
- // We want to perform get and has in the same operation.
- // We can only do so when this behavior is not observable. The
- // only time it is observable is when we encounter an opaque objects (ProxyObject and JSModuleNamespaceObject)
- // somewhere in the prototype chain.
- PropertySlot slot(object, PropertySlot::InternalMethodType::HasProperty);
- bool hasProperty = object->getPropertySlot(globalObject, index, slot);
- EXCEPTION_ASSERT(!scope.exception() || !hasProperty);
- if (!hasProperty)
- return { };
- if (UNLIKELY(slot.isTaintedByOpaqueObject()))
- RELEASE_AND_RETURN(scope, object->get(globalObject, index));
- RELEASE_AND_RETURN(scope, slot.getValue(globalObject, index));
+ // Don't return undefined if the property is not found.
+ auto property = object->getIfPropertyExists(globalObject, Identifier::from(vm, index));
+ RETURN_IF_EXCEPTION(scope, { });
+ return property.valueOr(JSValue());
}
static ALWAYS_INLINE void setLength(JSGlobalObject* globalObject, VM& vm, JSObject* obj, uint64_t value)
Modified: trunk/Source/_javascript_Core/runtime/ErrorInstance.cpp (277223 => 277224)
--- trunk/Source/_javascript_Core/runtime/ErrorInstance.cpp 2021-05-08 04:32:51 UTC (rev 277223)
+++ trunk/Source/_javascript_Core/runtime/ErrorInstance.cpp 2021-05-08 07:32:45 UTC (rev 277224)
@@ -135,22 +135,12 @@
if (!messageWithSource.isNull())
putDirect(vm, vm.propertyNames->message, jsString(vm, messageWithSource), static_cast<unsigned>(PropertyAttribute::DontEnum));
- // Since `throw undefined;` is valid, the spec specially recognizes the case where `cause` is an explicit undefined.
if (options.isObject()) {
- auto object = asObject(options);
-
- PropertySlot slot(object, PropertySlot::InternalMethodType::HasProperty);
- bool hasProperty = object->getPropertySlot(globalObject, vm.propertyNames->cause, slot);
+ // Since `throw undefined;` is valid, we need to distinguish the case where `cause` is an explicit undefined.
+ auto cause = asObject(options)->getIfPropertyExists(globalObject, vm.propertyNames->cause);
RETURN_IF_EXCEPTION(scope, void());
-
- if (hasProperty) {
- JSValue cause = UNLIKELY(slot.isTaintedByOpaqueObject())
- ? object->get(globalObject, vm.propertyNames->cause)
- : slot.getValue(globalObject, vm.propertyNames->cause);
- RETURN_IF_EXCEPTION(scope, void());
-
- putDirect(vm, vm.propertyNames->cause, cause, static_cast<unsigned>(PropertyAttribute::DontEnum));
- }
+ if (cause)
+ putDirect(vm, vm.propertyNames->cause, cause.value(), static_cast<unsigned>(PropertyAttribute::DontEnum));
}
}
Modified: trunk/Source/_javascript_Core/runtime/JSObject.h (277223 => 277224)
--- trunk/Source/_javascript_Core/runtime/JSObject.h 2021-05-08 04:32:51 UTC (rev 277223)
+++ trunk/Source/_javascript_Core/runtime/JSObject.h 2021-05-08 07:32:45 UTC (rev 277224)
@@ -162,6 +162,8 @@
template<typename CallbackWhenNoException> typename std::result_of<CallbackWhenNoException(bool, PropertySlot&)>::type getPropertySlot(JSGlobalObject*, PropertyName, CallbackWhenNoException) const;
template<typename CallbackWhenNoException> typename std::result_of<CallbackWhenNoException(bool, PropertySlot&)>::type getPropertySlot(JSGlobalObject*, PropertyName, PropertySlot&, CallbackWhenNoException) const;
+ Optional<JSValue> getIfPropertyExists(JSGlobalObject*, PropertyName);
+
private:
static bool getOwnPropertySlotImpl(JSObject*, JSGlobalObject*, PropertyName, PropertySlot&);
public:
Modified: trunk/Source/_javascript_Core/runtime/JSObjectInlines.h (277223 => 277224)
--- trunk/Source/_javascript_Core/runtime/JSObjectInlines.h 2021-05-08 04:32:51 UTC (rev 277223)
+++ trunk/Source/_javascript_Core/runtime/JSObjectInlines.h 2021-05-08 07:32:45 UTC (rev 277224)
@@ -191,6 +191,23 @@
return JSObject::getOwnPropertySlot(this, globalObject, propertyName, slot);
}
+inline Optional<JSValue> JSObject::getIfPropertyExists(JSGlobalObject* globalObject, PropertyName propertyName)
+{
+ VM& vm = globalObject->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ PropertySlot slot(this, PropertySlot::InternalMethodType::HasProperty);
+ bool hasProperty = getPropertySlot(globalObject, propertyName, slot);
+ EXCEPTION_ASSERT_UNUSED(scope, !scope.exception() || !hasProperty);
+
+ if (!hasProperty)
+ return WTF::nullopt;
+
+ return UNLIKELY(slot.isTaintedByOpaqueObject())
+ ? get(globalObject, propertyName)
+ : slot.getValue(globalObject, propertyName);
+}
+
inline bool JSObject::mayInterceptIndexedAccesses(VM& vm)
{
return structure(vm)->mayInterceptIndexedAccesses();