node/test/cctest/test_platform.cc
Joyee Cheung 9aa1afb527
src: use V8-owned CppHeap
As V8 is moving towards built-in CppHeap creation, change the
management so that the automatic CppHeap creation on Node.js's end
is also enforced at Isolate creation time.

1. If embedder uses NewIsolate(), either they use
  IsolateSettings::cpp_heap to specify a CppHeap that will be owned
  by V8, or if it's not configured, Node.js will create a CppHeap
  that will be owned by V8.
2. If the embedder uses SetIsolateUpForNode(),
  IsolateSettings::cpp_heap will be ignored (as V8 has deprecated
  attaching CppHeap post-isolate-creation). The embedders need to
  ensure that the v8::Isolate has a CppHeap attached while it's
  still used by Node.js, preferably using v8::CreateParams.

See https://issues.chromium.org/issues/42203693 for details. In
future version of V8, this CppHeap will be created by V8 if not
provided, and we can remove our own "if no CppHeap provided,
create one" code in NewIsolate().

PR-URL: https://github.com/nodejs/node/pull/58070
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Darshan Sen <raisinten@gmail.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
2025-05-02 15:10:38 +02:00

131 lines
4.4 KiB
C++

#include "node_internals.h"
#include "libplatform/libplatform.h"
#include <string>
#include "gtest/gtest.h"
#include "node_test_fixture.h"
// This task increments the given run counter and reposts itself until the
// repost counter reaches zero.
class RepostingTask : public v8::Task {
public:
explicit RepostingTask(int repost_count,
int* run_count,
v8::Isolate* isolate,
node::NodePlatform* platform)
: repost_count_(repost_count),
run_count_(run_count),
isolate_(isolate),
platform_(platform) {}
// v8::Task implementation
void Run() final {
++*run_count_;
if (repost_count_ > 0) {
--repost_count_;
std::shared_ptr<v8::TaskRunner> task_runner =
platform_->GetForegroundTaskRunner(isolate_,
v8::TaskPriority::kUserBlocking);
task_runner->PostTask(std::make_unique<RepostingTask>(
repost_count_, run_count_, isolate_, platform_));
}
}
private:
int repost_count_;
int* run_count_;
v8::Isolate* isolate_;
node::NodePlatform* platform_;
};
class PlatformTest : public EnvironmentTestFixture {};
TEST_F(PlatformTest, SkipNewTasksInFlushForegroundTasks) {
v8::Isolate::Scope isolate_scope(isolate_);
const v8::HandleScope handle_scope(isolate_);
const Argv argv;
Env env {handle_scope, argv};
int run_count = 0;
std::shared_ptr<v8::TaskRunner> task_runner =
platform->GetForegroundTaskRunner(isolate_,
v8::TaskPriority::kUserBlocking);
task_runner->PostTask(
std::make_unique<RepostingTask>(2, &run_count, isolate_, platform.get()));
EXPECT_TRUE(platform->FlushForegroundTasks(isolate_));
EXPECT_EQ(1, run_count);
EXPECT_TRUE(platform->FlushForegroundTasks(isolate_));
EXPECT_EQ(2, run_count);
EXPECT_TRUE(platform->FlushForegroundTasks(isolate_));
EXPECT_EQ(3, run_count);
EXPECT_FALSE(platform->FlushForegroundTasks(isolate_));
}
// Tests the registration of an abstract `IsolatePlatformDelegate` instance as
// opposed to the more common `uv_loop_s*` version of `RegisterIsolate`.
TEST_F(NodeZeroIsolateTestFixture, IsolatePlatformDelegateTest) {
// Allocate isolate
v8::Isolate::CreateParams create_params;
create_params.array_buffer_allocator = allocator.get();
create_params.cpp_heap =
v8::CppHeap::Create(platform.get(), v8::CppHeapCreateParams{{}})
.release();
auto isolate = v8::Isolate::Allocate();
CHECK_NOT_NULL(isolate);
// Register *first*, then initialize
auto delegate = std::make_shared<node::PerIsolatePlatformData>(
isolate,
&current_loop);
platform->RegisterIsolate(isolate, delegate.get());
v8::Isolate::Initialize(isolate, create_params);
// Try creating Context + IsolateData + Environment
{
v8::Locker locker(isolate);
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope handle_scope(isolate);
auto context = node::NewContext(isolate);
CHECK(!context.IsEmpty());
v8::Context::Scope context_scope(context);
std::unique_ptr<node::IsolateData, decltype(&node::FreeIsolateData)>
isolate_data{node::CreateIsolateData(isolate,
&current_loop,
platform.get()),
node::FreeIsolateData};
CHECK(isolate_data);
std::unique_ptr<node::Environment, decltype(&node::FreeEnvironment)>
environment{node::CreateEnvironment(isolate_data.get(),
context,
{},
{}),
node::FreeEnvironment};
CHECK(environment);
}
// Graceful shutdown
delegate->Shutdown();
isolate->Dispose();
platform->UnregisterIsolate(isolate);
}
TEST_F(PlatformTest, TracingControllerNullptr) {
v8::TracingController* orig_controller = node::GetTracingController();
node::SetTracingController(nullptr);
EXPECT_EQ(node::GetTracingController(), nullptr);
v8::Isolate::Scope isolate_scope(isolate_);
const v8::HandleScope handle_scope(isolate_);
const Argv argv;
Env env {handle_scope, argv};
node::LoadEnvironment(*env, [&](const node::StartExecutionCallbackInfo& info)
-> v8::MaybeLocal<v8::Value> {
return v8::Null(isolate_);
});
node::SetTracingController(orig_controller);
EXPECT_EQ(node::GetTracingController(), orig_controller);
}