%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /home/vacivi36/vittasync.vacivitta.com.br/vittasync/node/src/api/
Upload File :
Create Path :
Current File : /home/vacivi36/vittasync.vacivitta.com.br/vittasync/node/src/api/embed_helpers.cc

#include "debug_utils-inl.h"
#include "env-inl.h"
#include "node.h"
#include "node_snapshot_builder.h"

using v8::Context;
using v8::Function;
using v8::Global;
using v8::HandleScope;
using v8::Isolate;
using v8::Just;
using v8::Local;
using v8::Locker;
using v8::Maybe;
using v8::Nothing;
using v8::SealHandleScope;
using v8::SnapshotCreator;
using v8::TryCatch;

namespace node {

Maybe<ExitCode> SpinEventLoopInternal(Environment* env) {
  CHECK_NOT_NULL(env);
  MultiIsolatePlatform* platform = GetMultiIsolatePlatform(env);
  CHECK_NOT_NULL(platform);

  Isolate* isolate = env->isolate();
  HandleScope handle_scope(isolate);
  Context::Scope context_scope(env->context());
  SealHandleScope seal(isolate);

  if (env->is_stopping()) return Nothing<ExitCode>();

  env->set_trace_sync_io(env->options()->trace_sync_io);
  {
    bool more;
    env->performance_state()->Mark(
        node::performance::NODE_PERFORMANCE_MILESTONE_LOOP_START);
    do {
      if (env->is_stopping()) break;
      uv_run(env->event_loop(), UV_RUN_DEFAULT);
      if (env->is_stopping()) break;

      platform->DrainTasks(isolate);

      more = uv_loop_alive(env->event_loop());
      if (more && !env->is_stopping()) continue;

      if (EmitProcessBeforeExit(env).IsNothing())
        break;

      {
        HandleScope handle_scope(isolate);
        if (env->RunSnapshotSerializeCallback().IsEmpty()) {
          break;
        }
      }

      // Emit `beforeExit` if the loop became alive either after emitting
      // event, or after running some callbacks.
      more = uv_loop_alive(env->event_loop());
    } while (more == true && !env->is_stopping());
    env->performance_state()->Mark(
        node::performance::NODE_PERFORMANCE_MILESTONE_LOOP_EXIT);
  }
  if (env->is_stopping()) return Nothing<ExitCode>();

  env->set_trace_sync_io(false);
  // Clear the serialize callback even though the JS-land queue should
  // be empty this point so that the deserialized instance won't
  // attempt to call into JS again.
  env->set_snapshot_serialize_callback(Local<Function>());

  env->PrintInfoForSnapshotIfDebug();
  env->ForEachRealm([](Realm* realm) { realm->VerifyNoStrongBaseObjects(); });
  return EmitProcessExitInternal(env);
}

struct CommonEnvironmentSetup::Impl {
  MultiIsolatePlatform* platform = nullptr;
  uv_loop_t loop;
  std::shared_ptr<ArrayBufferAllocator> allocator;
  std::optional<SnapshotCreator> snapshot_creator;
  Isolate* isolate = nullptr;
  DeleteFnPtr<IsolateData, FreeIsolateData> isolate_data;
  DeleteFnPtr<Environment, FreeEnvironment> env;
  Global<Context> main_context;
};

CommonEnvironmentSetup::CommonEnvironmentSetup(
    MultiIsolatePlatform* platform,
    std::vector<std::string>* errors,
    const EmbedderSnapshotData* snapshot_data,
    uint32_t flags,
    std::function<Environment*(const CommonEnvironmentSetup*)> make_env,
    const SnapshotConfig* snapshot_config)
    : impl_(new Impl()) {
  CHECK_NOT_NULL(platform);
  CHECK_NOT_NULL(errors);

  impl_->platform = platform;
  uv_loop_t* loop = &impl_->loop;
  // Use `data` to tell the destructor whether the loop was initialized or not.
  loop->data = nullptr;
  int ret = uv_loop_init(loop);
  if (ret != 0) {
    errors->push_back(
        SPrintF("Failed to initialize loop: %s", uv_err_name(ret)));
    return;
  }
  loop->data = this;

  Isolate* isolate;
  if (flags & Flags::kIsForSnapshotting) {
    const std::vector<intptr_t>& external_references =
        SnapshotBuilder::CollectExternalReferences();
    isolate = impl_->isolate = Isolate::Allocate();
    // Must be done before the SnapshotCreator creation so  that the
    // memory reducer can be initialized.
    platform->RegisterIsolate(isolate, loop);
    impl_->snapshot_creator.emplace(isolate, external_references.data());
    isolate->SetCaptureStackTraceForUncaughtExceptions(
        true, 10, v8::StackTrace::StackTraceOptions::kDetailed);
    SetIsolateMiscHandlers(isolate, {});
  } else {
    impl_->allocator = ArrayBufferAllocator::Create();
    isolate = impl_->isolate =
        NewIsolate(impl_->allocator, &impl_->loop, platform, snapshot_data);
  }

  {
    Locker locker(isolate);
    Isolate::Scope isolate_scope(isolate);
    HandleScope handle_scope(isolate);

    TryCatch bootstrapCatch(isolate);
    auto print_Exception = OnScopeLeave([&]() {
      if (bootstrapCatch.HasCaught()) {
        errors->push_back(FormatCaughtException(
            isolate, isolate->GetCurrentContext(), bootstrapCatch));
      }
    });

    impl_->isolate_data.reset(CreateIsolateData(
        isolate, loop, platform, impl_->allocator.get(), snapshot_data));
    impl_->isolate_data->set_snapshot_config(snapshot_config);

    if (snapshot_data) {
      impl_->env.reset(make_env(this));
      if (impl_->env) {
        impl_->main_context.Reset(isolate, impl_->env->context());
      }
      return;
    }

    Local<Context> context = NewContext(isolate);
    impl_->main_context.Reset(isolate, context);
    if (context.IsEmpty()) {
      errors->push_back("Failed to initialize V8 Context");
      return;
    }

    Context::Scope context_scope(context);
    impl_->env.reset(make_env(this));
  }
}

CommonEnvironmentSetup::CommonEnvironmentSetup(
    MultiIsolatePlatform* platform,
    std::vector<std::string>* errors,
    std::function<Environment*(const CommonEnvironmentSetup*)> make_env)
    : CommonEnvironmentSetup(platform, errors, nullptr, false, make_env) {}

std::unique_ptr<CommonEnvironmentSetup>
CommonEnvironmentSetup::CreateForSnapshotting(
    MultiIsolatePlatform* platform,
    std::vector<std::string>* errors,
    const std::vector<std::string>& args,
    const std::vector<std::string>& exec_args,
    const SnapshotConfig& snapshot_config) {
  // It's not guaranteed that a context that goes through
  // v8_inspector::V8Inspector::contextCreated() is runtime-independent,
  // so do not start the inspector on the main context when building
  // the default snapshot.
  uint64_t env_flags =
      EnvironmentFlags::kDefaultFlags | EnvironmentFlags::kNoCreateInspector;

  auto ret = std::unique_ptr<CommonEnvironmentSetup>(new CommonEnvironmentSetup(
      platform,
      errors,
      nullptr,
      true,
      [&](const CommonEnvironmentSetup* setup) -> Environment* {
        return CreateEnvironment(
            setup->isolate_data(),
            setup->context(),
            args,
            exec_args,
            static_cast<EnvironmentFlags::Flags>(env_flags));
      },
      &snapshot_config));
  if (!errors->empty()) ret.reset();
  return ret;
}

CommonEnvironmentSetup::~CommonEnvironmentSetup() {
  if (impl_->isolate != nullptr) {
    Isolate* isolate = impl_->isolate;
    {
      Locker locker(isolate);
      Isolate::Scope isolate_scope(isolate);

      impl_->main_context.Reset();
      impl_->env.reset();
      impl_->isolate_data.reset();
    }

    bool platform_finished = false;
    impl_->platform->AddIsolateFinishedCallback(isolate, [](void* data) {
      *static_cast<bool*>(data) = true;
    }, &platform_finished);
    impl_->platform->UnregisterIsolate(isolate);
    if (impl_->snapshot_creator.has_value())
      impl_->snapshot_creator.reset();
    else
      isolate->Dispose();

    // Wait until the platform has cleaned up all relevant resources.
    while (!platform_finished)
      uv_run(&impl_->loop, UV_RUN_ONCE);
  }

  if (impl_->isolate || impl_->loop.data != nullptr)
    CheckedUvLoopClose(&impl_->loop);

  delete impl_;
}

EmbedderSnapshotData::Pointer CommonEnvironmentSetup::CreateSnapshot() {
  CHECK_NOT_NULL(snapshot_creator());
  SnapshotData* snapshot_data = new SnapshotData();
  EmbedderSnapshotData::Pointer result{
      new EmbedderSnapshotData(snapshot_data, true)};

  auto exit_code = SnapshotBuilder::CreateSnapshot(snapshot_data, this);
  if (exit_code != ExitCode::kNoFailure) return {};

  return result;
}

Maybe<int> SpinEventLoop(Environment* env) {
  Maybe<ExitCode> result = SpinEventLoopInternal(env);
  if (result.IsNothing()) {
    return Nothing<int>();
  }
  return Just(static_cast<int>(result.FromJust()));
}

uv_loop_t* CommonEnvironmentSetup::event_loop() const {
  return &impl_->loop;
}

std::shared_ptr<ArrayBufferAllocator>
CommonEnvironmentSetup::array_buffer_allocator() const {
  return impl_->allocator;
}

Isolate* CommonEnvironmentSetup::isolate() const {
  return impl_->isolate;
}

IsolateData* CommonEnvironmentSetup::isolate_data() const {
  return impl_->isolate_data.get();
}

Environment* CommonEnvironmentSetup::env() const {
  return impl_->env.get();
}

v8::Local<v8::Context> CommonEnvironmentSetup::context() const {
  return impl_->main_context.Get(impl_->isolate);
}

v8::SnapshotCreator* CommonEnvironmentSetup::snapshot_creator() {
  return impl_->snapshot_creator ? &impl_->snapshot_creator.value() : nullptr;
}

void EmbedderSnapshotData::DeleteSnapshotData::operator()(
    const EmbedderSnapshotData* data) const {
  CHECK_IMPLIES(data->owns_impl_, data->impl_);
  if (data->owns_impl_ &&
      data->impl_->data_ownership == SnapshotData::DataOwnership::kOwned) {
    delete data->impl_;
  }
  delete data;
}

EmbedderSnapshotData::Pointer EmbedderSnapshotData::BuiltinSnapshotData() {
  return EmbedderSnapshotData::Pointer{new EmbedderSnapshotData(
      SnapshotBuilder::GetEmbeddedSnapshotData(), false)};
}

EmbedderSnapshotData::Pointer EmbedderSnapshotData::FromBlob(
    const std::vector<char>& in) {
  SnapshotData* snapshot_data = new SnapshotData();
  CHECK_EQ(snapshot_data->data_ownership, SnapshotData::DataOwnership::kOwned);
  EmbedderSnapshotData::Pointer result{
      new EmbedderSnapshotData(snapshot_data, true)};
  if (!SnapshotData::FromBlob(snapshot_data, in)) {
    return {};
  }
  return result;
}

EmbedderSnapshotData::Pointer EmbedderSnapshotData::FromFile(FILE* in) {
  return FromBlob(ReadFileSync(in));
}

std::vector<char> EmbedderSnapshotData::ToBlob() const {
  return impl_->ToBlob();
}

void EmbedderSnapshotData::ToFile(FILE* out) const {
  impl_->ToFile(out);
}

EmbedderSnapshotData::EmbedderSnapshotData(const SnapshotData* impl,
                                           bool owns_impl)
    : impl_(impl), owns_impl_(owns_impl) {}

bool EmbedderSnapshotData::CanUseCustomSnapshotPerIsolate() {
#ifdef NODE_V8_SHARED_RO_HEAP
  return false;
#else
  return true;
#endif
}

}  // namespace node

Zerion Mini Shell 1.0