Commit fc4d99cb authored by jsbell@chromium.org's avatar jsbell@chromium.org

Replace IDBPendingTransactionMonitor with end-of-recursion-scope tasks

V8PerIsolateData cannot own IDBPendingTransactionMonitor, because
IDBPendingTransactionMonitor is defined in modules/indexeddb and
V8PerIsolateData is defined in bindings/core. Replace the monitor
entirely by having IDBTransactions register tasks to be run once
the scopes are unwound.

BUG=358074
R=haraken,tasak,adamk

Review URL: https://codereview.chromium.org/686153003

git-svn-id: svn://svn.chromium.org/blink/trunk@185137 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 436dd7a4
...@@ -12,5 +12,4 @@ include_rules = [ ...@@ -12,5 +12,4 @@ include_rules = [
# TODO(tasak): Get this list to zero. # TODO(tasak): Get this list to zero.
"!bindings/modules/v8/V8CryptoKey.h", "!bindings/modules/v8/V8CryptoKey.h",
"!bindings/modules/v8/V8DOMFileSystem.h", "!bindings/modules/v8/V8DOMFileSystem.h",
"!modules/indexeddb/IDBPendingTransactionMonitor.h",
] ]
...@@ -133,7 +133,7 @@ void V8PerIsolateData::willBeDestroyed(v8::Isolate* isolate) ...@@ -133,7 +133,7 @@ void V8PerIsolateData::willBeDestroyed(v8::Isolate* isolate)
// Clear any data that may have handles into the heap, // Clear any data that may have handles into the heap,
// prior to calling ThreadState::detach(). // prior to calling ThreadState::detach().
data->m_idbPendingTransactionMonitor.clear(); data->clearEndOfScopeTasks();
} }
void V8PerIsolateData::destroy(v8::Isolate* isolate) void V8PerIsolateData::destroy(v8::Isolate* isolate)
...@@ -249,11 +249,23 @@ v8::Handle<v8::FunctionTemplate> V8PerIsolateData::toStringTemplate() ...@@ -249,11 +249,23 @@ v8::Handle<v8::FunctionTemplate> V8PerIsolateData::toStringTemplate()
return m_toStringTemplate.newLocal(isolate()); return m_toStringTemplate.newLocal(isolate());
} }
IDBPendingTransactionMonitor* V8PerIsolateData::ensureIDBPendingTransactionMonitor() void V8PerIsolateData::addEndOfScopeTask(PassOwnPtr<EndOfScopeTask> task)
{ {
if (!m_idbPendingTransactionMonitor) m_endOfScopeTasks.append(task);
m_idbPendingTransactionMonitor = adoptPtr(new IDBPendingTransactionMonitor()); }
return m_idbPendingTransactionMonitor.get();
void V8PerIsolateData::runEndOfScopeTasks()
{
Vector<OwnPtr<EndOfScopeTask>> tasks;
tasks.swap(m_endOfScopeTasks);
for (const auto& task : tasks)
task->Run();
ASSERT(m_endOfScopeTasks.isEmpty());
}
void V8PerIsolateData::clearEndOfScopeTasks()
{
m_endOfScopeTasks.clear();
} }
} // namespace blink } // namespace blink
...@@ -31,7 +31,6 @@ ...@@ -31,7 +31,6 @@
#include "bindings/core/v8/V8HiddenValue.h" #include "bindings/core/v8/V8HiddenValue.h"
#include "bindings/core/v8/WrapperTypeInfo.h" #include "bindings/core/v8/WrapperTypeInfo.h"
#include "gin/public/isolate_holder.h" #include "gin/public/isolate_holder.h"
#include "modules/indexeddb/IDBPendingTransactionMonitor.h"
#include "wtf/HashMap.h" #include "wtf/HashMap.h"
#include "wtf/OwnPtr.h" #include "wtf/OwnPtr.h"
#include "wtf/Vector.h" #include "wtf/Vector.h"
...@@ -48,6 +47,12 @@ typedef WTF::Vector<DOMDataStore*> DOMDataStoreList; ...@@ -48,6 +47,12 @@ typedef WTF::Vector<DOMDataStore*> DOMDataStoreList;
class V8PerIsolateData { class V8PerIsolateData {
public: public:
class EndOfScopeTask {
public:
virtual ~EndOfScopeTask() { }
virtual void Run() = 0;
};
static v8::Isolate* initialize(); static v8::Isolate* initialize();
static V8PerIsolateData* from(v8::Isolate* isolate) static V8PerIsolateData* from(v8::Isolate* isolate)
{ {
...@@ -102,7 +107,13 @@ public: ...@@ -102,7 +107,13 @@ public:
const char* previousSamplingState() const { return m_previousSamplingState; } const char* previousSamplingState() const { return m_previousSamplingState; }
void setPreviousSamplingState(const char* name) { m_previousSamplingState = name; } void setPreviousSamplingState(const char* name) { m_previousSamplingState = name; }
IDBPendingTransactionMonitor* ensureIDBPendingTransactionMonitor(); // EndOfScopeTasks are run by V8RecursionScope when control is returning
// to C++ from script, after executing a script task (e.g. callback,
// event) or microtasks (e.g. promise). This is explicitly needed for
// Indexed DB transactions per spec, but should in general be avoided.
void addEndOfScopeTask(PassOwnPtr<EndOfScopeTask>);
void runEndOfScopeTasks();
void clearEndOfScopeTasks();
private: private:
V8PerIsolateData(); V8PerIsolateData();
...@@ -138,7 +149,7 @@ private: ...@@ -138,7 +149,7 @@ private:
OwnPtr<GCEventData> m_gcEventData; OwnPtr<GCEventData> m_gcEventData;
bool m_performingMicrotaskCheckpoint; bool m_performingMicrotaskCheckpoint;
OwnPtr<IDBPendingTransactionMonitor> m_idbPendingTransactionMonitor; Vector<OwnPtr<EndOfScopeTask>> m_endOfScopeTasks;
}; };
} // namespace blink } // namespace blink
......
...@@ -40,6 +40,7 @@ void V8RecursionScope::didLeaveScriptContext() ...@@ -40,6 +40,7 @@ void V8RecursionScope::didLeaveScriptContext()
{ {
Microtask::performCheckpoint(); Microtask::performCheckpoint();
ModuleProxy::moduleProxy().didLeaveScriptContextForRecursionScope(m_isolate); ModuleProxy::moduleProxy().didLeaveScriptContextForRecursionScope(m_isolate);
V8PerIsolateData::from(m_isolate)->runEndOfScopeTasks();
} }
} // namespace blink } // namespace blink
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
#include "bindings/core/v8/ModuleProxy.h" #include "bindings/core/v8/ModuleProxy.h"
#include "bindings/core/v8/V8PerIsolateData.h" #include "bindings/core/v8/V8PerIsolateData.h"
#include "core/dom/ExecutionContext.h" #include "core/dom/ExecutionContext.h"
#include "modules/indexeddb/IDBPendingTransactionMonitor.h"
namespace blink { namespace blink {
...@@ -18,9 +17,6 @@ void initPartialInterfacesInModules(); ...@@ -18,9 +17,6 @@ void initPartialInterfacesInModules();
static void didLeaveScriptContextForModule(v8::Isolate* isolate) static void didLeaveScriptContextForModule(v8::Isolate* isolate)
{ {
// Indexed DB requires that transactions are created with an internal |active| flag
// set to true, but the flag becomes false when control returns to the event loop.
V8PerIsolateData::from(isolate)->ensureIDBPendingTransactionMonitor()->deactivateNewTransactions();
} }
void ModuleBindingsInitializer::init() void ModuleBindingsInitializer::init()
......
/*
* Copyright (C) 2010 Google 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 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 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 "modules/indexeddb/IDBPendingTransactionMonitor.h"
#include "modules/indexeddb/IDBTransaction.h"
namespace blink {
IDBPendingTransactionMonitor::IDBPendingTransactionMonitor()
{
}
void IDBPendingTransactionMonitor::addNewTransaction(IDBTransaction& transaction)
{
m_transactions.append(&transaction);
}
void IDBPendingTransactionMonitor::deactivateNewTransactions()
{
for (size_t i = 0; i < m_transactions.size(); ++i)
m_transactions[i]->setActive(false);
// FIXME: Exercise this call to clear() in a layout test.
m_transactions.clear();
}
} // namespace blink
/*
* Copyright (C) 2010 Google 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 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 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.
*/
#ifndef IDBPendingTransactionMonitor_h
#define IDBPendingTransactionMonitor_h
#include "platform/heap/Handle.h"
#include "wtf/Noncopyable.h"
namespace blink {
class IDBTransaction;
// This class keeps track of the transactions created during the current
// Javascript execution context. Transactions have an internal |active| flag
// which is set to true on creation, but must be set to false when control
// returns to the event loop.
class IDBPendingTransactionMonitor {
WTF_MAKE_NONCOPYABLE(IDBPendingTransactionMonitor);
public:
IDBPendingTransactionMonitor();
void addNewTransaction(IDBTransaction&);
void deactivateNewTransactions();
private:
PersistentHeapVector<Member<IDBTransaction> > m_transactions;
};
} // namespace blink
#endif // IDBPendingTransactionMonitor_h
...@@ -59,6 +59,30 @@ IDBTransaction* IDBTransaction::create(ScriptState* scriptState, int64_t id, IDB ...@@ -59,6 +59,30 @@ IDBTransaction* IDBTransaction::create(ScriptState* scriptState, int64_t id, IDB
return transaction; return transaction;
} }
namespace {
class DeactivateTransactionTask : public V8PerIsolateData::EndOfScopeTask {
public:
static PassOwnPtr<DeactivateTransactionTask> create(IDBTransaction* transaction)
{
return adoptPtr(new DeactivateTransactionTask(transaction));
}
void Run() override
{
m_transaction->setActive(false);
m_transaction.clear();
}
private:
explicit DeactivateTransactionTask(IDBTransaction* transaction)
: m_transaction(transaction) { }
Persistent<IDBTransaction> m_transaction;
};
} // namespace
IDBTransaction::IDBTransaction(ScriptState* scriptState, int64_t id, const Vector<String>& objectStoreNames, WebIDBTransactionMode mode, IDBDatabase* db, IDBOpenDBRequest* openDBRequest, const IDBDatabaseMetadata& previousMetadata) IDBTransaction::IDBTransaction(ScriptState* scriptState, int64_t id, const Vector<String>& objectStoreNames, WebIDBTransactionMode mode, IDBDatabase* db, IDBOpenDBRequest* openDBRequest, const IDBDatabaseMetadata& previousMetadata)
: ActiveDOMObject(scriptState->executionContext()) : ActiveDOMObject(scriptState->executionContext())
, m_id(id) , m_id(id)
...@@ -77,7 +101,7 @@ IDBTransaction::IDBTransaction(ScriptState* scriptState, int64_t id, const Vecto ...@@ -77,7 +101,7 @@ IDBTransaction::IDBTransaction(ScriptState* scriptState, int64_t id, const Vecto
} }
if (m_state == Active) if (m_state == Active)
V8PerIsolateData::from(scriptState->isolate())->ensureIDBPendingTransactionMonitor()->addNewTransaction(*this); V8PerIsolateData::from(scriptState->isolate())->addEndOfScopeTask(DeactivateTransactionTask::create(this));
m_database->transactionCreated(this); m_database->transactionCreated(this);
} }
......
...@@ -63,7 +63,7 @@ public: ...@@ -63,7 +63,7 @@ public:
void deactivateNewTransactions() void deactivateNewTransactions()
{ {
V8PerIsolateData::from(isolate())->ensureIDBPendingTransactionMonitor()->deactivateNewTransactions(); V8PerIsolateData::from(isolate())->runEndOfScopeTasks();
} }
private: private:
......
...@@ -178,7 +178,7 @@ public: ...@@ -178,7 +178,7 @@ public:
IDBDatabase* idbDatabase = requestResult->idbDatabase(); IDBDatabase* idbDatabase = requestResult->idbDatabase();
m_executableWithDatabase->execute(idbDatabase); m_executableWithDatabase->execute(idbDatabase);
V8PerIsolateData::from(m_executableWithDatabase->scriptState()->isolate())->ensureIDBPendingTransactionMonitor()->deactivateNewTransactions(); V8PerIsolateData::from(m_executableWithDatabase->scriptState()->isolate())->runEndOfScopeTasks();
idbDatabase->close(); idbDatabase->close();
} }
......
...@@ -569,8 +569,6 @@ ...@@ -569,8 +569,6 @@
'indexeddb/IDBObjectStore.h', 'indexeddb/IDBObjectStore.h',
'indexeddb/IDBOpenDBRequest.cpp', 'indexeddb/IDBOpenDBRequest.cpp',
'indexeddb/IDBOpenDBRequest.h', 'indexeddb/IDBOpenDBRequest.h',
'indexeddb/IDBPendingTransactionMonitor.cpp',
'indexeddb/IDBPendingTransactionMonitor.h',
'indexeddb/IDBRequest.cpp', 'indexeddb/IDBRequest.cpp',
'indexeddb/IDBRequest.h', 'indexeddb/IDBRequest.h',
'indexeddb/IDBTracing.h', 'indexeddb/IDBTracing.h',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment