2016-10-02 18:10:27 +00:00
|
|
|
// Copyright 2016 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.
|
|
|
|
|
|
|
|
#if !defined(_WIN32) && !defined(_WIN64)
|
2021-04-29 16:54:13 +00:00
|
|
|
#include <unistd.h>
|
|
|
|
#endif // !defined(_WIN32) && !defined(_WIN64)
|
2016-10-02 18:10:27 +00:00
|
|
|
|
2016-10-13 20:31:17 +00:00
|
|
|
#include <locale.h>
|
2020-10-27 13:52:22 +00:00
|
|
|
|
2018-07-30 16:24:40 +00:00
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
2016-10-13 20:31:17 +00:00
|
|
|
|
2016-10-02 18:10:27 +00:00
|
|
|
#include "include/libplatform/libplatform.h"
|
2021-08-23 13:01:06 +00:00
|
|
|
#include "include/v8-initialization.h"
|
|
|
|
#include "include/v8-local-handle.h"
|
|
|
|
#include "include/v8-snapshot.h"
|
2016-10-02 18:10:27 +00:00
|
|
|
#include "src/base/platform/platform.h"
|
2020-11-05 17:00:11 +00:00
|
|
|
#include "src/base/small-vector.h"
|
2021-06-17 15:43:55 +00:00
|
|
|
#include "src/base/vector.h"
|
2019-05-24 13:51:59 +00:00
|
|
|
#include "src/flags/flags.h"
|
2019-06-20 16:42:31 +00:00
|
|
|
#include "src/heap/read-only-heap.h"
|
2019-05-23 13:27:57 +00:00
|
|
|
#include "src/utils/utils.h"
|
2020-10-28 17:29:03 +00:00
|
|
|
#include "test/inspector/frontend-channel.h"
|
2017-05-22 00:48:27 +00:00
|
|
|
#include "test/inspector/isolate-data.h"
|
2016-10-02 18:10:27 +00:00
|
|
|
#include "test/inspector/task-runner.h"
|
2020-10-27 13:52:22 +00:00
|
|
|
#include "test/inspector/tasks.h"
|
|
|
|
#include "test/inspector/utils.h"
|
2016-10-02 18:10:27 +00:00
|
|
|
|
2018-11-15 12:49:20 +00:00
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
|
|
|
|
|
|
|
extern void DisableEmbeddedBlobRefcounting();
|
|
|
|
extern void FreeCurrentEmbeddedBlob();
|
|
|
|
|
2019-05-16 12:19:13 +00:00
|
|
|
extern v8::StartupData CreateSnapshotDataBlobInternal(
|
|
|
|
v8::SnapshotCreator::FunctionCodeHandling function_code_handling,
|
|
|
|
const char* embedded_source, v8::Isolate* isolate);
|
|
|
|
extern v8::StartupData WarmUpSnapshotDataBlobInternal(
|
|
|
|
v8::StartupData cold_snapshot_blob, const char* warmup_source);
|
|
|
|
|
2016-10-02 18:10:27 +00:00
|
|
|
namespace {
|
|
|
|
|
2020-11-05 17:00:11 +00:00
|
|
|
base::SmallVector<TaskRunner*, 2> task_runners;
|
2016-10-19 02:04:34 +00:00
|
|
|
|
2021-08-24 13:00:06 +00:00
|
|
|
class UtilsExtension : public InspectorIsolateData::SetupGlobalTask {
|
2016-10-02 18:10:27 +00:00
|
|
|
public:
|
2017-04-20 18:04:24 +00:00
|
|
|
~UtilsExtension() override = default;
|
|
|
|
void Run(v8::Isolate* isolate,
|
2017-04-21 23:41:07 +00:00
|
|
|
v8::Local<v8::ObjectTemplate> global) override {
|
2017-04-20 18:04:24 +00:00
|
|
|
v8::Local<v8::ObjectTemplate> utils = v8::ObjectTemplate::New(isolate);
|
2020-09-16 09:54:02 +00:00
|
|
|
utils->Set(isolate, "print",
|
2017-04-20 18:04:24 +00:00
|
|
|
v8::FunctionTemplate::New(isolate, &UtilsExtension::Print));
|
2020-09-16 09:54:02 +00:00
|
|
|
utils->Set(isolate, "quit",
|
2017-04-20 18:04:24 +00:00
|
|
|
v8::FunctionTemplate::New(isolate, &UtilsExtension::Quit));
|
2020-09-16 09:54:02 +00:00
|
|
|
utils->Set(isolate, "setlocale",
|
2017-04-20 18:04:24 +00:00
|
|
|
v8::FunctionTemplate::New(isolate, &UtilsExtension::Setlocale));
|
2020-09-16 09:54:02 +00:00
|
|
|
utils->Set(isolate, "read",
|
2017-04-20 18:04:24 +00:00
|
|
|
v8::FunctionTemplate::New(isolate, &UtilsExtension::Read));
|
2020-09-16 09:54:02 +00:00
|
|
|
utils->Set(isolate, "load",
|
2017-04-20 18:04:24 +00:00
|
|
|
v8::FunctionTemplate::New(isolate, &UtilsExtension::Load));
|
2020-09-16 09:54:02 +00:00
|
|
|
utils->Set(isolate, "compileAndRunWithOrigin",
|
2017-04-20 18:04:24 +00:00
|
|
|
v8::FunctionTemplate::New(
|
|
|
|
isolate, &UtilsExtension::CompileAndRunWithOrigin));
|
2020-09-16 09:54:02 +00:00
|
|
|
utils->Set(isolate, "setCurrentTimeMSForTest",
|
2017-04-20 18:04:24 +00:00
|
|
|
v8::FunctionTemplate::New(
|
|
|
|
isolate, &UtilsExtension::SetCurrentTimeMSForTest));
|
2020-09-16 09:54:02 +00:00
|
|
|
utils->Set(isolate, "setMemoryInfoForTest",
|
2017-04-20 18:04:24 +00:00
|
|
|
v8::FunctionTemplate::New(
|
|
|
|
isolate, &UtilsExtension::SetMemoryInfoForTest));
|
2020-09-16 09:54:02 +00:00
|
|
|
utils->Set(isolate, "schedulePauseOnNextStatement",
|
2017-04-20 18:04:24 +00:00
|
|
|
v8::FunctionTemplate::New(
|
|
|
|
isolate, &UtilsExtension::SchedulePauseOnNextStatement));
|
2020-09-16 09:54:02 +00:00
|
|
|
utils->Set(isolate, "cancelPauseOnNextStatement",
|
2017-04-20 18:04:24 +00:00
|
|
|
v8::FunctionTemplate::New(
|
|
|
|
isolate, &UtilsExtension::CancelPauseOnNextStatement));
|
2020-09-16 09:54:02 +00:00
|
|
|
utils->Set(isolate, "setLogConsoleApiMessageCalls",
|
2017-04-20 18:04:24 +00:00
|
|
|
v8::FunctionTemplate::New(
|
|
|
|
isolate, &UtilsExtension::SetLogConsoleApiMessageCalls));
|
2020-09-29 19:24:48 +00:00
|
|
|
utils->Set(isolate, "setAdditionalConsoleApi",
|
|
|
|
v8::FunctionTemplate::New(
|
|
|
|
isolate, &UtilsExtension::SetAdditionalConsoleApi));
|
2017-10-18 18:47:30 +00:00
|
|
|
utils->Set(
|
2020-09-16 09:54:02 +00:00
|
|
|
isolate, "setLogMaxAsyncCallStackDepthChanged",
|
2017-10-18 18:47:30 +00:00
|
|
|
v8::FunctionTemplate::New(
|
|
|
|
isolate, &UtilsExtension::SetLogMaxAsyncCallStackDepthChanged));
|
2020-09-16 09:54:02 +00:00
|
|
|
utils->Set(isolate, "createContextGroup",
|
2017-04-20 18:04:24 +00:00
|
|
|
v8::FunctionTemplate::New(isolate,
|
|
|
|
&UtilsExtension::CreateContextGroup));
|
2020-09-30 22:20:01 +00:00
|
|
|
utils->Set(
|
|
|
|
isolate, "createContext",
|
|
|
|
v8::FunctionTemplate::New(isolate, &UtilsExtension::CreateContext));
|
2018-11-06 21:42:48 +00:00
|
|
|
utils->Set(
|
2020-09-16 09:54:02 +00:00
|
|
|
isolate, "resetContextGroup",
|
2018-11-06 21:42:48 +00:00
|
|
|
v8::FunctionTemplate::New(isolate, &UtilsExtension::ResetContextGroup));
|
2017-05-18 23:11:20 +00:00
|
|
|
utils->Set(
|
2020-09-16 09:54:02 +00:00
|
|
|
isolate, "connectSession",
|
2017-05-18 23:11:20 +00:00
|
|
|
v8::FunctionTemplate::New(isolate, &UtilsExtension::ConnectSession));
|
|
|
|
utils->Set(
|
2020-09-16 09:54:02 +00:00
|
|
|
isolate, "disconnectSession",
|
2017-05-18 23:11:20 +00:00
|
|
|
v8::FunctionTemplate::New(isolate, &UtilsExtension::DisconnectSession));
|
2020-09-16 09:54:02 +00:00
|
|
|
utils->Set(isolate, "sendMessageToBackend",
|
2017-05-18 23:11:20 +00:00
|
|
|
v8::FunctionTemplate::New(
|
|
|
|
isolate, &UtilsExtension::SendMessageToBackend));
|
2020-12-24 10:08:09 +00:00
|
|
|
utils->Set(isolate, "interruptForMessages",
|
|
|
|
v8::FunctionTemplate::New(
|
|
|
|
isolate, &UtilsExtension::InterruptForMessages));
|
2020-09-16 09:54:02 +00:00
|
|
|
global->Set(isolate, "utils", utils);
|
2016-10-02 18:10:27 +00:00
|
|
|
}
|
|
|
|
|
2016-11-04 19:59:11 +00:00
|
|
|
static void set_backend_task_runner(TaskRunner* runner) {
|
|
|
|
backend_runner_ = runner;
|
|
|
|
}
|
|
|
|
|
2017-11-16 15:29:57 +00:00
|
|
|
static void ClearAllSessions() { channels_.clear(); }
|
|
|
|
|
2016-10-02 18:10:27 +00:00
|
|
|
private:
|
2016-11-04 19:59:11 +00:00
|
|
|
static TaskRunner* backend_runner_;
|
|
|
|
|
2016-10-02 18:10:27 +00:00
|
|
|
static void Print(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
|
for (int i = 0; i < args.Length(); i++) {
|
|
|
|
v8::HandleScope handle_scope(args.GetIsolate());
|
|
|
|
if (i != 0) {
|
|
|
|
printf(" ");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Explicitly catch potential exceptions in toString().
|
|
|
|
v8::TryCatch try_catch(args.GetIsolate());
|
|
|
|
v8::Local<v8::Value> arg = args[i];
|
|
|
|
v8::Local<v8::String> str_obj;
|
|
|
|
|
|
|
|
if (arg->IsSymbol()) {
|
2021-04-12 18:12:33 +00:00
|
|
|
arg = v8::Local<v8::Symbol>::Cast(arg)->Description(args.GetIsolate());
|
2016-10-02 18:10:27 +00:00
|
|
|
}
|
|
|
|
if (!arg->ToString(args.GetIsolate()->GetCurrentContext())
|
|
|
|
.ToLocal(&str_obj)) {
|
|
|
|
try_catch.ReThrow();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-08-24 21:49:48 +00:00
|
|
|
v8::String::Utf8Value str(args.GetIsolate(), str_obj);
|
2016-10-02 18:10:27 +00:00
|
|
|
int n =
|
|
|
|
static_cast<int>(fwrite(*str, sizeof(**str), str.length(), stdout));
|
|
|
|
if (n != str.length()) {
|
2020-11-04 17:42:04 +00:00
|
|
|
FATAL("Error in fwrite\n");
|
2016-10-02 18:10:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
fflush(stdout);
|
|
|
|
}
|
|
|
|
|
2020-11-04 17:42:04 +00:00
|
|
|
static void Quit(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
|
fflush(stdout);
|
|
|
|
fflush(stderr);
|
[inspector][fuzzer] Fix termination
Joining the thread from the watchdog is problematic, since e.g.
{pthread_join} (the implementation of {Thread::Join} on POSIX systems)
has undefined behaviour if multiple threads try to join at the same
time. In practice, this leads to deadlocks.
Thus implement termination by just calling {TaskRunner::Terminate}, but
not {TaskRunner::Join}. This fixes the deadlocks in the inspector
fuzzer.
The inspector test binary is fixed simarly, even though there it seems
to not cause problems so far.
In both files, the {Terminate} function is inlined into callers because
it's only a single line now, with one to two users.
Also, replace the single fuzzer test (which is invalid javascript) by
two tests: One called "invalid" explicitly, still with invalid
javascript, and one empty file, which is valid input. That one
reproduced the deadlock.
R=szuend@chromium.org
Bug: chromium:1142437
Change-Id: I8fb98b0cdbf3ceff6af6849397e5da5a4e9acd3c
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2526384
Reviewed-by: Simon Zünd <szuend@chromium.org>
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71054}
2020-11-09 13:37:17 +00:00
|
|
|
// Only terminate, so not join the threads here, since joining concurrently
|
|
|
|
// from multiple threads can be undefined behaviour (see pthread_join).
|
|
|
|
for (TaskRunner* task_runner : task_runners) task_runner->Terminate();
|
2020-11-04 17:42:04 +00:00
|
|
|
}
|
2016-10-13 20:31:17 +00:00
|
|
|
|
2017-04-20 18:04:24 +00:00
|
|
|
static void Setlocale(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
2016-10-13 20:31:17 +00:00
|
|
|
if (args.Length() != 1 || !args[0]->IsString()) {
|
2020-11-04 17:42:04 +00:00
|
|
|
FATAL("Internal error: setlocale get one string argument.");
|
2016-10-13 20:31:17 +00:00
|
|
|
}
|
2017-08-24 21:49:48 +00:00
|
|
|
|
|
|
|
v8::String::Utf8Value str(args.GetIsolate(), args[1]);
|
2016-10-13 20:31:17 +00:00
|
|
|
setlocale(LC_NUMERIC, *str);
|
|
|
|
}
|
2016-10-18 09:58:20 +00:00
|
|
|
|
2017-02-27 20:20:39 +00:00
|
|
|
static bool ReadFile(v8::Isolate* isolate, v8::Local<v8::Value> name,
|
2018-07-30 16:24:40 +00:00
|
|
|
std::string* chars) {
|
2017-08-24 21:49:48 +00:00
|
|
|
v8::String::Utf8Value str(isolate, name);
|
2016-10-18 09:58:20 +00:00
|
|
|
bool exists = false;
|
|
|
|
std::string filename(*str, str.length());
|
2017-02-27 20:20:39 +00:00
|
|
|
*chars = v8::internal::ReadFile(filename.c_str(), &exists);
|
2016-10-18 09:58:20 +00:00
|
|
|
if (!exists) {
|
2021-04-15 08:10:06 +00:00
|
|
|
isolate->ThrowError("Error reading file");
|
2017-02-27 20:20:39 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void Read(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
|
if (args.Length() != 1 || !args[0]->IsString()) {
|
2020-11-04 17:42:04 +00:00
|
|
|
FATAL("Internal error: read gets one string argument.");
|
2017-02-27 20:20:39 +00:00
|
|
|
}
|
2018-07-30 16:24:40 +00:00
|
|
|
std::string chars;
|
2017-02-27 20:20:39 +00:00
|
|
|
v8::Isolate* isolate = args.GetIsolate();
|
2018-07-19 09:35:49 +00:00
|
|
|
if (ReadFile(isolate, args[0], &chars)) {
|
2018-07-30 16:24:40 +00:00
|
|
|
args.GetReturnValue().Set(ToV8String(isolate, chars));
|
2018-07-19 09:35:49 +00:00
|
|
|
}
|
2017-02-27 20:20:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void Load(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
|
if (args.Length() != 1 || !args[0]->IsString()) {
|
2020-11-04 17:42:04 +00:00
|
|
|
FATAL("Internal error: load gets one string argument.");
|
2017-02-27 20:20:39 +00:00
|
|
|
}
|
2018-07-30 16:24:40 +00:00
|
|
|
std::string chars;
|
2017-02-27 20:20:39 +00:00
|
|
|
v8::Isolate* isolate = args.GetIsolate();
|
2017-05-18 23:11:20 +00:00
|
|
|
v8::Local<v8::Context> context = isolate->GetCurrentContext();
|
2021-08-24 13:00:06 +00:00
|
|
|
InspectorIsolateData* data = InspectorIsolateData::FromContext(context);
|
2017-05-18 23:11:20 +00:00
|
|
|
int context_group_id = data->GetContextGroupId(context);
|
2017-02-27 20:20:39 +00:00
|
|
|
if (ReadFile(isolate, args[0], &chars)) {
|
2017-05-22 20:46:42 +00:00
|
|
|
ExecuteStringTask(chars, context_group_id).Run(data);
|
2016-10-18 09:58:20 +00:00
|
|
|
}
|
|
|
|
}
|
2016-11-04 19:59:11 +00:00
|
|
|
|
|
|
|
static void CompileAndRunWithOrigin(
|
|
|
|
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
2017-05-18 23:11:20 +00:00
|
|
|
if (args.Length() != 6 || !args[0]->IsInt32() || !args[1]->IsString() ||
|
|
|
|
!args[2]->IsString() || !args[3]->IsInt32() || !args[4]->IsInt32() ||
|
|
|
|
!args[5]->IsBoolean()) {
|
2020-11-04 17:42:04 +00:00
|
|
|
FATAL(
|
|
|
|
"Internal error: compileAndRunWithOrigin(context_group_id, source, "
|
|
|
|
"name, line, column, is_module).");
|
2016-11-04 19:59:11 +00:00
|
|
|
}
|
|
|
|
|
2020-11-05 16:15:32 +00:00
|
|
|
backend_runner_->Append(std::make_unique<ExecuteStringTask>(
|
2018-07-23 02:35:30 +00:00
|
|
|
args.GetIsolate(), args[0].As<v8::Int32>()->Value(),
|
|
|
|
ToVector(args.GetIsolate(), args[1].As<v8::String>()),
|
2017-05-22 20:46:42 +00:00
|
|
|
args[2].As<v8::String>(), args[3].As<v8::Int32>(),
|
|
|
|
args[4].As<v8::Int32>(), args[5].As<v8::Boolean>()));
|
2016-11-04 19:59:11 +00:00
|
|
|
}
|
2017-01-17 20:21:38 +00:00
|
|
|
|
|
|
|
static void SetCurrentTimeMSForTest(
|
|
|
|
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
|
if (args.Length() != 1 || !args[0]->IsNumber()) {
|
2020-11-04 17:42:04 +00:00
|
|
|
FATAL("Internal error: setCurrentTimeMSForTest(time).");
|
2017-01-17 20:21:38 +00:00
|
|
|
}
|
2017-05-22 00:48:27 +00:00
|
|
|
backend_runner_->data()->SetCurrentTimeMS(
|
2017-01-17 20:21:38 +00:00
|
|
|
args[0].As<v8::Number>()->Value());
|
|
|
|
}
|
2017-01-18 16:57:00 +00:00
|
|
|
|
2017-03-29 21:40:07 +00:00
|
|
|
static void SetMemoryInfoForTest(
|
|
|
|
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
|
if (args.Length() != 1) {
|
2020-11-04 17:42:04 +00:00
|
|
|
FATAL("Internal error: setMemoryInfoForTest(value).");
|
2017-03-29 21:40:07 +00:00
|
|
|
}
|
2017-05-22 00:48:27 +00:00
|
|
|
backend_runner_->data()->SetMemoryInfo(args[0]);
|
2017-03-29 21:40:07 +00:00
|
|
|
}
|
|
|
|
|
2017-01-18 16:57:00 +00:00
|
|
|
static void SchedulePauseOnNextStatement(
|
|
|
|
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
2017-05-18 23:11:20 +00:00
|
|
|
if (args.Length() != 3 || !args[0]->IsInt32() || !args[1]->IsString() ||
|
|
|
|
!args[2]->IsString()) {
|
2020-11-04 17:42:04 +00:00
|
|
|
FATAL(
|
|
|
|
"Internal error: schedulePauseOnNextStatement(context_group_id, "
|
|
|
|
"'reason', 'details').");
|
2017-01-18 16:57:00 +00:00
|
|
|
}
|
2018-07-30 16:24:40 +00:00
|
|
|
std::vector<uint16_t> reason =
|
2018-07-23 02:35:30 +00:00
|
|
|
ToVector(args.GetIsolate(), args[1].As<v8::String>());
|
2018-07-30 16:24:40 +00:00
|
|
|
std::vector<uint16_t> details =
|
2018-07-23 02:35:30 +00:00
|
|
|
ToVector(args.GetIsolate(), args[2].As<v8::String>());
|
2017-05-22 20:46:42 +00:00
|
|
|
int context_group_id = args[0].As<v8::Int32>()->Value();
|
2018-07-30 16:24:40 +00:00
|
|
|
RunSyncTask(backend_runner_,
|
2021-08-24 13:00:06 +00:00
|
|
|
[&context_group_id, &reason,
|
|
|
|
&details](InspectorIsolateData* data) {
|
2018-07-30 16:24:40 +00:00
|
|
|
data->SchedulePauseOnNextStatement(
|
|
|
|
context_group_id,
|
|
|
|
v8_inspector::StringView(reason.data(), reason.size()),
|
|
|
|
v8_inspector::StringView(details.data(), details.size()));
|
|
|
|
});
|
2017-01-18 16:57:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void CancelPauseOnNextStatement(
|
|
|
|
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
2017-05-18 23:11:20 +00:00
|
|
|
if (args.Length() != 1 || !args[0]->IsInt32()) {
|
2020-11-04 17:42:04 +00:00
|
|
|
FATAL("Internal error: cancelPauseOnNextStatement(context_group_id).");
|
2017-01-18 16:57:00 +00:00
|
|
|
}
|
2017-05-22 20:46:42 +00:00
|
|
|
int context_group_id = args[0].As<v8::Int32>()->Value();
|
2021-08-24 13:00:06 +00:00
|
|
|
RunSyncTask(backend_runner_,
|
|
|
|
[&context_group_id](InspectorIsolateData* data) {
|
|
|
|
data->CancelPauseOnNextStatement(context_group_id);
|
|
|
|
});
|
2017-01-18 16:57:00 +00:00
|
|
|
}
|
2017-02-28 20:22:24 +00:00
|
|
|
|
2017-05-18 23:11:20 +00:00
|
|
|
static void SetLogConsoleApiMessageCalls(
|
|
|
|
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
|
if (args.Length() != 1 || !args[0]->IsBoolean()) {
|
2020-11-04 17:42:04 +00:00
|
|
|
FATAL("Internal error: setLogConsoleApiMessageCalls(bool).");
|
2017-05-18 23:11:20 +00:00
|
|
|
}
|
2017-05-22 00:48:27 +00:00
|
|
|
backend_runner_->data()->SetLogConsoleApiMessageCalls(
|
2017-05-18 23:11:20 +00:00
|
|
|
args[0].As<v8::Boolean>()->Value());
|
|
|
|
}
|
|
|
|
|
2017-10-18 18:47:30 +00:00
|
|
|
static void SetLogMaxAsyncCallStackDepthChanged(
|
|
|
|
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
|
if (args.Length() != 1 || !args[0]->IsBoolean()) {
|
2020-11-04 17:42:04 +00:00
|
|
|
FATAL("Internal error: setLogMaxAsyncCallStackDepthChanged(bool).");
|
2017-10-18 18:47:30 +00:00
|
|
|
}
|
|
|
|
backend_runner_->data()->SetLogMaxAsyncCallStackDepthChanged(
|
|
|
|
args[0].As<v8::Boolean>()->Value());
|
|
|
|
}
|
|
|
|
|
2020-09-29 19:24:48 +00:00
|
|
|
static void SetAdditionalConsoleApi(
|
|
|
|
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
|
if (args.Length() != 1 || !args[0]->IsString()) {
|
2020-11-04 17:42:04 +00:00
|
|
|
FATAL("Internal error: SetAdditionalConsoleApi(string).");
|
2020-09-29 19:24:48 +00:00
|
|
|
}
|
|
|
|
std::vector<uint16_t> script =
|
|
|
|
ToVector(args.GetIsolate(), args[0].As<v8::String>());
|
2021-08-24 13:00:06 +00:00
|
|
|
RunSyncTask(backend_runner_, [&script](InspectorIsolateData* data) {
|
2020-09-29 19:24:48 +00:00
|
|
|
data->SetAdditionalConsoleApi(
|
|
|
|
v8_inspector::StringView(script.data(), script.size()));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-05-18 23:11:20 +00:00
|
|
|
static void CreateContextGroup(
|
|
|
|
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
2017-02-28 20:22:24 +00:00
|
|
|
if (args.Length() != 0) {
|
2020-11-04 17:42:04 +00:00
|
|
|
FATAL("Internal error: createContextGroup().");
|
2017-02-28 20:22:24 +00:00
|
|
|
}
|
2017-05-18 23:11:20 +00:00
|
|
|
int context_group_id = 0;
|
2021-08-24 13:00:06 +00:00
|
|
|
RunSyncTask(backend_runner_,
|
|
|
|
[&context_group_id](InspectorIsolateData* data) {
|
|
|
|
context_group_id = data->CreateContextGroup();
|
|
|
|
});
|
2017-05-18 23:11:20 +00:00
|
|
|
args.GetReturnValue().Set(
|
|
|
|
v8::Int32::New(args.GetIsolate(), context_group_id));
|
2017-02-28 20:22:24 +00:00
|
|
|
}
|
2017-03-07 22:30:05 +00:00
|
|
|
|
2020-09-30 22:20:01 +00:00
|
|
|
static void CreateContext(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
|
if (args.Length() != 2) {
|
2020-11-04 17:42:04 +00:00
|
|
|
FATAL("Internal error: createContext(context, name).");
|
2020-09-30 22:20:01 +00:00
|
|
|
}
|
|
|
|
int context_group_id = args[0].As<v8::Int32>()->Value();
|
|
|
|
std::vector<uint16_t> name =
|
|
|
|
ToVector(args.GetIsolate(), args[1].As<v8::String>());
|
|
|
|
|
2021-08-24 13:00:06 +00:00
|
|
|
RunSyncTask(backend_runner_, [&context_group_id,
|
|
|
|
name](InspectorIsolateData* data) {
|
2021-03-22 16:49:26 +00:00
|
|
|
CHECK(data->CreateContext(
|
|
|
|
context_group_id,
|
|
|
|
v8_inspector::StringView(name.data(), name.size())));
|
2020-09-30 22:20:01 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-11-06 21:42:48 +00:00
|
|
|
static void ResetContextGroup(
|
|
|
|
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
|
if (args.Length() != 1 || !args[0]->IsInt32()) {
|
2020-11-04 17:42:04 +00:00
|
|
|
FATAL("Internal error: resetContextGroup(context_group_id).");
|
2018-11-06 21:42:48 +00:00
|
|
|
}
|
|
|
|
int context_group_id = args[0].As<v8::Int32>()->Value();
|
2021-08-24 13:00:06 +00:00
|
|
|
RunSyncTask(backend_runner_,
|
|
|
|
[&context_group_id](InspectorIsolateData* data) {
|
|
|
|
data->ResetContextGroup(context_group_id);
|
|
|
|
});
|
2018-11-06 21:42:48 +00:00
|
|
|
}
|
|
|
|
|
2017-05-18 23:11:20 +00:00
|
|
|
static void ConnectSession(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
|
if (args.Length() != 3 || !args[0]->IsInt32() || !args[1]->IsString() ||
|
|
|
|
!args[2]->IsFunction()) {
|
2020-11-04 17:42:04 +00:00
|
|
|
FATAL(
|
|
|
|
"Internal error: connectionSession(context_group_id, state, "
|
|
|
|
"dispatch).");
|
2017-04-25 22:55:45 +00:00
|
|
|
}
|
2017-05-22 20:46:42 +00:00
|
|
|
v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
|
|
|
|
FrontendChannelImpl* channel = new FrontendChannelImpl(
|
2021-08-24 13:00:06 +00:00
|
|
|
InspectorIsolateData::FromContext(context)->task_runner(),
|
|
|
|
InspectorIsolateData::FromContext(context)->GetContextGroupId(context),
|
2017-05-22 20:46:42 +00:00
|
|
|
args.GetIsolate(), args[2].As<v8::Function>());
|
|
|
|
|
2019-05-14 23:07:29 +00:00
|
|
|
std::vector<uint8_t> state =
|
|
|
|
ToBytes(args.GetIsolate(), args[1].As<v8::String>());
|
2017-05-22 20:46:42 +00:00
|
|
|
int context_group_id = args[0].As<v8::Int32>()->Value();
|
2017-05-18 23:11:20 +00:00
|
|
|
int session_id = 0;
|
2017-05-22 20:46:42 +00:00
|
|
|
RunSyncTask(backend_runner_, [&context_group_id, &session_id, &channel,
|
2021-08-24 13:00:06 +00:00
|
|
|
&state](InspectorIsolateData* data) {
|
2017-05-22 20:46:42 +00:00
|
|
|
session_id = data->ConnectSession(
|
|
|
|
context_group_id,
|
2018-07-30 16:24:40 +00:00
|
|
|
v8_inspector::StringView(state.data(), state.size()), channel);
|
2017-05-22 20:46:42 +00:00
|
|
|
channel->set_session_id(session_id);
|
|
|
|
});
|
|
|
|
|
|
|
|
channels_[session_id].reset(channel);
|
2017-05-18 23:11:20 +00:00
|
|
|
args.GetReturnValue().Set(v8::Int32::New(args.GetIsolate(), session_id));
|
2017-04-25 22:55:45 +00:00
|
|
|
}
|
|
|
|
|
2017-05-18 23:11:20 +00:00
|
|
|
static void DisconnectSession(
|
2017-04-18 15:53:08 +00:00
|
|
|
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
2017-05-18 23:11:20 +00:00
|
|
|
if (args.Length() != 1 || !args[0]->IsInt32()) {
|
2020-11-04 17:42:04 +00:00
|
|
|
FATAL("Internal error: disconnectionSession(session_id).");
|
2017-04-18 15:53:08 +00:00
|
|
|
}
|
2017-05-18 23:11:20 +00:00
|
|
|
int session_id = args[0].As<v8::Int32>()->Value();
|
2019-05-14 23:07:29 +00:00
|
|
|
std::vector<uint8_t> state;
|
2021-08-24 13:00:06 +00:00
|
|
|
RunSyncTask(backend_runner_,
|
|
|
|
[&session_id, &state](InspectorIsolateData* data) {
|
|
|
|
state = data->DisconnectSession(session_id);
|
|
|
|
});
|
2017-05-22 20:46:42 +00:00
|
|
|
channels_.erase(session_id);
|
|
|
|
args.GetReturnValue().Set(ToV8String(args.GetIsolate(), state));
|
2017-04-18 15:53:08 +00:00
|
|
|
}
|
|
|
|
|
2017-05-18 23:11:20 +00:00
|
|
|
static void SendMessageToBackend(
|
|
|
|
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
|
if (args.Length() != 2 || !args[0]->IsInt32() || !args[1]->IsString()) {
|
2020-11-04 17:42:04 +00:00
|
|
|
FATAL("Internal error: sendMessageToBackend(session_id, message).");
|
2017-05-18 23:11:20 +00:00
|
|
|
}
|
2020-11-05 16:15:32 +00:00
|
|
|
backend_runner_->Append(std::make_unique<SendMessageToBackendTask>(
|
2018-07-23 02:35:30 +00:00
|
|
|
args[0].As<v8::Int32>()->Value(),
|
|
|
|
ToVector(args.GetIsolate(), args[1].As<v8::String>())));
|
2017-05-18 23:11:20 +00:00
|
|
|
}
|
2017-05-22 20:46:42 +00:00
|
|
|
|
2020-12-24 10:08:09 +00:00
|
|
|
static void InterruptForMessages(
|
|
|
|
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
|
backend_runner_->InterruptForMessages();
|
|
|
|
}
|
|
|
|
|
2017-05-22 20:46:42 +00:00
|
|
|
static std::map<int, std::unique_ptr<FrontendChannelImpl>> channels_;
|
2016-10-02 18:10:27 +00:00
|
|
|
};
|
|
|
|
|
2016-11-04 19:59:11 +00:00
|
|
|
TaskRunner* UtilsExtension::backend_runner_ = nullptr;
|
2017-05-22 20:46:42 +00:00
|
|
|
std::map<int, std::unique_ptr<FrontendChannelImpl>> UtilsExtension::channels_;
|
2016-11-04 19:59:11 +00:00
|
|
|
|
2017-02-04 01:21:58 +00:00
|
|
|
bool StrictAccessCheck(v8::Local<v8::Context> accessing_context,
|
|
|
|
v8::Local<v8::Object> accessed_object,
|
|
|
|
v8::Local<v8::Value> data) {
|
|
|
|
CHECK(accessing_context.IsEmpty());
|
|
|
|
return accessing_context.IsEmpty();
|
|
|
|
}
|
|
|
|
|
2022-02-08 14:48:01 +00:00
|
|
|
class ConsoleExtension : public InspectorIsolateData::SetupGlobalTask {
|
|
|
|
public:
|
|
|
|
~ConsoleExtension() override = default;
|
|
|
|
void Run(v8::Isolate* isolate,
|
|
|
|
v8::Local<v8::ObjectTemplate> global) override {
|
|
|
|
v8::Local<v8::String> name =
|
|
|
|
v8::String::NewFromUtf8Literal(isolate, "console");
|
|
|
|
global->SetAccessor(name, &ConsoleGetterCallback, nullptr, {}, v8::DEFAULT,
|
|
|
|
v8::DontEnum);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
static void ConsoleGetterCallback(
|
|
|
|
v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>& info) {
|
|
|
|
v8::Isolate* isolate = info.GetIsolate();
|
|
|
|
v8::HandleScope scope(isolate);
|
|
|
|
v8::Local<v8::Context> context = isolate->GetCurrentContext();
|
|
|
|
v8::Local<v8::String> name =
|
|
|
|
v8::String::NewFromUtf8Literal(isolate, "console");
|
|
|
|
v8::Local<v8::Object> console = context->GetExtrasBindingObject()
|
|
|
|
->Get(context, name)
|
|
|
|
.ToLocalChecked()
|
|
|
|
.As<v8::Object>();
|
|
|
|
info.GetReturnValue().Set(console);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-08-24 13:00:06 +00:00
|
|
|
class InspectorExtension : public InspectorIsolateData::SetupGlobalTask {
|
2016-10-26 20:26:56 +00:00
|
|
|
public:
|
2017-04-21 23:41:07 +00:00
|
|
|
~InspectorExtension() override = default;
|
|
|
|
void Run(v8::Isolate* isolate,
|
|
|
|
v8::Local<v8::ObjectTemplate> global) override {
|
|
|
|
v8::Local<v8::ObjectTemplate> inspector = v8::ObjectTemplate::New(isolate);
|
2020-09-16 09:54:02 +00:00
|
|
|
inspector->Set(isolate, "fireContextCreated",
|
2017-05-18 23:11:20 +00:00
|
|
|
v8::FunctionTemplate::New(
|
|
|
|
isolate, &InspectorExtension::FireContextCreated));
|
2020-09-16 09:54:02 +00:00
|
|
|
inspector->Set(isolate, "fireContextDestroyed",
|
2017-05-18 23:11:20 +00:00
|
|
|
v8::FunctionTemplate::New(
|
|
|
|
isolate, &InspectorExtension::FireContextDestroyed));
|
2017-08-01 21:17:31 +00:00
|
|
|
inspector->Set(
|
2020-09-16 09:54:02 +00:00
|
|
|
isolate, "freeContext",
|
2017-08-01 21:17:31 +00:00
|
|
|
v8::FunctionTemplate::New(isolate, &InspectorExtension::FreeContext));
|
2020-09-16 09:54:02 +00:00
|
|
|
inspector->Set(isolate, "addInspectedObject",
|
2017-06-05 17:37:25 +00:00
|
|
|
v8::FunctionTemplate::New(
|
|
|
|
isolate, &InspectorExtension::AddInspectedObject));
|
2020-09-16 09:54:02 +00:00
|
|
|
inspector->Set(isolate, "setMaxAsyncTaskStacks",
|
2017-04-21 23:41:07 +00:00
|
|
|
v8::FunctionTemplate::New(
|
|
|
|
isolate, &InspectorExtension::SetMaxAsyncTaskStacks));
|
|
|
|
inspector->Set(
|
2020-09-16 09:54:02 +00:00
|
|
|
isolate, "dumpAsyncTaskStacksStateForTest",
|
2017-04-21 23:41:07 +00:00
|
|
|
v8::FunctionTemplate::New(
|
|
|
|
isolate, &InspectorExtension::DumpAsyncTaskStacksStateForTest));
|
|
|
|
inspector->Set(
|
2020-09-16 09:54:02 +00:00
|
|
|
isolate, "breakProgram",
|
2017-04-21 23:41:07 +00:00
|
|
|
v8::FunctionTemplate::New(isolate, &InspectorExtension::BreakProgram));
|
|
|
|
inspector->Set(
|
2020-09-16 09:54:02 +00:00
|
|
|
isolate, "createObjectWithStrictCheck",
|
2017-04-21 23:41:07 +00:00
|
|
|
v8::FunctionTemplate::New(
|
|
|
|
isolate, &InspectorExtension::CreateObjectWithStrictCheck));
|
2020-09-16 09:54:02 +00:00
|
|
|
inspector->Set(isolate, "callWithScheduledBreak",
|
2017-04-21 23:41:07 +00:00
|
|
|
v8::FunctionTemplate::New(
|
|
|
|
isolate, &InspectorExtension::CallWithScheduledBreak));
|
2017-08-23 19:40:46 +00:00
|
|
|
inspector->Set(
|
2020-09-16 09:54:02 +00:00
|
|
|
isolate, "markObjectAsNotInspectable",
|
2017-08-23 19:40:46 +00:00
|
|
|
v8::FunctionTemplate::New(
|
|
|
|
isolate, &InspectorExtension::MarkObjectAsNotInspectable));
|
2020-09-16 09:54:02 +00:00
|
|
|
inspector->Set(isolate, "createObjectWithAccessor",
|
2017-11-06 16:22:10 +00:00
|
|
|
v8::FunctionTemplate::New(
|
|
|
|
isolate, &InspectorExtension::CreateObjectWithAccessor));
|
2020-09-16 09:54:02 +00:00
|
|
|
inspector->Set(isolate, "storeCurrentStackTrace",
|
2017-11-22 19:46:33 +00:00
|
|
|
v8::FunctionTemplate::New(
|
|
|
|
isolate, &InspectorExtension::StoreCurrentStackTrace));
|
2020-09-16 09:54:02 +00:00
|
|
|
inspector->Set(isolate, "externalAsyncTaskStarted",
|
2017-11-22 19:46:33 +00:00
|
|
|
v8::FunctionTemplate::New(
|
|
|
|
isolate, &InspectorExtension::ExternalAsyncTaskStarted));
|
|
|
|
inspector->Set(
|
2020-09-16 09:54:02 +00:00
|
|
|
isolate, "externalAsyncTaskFinished",
|
2017-11-22 19:46:33 +00:00
|
|
|
v8::FunctionTemplate::New(
|
|
|
|
isolate, &InspectorExtension::ExternalAsyncTaskFinished));
|
2020-09-16 09:54:02 +00:00
|
|
|
inspector->Set(isolate, "scheduleWithAsyncStack",
|
2017-12-14 19:49:25 +00:00
|
|
|
v8::FunctionTemplate::New(
|
|
|
|
isolate, &InspectorExtension::ScheduleWithAsyncStack));
|
2018-02-15 01:41:33 +00:00
|
|
|
inspector->Set(
|
2020-09-16 09:54:02 +00:00
|
|
|
isolate, "setAllowCodeGenerationFromStrings",
|
2018-02-15 01:41:33 +00:00
|
|
|
v8::FunctionTemplate::New(
|
|
|
|
isolate, &InspectorExtension::SetAllowCodeGenerationFromStrings));
|
2020-09-16 09:54:02 +00:00
|
|
|
inspector->Set(isolate, "setResourceNamePrefix",
|
2018-08-09 17:27:00 +00:00
|
|
|
v8::FunctionTemplate::New(
|
|
|
|
isolate, &InspectorExtension::SetResourceNamePrefix));
|
2021-06-17 06:41:11 +00:00
|
|
|
inspector->Set(isolate, "newExceptionWithMetaData",
|
|
|
|
v8::FunctionTemplate::New(
|
|
|
|
isolate, &InspectorExtension::newExceptionWithMetaData));
|
2020-09-16 09:54:02 +00:00
|
|
|
global->Set(isolate, "inspector", inspector);
|
2016-10-26 20:26:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2017-05-18 23:11:20 +00:00
|
|
|
static void FireContextCreated(
|
|
|
|
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
|
v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
|
2021-08-24 13:00:06 +00:00
|
|
|
InspectorIsolateData* data = InspectorIsolateData::FromContext(context);
|
2020-09-30 22:20:01 +00:00
|
|
|
data->FireContextCreated(context, data->GetContextGroupId(context),
|
|
|
|
v8_inspector::StringView());
|
2016-10-26 20:26:56 +00:00
|
|
|
}
|
|
|
|
|
2017-05-18 23:11:20 +00:00
|
|
|
static void FireContextDestroyed(
|
|
|
|
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
|
v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
|
2021-08-24 13:00:06 +00:00
|
|
|
InspectorIsolateData* data = InspectorIsolateData::FromContext(context);
|
2017-05-22 00:48:27 +00:00
|
|
|
data->FireContextDestroyed(context);
|
2016-10-26 20:26:56 +00:00
|
|
|
}
|
2016-12-18 17:04:40 +00:00
|
|
|
|
2017-08-01 21:17:31 +00:00
|
|
|
static void FreeContext(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
|
v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
|
2021-08-24 13:00:06 +00:00
|
|
|
InspectorIsolateData* data = InspectorIsolateData::FromContext(context);
|
2017-08-01 21:17:31 +00:00
|
|
|
data->FreeContext(context);
|
|
|
|
}
|
|
|
|
|
2017-06-05 17:37:25 +00:00
|
|
|
static void AddInspectedObject(
|
|
|
|
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
|
if (args.Length() != 2 || !args[0]->IsInt32()) {
|
2020-11-04 17:42:04 +00:00
|
|
|
FATAL("Internal error: addInspectedObject(session_id, object).");
|
2017-06-05 17:37:25 +00:00
|
|
|
}
|
|
|
|
v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
|
2021-08-24 13:00:06 +00:00
|
|
|
InspectorIsolateData* data = InspectorIsolateData::FromContext(context);
|
2017-06-05 17:37:25 +00:00
|
|
|
data->AddInspectedObject(args[0].As<v8::Int32>()->Value(), args[1]);
|
|
|
|
}
|
|
|
|
|
2016-12-18 17:04:40 +00:00
|
|
|
static void SetMaxAsyncTaskStacks(
|
|
|
|
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
|
if (args.Length() != 1 || !args[0]->IsInt32()) {
|
2020-11-04 17:42:04 +00:00
|
|
|
FATAL("Internal error: setMaxAsyncTaskStacks(max).");
|
2016-12-18 17:04:40 +00:00
|
|
|
}
|
2021-08-24 13:00:06 +00:00
|
|
|
InspectorIsolateData::FromContext(args.GetIsolate()->GetCurrentContext())
|
2017-05-22 20:46:42 +00:00
|
|
|
->SetMaxAsyncTaskStacksForTest(args[0].As<v8::Int32>()->Value());
|
2016-12-18 17:04:40 +00:00
|
|
|
}
|
2017-01-18 16:57:00 +00:00
|
|
|
|
2017-04-20 15:49:02 +00:00
|
|
|
static void DumpAsyncTaskStacksStateForTest(
|
|
|
|
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
|
if (args.Length() != 0) {
|
2020-11-04 17:42:04 +00:00
|
|
|
FATAL("Internal error: dumpAsyncTaskStacksStateForTest().");
|
2017-04-20 15:49:02 +00:00
|
|
|
}
|
2021-08-24 13:00:06 +00:00
|
|
|
InspectorIsolateData::FromContext(args.GetIsolate()->GetCurrentContext())
|
2017-05-22 20:46:42 +00:00
|
|
|
->DumpAsyncTaskStacksStateForTest();
|
2017-04-20 15:49:02 +00:00
|
|
|
}
|
|
|
|
|
2017-01-18 16:57:00 +00:00
|
|
|
static void BreakProgram(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
|
if (args.Length() != 2 || !args[0]->IsString() || !args[1]->IsString()) {
|
2020-11-04 17:42:04 +00:00
|
|
|
FATAL("Internal error: breakProgram('reason', 'details').");
|
2017-01-18 16:57:00 +00:00
|
|
|
}
|
2017-05-18 23:11:20 +00:00
|
|
|
v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
|
2021-08-24 13:00:06 +00:00
|
|
|
InspectorIsolateData* data = InspectorIsolateData::FromContext(context);
|
2018-07-30 16:24:40 +00:00
|
|
|
std::vector<uint16_t> reason =
|
2018-07-23 02:35:30 +00:00
|
|
|
ToVector(args.GetIsolate(), args[0].As<v8::String>());
|
2018-07-30 16:24:40 +00:00
|
|
|
v8_inspector::StringView reason_view(reason.data(), reason.size());
|
|
|
|
std::vector<uint16_t> details =
|
2018-07-23 02:35:30 +00:00
|
|
|
ToVector(args.GetIsolate(), args[1].As<v8::String>());
|
2018-07-30 16:24:40 +00:00
|
|
|
v8_inspector::StringView details_view(details.data(), details.size());
|
2017-05-22 00:48:27 +00:00
|
|
|
data->BreakProgram(data->GetContextGroupId(context), reason_view,
|
|
|
|
details_view);
|
2017-01-18 16:57:00 +00:00
|
|
|
}
|
2017-02-04 01:21:58 +00:00
|
|
|
|
|
|
|
static void CreateObjectWithStrictCheck(
|
|
|
|
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
|
if (args.Length() != 0) {
|
2020-11-04 17:42:04 +00:00
|
|
|
FATAL("Internal error: createObjectWithStrictCheck().");
|
2017-02-04 01:21:58 +00:00
|
|
|
}
|
|
|
|
v8::Local<v8::ObjectTemplate> templ =
|
|
|
|
v8::ObjectTemplate::New(args.GetIsolate());
|
|
|
|
templ->SetAccessCheckCallback(&StrictAccessCheck);
|
|
|
|
args.GetReturnValue().Set(
|
|
|
|
templ->NewInstance(args.GetIsolate()->GetCurrentContext())
|
|
|
|
.ToLocalChecked());
|
|
|
|
}
|
2017-02-08 01:42:54 +00:00
|
|
|
|
|
|
|
static void CallWithScheduledBreak(
|
|
|
|
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
|
if (args.Length() != 3 || !args[0]->IsFunction() || !args[1]->IsString() ||
|
|
|
|
!args[2]->IsString()) {
|
2020-11-04 17:42:04 +00:00
|
|
|
FATAL("Internal error: callWithScheduledBreak('reason', 'details').");
|
2017-02-08 01:42:54 +00:00
|
|
|
}
|
2018-07-30 16:24:40 +00:00
|
|
|
std::vector<uint16_t> reason =
|
2018-07-23 02:35:30 +00:00
|
|
|
ToVector(args.GetIsolate(), args[1].As<v8::String>());
|
2018-07-30 16:24:40 +00:00
|
|
|
v8_inspector::StringView reason_view(reason.data(), reason.size());
|
|
|
|
std::vector<uint16_t> details =
|
2018-07-23 02:35:30 +00:00
|
|
|
ToVector(args.GetIsolate(), args[2].As<v8::String>());
|
2018-07-30 16:24:40 +00:00
|
|
|
v8_inspector::StringView details_view(details.data(), details.size());
|
2017-02-08 01:42:54 +00:00
|
|
|
v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
|
2021-08-24 13:00:06 +00:00
|
|
|
InspectorIsolateData* data = InspectorIsolateData::FromContext(context);
|
2017-05-18 23:11:20 +00:00
|
|
|
int context_group_id = data->GetContextGroupId(context);
|
2017-05-22 00:48:27 +00:00
|
|
|
data->SchedulePauseOnNextStatement(context_group_id, reason_view,
|
|
|
|
details_view);
|
2017-02-08 01:42:54 +00:00
|
|
|
v8::MaybeLocal<v8::Value> result;
|
|
|
|
result = args[0].As<v8::Function>()->Call(context, context->Global(), 0,
|
|
|
|
nullptr);
|
2017-05-22 00:48:27 +00:00
|
|
|
data->CancelPauseOnNextStatement(context_group_id);
|
2017-02-08 01:42:54 +00:00
|
|
|
}
|
2017-03-03 19:30:40 +00:00
|
|
|
|
2017-08-23 19:40:46 +00:00
|
|
|
static void MarkObjectAsNotInspectable(
|
|
|
|
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
|
if (args.Length() != 1 || !args[0]->IsObject()) {
|
2020-11-04 17:42:04 +00:00
|
|
|
FATAL("Internal error: markObjectAsNotInspectable(object).");
|
2017-08-23 19:40:46 +00:00
|
|
|
}
|
|
|
|
v8::Local<v8::Object> object = args[0].As<v8::Object>();
|
|
|
|
v8::Isolate* isolate = args.GetIsolate();
|
|
|
|
v8::Local<v8::Private> notInspectablePrivate =
|
|
|
|
v8::Private::ForApi(isolate, ToV8String(isolate, "notInspectable"));
|
|
|
|
object
|
|
|
|
->SetPrivate(isolate->GetCurrentContext(), notInspectablePrivate,
|
|
|
|
v8::True(isolate))
|
|
|
|
.ToChecked();
|
|
|
|
}
|
2017-11-06 16:22:10 +00:00
|
|
|
|
|
|
|
static void CreateObjectWithAccessor(
|
|
|
|
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
|
if (args.Length() != 2 || !args[0]->IsString() || !args[1]->IsBoolean()) {
|
2020-11-04 17:42:04 +00:00
|
|
|
FATAL(
|
|
|
|
"Internal error: createObjectWithAccessor('accessor name', "
|
|
|
|
"hasSetter)\n");
|
2017-11-06 16:22:10 +00:00
|
|
|
}
|
|
|
|
v8::Isolate* isolate = args.GetIsolate();
|
|
|
|
v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
|
|
|
|
if (args[1].As<v8::Boolean>()->Value()) {
|
|
|
|
templ->SetAccessor(v8::Local<v8::String>::Cast(args[0]), AccessorGetter,
|
|
|
|
AccessorSetter);
|
|
|
|
} else {
|
|
|
|
templ->SetAccessor(v8::Local<v8::String>::Cast(args[0]), AccessorGetter);
|
|
|
|
}
|
|
|
|
args.GetReturnValue().Set(
|
|
|
|
templ->NewInstance(isolate->GetCurrentContext()).ToLocalChecked());
|
|
|
|
}
|
|
|
|
|
|
|
|
static void AccessorGetter(v8::Local<v8::String> property,
|
|
|
|
const v8::PropertyCallbackInfo<v8::Value>& info) {
|
|
|
|
v8::Isolate* isolate = info.GetIsolate();
|
2021-04-15 08:10:06 +00:00
|
|
|
isolate->ThrowError("Getter is called");
|
2017-11-06 16:22:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void AccessorSetter(v8::Local<v8::String> property,
|
|
|
|
v8::Local<v8::Value> value,
|
|
|
|
const v8::PropertyCallbackInfo<void>& info) {
|
|
|
|
v8::Isolate* isolate = info.GetIsolate();
|
2021-04-15 08:10:06 +00:00
|
|
|
isolate->ThrowError("Setter is called");
|
2017-11-06 16:22:10 +00:00
|
|
|
}
|
2017-11-22 19:46:33 +00:00
|
|
|
|
|
|
|
static void StoreCurrentStackTrace(
|
|
|
|
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
|
if (args.Length() != 1 || !args[0]->IsString()) {
|
2020-11-04 17:42:04 +00:00
|
|
|
FATAL("Internal error: storeCurrentStackTrace('description')\n");
|
2017-11-22 19:46:33 +00:00
|
|
|
}
|
|
|
|
v8::Isolate* isolate = args.GetIsolate();
|
|
|
|
v8::Local<v8::Context> context = isolate->GetCurrentContext();
|
2021-08-24 13:00:06 +00:00
|
|
|
InspectorIsolateData* data = InspectorIsolateData::FromContext(context);
|
2018-07-30 16:24:40 +00:00
|
|
|
std::vector<uint16_t> description =
|
2018-07-23 02:35:30 +00:00
|
|
|
ToVector(isolate, args[0].As<v8::String>());
|
2018-07-30 16:24:40 +00:00
|
|
|
v8_inspector::StringView description_view(description.data(),
|
|
|
|
description.size());
|
2017-11-22 19:46:33 +00:00
|
|
|
v8_inspector::V8StackTraceId id =
|
|
|
|
data->StoreCurrentStackTrace(description_view);
|
|
|
|
v8::Local<v8::ArrayBuffer> buffer =
|
|
|
|
v8::ArrayBuffer::New(isolate, sizeof(id));
|
2019-09-18 11:04:58 +00:00
|
|
|
*static_cast<v8_inspector::V8StackTraceId*>(
|
|
|
|
buffer->GetBackingStore()->Data()) = id;
|
2017-11-22 19:46:33 +00:00
|
|
|
args.GetReturnValue().Set(buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ExternalAsyncTaskStarted(
|
|
|
|
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
|
if (args.Length() != 1 || !args[0]->IsArrayBuffer()) {
|
2020-11-04 17:42:04 +00:00
|
|
|
FATAL("Internal error: externalAsyncTaskStarted(id)\n");
|
2017-11-22 19:46:33 +00:00
|
|
|
}
|
|
|
|
v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
|
2021-08-24 13:00:06 +00:00
|
|
|
InspectorIsolateData* data = InspectorIsolateData::FromContext(context);
|
2017-11-22 19:46:33 +00:00
|
|
|
v8_inspector::V8StackTraceId* id =
|
|
|
|
static_cast<v8_inspector::V8StackTraceId*>(
|
2019-09-18 11:04:58 +00:00
|
|
|
args[0].As<v8::ArrayBuffer>()->GetBackingStore()->Data());
|
2017-11-22 19:46:33 +00:00
|
|
|
data->ExternalAsyncTaskStarted(*id);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ExternalAsyncTaskFinished(
|
|
|
|
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
|
if (args.Length() != 1 || !args[0]->IsArrayBuffer()) {
|
2020-11-04 17:42:04 +00:00
|
|
|
FATAL("Internal error: externalAsyncTaskFinished(id)\n");
|
2017-11-22 19:46:33 +00:00
|
|
|
}
|
|
|
|
v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
|
2021-08-24 13:00:06 +00:00
|
|
|
InspectorIsolateData* data = InspectorIsolateData::FromContext(context);
|
2017-11-22 19:46:33 +00:00
|
|
|
v8_inspector::V8StackTraceId* id =
|
|
|
|
static_cast<v8_inspector::V8StackTraceId*>(
|
2019-09-18 11:04:58 +00:00
|
|
|
args[0].As<v8::ArrayBuffer>()->GetBackingStore()->Data());
|
2017-11-22 19:46:33 +00:00
|
|
|
data->ExternalAsyncTaskFinished(*id);
|
|
|
|
}
|
2017-12-14 19:49:25 +00:00
|
|
|
|
|
|
|
static void ScheduleWithAsyncStack(
|
|
|
|
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
|
if (args.Length() != 3 || !args[0]->IsFunction() || !args[1]->IsString() ||
|
|
|
|
!args[2]->IsBoolean()) {
|
2020-11-04 17:42:04 +00:00
|
|
|
FATAL(
|
|
|
|
"Internal error: scheduleWithAsyncStack(function, 'task-name', "
|
|
|
|
"with_empty_stack).");
|
2017-12-14 19:49:25 +00:00
|
|
|
}
|
|
|
|
v8::Isolate* isolate = args.GetIsolate();
|
|
|
|
v8::Local<v8::Context> context = isolate->GetCurrentContext();
|
2021-08-24 13:00:06 +00:00
|
|
|
InspectorIsolateData* data = InspectorIsolateData::FromContext(context);
|
2017-12-14 19:49:25 +00:00
|
|
|
int context_group_id = data->GetContextGroupId(context);
|
|
|
|
bool with_empty_stack = args[2].As<v8::Boolean>()->Value();
|
|
|
|
if (with_empty_stack) context->Exit();
|
|
|
|
|
2018-07-30 16:24:40 +00:00
|
|
|
std::vector<uint16_t> task_name =
|
2018-07-23 02:35:30 +00:00
|
|
|
ToVector(isolate, args[1].As<v8::String>());
|
2018-07-30 16:24:40 +00:00
|
|
|
v8_inspector::StringView task_name_view(task_name.data(), task_name.size());
|
2017-12-14 19:49:25 +00:00
|
|
|
|
2020-11-05 16:15:32 +00:00
|
|
|
RunAsyncTask(
|
|
|
|
data->task_runner(), task_name_view,
|
|
|
|
std::make_unique<SetTimeoutTask>(
|
|
|
|
context_group_id, isolate, v8::Local<v8::Function>::Cast(args[0])));
|
2017-12-14 19:49:25 +00:00
|
|
|
if (with_empty_stack) context->Enter();
|
|
|
|
}
|
2018-02-15 01:41:33 +00:00
|
|
|
|
|
|
|
static void SetAllowCodeGenerationFromStrings(
|
|
|
|
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
|
if (args.Length() != 1 || !args[0]->IsBoolean()) {
|
2020-11-04 17:42:04 +00:00
|
|
|
FATAL("Internal error: setAllowCodeGenerationFromStrings(allow).");
|
2018-02-15 01:41:33 +00:00
|
|
|
}
|
|
|
|
args.GetIsolate()->GetCurrentContext()->AllowCodeGenerationFromStrings(
|
|
|
|
args[0].As<v8::Boolean>()->Value());
|
|
|
|
}
|
2018-08-09 17:27:00 +00:00
|
|
|
static void SetResourceNamePrefix(
|
|
|
|
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
|
if (args.Length() != 1 || !args[0]->IsString()) {
|
2020-11-04 17:42:04 +00:00
|
|
|
FATAL("Internal error: setResourceNamePrefix('prefix').");
|
2018-08-09 17:27:00 +00:00
|
|
|
}
|
|
|
|
v8::Isolate* isolate = args.GetIsolate();
|
|
|
|
v8::Local<v8::Context> context = isolate->GetCurrentContext();
|
2021-08-24 13:00:06 +00:00
|
|
|
InspectorIsolateData* data = InspectorIsolateData::FromContext(context);
|
2018-08-09 17:27:00 +00:00
|
|
|
data->SetResourceNamePrefix(v8::Local<v8::String>::Cast(args[0]));
|
|
|
|
}
|
2021-06-17 06:41:11 +00:00
|
|
|
|
|
|
|
static void newExceptionWithMetaData(
|
|
|
|
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
|
if (args.Length() != 3 || !args[0]->IsString() || !args[1]->IsString() ||
|
|
|
|
!args[2]->IsString()) {
|
|
|
|
FATAL(
|
|
|
|
"Internal error: newExceptionWithMetaData('message', 'key', "
|
|
|
|
"'value').");
|
|
|
|
}
|
|
|
|
v8::Isolate* isolate = args.GetIsolate();
|
|
|
|
v8::Local<v8::Context> context = isolate->GetCurrentContext();
|
2021-08-24 13:00:06 +00:00
|
|
|
InspectorIsolateData* data = InspectorIsolateData::FromContext(context);
|
2021-06-17 06:41:11 +00:00
|
|
|
|
|
|
|
auto error = v8::Exception::Error(args[0].As<v8::String>());
|
|
|
|
CHECK(data->AssociateExceptionData(error, args[1].As<v8::String>(),
|
|
|
|
args[2].As<v8::String>()));
|
|
|
|
args.GetReturnValue().Set(error);
|
|
|
|
}
|
2016-10-26 20:26:56 +00:00
|
|
|
};
|
|
|
|
|
2020-10-27 13:52:22 +00:00
|
|
|
int InspectorTestMain(int argc, char* argv[]) {
|
2016-10-02 18:10:27 +00:00
|
|
|
v8::V8::InitializeICUDefaultLocation(argv[0]);
|
2020-10-27 13:52:22 +00:00
|
|
|
std::unique_ptr<Platform> platform(platform::NewDefaultPlatform());
|
2017-11-13 13:16:49 +00:00
|
|
|
v8::V8::InitializePlatform(platform.get());
|
V8 Sandbox rebranding
This CL renames a number of things related to the V8 sandbox.
Mainly, what used to be under V8_HEAP_SANDBOX is now under
V8_SANDBOXED_EXTERNAL_POINTERS, while the previous V8 VirtualMemoryCage
is now simply the V8 Sandbox:
V8_VIRTUAL_MEMORY_CAGE => V8_SANDBOX
V8_HEAP_SANDBOX => V8_SANDBOXED_EXTERNAL_POINTERS
V8_CAGED_POINTERS => V8_SANDBOXED_POINTERS
V8VirtualMemoryCage => Sandbox
CagedPointer => SandboxedPointer
fake cage => partially reserved sandbox
src/security => src/sandbox
This naming scheme should simplify things: the sandbox is now the large
region of virtual address space inside which V8 mainly operates and
which should be considered untrusted. Mechanisms like sandboxed pointers
are then used to attempt to prevent escapes from the sandbox (i.e.
corruption of memory outside of it). Furthermore, the new naming scheme
avoids the confusion with the various other "cages" in V8, in
particular, the VirtualMemoryCage class, by dropping that name entirely.
Future sandbox features are developed under their own V8_SANDBOX_X flag,
and will, once final, be merged into V8_SANDBOX. Current future features
are sandboxed external pointers (using the external pointer table), and
sandboxed pointers (pointers guaranteed to point into the sandbox, e.g.
because they are encoded as offsets). This CL then also introduces a new
build flag, v8_enable_sandbox_future, which enables all future features.
Bug: v8:10391
Change-Id: I5174ea8f5ab40fb96a04af10853da735ad775c96
Cq-Include-Trybots: luci.v8.try:v8_linux64_heap_sandbox_dbg_ng,v8_linux_arm64_sim_heap_sandbox_dbg_ng
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3322981
Reviewed-by: Hannes Payer <hpayer@chromium.org>
Reviewed-by: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Michael Achenbach <machenbach@chromium.org>
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Commit-Queue: Samuel Groß <saelo@chromium.org>
Cr-Commit-Position: refs/heads/main@{#78384}
2021-12-15 13:39:15 +00:00
|
|
|
#ifdef V8_SANDBOX
|
|
|
|
if (!v8::V8::InitializeSandbox()) {
|
|
|
|
FATAL("Could not initialize the sandbox");
|
2021-08-24 19:12:19 +00:00
|
|
|
}
|
|
|
|
#endif
|
2020-10-27 13:52:22 +00:00
|
|
|
FLAG_abort_on_contradictory_flags = true;
|
2016-10-18 20:07:41 +00:00
|
|
|
v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
|
2016-10-02 18:10:27 +00:00
|
|
|
v8::V8::InitializeExternalStartupData(argv[0]);
|
|
|
|
v8::V8::Initialize();
|
2018-11-15 12:49:20 +00:00
|
|
|
i::DisableEmbeddedBlobRefcounting();
|
2016-10-02 18:10:27 +00:00
|
|
|
|
2020-10-27 13:52:22 +00:00
|
|
|
base::Semaphore ready_semaphore(0);
|
2016-10-02 18:10:27 +00:00
|
|
|
|
2020-10-27 13:52:22 +00:00
|
|
|
StartupData startup_data = {nullptr, 0};
|
2017-04-26 15:13:14 +00:00
|
|
|
for (int i = 1; i < argc; ++i) {
|
|
|
|
if (strcmp(argv[i], "--embed") == 0) {
|
|
|
|
argv[i++] = nullptr;
|
|
|
|
printf("Embedding script '%s'\n", argv[i]);
|
2019-05-16 12:19:13 +00:00
|
|
|
startup_data = i::CreateSnapshotDataBlobInternal(
|
2020-10-27 13:52:22 +00:00
|
|
|
SnapshotCreator::FunctionCodeHandling::kClear, argv[i], nullptr);
|
2017-04-26 15:13:14 +00:00
|
|
|
argv[i] = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-15 12:49:20 +00:00
|
|
|
{
|
2021-08-24 13:00:06 +00:00
|
|
|
InspectorIsolateData::SetupGlobalTasks frontend_extensions;
|
2018-11-15 12:49:20 +00:00
|
|
|
frontend_extensions.emplace_back(new UtilsExtension());
|
2022-02-08 14:48:01 +00:00
|
|
|
frontend_extensions.emplace_back(new ConsoleExtension());
|
2020-11-12 12:57:48 +00:00
|
|
|
TaskRunner frontend_runner(std::move(frontend_extensions),
|
|
|
|
kFailOnUncaughtExceptions, &ready_semaphore,
|
|
|
|
startup_data.data ? &startup_data : nullptr,
|
|
|
|
kNoInspector);
|
2018-11-15 12:49:20 +00:00
|
|
|
ready_semaphore.Wait();
|
|
|
|
|
|
|
|
int frontend_context_group_id = 0;
|
|
|
|
RunSyncTask(&frontend_runner,
|
2021-08-24 13:00:06 +00:00
|
|
|
[&frontend_context_group_id](InspectorIsolateData* data) {
|
2018-11-15 12:49:20 +00:00
|
|
|
frontend_context_group_id = data->CreateContextGroup();
|
|
|
|
});
|
2017-05-18 23:11:20 +00:00
|
|
|
|
2021-08-24 13:00:06 +00:00
|
|
|
InspectorIsolateData::SetupGlobalTasks backend_extensions;
|
2018-11-15 12:49:20 +00:00
|
|
|
backend_extensions.emplace_back(new SetTimeoutExtension());
|
2022-02-08 14:48:01 +00:00
|
|
|
backend_extensions.emplace_back(new ConsoleExtension());
|
2018-11-15 12:49:20 +00:00
|
|
|
backend_extensions.emplace_back(new InspectorExtension());
|
|
|
|
TaskRunner backend_runner(
|
2020-11-12 12:57:48 +00:00
|
|
|
std::move(backend_extensions), kStandardPropagateUncaughtExceptions,
|
|
|
|
&ready_semaphore, startup_data.data ? &startup_data : nullptr,
|
|
|
|
kWithInspector);
|
2018-11-15 12:49:20 +00:00
|
|
|
ready_semaphore.Wait();
|
|
|
|
UtilsExtension::set_backend_task_runner(&backend_runner);
|
|
|
|
|
2020-11-05 17:00:11 +00:00
|
|
|
task_runners = {&frontend_runner, &backend_runner};
|
2018-11-15 12:49:20 +00:00
|
|
|
|
|
|
|
for (int i = 1; i < argc; ++i) {
|
|
|
|
// Ignore unknown flags.
|
|
|
|
if (argv[i] == nullptr || argv[i][0] == '-') continue;
|
|
|
|
|
|
|
|
bool exists = false;
|
2020-10-27 13:52:22 +00:00
|
|
|
std::string chars = ReadFile(argv[i], &exists, true);
|
2018-11-15 12:49:20 +00:00
|
|
|
if (!exists) {
|
2020-11-04 17:42:04 +00:00
|
|
|
FATAL("Internal error: script file doesn't exists: %s\n", argv[i]);
|
2018-11-15 12:49:20 +00:00
|
|
|
}
|
2020-11-05 16:15:32 +00:00
|
|
|
frontend_runner.Append(std::make_unique<ExecuteStringTask>(
|
|
|
|
chars, frontend_context_group_id));
|
2018-11-15 12:49:20 +00:00
|
|
|
}
|
2016-10-02 18:10:27 +00:00
|
|
|
|
2018-11-15 12:49:20 +00:00
|
|
|
frontend_runner.Join();
|
|
|
|
backend_runner.Join();
|
2016-10-19 02:04:34 +00:00
|
|
|
|
2018-11-15 12:49:20 +00:00
|
|
|
UtilsExtension::ClearAllSessions();
|
2020-11-06 12:25:53 +00:00
|
|
|
delete[] startup_data.data;
|
2016-10-02 18:10:27 +00:00
|
|
|
|
2018-11-15 12:49:20 +00:00
|
|
|
// TaskRunners go out of scope here, which causes Isolate teardown and all
|
|
|
|
// running background tasks to be properly joined.
|
2016-10-02 18:10:27 +00:00
|
|
|
}
|
|
|
|
|
2018-11-15 12:49:20 +00:00
|
|
|
i::FreeCurrentEmbeddedBlob();
|
2016-10-02 18:10:27 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2020-10-27 13:52:22 +00:00
|
|
|
} // namespace
|
|
|
|
|
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|
|
|
|
|
|
|
|
int main(int argc, char* argv[]) {
|
|
|
|
return v8::internal::InspectorTestMain(argc, argv);
|
|
|
|
}
|