Diff
Modified: trunk/LayoutTests/ChangeLog (235855 => 235856)
--- trunk/LayoutTests/ChangeLog 2018-09-10 19:39:10 UTC (rev 235855)
+++ trunk/LayoutTests/ChangeLog 2018-09-10 20:08:00 UTC (rev 235856)
@@ -1,3 +1,14 @@
+2018-09-10 Andy Estes <[email protected]>
+
+ [Payment Request] Use JSValueInWrappedObject for PaymentResponse's details attribute
+ https://bugs.webkit.org/show_bug.cgi?id=189458
+
+ Reviewed by Youenn Fablet.
+
+ * fast/dom/reference-cycle-leaks.html:
+ * http/tests/paymentrequest/payment-response-reference-cycle-leak.https-expected.txt: Added.
+ * http/tests/paymentrequest/payment-response-reference-cycle-leak.https.html: Added.
+
2018-09-10 Frederic Wang <[email protected]>
[CSSOM View] Handle the scrollingElement in Element::scroll(Left/Top/Width/Height/To)
Modified: trunk/LayoutTests/fast/dom/reference-cycle-leaks.html (235855 => 235856)
--- trunk/LayoutTests/fast/dom/reference-cycle-leaks.html 2018-09-10 19:39:10 UTC (rev 235855)
+++ trunk/LayoutTests/fast/dom/reference-cycle-leaks.html 2018-09-10 20:08:00 UTC (rev 235856)
@@ -125,13 +125,8 @@
// Add another property to the result object that references a leak detection node.
}
-function createPaymentResponseDetailsCycle()
-{
- // FIXME: Need to write this test and reorganize so it can be asynchronous.
- // Get a PaymentResponse, requires simulating a successful payment.
- // Add a property to the details object that references the PaymentResponse.
- // Add another property to the details object that references a leak detection node.
-}
+// PaymentResponse details reference cycle is tested in
+// http/tests/paymentrequest/payment-response-reference-cycle-leak.https.html.
function createRTCStatsReportCycle()
{
Added: trunk/LayoutTests/http/tests/paymentrequest/payment-response-reference-cycle-leak.https-expected.txt (0 => 235856)
--- trunk/LayoutTests/http/tests/paymentrequest/payment-response-reference-cycle-leak.https-expected.txt (rev 0)
+++ trunk/LayoutTests/http/tests/paymentrequest/payment-response-reference-cycle-leak.https-expected.txt 2018-09-10 20:08:00 UTC (rev 235856)
@@ -0,0 +1,3 @@
+
+PASS PaymentResponse should not leak when there is a reference cycle due to the details attribute
+
Added: trunk/LayoutTests/http/tests/paymentrequest/payment-response-reference-cycle-leak.https.html (0 => 235856)
--- trunk/LayoutTests/http/tests/paymentrequest/payment-response-reference-cycle-leak.https.html (rev 0)
+++ trunk/LayoutTests/http/tests/paymentrequest/payment-response-reference-cycle-leak.https.html 2018-09-10 20:08:00 UTC (rev 235856)
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Test for leaks caused by reference cycles that pass through PaymentResponse</title>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+<body>
+<script>
+async function checkForNodeLeaks(testFunction, underlyingClass)
+{
+ // Bump this number as high as we need to, to get reproducible results.
+ const repetitions = 40;
+
+ GCController.collect();
+ const beforeCount = internals.numberOfLiveNodes();
+ for (var i = 0; i < repetitions; ++i)
+ await testFunction();
+ GCController.collect();
+ const leaks = internals.numberOfLiveNodes() - beforeCount;
+
+ if (leaks == repetitions)
+ return "leaked";
+ if (leaks < repetitions / 10)
+ return "did not leak";
+ return "leaked an unexpected number of nodes: " + leaks + " leaks in " + repetitions + " runs";
+}
+
+async function createPaymentResponseDetailsCycle()
+{
+ const applePay = {
+ supportedMethods: "https://apple.com/apple-pay",
+ data: {
+ version: 2,
+ merchantIdentifier: '',
+ merchantCapabilities: ['supports3DS'],
+ supportedNetworks: ['visa', 'masterCard'],
+ countryCode: 'US',
+ },
+ };
+
+ const details = {
+ total: {
+ label: "Total",
+ amount: {
+ currency: "USD",
+ value: "1.00",
+ },
+ },
+ };
+
+ const paymentRequest = new PaymentRequest([applePay], details);
+ await activateThen(async () => {
+ const acceptPromise = paymentRequest.show();
+ internals.mockPaymentCoordinator.acceptPayment();
+ const paymentResponse = await acceptPromise;
+
+ const leakDetectionNode = document.createTextNode("");
+ const details = paymentResponse.details;
+ leakDetectionNode.details = details;
+ details.leakDetectionNode = leakDetectionNode;
+
+ paymentResponse.complete("success");
+ });
+}
+
+promise_test(async t => {
+ const result = await checkForNodeLeaks(createPaymentResponseDetailsCycle);
+ assert_equals(result, 'did not leak');
+}, "PaymentResponse should not leak when there is a reference cycle due to the details attribute");
+
+</script>
Modified: trunk/Source/WebCore/ChangeLog (235855 => 235856)
--- trunk/Source/WebCore/ChangeLog 2018-09-10 19:39:10 UTC (rev 235855)
+++ trunk/Source/WebCore/ChangeLog 2018-09-10 20:08:00 UTC (rev 235856)
@@ -1,3 +1,46 @@
+2018-09-10 Andy Estes <[email protected]>
+
+ [Payment Request] Use JSValueInWrappedObject for PaymentResponse's details attribute
+ https://bugs.webkit.org/show_bug.cgi?id=189458
+
+ Reviewed by Youenn Fablet.
+
+ Test: http/tests/paymentrequest/payment-response-reference-cycle-leak.https.html
+
+ * Modules/applepay/paymentrequest/ApplePayPaymentHandler.cpp:
+ (WebCore::ApplePayPaymentHandler::didAuthorizePayment):
+
+ Created a PaymentResponse::DetailsFunction that converts the ApplePayPayment into a JSValue.
+
+ * Modules/paymentrequest/PaymentRequest.cpp:
+ (WebCore::PaymentRequest::accept):
+
+ Passed detailsFunction into PaymentResponse::create().
+
+ * Modules/paymentrequest/PaymentRequest.h:
+ * Modules/paymentrequest/PaymentResponse.cpp:
+ (WebCore::PaymentResponse::PaymentResponse):
+ * Modules/paymentrequest/PaymentResponse.h:
+ * Modules/paymentrequest/PaymentResponse.idl:
+
+ Removed m_details and replaced it with a DetailsFunction and a cached JSValueInWrappedObject.
+ JSPaymentResponseCustom.cpp uses these values to implement the details attribute getter.
+
+ * Sources.txt:
+ * WebCore.xcodeproj/project.pbxproj:
+ * bindings/js/JSPaymentResponseCustom.cpp: Added.
+ (WebCore::JSPaymentResponse::details const):
+
+ Called PaymentResponse::detailsFunction() to cache a JSValue for the details attribute.
+
+ (WebCore::JSPaymentResponse::visitAdditionalChildren):
+
+ Visited PaymentResponse::cachedDetails().
+
+ * bindings/js/JSServiceWorkerClientCustom.cpp:
+
+ Fixed a missing include issue that cropped up due to unified source shuffling.
+
2018-09-10 Antoine Quint <[email protected]>
[Web Animations] Positive delays of accelerated animations are not respected
Modified: trunk/Source/WebCore/Modules/applepay/paymentrequest/ApplePayPaymentHandler.cpp (235855 => 235856)
--- trunk/Source/WebCore/Modules/applepay/paymentrequest/ApplePayPaymentHandler.cpp 2018-09-10 19:39:10 UTC (rev 235855)
+++ trunk/Source/WebCore/Modules/applepay/paymentrequest/ApplePayPaymentHandler.cpp 2018-09-10 20:08:00 UTC (rev 235856)
@@ -453,9 +453,12 @@
ASSERT(!m_isUpdating);
auto applePayPayment = payment.toApplePayPayment(version());
- auto details = toJSDictionary(*document().execState(), applePayPayment);
- const auto& shippingContact = applePayPayment.shippingContact.value_or(ApplePayPaymentContact());
- m_paymentRequest->accept(WTF::get<URL>(m_identifier).string(), WTFMove(details), convert(shippingContact), shippingContact.localizedName, shippingContact.emailAddress, shippingContact.phoneNumber);
+ auto shippingContact = applePayPayment.shippingContact.value_or(ApplePayPaymentContact());
+ auto detailsFunction = [applePayPayment = WTFMove(applePayPayment)](JSC::ExecState& execState) {
+ return toJSDictionary(execState, applePayPayment);
+ };
+
+ m_paymentRequest->accept(WTF::get<URL>(m_identifier).string(), WTFMove(detailsFunction), convert(shippingContact), shippingContact.localizedName, shippingContact.emailAddress, shippingContact.phoneNumber);
}
void ApplePayPaymentHandler::didSelectShippingMethod(const ApplePaySessionPaymentRequest::ShippingMethod& shippingMethod)
Modified: trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.cpp (235855 => 235856)
--- trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.cpp 2018-09-10 19:39:10 UTC (rev 235855)
+++ trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.cpp 2018-09-10 20:08:00 UTC (rev 235856)
@@ -42,7 +42,6 @@
#include "PaymentMethodData.h"
#include "PaymentOptions.h"
#include "PaymentRequestUpdateEvent.h"
-#include "PaymentResponse.h"
#include "ScriptController.h"
#include <_javascript_Core/JSONObject.h>
#include <_javascript_Core/ThrowScope.h>
@@ -683,14 +682,13 @@
});
}
-void PaymentRequest::accept(const String& methodName, JSC::Strong<JSC::JSObject>&& details, Ref<PaymentAddress>&& shippingAddress, const String& payerName, const String& payerEmail, const String& payerPhone)
+void PaymentRequest::accept(const String& methodName, PaymentResponse::DetailsFunction&& detailsFunction, Ref<PaymentAddress>&& shippingAddress, const String& payerName, const String& payerEmail, const String& payerPhone)
{
ASSERT(m_state == State::Interactive);
- auto response = PaymentResponse::create(*this);
+ auto response = PaymentResponse::create(*this, WTFMove(detailsFunction));
response->setRequestId(m_details.id);
response->setMethodName(methodName);
- response->setDetails(WTFMove(details));
if (m_options.requestShipping) {
response->setShippingAddress(shippingAddress.ptr());
Modified: trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.h (235855 => 235856)
--- trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.h 2018-09-10 19:39:10 UTC (rev 235855)
+++ trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.h 2018-09-10 20:08:00 UTC (rev 235856)
@@ -34,6 +34,7 @@
#include "PaymentDetailsInit.h"
#include "PaymentMethodChangeEvent.h"
#include "PaymentOptions.h"
+#include "PaymentResponse.h"
#include "URL.h"
#include <wtf/Variant.h>
@@ -91,7 +92,7 @@
void paymentMethodChanged(const String& methodName, PaymentMethodChangeEvent::MethodDetailsFunction&&);
ExceptionOr<void> updateWith(UpdateReason, Ref<DOMPromise>&&);
ExceptionOr<void> completeMerchantValidation(Event&, Ref<DOMPromise>&&);
- void accept(const String& methodName, JSC::Strong<JSC::JSObject>&& details, Ref<PaymentAddress>&& shippingAddress, const String& payerName, const String& payerEmail, const String& payerPhone);
+ void accept(const String& methodName, PaymentResponse::DetailsFunction&&, Ref<PaymentAddress>&& shippingAddress, const String& payerName, const String& payerEmail, const String& payerPhone);
void complete(std::optional<PaymentComplete>&&);
void cancel();
Modified: trunk/Source/WebCore/Modules/paymentrequest/PaymentResponse.cpp (235855 => 235856)
--- trunk/Source/WebCore/Modules/paymentrequest/PaymentResponse.cpp 2018-09-10 19:39:10 UTC (rev 235855)
+++ trunk/Source/WebCore/Modules/paymentrequest/PaymentResponse.cpp 2018-09-10 20:08:00 UTC (rev 235856)
@@ -34,9 +34,11 @@
namespace WebCore {
-PaymentResponse::PaymentResponse(PaymentRequest& request)
+PaymentResponse::PaymentResponse(PaymentRequest& request, DetailsFunction&& detailsFunction)
: m_request { request }
+ , m_detailsFunction { WTFMove(detailsFunction) }
{
+ ASSERT(m_detailsFunction);
}
PaymentResponse::~PaymentResponse() = default;
Modified: trunk/Source/WebCore/Modules/paymentrequest/PaymentResponse.h (235855 => 235856)
--- trunk/Source/WebCore/Modules/paymentrequest/PaymentResponse.h 2018-09-10 19:39:10 UTC (rev 235855)
+++ trunk/Source/WebCore/Modules/paymentrequest/PaymentResponse.h 2018-09-10 20:08:00 UTC (rev 235856)
@@ -29,6 +29,7 @@
#include "EventTarget.h"
#include "JSDOMPromiseDeferred.h"
+#include "JSValueInWrappedObject.h"
#include "PaymentAddress.h"
#include "PaymentComplete.h"
@@ -40,9 +41,11 @@
class PaymentResponse final : public RefCounted<PaymentResponse>, public EventTargetWithInlineData {
public:
- static Ref<PaymentResponse> create(PaymentRequest& request)
+ using DetailsFunction = Function<JSC::Strong<JSC::JSObject>(JSC::ExecState&)>;
+
+ static Ref<PaymentResponse> create(PaymentRequest& request, DetailsFunction&& detailsFunction)
{
- return adoptRef(*new PaymentResponse(request));
+ return adoptRef(*new PaymentResponse(request, WTFMove(detailsFunction)));
}
~PaymentResponse();
@@ -53,8 +56,8 @@
const String& methodName() const { return m_methodName; }
void setMethodName(const String& methodName) { m_methodName = methodName; }
- const JSC::Strong<JSC::JSObject>& details() const { return m_details; }
- void setDetails(JSC::Strong<JSC::JSObject>&& details) { m_details = WTFMove(details); }
+ const DetailsFunction& detailsFunction() const { return m_detailsFunction; }
+ JSValueInWrappedObject& cachedDetails() { return m_cachedDetails; }
PaymentAddress* shippingAddress() const { return m_shippingAddress.get(); }
void setShippingAddress(PaymentAddress* shippingAddress) { m_shippingAddress = shippingAddress; }
@@ -78,7 +81,7 @@
using RefCounted<PaymentResponse>::deref;
private:
- explicit PaymentResponse(PaymentRequest&);
+ PaymentResponse(PaymentRequest&, DetailsFunction&&);
// EventTarget
EventTargetInterface eventTargetInterface() const final { return PaymentResponseEventTargetInterfaceType; }
@@ -89,9 +92,8 @@
Ref<PaymentRequest> m_request;
String m_requestId;
String m_methodName;
- // FIXME: The following use of JSC::Strong is incorrect and can lead to storage leaks
- // due to reference cycles; we should use JSValueInWrappedObject instead.
- JSC::Strong<JSC::JSObject> m_details;
+ DetailsFunction m_detailsFunction;
+ JSValueInWrappedObject m_cachedDetails;
RefPtr<PaymentAddress> m_shippingAddress;
String m_shippingOption;
String m_payerName;
Modified: trunk/Source/WebCore/Modules/paymentrequest/PaymentResponse.idl (235855 => 235856)
--- trunk/Source/WebCore/Modules/paymentrequest/PaymentResponse.idl 2018-09-10 19:39:10 UTC (rev 235855)
+++ trunk/Source/WebCore/Modules/paymentrequest/PaymentResponse.idl 2018-09-10 20:08:00 UTC (rev 235856)
@@ -27,6 +27,7 @@
Conditional=PAYMENT_REQUEST,
EnabledBySetting=PaymentRequest,
Exposed=Window,
+ JSCustomMarkFunction,
SecureContext,
] interface PaymentResponse : EventTarget {
serializer = { attribute };
@@ -33,7 +34,7 @@
readonly attribute DOMString requestId;
readonly attribute DOMString methodName;
- readonly attribute object details;
+ [CustomGetter] readonly attribute object details;
readonly attribute PaymentAddress? shippingAddress;
readonly attribute DOMString? shippingOption;
readonly attribute DOMString? payerName;
Modified: trunk/Source/WebCore/Sources.txt (235855 => 235856)
--- trunk/Source/WebCore/Sources.txt 2018-09-10 19:39:10 UTC (rev 235855)
+++ trunk/Source/WebCore/Sources.txt 2018-09-10 20:08:00 UTC (rev 235856)
@@ -430,6 +430,7 @@
bindings/js/JSNodeListCustom.cpp
bindings/js/JSOffscreenCanvasRenderingContext2DCustom.cpp
bindings/js/JSPaymentMethodChangeEventCustom.cpp
+bindings/js/JSPaymentResponseCustom.cpp
bindings/js/JSPerformanceEntryCustom.cpp
bindings/js/JSPerformanceObserverCustom.cpp
bindings/js/JSPluginElementFunctions.cpp
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (235855 => 235856)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2018-09-10 19:39:10 UTC (rev 235855)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2018-09-10 20:08:00 UTC (rev 235856)
@@ -10879,6 +10879,7 @@
A10BB5831484E3A700B2E87A /* RenderSVGRect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderSVGRect.h; sourceTree = "<group>"; };
A10BB5881484E3B300B2E87A /* RenderSVGShape.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderSVGShape.cpp; sourceTree = "<group>"; };
A10BB5891484E3B300B2E87A /* RenderSVGShape.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderSVGShape.h; sourceTree = "<group>"; };
+ A10D6E942144C99800FDD14D /* JSPaymentResponseCustom.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = JSPaymentResponseCustom.cpp; sourceTree = "<group>"; };
A10DBF4618F92317000D70C6 /* PreviewLoaderClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PreviewLoaderClient.h; sourceTree = "<group>"; };
A10DC76814747BAB005E2471 /* StyleGridData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StyleGridData.cpp; sourceTree = "<group>"; };
A10DC76914747BAB005E2471 /* StyleGridData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleGridData.h; sourceTree = "<group>"; };
@@ -19943,6 +19944,7 @@
BCE7B1920D4E86960075A539 /* JSHistoryCustom.cpp */,
410B7E711045FAB000D8224F /* JSMessageEventCustom.cpp */,
A1677E242144532800A08C34 /* JSPaymentMethodChangeEventCustom.cpp */,
+ A10D6E942144C99800FDD14D /* JSPaymentResponseCustom.cpp */,
A85F22081430377D007CC884 /* JSPopStateEventCustom.cpp */,
BC348BBD0DB7F531004ABAB9 /* JSXMLHttpRequestCustom.cpp */,
);
Copied: trunk/Source/WebCore/bindings/js/JSPaymentResponseCustom.cpp (from rev 235855, trunk/Source/WebCore/bindings/js/JSServiceWorkerClientCustom.cpp) (0 => 235856)
--- trunk/Source/WebCore/bindings/js/JSPaymentResponseCustom.cpp (rev 0)
+++ trunk/Source/WebCore/bindings/js/JSPaymentResponseCustom.cpp 2018-09-10 20:08:00 UTC (rev 235856)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSPaymentResponse.h"
+
+#if ENABLE(PAYMENT_REQUEST)
+
+namespace WebCore {
+
+JSC::JSValue JSPaymentResponse::details(JSC::ExecState& state) const
+{
+ return cachedPropertyValue(state, *this, wrapped().cachedDetails(), [this, &state] {
+ return wrapped().detailsFunction()(state).get();
+ });
+}
+
+void JSPaymentResponse::visitAdditionalChildren(JSC::SlotVisitor& visitor)
+{
+ wrapped().cachedDetails().visit(visitor);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(PAYMENT_REQUEST)
Modified: trunk/Source/WebCore/bindings/js/JSServiceWorkerClientCustom.cpp (235855 => 235856)
--- trunk/Source/WebCore/bindings/js/JSServiceWorkerClientCustom.cpp 2018-09-10 19:39:10 UTC (rev 235855)
+++ trunk/Source/WebCore/bindings/js/JSServiceWorkerClientCustom.cpp 2018-09-10 20:08:00 UTC (rev 235856)
@@ -28,6 +28,7 @@
#if ENABLE(SERVICE_WORKER)
#include "JSServiceWorkerClient.h"
+#include "JSDOMBinding.h"
#include "JSServiceWorkerWindowClient.h"
namespace WebCore {