WebKit Bugzilla
Attachment 348654 Details for
Bug 189201
: IDBRequest and IDBCursor should not hold strong references to JSValue
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-189201-20180831111812.patch (text/plain), 23.36 KB, created by
youenn fablet
on 2018-08-31 11:18:13 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
youenn fablet
Created:
2018-08-31 11:18:13 PDT
Size:
23.36 KB
patch
obsolete
>Subversion Revision: 235525 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index a5427ec267eb37f0e9f0df6d4d0d657968f680a4..2d6bd06636ec3952f093f9e03e0d79beb7690056 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,43 @@ >+2018-08-31 Youenn Fablet <youenn@apple.com> >+ >+ IDBRequest and IDBCursor should not hold strong references to JSValue >+ https://bugs.webkit.org/show_bug.cgi?id=189201 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ IDBRequest and IDBCursor previously were keeping strong references to JS objects. >+ This made it possible to create reference cycles that GC cannot break. >+ Instead, replace JS Strong with JSValueInWrappedObject and mark every JS object whenthe DOM object is being visited. >+ This requires to mark JSIDBRequest as JSCustomMarkFunction. >+ >+ Test: http/tests/IndexedDB/collect-IDB-cursor.https.html >+ >+ * Modules/indexeddb/IDBCursor.cpp: >+ (WebCore::IDBCursor::update): >+ (WebCore::IDBCursor::deleteFunction): >+ (WebCore::IDBCursor::setGetResult): >+ * Modules/indexeddb/IDBCursor.h: >+ (WebCore::IDBCursor::currentKey): >+ (WebCore::IDBCursor::currentPrimaryKey): >+ (WebCore::IDBCursor::currentValue): >+ (WebCore::IDBCursor::key const): >+ (WebCore::IDBCursor::primaryKey const): >+ (WebCore::IDBCursor::value const): >+ * Modules/indexeddb/IDBRequest.cpp: >+ (WebCore::IDBRequest::result const): >+ (WebCore::IDBRequest::setResult): >+ (WebCore::IDBRequest::setResultToStructuredClone): >+ (WebCore::IDBRequest::setResultToUndefined): >+ (WebCore::IDBRequest::resultValue): >+ * Modules/indexeddb/IDBRequest.h: >+ * Modules/indexeddb/IDBRequest.idl: >+ * Sources.txt: >+ * WebCore.xcodeproj/project.pbxproj: >+ * bindings/js/JSIDBCursorCustom.cpp: >+ (WebCore::JSIDBCursor::visitAdditionalChildren): >+ * bindings/js/JSIDBRequestCustom.cpp: Added. >+ (WebCore::JSIDBRequest::visitAdditionalChildren): >+ > 2018-08-30 Olivia Barnett <obarnett@apple.com> > > REGRESSION(r235489): fast/dom/navigator-detached-no-crash.html crashes under Navigator::share >diff --git a/Source/WebCore/Modules/indexeddb/IDBCursor.cpp b/Source/WebCore/Modules/indexeddb/IDBCursor.cpp >index 9b59cffce546669e8fce3f4642fe1a1bb740c93a..99d4b46695933f6ce6ab75d586e8a754ee80a658 100644 >--- a/Source/WebCore/Modules/indexeddb/IDBCursor.cpp >+++ b/Source/WebCore/Modules/indexeddb/IDBCursor.cpp >@@ -128,7 +128,7 @@ ExceptionOr<Ref<IDBRequest>> IDBCursor::update(ExecState& state, JSValue value) > return Exception { DataError, "Failed to execute 'update' on 'IDBCursor': The effective object store of this cursor uses in-line keys and evaluating the key path of the value parameter results in a different value than the cursor's effective key."_s }; > } > >- auto putResult = effectiveObjectStore().putForCursorUpdate(state, value, m_currentPrimaryKey.get()); >+ auto putResult = effectiveObjectStore().putForCursorUpdate(state, value, m_currentPrimaryKey); > if (putResult.hasException()) > return putResult.releaseException(); > >@@ -299,7 +299,7 @@ ExceptionOr<Ref<WebCore::IDBRequest>> IDBCursor::deleteFunction(ExecState& state > if (!isKeyCursorWithValue()) > return Exception { InvalidStateError, "Failed to execute 'delete' on 'IDBCursor': The cursor is a key cursor."_s }; > >- auto result = effectiveObjectStore().deleteFunction(state, m_currentPrimaryKey.get()); >+ auto result = effectiveObjectStore().deleteFunction(state, m_currentPrimaryKey); > if (result.hasException()) > return result.releaseException(); > >@@ -333,17 +333,15 @@ void IDBCursor::setGetResult(IDBRequest& request, const IDBGetResult& getResult) > return; > } > >- auto& vm = context->vm(); >- > // FIXME: This conversion should be done lazily, when script needs the JSValues, so that global object > // of the IDBCursor wrapper can be used, rather than the lexicalGlobalObject. >- m_currentKey = { vm, toJS(*exec, *exec->lexicalGlobalObject(), getResult.keyData().maybeCreateIDBKey().get()) }; >+ m_currentKey = toJS(*exec, *exec->lexicalGlobalObject(), getResult.keyData().maybeCreateIDBKey().get()); > m_currentKeyData = getResult.keyData(); >- m_currentPrimaryKey = { vm, toJS(*exec, *exec->lexicalGlobalObject(), getResult.primaryKeyData().maybeCreateIDBKey().get()) }; >+ m_currentPrimaryKey = toJS(*exec, *exec->lexicalGlobalObject(), getResult.primaryKeyData().maybeCreateIDBKey().get()); > m_currentPrimaryKeyData = getResult.primaryKeyData(); > > if (isKeyCursorWithValue()) >- m_currentValue = { vm, deserializeIDBValueToJSValue(*exec, getResult.value()) }; >+ m_currentValue = deserializeIDBValueToJSValue(*exec, getResult.value()); > else > m_currentValue = { }; > >diff --git a/Source/WebCore/Modules/indexeddb/IDBCursor.h b/Source/WebCore/Modules/indexeddb/IDBCursor.h >index 9ba27f370361b1df3502b4cc6c572d5d75015bbc..97675411da52760fffab8c53daf9af6bcd3fe083 100644 >--- a/Source/WebCore/Modules/indexeddb/IDBCursor.h >+++ b/Source/WebCore/Modules/indexeddb/IDBCursor.h >@@ -30,6 +30,7 @@ > #include "ExceptionOr.h" > #include "IDBCursorDirection.h" > #include "IDBCursorInfo.h" >+#include "JSValueInWrappedObject.h" > #include <JavaScriptCore/Strong.h> > #include <wtf/Variant.h> > #include <wtf/WeakPtr.h> >@@ -74,6 +75,10 @@ public: > > virtual bool isKeyCursorWithValue() const { return false; } > >+ JSValueInWrappedObject& currentKey() { return m_currentKey; } >+ JSValueInWrappedObject& currentPrimaryKey() { return m_currentPrimaryKey; } >+ JSValueInWrappedObject& currentValue() { return m_currentValue; } >+ > protected: > IDBCursor(IDBObjectStore&, const IDBCursorInfo&); > IDBCursor(IDBIndex&, const IDBCursorInfo&); >@@ -97,9 +102,9 @@ private: > > // FIXME: The following uses of JSC::Strong are incorrect and can lead to storage leaks > // due to reference cycles; we should use JSValueInWrappedObject instead. >- JSC::Strong<JSC::Unknown> m_currentKey; >- JSC::Strong<JSC::Unknown> m_currentPrimaryKey; >- JSC::Strong<JSC::Unknown> m_currentValue; >+ JSValueInWrappedObject m_currentKey; >+ JSValueInWrappedObject m_currentPrimaryKey; >+ JSValueInWrappedObject m_currentValue; > }; > > >@@ -115,17 +120,17 @@ inline IDBCursorDirection IDBCursor::direction() const > > inline JSC::JSValue IDBCursor::key() const > { >- return m_currentKey.get(); >+ return m_currentKey; > } > > inline JSC::JSValue IDBCursor::primaryKey() const > { >- return m_currentPrimaryKey.get(); >+ return m_currentPrimaryKey; > } > > inline JSC::JSValue IDBCursor::value() const > { >- return m_currentValue.get(); >+ return m_currentValue; > } > > } // namespace WebCore >diff --git a/Source/WebCore/Modules/indexeddb/IDBRequest.cpp b/Source/WebCore/Modules/indexeddb/IDBRequest.cpp >index 6f5ce0e972653f6573ad5db76a4fccd49f22da9b..aae9023fdbcce991f10dc6bd49814bfc4ff24c9e 100644 >--- a/Source/WebCore/Modules/indexeddb/IDBRequest.cpp >+++ b/Source/WebCore/Modules/indexeddb/IDBRequest.cpp >@@ -153,12 +153,26 @@ IDBRequest::~IDBRequest() > } > } > >-ExceptionOr<std::optional<IDBRequest::Result>> IDBRequest::result() const >+ExceptionOr<std::optional<IDBRequest::JSResult>> IDBRequest::result() const > { > if (!isDone()) > return Exception { InvalidStateError, "Failed to read the 'result' property from 'IDBRequest': The request has not finished."_s }; > >- return std::optional<IDBRequest::Result> { m_result }; >+ if (!m_result) >+ return std::optional<IDBRequest::JSResult> { }; >+ >+ // FIXME: Binding generator should be able to take a Result instead of JSResult. >+ auto result = switchOn(m_result.value(), [](const RefPtr<IDBCursor>& cursor) { >+ return JSResult { cursor }; >+ }, [](const RefPtr<IDBDatabase>& database) { >+ return JSResult { database }; >+ }, [&](const JSValueInWrappedObject& object) { >+ VM& vm = scriptExecutionContext()->vm(); >+ JSLockHolder lock(vm); >+ return JSResult { JSC::Strong<JSC::Unknown> { vm, JSValue(object) } }; >+ }); >+ >+ return std::optional<IDBRequest::JSResult> { WTFMove(result) }; > } > > ExceptionOr<DOMException*> IDBRequest::error() const >@@ -362,7 +376,7 @@ void IDBRequest::setResult(const IDBKeyData& keyData) > // of the IDBRequest wrapper can be used, rather than the lexicalGlobalObject. > VM& vm = context->vm(); > JSLockHolder lock(vm); >- m_result = Result { JSC::Strong<JSC::Unknown> { vm, toJS<IDLIDBKeyData>(*state, *jsCast<JSDOMGlobalObject*>(state->lexicalGlobalObject()), keyData) } }; >+ m_result = Result { JSValueInWrappedObject { toJS<IDLIDBKeyData>(*state, *jsCast<JSDOMGlobalObject*>(state->lexicalGlobalObject()), keyData) } }; > } > > void IDBRequest::setResult(const Vector<IDBKeyData>& keyDatas) >@@ -381,7 +395,7 @@ void IDBRequest::setResult(const Vector<IDBKeyData>& keyDatas) > // of the IDBRequest wrapper can be used, rather than the lexicalGlobalObject. > VM& vm = context->vm(); > JSLockHolder lock(vm); >- m_result = Result { JSC::Strong<JSC::Unknown> { vm, toJS<IDLSequence<IDLIDBKeyData>>(*state, *jsCast<JSDOMGlobalObject*>(state->lexicalGlobalObject()), keyDatas) } }; >+ m_result = Result { JSValueInWrappedObject { toJS<IDLSequence<IDLIDBKeyData>>(*state, *jsCast<JSDOMGlobalObject*>(state->lexicalGlobalObject()), keyDatas) } }; > } > > void IDBRequest::setResult(const Vector<IDBValue>& values) >@@ -400,7 +414,7 @@ void IDBRequest::setResult(const Vector<IDBValue>& values) > // of the IDBRequest wrapper can be used, rather than the lexicalGlobalObject. > VM& vm = context->vm(); > JSLockHolder lock(vm); >- m_result = Result { JSC::Strong<JSC::Unknown> { vm, toJS<IDLSequence<IDLIDBValue>>(*state, *jsCast<JSDOMGlobalObject*>(state->lexicalGlobalObject()), values) } }; >+ m_result = Result { JSValueInWrappedObject { toJS<IDLSequence<IDLIDBValue>>(*state, *jsCast<JSDOMGlobalObject*>(state->lexicalGlobalObject()), values) } }; > } > > void IDBRequest::setResult(uint64_t number) >@@ -411,7 +425,7 @@ void IDBRequest::setResult(uint64_t number) > if (!context) > return; > >- m_result = Result { JSC::Strong<JSC::Unknown> { context->vm(), toJS<IDLUnrestrictedDouble>(number) } }; >+ m_result = Result { JSValueInWrappedObject { toJS<IDLUnrestrictedDouble>(number) } }; > } > > void IDBRequest::setResultToStructuredClone(const IDBValue& value) >@@ -432,18 +446,14 @@ void IDBRequest::setResultToStructuredClone(const IDBValue& value) > // of the IDBRequest wrapper can be used, rather than the lexicalGlobalObject. > VM& vm = context->vm(); > JSLockHolder lock(vm); >- m_result = Result { JSC::Strong<JSC::Unknown> { vm, toJS<IDLIDBValue>(*state, *jsCast<JSDOMGlobalObject*>(state->lexicalGlobalObject()), value) } }; >+ m_result = Result { JSValueInWrappedObject { toJS<IDLIDBValue>(*state, *jsCast<JSDOMGlobalObject*>(state->lexicalGlobalObject()), value) } }; > } > > void IDBRequest::setResultToUndefined() > { > ASSERT(&originThread() == &Thread::current()); > >- auto* context = scriptExecutionContext(); >- if (!context) >- return; >- >- m_result = Result { JSC::Strong<JSC::Unknown> { context->vm(), JSC::jsUndefined() } }; >+ m_result = Result { JSValueInWrappedObject { JSC::jsUndefined() } }; > } > > IDBCursor* IDBRequest::resultCursor() >@@ -459,6 +469,18 @@ IDBCursor* IDBRequest::resultCursor() > ); > } > >+JSValueInWrappedObject* IDBRequest::resultValue() >+{ >+ if (!m_result) >+ return nullptr; >+ >+ return switchOn(m_result.value(), [](JSValueInWrappedObject& object) { >+ return &object; >+ }, [](auto&) -> JSValueInWrappedObject* { >+ return nullptr; >+ }); >+} >+ > void IDBRequest::willIterateCursor(IDBCursor& cursor) > { > ASSERT(&originThread() == &Thread::current()); >diff --git a/Source/WebCore/Modules/indexeddb/IDBRequest.h b/Source/WebCore/Modules/indexeddb/IDBRequest.h >index e625cd3c7fbdc8913d6d49aa340ed9bb7239b5e8..c0df443e186973eb41e6324ba9edc94f00d1ff28 100644 >--- a/Source/WebCore/Modules/indexeddb/IDBRequest.h >+++ b/Source/WebCore/Modules/indexeddb/IDBRequest.h >@@ -33,6 +33,7 @@ > #include "IDBError.h" > #include "IDBResourceIdentifier.h" > #include "IndexedDB.h" >+#include "JSValueInWrappedObject.h" > #include <JavaScriptCore/Strong.h> > #include <wtf/Function.h> > #include <wtf/Scope.h> >@@ -69,10 +70,9 @@ public: > > virtual ~IDBRequest(); > >- // FIXME: The following use of JSC::Strong is incorrect and can lead to storage leaks >- // due to reference cycles; we should use JSValueInWrappedObject instead. >- using Result = Variant<RefPtr<IDBCursor>, RefPtr<IDBDatabase>, JSC::Strong<JSC::Unknown>>; >- ExceptionOr<std::optional<Result>> result() const; >+ using Result = Variant<RefPtr<IDBCursor>, RefPtr<IDBDatabase>, JSValueInWrappedObject>; >+ using JSResult = Variant<RefPtr<IDBCursor>, RefPtr<IDBDatabase>, JSC::Strong<JSC::Unknown>>; >+ ExceptionOr<std::optional<JSResult>> result() const; > > using Source = Variant<RefPtr<IDBObjectStore>, RefPtr<IDBIndex>, RefPtr<IDBCursor>>; > const std::optional<Source>& source() const { return m_source; } >@@ -117,6 +117,8 @@ public: > > bool hasPendingActivity() const final; > >+ JSValueInWrappedObject* resultValue(); >+ > protected: > IDBRequest(ScriptExecutionContext&, IDBClient::IDBConnectionProxy&); > >diff --git a/Source/WebCore/Modules/indexeddb/IDBRequest.idl b/Source/WebCore/Modules/indexeddb/IDBRequest.idl >index 7751e205282b8e8a58895155f4b54e0aaabb04ad..13666a932d4121f793c508d4e3415b1a8847856b 100644 >--- a/Source/WebCore/Modules/indexeddb/IDBRequest.idl >+++ b/Source/WebCore/Modules/indexeddb/IDBRequest.idl >@@ -31,6 +31,7 @@ > ActiveDOMObject, > Conditional=INDEXED_DATABASE, > GenerateIsReachable=Impl, >+ JSCustomMarkFunction, > SkipVTableValidation, > ] interface IDBRequest : EventTarget { > readonly attribute (IDBCursor or IDBDatabase or any)? result; >diff --git a/Source/WebCore/Sources.txt b/Source/WebCore/Sources.txt >index 5915736c5168492c500b8ae5c23f90ab48854560..61c773e65c494e7fa9278e0b93c5ec2d0822c753 100644 >--- a/Source/WebCore/Sources.txt >+++ b/Source/WebCore/Sources.txt >@@ -415,6 +415,7 @@ bindings/js/JSIDBCursorCustom.cpp > bindings/js/JSIDBCursorWithValueCustom.cpp > bindings/js/JSIDBIndexCustom.cpp > bindings/js/JSIDBObjectStoreCustom.cpp >+bindings/js/JSIDBRequestCustom.cpp > bindings/js/JSIDBTransactionCustom.cpp > bindings/js/JSImageDataCustom.cpp > bindings/js/JSLazyEventListener.cpp >diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >index dc460f1a654a74f5d956c92d582f07b98eeef2f3..2af74096630034d1310d5156f79c19d83ffb2455 100644 >--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj >+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >@@ -7258,6 +7258,7 @@ > 417F0D7E1FFEE14E008EF303 /* ServiceWorkerInternals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ServiceWorkerInternals.h; sourceTree = "<group>"; }; > 417F0D801FFEE14F008EF303 /* ServiceWorkerInternals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ServiceWorkerInternals.cpp; sourceTree = "<group>"; }; > 417F0D811FFEE150008EF303 /* ServiceWorkerInternals.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ServiceWorkerInternals.idl; sourceTree = "<group>"; }; >+ 417F7AD82139AF6E00FBA7EC /* JSIDBRequestCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSIDBRequestCustom.cpp; sourceTree = "<group>"; }; > 41813F9113818AD60057AAA4 /* Internals.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Internals.idl; sourceTree = "<group>"; }; > 41815C1C138319830057AAA4 /* WebCoreTestSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebCoreTestSupport.cpp; sourceTree = "<group>"; }; > 41815C1D138319830057AAA4 /* WebCoreTestSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebCoreTestSupport.h; sourceTree = "<group>"; }; >@@ -19745,6 +19746,7 @@ > 5141298D1C5FD7E90059E714 /* JSIDBCursorWithValueCustom.cpp */, > 5141299A1C6C166D0059E714 /* JSIDBIndexCustom.cpp */, > 511EF2CE17F0FDF100E4FA16 /* JSIDBObjectStoreCustom.cpp */, >+ 417F7AD82139AF6E00FBA7EC /* JSIDBRequestCustom.cpp */, > 51E269321DD3BC43006B6A58 /* JSIDBTransactionCustom.cpp */, > A7D0318D0E93540300E24ACD /* JSImageDataCustom.cpp */, > AD726FE716D9F204003A4E6D /* JSMediaListCustom.h */, >diff --git a/Source/WebCore/bindings/js/JSIDBCursorCustom.cpp b/Source/WebCore/bindings/js/JSIDBCursorCustom.cpp >index bafe2fe0bf427af9c14a217945b6b23bd06c9b93..3ad02992472790e9f3dba26ac62a5b05f220a50d 100644 >--- a/Source/WebCore/bindings/js/JSIDBCursorCustom.cpp >+++ b/Source/WebCore/bindings/js/JSIDBCursorCustom.cpp >@@ -40,6 +40,10 @@ void JSIDBCursor::visitAdditionalChildren(SlotVisitor& visitor) > auto& cursor = wrapped(); > if (auto* request = cursor.request()) > visitor.addOpaqueRoot(request); >+ >+ wrapped().currentKey().visit(visitor); >+ wrapped().currentPrimaryKey().visit(visitor); >+ wrapped().currentValue().visit(visitor); > } > > JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject* globalObject, Ref<IDBCursor>&& cursor) >diff --git a/Source/WebCore/bindings/js/JSIDBRequestCustom.cpp b/Source/WebCore/bindings/js/JSIDBRequestCustom.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..62eca315bcbfac83cfa4012128a122c6245f39da >--- /dev/null >+++ b/Source/WebCore/bindings/js/JSIDBRequestCustom.cpp >@@ -0,0 +1,42 @@ >+/* >+ * 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 "JSIDBRequest.h" >+ >+#if ENABLE(INDEXED_DATABASE) >+ >+namespace WebCore { >+using namespace JSC; >+ >+void JSIDBRequest::visitAdditionalChildren(SlotVisitor& visitor) >+{ >+ if (auto* value = wrapped().resultValue()) >+ value->visit(visitor); >+} >+ >+} // namespace WebCore >+ >+#endif // ENABLE(INDEXED_DATABASE) >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index 34abd263c985ae7baf5b1289fe46beb1b18c7775..a419056a1746869a22ee04e3967541038eb22839 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,14 @@ >+2018-08-31 Youenn Fablet <youenn@apple.com> >+ >+ IDBRequest and IDBCursor should not hold strong references to JSValue >+ https://bugs.webkit.org/show_bug.cgi?id=189201 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * http/tests/IndexedDB/collect-IDB-objects-reference-cycles.https-expected.txt: Added. >+ * http/tests/IndexedDB/collect-IDB-objects-reference-cycles.https.html: Added. >+ * http/tests/IndexedDB/resources/myidbframe-cursor.htm: Added. >+ > 2018-08-30 Truitt Savell <tsavell@apple.com> > > Unreviewed, rolling out r235516. >diff --git a/LayoutTests/http/tests/IndexedDB/collect-IDB-objects-reference-cycles.https-expected.txt b/LayoutTests/http/tests/IndexedDB/collect-IDB-objects-reference-cycles.https-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..1097660dff1e8e07c7250245838d6ddbf2a684f8 >--- /dev/null >+++ b/LayoutTests/http/tests/IndexedDB/collect-IDB-objects-reference-cycles.https-expected.txt >@@ -0,0 +1,4 @@ >+ >+ >+PASS Ensure that IDBCursor/IDBRequest do not create reference cycles that GC cannot break >+ >diff --git a/LayoutTests/http/tests/IndexedDB/collect-IDB-objects-reference-cycles.https.html b/LayoutTests/http/tests/IndexedDB/collect-IDB-objects-reference-cycles.https.html >new file mode 100644 >index 0000000000000000000000000000000000000000..d8b633319d66cbea65d58035c242efc12b9b24d8 >--- /dev/null >+++ b/LayoutTests/http/tests/IndexedDB/collect-IDB-objects-reference-cycles.https.html >@@ -0,0 +1,45 @@ >+<!DOCTYPE html> >+<meta charset="utf-8"> >+<script src="/resources/testharness.js"></script> >+<script src="/resources/testharnessreport.js"></script> >+<script> >+function waitFor(duration) >+{ >+ return new Promise((resolve) => setTimeout(resolve, duration)); >+} >+ >+var resolveCallback, rejectCallback; >+var promise = new Promise((resolve, reject) => { >+ resolveCallback = resolve; >+ rejectCallback = reject; >+}); >+ >+async function done() >+{ >+ try { >+ const frameIdentifier = internals.documentIdentifier(iframe.contentDocument); >+ iframe.src = "non-existent-frame"; >+ let counter = 0; >+ while (++counter < 50) { >+ if (!internals.isDocumentAlive(frameIdentifier)) { >+ resolveCallback(); >+ return; >+ } >+ if (window.GCController) >+ GCController.collect(); >+ >+ await waitFor(50); >+ } >+ } finally { >+ rejectCallback("Test failed"); >+ } >+} >+ >+promise_test((test) => { >+ if (!window.internals) >+ rejectCallback("Test require internals API"); >+ return promise; >+}, "Ensure that IDBCursor/IDBRequest do not create reference cycles that GC cannot break"); >+ >+</script> >+<iframe src="resources/myidbframe-cursor.htm" id="iframe"></iframe> >diff --git a/LayoutTests/http/tests/IndexedDB/resources/myidbframe-cursor.htm b/LayoutTests/http/tests/IndexedDB/resources/myidbframe-cursor.htm >new file mode 100644 >index 0000000000000000000000000000000000000000..4f877ed6a827135acfe0f9a590e0ef987e16535e >--- /dev/null >+++ b/LayoutTests/http/tests/IndexedDB/resources/myidbframe-cursor.htm >@@ -0,0 +1,37 @@ >+<!DOCTYPE html> >+<script src="../../resources/testharness.js"></script> >+<script src="support.js"></script> >+ >+<script> >+var db, >+t = async_test(), >+records = [ { pKey: "primaryKey", iKey: "indexKey" }]; >+ >+var open_rq = createdb(t); >+open_rq.onupgradeneeded = function(e) { >+ db = e.target.result; >+ var objStore = db.createObjectStore("test", { keyPath: "pKey" }); >+ var index = objStore.createIndex("index", "iKey"); >+ >+ objStore.add(records[0]); >+ >+ let request1 = objStore.get(records[0].pKey); >+ request1.onsuccess = (e) => { >+ request1.result.request = request1; >+ }; >+ >+ let request2 = index.openCursor(); >+ request2.onsuccess = t.step_func(function(e) { >+ var cursor = e.target.result; >+ cursor.value.cursor = cursor; >+ cursor.primaryKey.cursor = cursor; >+ cursor.key.cursor = cursor; >+ }); >+ >+ e.target.transaction.oncomplete = t.step_func(function(e) { >+ t.done(); >+ parent.done(); >+ }); >+} >+ >+</script>
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 189201
:
348654
|
348669
|
348684
|
348692
|
348707
|
348712
|
348714
|
348826