d9a91da635
At the moment the inspector tests do not dispose the isolate. This is a problem because the disposal of the isolate is used to stop the execution of background tasks. The missing disposal of the isolate caused flaky tests on the bots recently. With this CL the isolates of the inspector tests get disposed. The disposal of the isolate requires the following changes: 1) Store the isolate in a unique_ptr so that it gets disposed when the isolate-data gets disposed. It is necessary to use the unique_ptr so that the isolate gets disposed after other members of isolate-data get disposed. 2) Dispose all sessions. The reason is that the sessions require the isolate to exist when they get disposed because they own handles. Sessions, however, are stored in a static map, whereas the isolate is stored indirectly in a local variable of the main function. Since local variables get disposed before the static map is cleared, we have to clear the map before the end of the main function. R=kozyatinskiy@chromium.org Change-Id: Icb33184de254638b6cdfb899e940f18e6064cd69 Reviewed-on: https://chromium-review.googlesource.com/774885 Reviewed-by: Aleksey Kozyatinskiy <kozyatinskiy@chromium.org> Commit-Queue: Andreas Haas <ahaas@chromium.org> Cr-Commit-Position: refs/heads/master@{#49424}
143 lines
6.1 KiB
C++
143 lines
6.1 KiB
C++
// Copyright 2017 the V8 project authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#ifndef V8_TEST_INSPECTOR_PROTOCOL_ISOLATE_DATA_H_
|
|
#define V8_TEST_INSPECTOR_PROTOCOL_ISOLATE_DATA_H_
|
|
|
|
#include <map>
|
|
|
|
#include "include/v8-inspector.h"
|
|
#include "include/v8-platform.h"
|
|
#include "include/v8.h"
|
|
#include "src/base/macros.h"
|
|
#include "src/base/platform/platform.h"
|
|
#include "src/vector.h"
|
|
|
|
class TaskRunner;
|
|
|
|
class IsolateData : public v8_inspector::V8InspectorClient {
|
|
public:
|
|
class SetupGlobalTask {
|
|
public:
|
|
virtual ~SetupGlobalTask() = default;
|
|
virtual void Run(v8::Isolate* isolate,
|
|
v8::Local<v8::ObjectTemplate> global) = 0;
|
|
};
|
|
using SetupGlobalTasks = std::vector<std::unique_ptr<SetupGlobalTask>>;
|
|
|
|
IsolateData(TaskRunner* task_runner, SetupGlobalTasks setup_global_tasks,
|
|
v8::StartupData* startup_data, bool with_inspector);
|
|
static IsolateData* FromContext(v8::Local<v8::Context> context);
|
|
|
|
v8::Isolate* isolate() const { return isolate_.get(); }
|
|
TaskRunner* task_runner() const { return task_runner_; }
|
|
|
|
// Setting things up.
|
|
int CreateContextGroup();
|
|
v8::Local<v8::Context> GetContext(int context_group_id);
|
|
int GetContextGroupId(v8::Local<v8::Context> context);
|
|
void RegisterModule(v8::Local<v8::Context> context,
|
|
v8::internal::Vector<uint16_t> name,
|
|
v8::ScriptCompiler::Source* source);
|
|
|
|
// Working with V8Inspector api.
|
|
int ConnectSession(int context_group_id,
|
|
const v8_inspector::StringView& state,
|
|
v8_inspector::V8Inspector::Channel* channel);
|
|
std::unique_ptr<v8_inspector::StringBuffer> DisconnectSession(int session_id);
|
|
void SendMessage(int session_id, const v8_inspector::StringView& message);
|
|
void BreakProgram(int context_group_id,
|
|
const v8_inspector::StringView& reason,
|
|
const v8_inspector::StringView& details);
|
|
void SchedulePauseOnNextStatement(int context_group_id,
|
|
const v8_inspector::StringView& reason,
|
|
const v8_inspector::StringView& details);
|
|
void CancelPauseOnNextStatement(int context_group_id);
|
|
void AsyncTaskScheduled(const v8_inspector::StringView& name, void* task,
|
|
bool recurring);
|
|
void AsyncTaskStarted(void* task);
|
|
void AsyncTaskFinished(void* task);
|
|
void AddInspectedObject(int session_id, v8::Local<v8::Value> object);
|
|
|
|
// Test utilities.
|
|
void SetCurrentTimeMS(double time);
|
|
void SetMemoryInfo(v8::Local<v8::Value> memory_info);
|
|
void SetLogConsoleApiMessageCalls(bool log);
|
|
void SetLogMaxAsyncCallStackDepthChanged(bool log);
|
|
void SetMaxAsyncTaskStacksForTest(int limit);
|
|
void DumpAsyncTaskStacksStateForTest();
|
|
void FireContextCreated(v8::Local<v8::Context> context, int context_group_id);
|
|
void FireContextDestroyed(v8::Local<v8::Context> context);
|
|
void FreeContext(v8::Local<v8::Context> context);
|
|
|
|
private:
|
|
struct VectorCompare {
|
|
bool operator()(const v8::internal::Vector<uint16_t>& lhs,
|
|
const v8::internal::Vector<uint16_t>& rhs) const {
|
|
for (int i = 0; i < lhs.length() && i < rhs.length(); ++i) {
|
|
if (lhs[i] != rhs[i]) return lhs[i] < rhs[i];
|
|
}
|
|
return false;
|
|
}
|
|
};
|
|
static v8::MaybeLocal<v8::Module> ModuleResolveCallback(
|
|
v8::Local<v8::Context> context, v8::Local<v8::String> specifier,
|
|
v8::Local<v8::Module> referrer);
|
|
static void MessageHandler(v8::Local<v8::Message> message,
|
|
v8::Local<v8::Value> exception);
|
|
static void PromiseRejectHandler(v8::PromiseRejectMessage data);
|
|
static int HandleMessage(v8::Local<v8::Message> message,
|
|
v8::Local<v8::Value> exception);
|
|
std::vector<int> GetSessionIds(int context_group_id);
|
|
|
|
// V8InspectorClient implementation.
|
|
bool formatAccessorsAsProperties(v8::Local<v8::Value>) override;
|
|
v8::Local<v8::Context> ensureDefaultContextInGroup(
|
|
int context_group_id) override;
|
|
double currentTimeMS() override;
|
|
v8::MaybeLocal<v8::Value> memoryInfo(v8::Isolate* isolate,
|
|
v8::Local<v8::Context>) override;
|
|
void runMessageLoopOnPause(int context_group_id) override;
|
|
void quitMessageLoopOnPause() override;
|
|
void consoleAPIMessage(int contextGroupId,
|
|
v8::Isolate::MessageErrorLevel level,
|
|
const v8_inspector::StringView& message,
|
|
const v8_inspector::StringView& url,
|
|
unsigned lineNumber, unsigned columnNumber,
|
|
v8_inspector::V8StackTrace*) override;
|
|
bool isInspectableHeapObject(v8::Local<v8::Object>) override;
|
|
void maxAsyncCallStackDepthChanged(int depth) override;
|
|
|
|
// The isolate gets deleted by its {Dispose} method, not by the default
|
|
// deleter. Therefore we have to define a custom deleter for the unique_ptr to
|
|
// call {Dispose}. We have to use the unique_ptr so that the isolate get
|
|
// disposed in the right order, relative to other member variables.
|
|
struct IsolateDeleter {
|
|
void operator()(v8::Isolate* isolate) const { isolate->Dispose(); }
|
|
};
|
|
|
|
TaskRunner* task_runner_;
|
|
SetupGlobalTasks setup_global_tasks_;
|
|
std::unique_ptr<v8::Isolate, IsolateDeleter> isolate_;
|
|
std::unique_ptr<v8_inspector::V8Inspector> inspector_;
|
|
int last_context_group_id_ = 0;
|
|
std::map<int, v8::Global<v8::Context>> contexts_;
|
|
std::map<v8::internal::Vector<uint16_t>, v8::Global<v8::Module>,
|
|
VectorCompare>
|
|
modules_;
|
|
int last_session_id_ = 0;
|
|
std::map<int, std::unique_ptr<v8_inspector::V8InspectorSession>> sessions_;
|
|
std::map<v8_inspector::V8InspectorSession*, int> context_group_by_session_;
|
|
v8::Global<v8::Value> memory_info_;
|
|
bool current_time_set_ = false;
|
|
double current_time_ = 0.0;
|
|
bool log_console_api_message_calls_ = false;
|
|
bool log_max_async_call_stack_depth_changed_ = false;
|
|
v8::Global<v8::Private> not_inspectable_private_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(IsolateData);
|
|
};
|
|
|
|
#endif // V8_TEST_INSPECTOR_PROTOCOL_ISOLATE_DATA_H_
|