javascript_environment.cc 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. // Copyright (c) 2013 GitHub, Inc.
  2. // Use of this source code is governed by the MIT license that can be
  3. // found in the LICENSE file.
  4. #include "shell/browser/javascript_environment.h"
  5. #include <memory>
  6. #include <string>
  7. #include <utility>
  8. #include "base/allocator/partition_alloc_features.h"
  9. #include "base/allocator/partition_allocator/src/partition_alloc/partition_alloc.h"
  10. #include "base/bits.h"
  11. #include "base/command_line.h"
  12. #include "base/feature_list.h"
  13. #include "base/task/current_thread.h"
  14. #include "base/task/single_thread_task_runner.h"
  15. #include "base/task/thread_pool/initialization_util.h"
  16. #include "gin/array_buffer.h"
  17. #include "gin/v8_initializer.h"
  18. #include "shell/browser/microtasks_runner.h"
  19. #include "shell/common/gin_helper/cleaned_up_at_exit.h"
  20. #include "shell/common/node_includes.h"
  21. #include "third_party/blink/public/common/switches.h"
  22. #include "third_party/electron_node/src/node_wasm_web_api.h"
  23. namespace {
  24. v8::Isolate* g_isolate;
  25. }
  26. namespace electron {
  27. namespace {
  28. gin::IsolateHolder CreateIsolateHolder(v8::Isolate* isolate,
  29. size_t* max_young_generation_size) {
  30. std::unique_ptr<v8::Isolate::CreateParams> create_params =
  31. gin::IsolateHolder::getDefaultIsolateParams();
  32. // The value is needed to adjust heap limit when capturing
  33. // snapshot via v8.setHeapSnapshotNearHeapLimit(limit) or
  34. // --heapsnapshot-near-heap-limit=max_count.
  35. *max_young_generation_size =
  36. create_params->constraints.max_young_generation_size_in_bytes();
  37. // Align behavior with V8 Isolate default for Node.js.
  38. // This is necessary for important aspects of Node.js
  39. // including heap and cpu profilers to function properly.
  40. return {base::SingleThreadTaskRunner::GetCurrentDefault(),
  41. gin::IsolateHolder::kSingleThread,
  42. gin::IsolateHolder::IsolateType::kUtility,
  43. std::move(create_params),
  44. gin::IsolateHolder::IsolateCreationMode::kNormal,
  45. nullptr,
  46. nullptr,
  47. isolate};
  48. }
  49. } // namespace
  50. JavascriptEnvironment::JavascriptEnvironment(uv_loop_t* event_loop,
  51. bool setup_wasm_streaming)
  52. : isolate_holder_{CreateIsolateHolder(
  53. Initialize(event_loop, setup_wasm_streaming),
  54. &max_young_generation_size_)},
  55. isolate_{isolate_holder_.isolate()},
  56. locker_{isolate_} {
  57. isolate_->Enter();
  58. v8::HandleScope scope(isolate_);
  59. auto context = node::NewContext(isolate_);
  60. CHECK(!context.IsEmpty());
  61. context->Enter();
  62. }
  63. JavascriptEnvironment::~JavascriptEnvironment() {
  64. DCHECK_NE(platform_, nullptr);
  65. {
  66. v8::HandleScope scope(isolate_);
  67. isolate_->GetCurrentContext()->Exit();
  68. }
  69. isolate_->Exit();
  70. g_isolate = nullptr;
  71. platform_->UnregisterIsolate(isolate_);
  72. }
  73. v8::Isolate* JavascriptEnvironment::Initialize(uv_loop_t* event_loop,
  74. bool setup_wasm_streaming) {
  75. auto* cmd = base::CommandLine::ForCurrentProcess();
  76. // --js-flags.
  77. std::string js_flags = "--no-freeze-flags-after-init ";
  78. js_flags.append(cmd->GetSwitchValueASCII(blink::switches::kJavaScriptFlags));
  79. v8::V8::SetFlagsFromString(js_flags.c_str(), js_flags.size());
  80. // The V8Platform of gin relies on Chromium's task schedule, which has not
  81. // been started at this point, so we have to rely on Node's V8Platform.
  82. auto* tracing_agent = new node::tracing::Agent();
  83. auto* tracing_controller = tracing_agent->GetTracingController();
  84. node::tracing::TraceEventHelper::SetAgent(tracing_agent);
  85. platform_ = node::MultiIsolatePlatform::Create(
  86. base::RecommendedMaxNumberOfThreadsInThreadGroup(3, 8, 0.1, 0),
  87. tracing_controller, gin::V8Platform::GetCurrentPageAllocator());
  88. v8::V8::InitializePlatform(platform_.get());
  89. gin::IsolateHolder::Initialize(
  90. gin::IsolateHolder::kNonStrictMode,
  91. gin::ArrayBufferAllocator::SharedInstance(),
  92. nullptr /* external_reference_table */, js_flags,
  93. false /* disallow_v8_feature_flag_overrides */,
  94. nullptr /* fatal_error_callback */, nullptr /* oom_error_callback */,
  95. false /* create_v8_platform */);
  96. v8::Isolate* isolate = v8::Isolate::Allocate();
  97. platform_->RegisterIsolate(isolate, event_loop);
  98. // This is done here because V8 checks for the callback in NewContext.
  99. // Our setup order doesn't allow for calling SetupIsolateForNode
  100. // before NewContext without polluting JavaScriptEnvironment with
  101. // Node.js logic and so we conditionally do it here to keep
  102. // concerns separate.
  103. if (setup_wasm_streaming) {
  104. isolate->SetWasmStreamingCallback(
  105. node::wasm_web_api::StartStreamingCompilation);
  106. }
  107. g_isolate = isolate;
  108. return isolate;
  109. }
  110. // static
  111. v8::Isolate* JavascriptEnvironment::GetIsolate() {
  112. CHECK(g_isolate);
  113. return g_isolate;
  114. }
  115. void JavascriptEnvironment::CreateMicrotasksRunner() {
  116. DCHECK(!microtasks_runner_);
  117. microtasks_runner_ = std::make_unique<MicrotasksRunner>(isolate());
  118. isolate_holder_.WillCreateMicrotasksRunner();
  119. base::CurrentThread::Get()->AddTaskObserver(microtasks_runner_.get());
  120. }
  121. void JavascriptEnvironment::DestroyMicrotasksRunner() {
  122. DCHECK(microtasks_runner_);
  123. // Should be called before running gin_helper::CleanedUpAtExit::DoCleanup.
  124. // This helps to signal wrappable finalizer callbacks to not act on freed
  125. // parameters.
  126. isolate_holder_.WillDestroyMicrotasksRunner();
  127. {
  128. v8::HandleScope scope(isolate_);
  129. gin_helper::CleanedUpAtExit::DoCleanup();
  130. }
  131. base::CurrentThread::Get()->RemoveTaskObserver(microtasks_runner_.get());
  132. }
  133. } // namespace electron