| 
									
										
										
										
											2014-10-31 11:17:05 -07:00
										 |  |  | // Copyright (c) 2013 GitHub, Inc.
 | 
					
						
							| 
									
										
										
										
											2014-07-28 16:00:15 +08:00
										 |  |  | // Use of this source code is governed by the MIT license that can be
 | 
					
						
							|  |  |  | // found in the LICENSE file.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-19 13:46:59 -07:00
										 |  |  | #include "shell/browser/javascript_environment.h"
 | 
					
						
							| 
									
										
										
										
											2014-07-28 16:00:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-16 18:12:00 -04:00
										 |  |  | #include <memory>
 | 
					
						
							| 
									
										
										
										
											2015-11-13 12:22:08 +08:00
										 |  |  | #include <string>
 | 
					
						
							| 
									
										
										
										
											2020-08-21 09:25:30 -07:00
										 |  |  | #include <unordered_set>
 | 
					
						
							|  |  |  | #include <utility>
 | 
					
						
							| 
									
										
										
										
											2015-11-13 12:22:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-29 12:38:55 -07:00
										 |  |  | #include "base/allocator/partition_allocator/partition_alloc.h"
 | 
					
						
							| 
									
										
										
										
											2015-10-22 16:20:48 +05:30
										 |  |  | #include "base/command_line.h"
 | 
					
						
							| 
									
										
										
										
											2020-07-21 22:34:34 -07:00
										 |  |  | #include "base/task/current_thread.h"
 | 
					
						
							| 
									
										
										
										
											2019-04-20 13:20:37 -04:00
										 |  |  | #include "base/task/thread_pool/initialization_util.h"
 | 
					
						
							| 
									
										
										
										
											2017-04-11 15:01:57 +09:00
										 |  |  | #include "base/threading/thread_task_runner_handle.h"
 | 
					
						
							| 
									
										
										
										
											2020-08-21 09:25:30 -07:00
										 |  |  | #include "base/trace_event/trace_event.h"
 | 
					
						
							| 
									
										
										
										
											2015-11-13 12:22:08 +08:00
										 |  |  | #include "content/public/common/content_switches.h"
 | 
					
						
							| 
									
										
										
										
											2017-05-14 19:25:07 +09:00
										 |  |  | #include "gin/array_buffer.h"
 | 
					
						
							| 
									
										
										
										
											2015-08-04 16:39:37 +08:00
										 |  |  | #include "gin/v8_initializer.h"
 | 
					
						
							| 
									
										
										
										
											2019-06-19 13:46:59 -07:00
										 |  |  | #include "shell/browser/microtasks_runner.h"
 | 
					
						
							| 
									
										
										
										
											2020-03-29 18:32:02 -07:00
										 |  |  | #include "shell/common/gin_helper/cleaned_up_at_exit.h"
 | 
					
						
							| 
									
										
										
										
											2019-06-19 13:46:59 -07:00
										 |  |  | #include "shell/common/node_includes.h"
 | 
					
						
							| 
									
										
										
										
											2018-05-01 16:22:39 -07:00
										 |  |  | #include "tracing/trace_event.h"
 | 
					
						
							| 
									
										
										
										
											2017-02-28 09:56:09 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-27 11:38:43 -07:00
										 |  |  | namespace { | 
					
						
							|  |  |  | v8::Isolate* g_isolate; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-21 09:25:30 -07:00
										 |  |  | namespace gin { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ConvertableToTraceFormatWrapper final | 
					
						
							|  |  |  |     : public base::trace_event::ConvertableToTraceFormat { | 
					
						
							|  |  |  |  public: | 
					
						
							|  |  |  |   explicit ConvertableToTraceFormatWrapper( | 
					
						
							|  |  |  |       std::unique_ptr<v8::ConvertableToTraceFormat> inner) | 
					
						
							|  |  |  |       : inner_(std::move(inner)) {} | 
					
						
							|  |  |  |   ~ConvertableToTraceFormatWrapper() override = default; | 
					
						
							|  |  |  |   void AppendAsTraceFormat(std::string* out) const final { | 
					
						
							|  |  |  |     inner_->AppendAsTraceFormat(out); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  private: | 
					
						
							|  |  |  |   std::unique_ptr<v8::ConvertableToTraceFormat> inner_; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   DISALLOW_COPY_AND_ASSIGN(ConvertableToTraceFormatWrapper); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | }  // namespace gin
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Allow std::unique_ptr<v8::ConvertableToTraceFormat> to be a valid
 | 
					
						
							|  |  |  | // initialization value for trace macros.
 | 
					
						
							|  |  |  | template <> | 
					
						
							|  |  |  | struct base::trace_event::TraceValue::Helper< | 
					
						
							|  |  |  |     std::unique_ptr<v8::ConvertableToTraceFormat>> { | 
					
						
							|  |  |  |   static constexpr unsigned char kType = TRACE_VALUE_TYPE_CONVERTABLE; | 
					
						
							|  |  |  |   static inline void SetValue( | 
					
						
							|  |  |  |       TraceValue* v, | 
					
						
							|  |  |  |       std::unique_ptr<v8::ConvertableToTraceFormat> value) { | 
					
						
							|  |  |  |     // NOTE: |as_convertable| is an owning pointer, so using new here
 | 
					
						
							|  |  |  |     // is acceptable.
 | 
					
						
							|  |  |  |     v->as_convertable = | 
					
						
							|  |  |  |         new gin::ConvertableToTraceFormatWrapper(std::move(value)); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-19 14:23:04 -07:00
										 |  |  | namespace electron { | 
					
						
							| 
									
										
										
										
											2014-07-28 16:00:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-29 12:38:55 -07:00
										 |  |  | class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator { | 
					
						
							|  |  |  |  public: | 
					
						
							|  |  |  |   enum InitializationPolicy { kZeroInitialize, kDontInitialize }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ArrayBufferAllocator() { | 
					
						
							|  |  |  |     // Ref.
 | 
					
						
							|  |  |  |     // https://source.chromium.org/chromium/chromium/src/+/master:third_party/blink/renderer/platform/wtf/allocator/partitions.cc;l=94;drc=062c315a858a87f834e16a144c2c8e9591af2beb
 | 
					
						
							|  |  |  |     allocator_->init({base::PartitionOptions::Alignment::kRegular, | 
					
						
							|  |  |  |                       base::PartitionOptions::ThreadCache::kDisabled, | 
					
						
							|  |  |  |                       base::PartitionOptions::Quarantine::kAllowed, | 
					
						
							|  |  |  |                       base::PartitionOptions::RefCount::kDisabled}); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Allocate() methods return null to signal allocation failure to V8, which
 | 
					
						
							|  |  |  |   // should respond by throwing a RangeError, per
 | 
					
						
							|  |  |  |   // http://www.ecma-international.org/ecma-262/6.0/#sec-createbytedatablock.
 | 
					
						
							|  |  |  |   void* Allocate(size_t size) override { | 
					
						
							|  |  |  |     void* result = AllocateMemoryOrNull(size, kZeroInitialize); | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void* AllocateUninitialized(size_t size) override { | 
					
						
							|  |  |  |     void* result = AllocateMemoryOrNull(size, kDontInitialize); | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void* Realloc(void* data, size_t size) override { | 
					
						
							|  |  |  |     return allocator_->root()->Realloc(data, size, "Electron"); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void Free(void* data, size_t size) override { | 
					
						
							|  |  |  |     allocator_->root()->Free(data); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  private: | 
					
						
							|  |  |  |   static void* AllocateMemoryOrNull(size_t size, InitializationPolicy policy) { | 
					
						
							|  |  |  |     return AllocateMemoryWithFlags(size, policy, | 
					
						
							|  |  |  |                                    base::PartitionAllocReturnNull); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   static void* AllocateMemoryWithFlags(size_t size, | 
					
						
							|  |  |  |                                        InitializationPolicy policy, | 
					
						
							|  |  |  |                                        int flags) { | 
					
						
							|  |  |  |     // The array buffer contents are sometimes expected to be 16-byte aligned in
 | 
					
						
							|  |  |  |     // order to get the best optimization of SSE, especially in case of audio
 | 
					
						
							|  |  |  |     // and video buffers.  Hence, align the given size up to 16-byte boundary.
 | 
					
						
							|  |  |  |     // Technically speaking, 16-byte aligned size doesn't mean 16-byte aligned
 | 
					
						
							|  |  |  |     // address, but this heuristics works with the current implementation of
 | 
					
						
							|  |  |  |     // PartitionAlloc (and PartitionAlloc doesn't support a better way for now).
 | 
					
						
							|  |  |  |     if (base::kAlignment < | 
					
						
							|  |  |  |         16) {  // base::kAlignment is a compile-time constant.
 | 
					
						
							|  |  |  |       size_t aligned_size = base::bits::AlignUp(size, 16); | 
					
						
							|  |  |  |       if (size == 0) { | 
					
						
							|  |  |  |         aligned_size = 16; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (aligned_size >= size) {  // Only when no overflow
 | 
					
						
							|  |  |  |         size = aligned_size; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (policy == kZeroInitialize) { | 
					
						
							|  |  |  |       flags |= base::PartitionAllocZeroFill; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     void* data = allocator_->root()->AllocFlags(flags, size, "Electron"); | 
					
						
							|  |  |  |     if (base::kAlignment < 16) { | 
					
						
							|  |  |  |       char* ptr = reinterpret_cast<char*>(data); | 
					
						
							|  |  |  |       DCHECK_EQ(base::bits::AlignUp(ptr, 16), ptr) | 
					
						
							|  |  |  |           << "Pointer " << ptr << " not 16B aligned for size " << size; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return data; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   static base::NoDestructor<base::PartitionAllocator> allocator_; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | base::NoDestructor<base::PartitionAllocator> ArrayBufferAllocator::allocator_{}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-06 00:10:17 +05:30
										 |  |  | JavascriptEnvironment::JavascriptEnvironment(uv_loop_t* event_loop) | 
					
						
							|  |  |  |     : isolate_(Initialize(event_loop)), | 
					
						
							| 
									
										
										
										
											2018-10-03 17:06:40 +10:00
										 |  |  |       isolate_holder_(base::ThreadTaskRunnerHandle::Get(), | 
					
						
							| 
									
										
										
										
											2018-10-06 00:10:17 +05:30
										 |  |  |                       gin::IsolateHolder::kSingleThread, | 
					
						
							|  |  |  |                       gin::IsolateHolder::kAllowAtomicsWait, | 
					
						
							| 
									
										
										
										
											2018-10-26 01:00:45 +05:30
										 |  |  |                       gin::IsolateHolder::IsolateType::kUtility, | 
					
						
							| 
									
										
										
										
											2018-10-06 00:10:17 +05:30
										 |  |  |                       gin::IsolateHolder::IsolateCreationMode::kNormal, | 
					
						
							|  |  |  |                       isolate_), | 
					
						
							| 
									
										
										
										
											2020-03-10 18:16:58 -07:00
										 |  |  |       locker_(isolate_) { | 
					
						
							|  |  |  |   isolate_->Enter(); | 
					
						
							|  |  |  |   v8::HandleScope scope(isolate_); | 
					
						
							|  |  |  |   auto context = node::NewContext(isolate_); | 
					
						
							|  |  |  |   context_ = v8::Global<v8::Context>(isolate_, context); | 
					
						
							|  |  |  |   context->Enter(); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-07-28 16:00:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-10 18:16:58 -07:00
										 |  |  | JavascriptEnvironment::~JavascriptEnvironment() { | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2020-03-29 18:32:02 -07:00
										 |  |  |     v8::Locker locker(isolate_); | 
					
						
							| 
									
										
										
										
											2020-03-10 18:16:58 -07:00
										 |  |  |     v8::HandleScope scope(isolate_); | 
					
						
							|  |  |  |     context_.Get(isolate_)->Exit(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   isolate_->Exit(); | 
					
						
							| 
									
										
										
										
											2020-04-27 11:38:43 -07:00
										 |  |  |   g_isolate = nullptr; | 
					
						
							| 
									
										
										
										
											2020-03-10 18:16:58 -07:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-04-17 16:37:22 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-21 09:25:30 -07:00
										 |  |  | class EnabledStateObserverImpl final | 
					
						
							|  |  |  |     : public base::trace_event::TraceLog::EnabledStateObserver { | 
					
						
							|  |  |  |  public: | 
					
						
							|  |  |  |   EnabledStateObserverImpl() { | 
					
						
							|  |  |  |     base::trace_event::TraceLog::GetInstance()->AddEnabledStateObserver(this); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ~EnabledStateObserverImpl() override { | 
					
						
							|  |  |  |     base::trace_event::TraceLog::GetInstance()->RemoveEnabledStateObserver( | 
					
						
							|  |  |  |         this); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void OnTraceLogEnabled() final { | 
					
						
							|  |  |  |     base::AutoLock lock(mutex_); | 
					
						
							|  |  |  |     for (auto* o : observers_) { | 
					
						
							|  |  |  |       o->OnTraceEnabled(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void OnTraceLogDisabled() final { | 
					
						
							|  |  |  |     base::AutoLock lock(mutex_); | 
					
						
							|  |  |  |     for (auto* o : observers_) { | 
					
						
							|  |  |  |       o->OnTraceDisabled(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void AddObserver(v8::TracingController::TraceStateObserver* observer) { | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       base::AutoLock lock(mutex_); | 
					
						
							|  |  |  |       DCHECK(!observers_.count(observer)); | 
					
						
							|  |  |  |       observers_.insert(observer); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Fire the observer if recording is already in progress.
 | 
					
						
							|  |  |  |     if (base::trace_event::TraceLog::GetInstance()->IsEnabled()) | 
					
						
							|  |  |  |       observer->OnTraceEnabled(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void RemoveObserver(v8::TracingController::TraceStateObserver* observer) { | 
					
						
							|  |  |  |     base::AutoLock lock(mutex_); | 
					
						
							|  |  |  |     DCHECK_EQ(observers_.count(observer), 1lu); | 
					
						
							|  |  |  |     observers_.erase(observer); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  private: | 
					
						
							|  |  |  |   base::Lock mutex_; | 
					
						
							|  |  |  |   std::unordered_set<v8::TracingController::TraceStateObserver*> observers_; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   DISALLOW_COPY_AND_ASSIGN(EnabledStateObserverImpl); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | base::LazyInstance<EnabledStateObserverImpl>::Leaky g_trace_state_dispatcher = | 
					
						
							|  |  |  |     LAZY_INSTANCE_INITIALIZER; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class TracingControllerImpl : public node::tracing::TracingController { | 
					
						
							|  |  |  |  public: | 
					
						
							|  |  |  |   TracingControllerImpl() = default; | 
					
						
							|  |  |  |   ~TracingControllerImpl() override = default; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // TracingController implementation.
 | 
					
						
							|  |  |  |   const uint8_t* GetCategoryGroupEnabled(const char* name) override { | 
					
						
							|  |  |  |     return TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(name); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   uint64_t AddTraceEvent( | 
					
						
							|  |  |  |       char phase, | 
					
						
							|  |  |  |       const uint8_t* category_enabled_flag, | 
					
						
							|  |  |  |       const char* name, | 
					
						
							|  |  |  |       const char* scope, | 
					
						
							|  |  |  |       uint64_t id, | 
					
						
							|  |  |  |       uint64_t bind_id, | 
					
						
							|  |  |  |       int32_t num_args, | 
					
						
							|  |  |  |       const char** arg_names, | 
					
						
							|  |  |  |       const uint8_t* arg_types, | 
					
						
							|  |  |  |       const uint64_t* arg_values, | 
					
						
							|  |  |  |       std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables, | 
					
						
							|  |  |  |       unsigned int flags) override { | 
					
						
							|  |  |  |     base::trace_event::TraceArguments args( | 
					
						
							|  |  |  |         num_args, arg_names, arg_types, | 
					
						
							|  |  |  |         reinterpret_cast<const unsigned long long*>(  // NOLINT(runtime/int)
 | 
					
						
							|  |  |  |             arg_values), | 
					
						
							|  |  |  |         arg_convertables); | 
					
						
							|  |  |  |     DCHECK_LE(num_args, 2); | 
					
						
							|  |  |  |     base::trace_event::TraceEventHandle handle = | 
					
						
							|  |  |  |         TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_BIND_ID( | 
					
						
							|  |  |  |             phase, category_enabled_flag, name, scope, id, bind_id, &args, | 
					
						
							|  |  |  |             flags); | 
					
						
							|  |  |  |     uint64_t result; | 
					
						
							|  |  |  |     memcpy(&result, &handle, sizeof(result)); | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   uint64_t AddTraceEventWithTimestamp( | 
					
						
							|  |  |  |       char phase, | 
					
						
							|  |  |  |       const uint8_t* category_enabled_flag, | 
					
						
							|  |  |  |       const char* name, | 
					
						
							|  |  |  |       const char* scope, | 
					
						
							|  |  |  |       uint64_t id, | 
					
						
							|  |  |  |       uint64_t bind_id, | 
					
						
							|  |  |  |       int32_t num_args, | 
					
						
							|  |  |  |       const char** arg_names, | 
					
						
							|  |  |  |       const uint8_t* arg_types, | 
					
						
							|  |  |  |       const uint64_t* arg_values, | 
					
						
							|  |  |  |       std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables, | 
					
						
							|  |  |  |       unsigned int flags, | 
					
						
							|  |  |  |       int64_t timestampMicroseconds) override { | 
					
						
							|  |  |  |     base::trace_event::TraceArguments args( | 
					
						
							|  |  |  |         num_args, arg_names, arg_types, | 
					
						
							|  |  |  |         reinterpret_cast<const unsigned long long*>(  // NOLINT(runtime/int)
 | 
					
						
							|  |  |  |             arg_values), | 
					
						
							|  |  |  |         arg_convertables); | 
					
						
							|  |  |  |     DCHECK_LE(num_args, 2); | 
					
						
							|  |  |  |     base::TimeTicks timestamp = | 
					
						
							|  |  |  |         base::TimeTicks() + | 
					
						
							|  |  |  |         base::TimeDelta::FromMicroseconds(timestampMicroseconds); | 
					
						
							|  |  |  |     base::trace_event::TraceEventHandle handle = | 
					
						
							|  |  |  |         TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( | 
					
						
							|  |  |  |             phase, category_enabled_flag, name, scope, id, bind_id, | 
					
						
							|  |  |  |             TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, &args, flags); | 
					
						
							|  |  |  |     uint64_t result; | 
					
						
							|  |  |  |     memcpy(&result, &handle, sizeof(result)); | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   void UpdateTraceEventDuration(const uint8_t* category_enabled_flag, | 
					
						
							|  |  |  |                                 const char* name, | 
					
						
							|  |  |  |                                 uint64_t handle) override { | 
					
						
							|  |  |  |     base::trace_event::TraceEventHandle traceEventHandle; | 
					
						
							|  |  |  |     memcpy(&traceEventHandle, &handle, sizeof(handle)); | 
					
						
							|  |  |  |     TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_enabled_flag, name, | 
					
						
							|  |  |  |                                                 traceEventHandle); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   void AddTraceStateObserver(TraceStateObserver* observer) override { | 
					
						
							|  |  |  |     g_trace_state_dispatcher.Get().AddObserver(observer); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   void RemoveTraceStateObserver(TraceStateObserver* observer) override { | 
					
						
							|  |  |  |     g_trace_state_dispatcher.Get().RemoveObserver(observer); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  private: | 
					
						
							|  |  |  |   DISALLOW_COPY_AND_ASSIGN(TracingControllerImpl); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-06 00:10:17 +05:30
										 |  |  | v8::Isolate* JavascriptEnvironment::Initialize(uv_loop_t* event_loop) { | 
					
						
							| 
									
										
										
										
											2018-04-17 15:41:47 -07:00
										 |  |  |   auto* cmd = base::CommandLine::ForCurrentProcess(); | 
					
						
							| 
									
										
										
										
											2015-11-12 01:00:41 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-13 12:22:08 +08:00
										 |  |  |   // --js-flags.
 | 
					
						
							|  |  |  |   std::string js_flags = cmd->GetSwitchValueASCII(switches::kJavaScriptFlags); | 
					
						
							|  |  |  |   if (!js_flags.empty()) | 
					
						
							|  |  |  |     v8::V8::SetFlagsFromString(js_flags.c_str(), js_flags.size()); | 
					
						
							| 
									
										
										
										
											2015-11-12 01:00:41 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-08 09:23:17 +09:00
										 |  |  |   // The V8Platform of gin relies on Chromium's task schedule, which has not
 | 
					
						
							|  |  |  |   // been started at this point, so we have to rely on Node's V8Platform.
 | 
					
						
							| 
									
										
										
										
											2018-10-26 15:37:50 +11:00
										 |  |  |   auto* tracing_agent = node::CreateAgent(); | 
					
						
							| 
									
										
										
										
											2020-08-21 09:25:30 -07:00
										 |  |  |   auto* tracing_controller = new TracingControllerImpl(); | 
					
						
							| 
									
										
										
										
											2018-10-26 15:37:50 +11:00
										 |  |  |   node::tracing::TraceEventHelper::SetAgent(tracing_agent); | 
					
						
							| 
									
										
										
										
											2017-12-08 09:23:17 +09:00
										 |  |  |   platform_ = node::CreatePlatform( | 
					
						
							| 
									
										
										
										
											2019-05-03 12:06:10 -07:00
										 |  |  |       base::RecommendedMaxNumberOfThreadsInThreadGroup(3, 8, 0.1, 0), | 
					
						
							| 
									
										
										
										
											2020-11-09 13:57:24 -08:00
										 |  |  |       tracing_controller, gin::V8Platform::PageAllocator()); | 
					
						
							| 
									
										
										
										
											2018-10-06 00:10:17 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-08 09:23:17 +09:00
										 |  |  |   v8::V8::InitializePlatform(platform_); | 
					
						
							| 
									
										
										
										
											2021-03-29 12:38:55 -07:00
										 |  |  |   gin::IsolateHolder::Initialize( | 
					
						
							|  |  |  |       gin::IsolateHolder::kNonStrictMode, new ArrayBufferAllocator(), | 
					
						
							|  |  |  |       nullptr /* external_reference_table */, false /* create_v8_platform */); | 
					
						
							| 
									
										
										
										
											2018-10-06 00:10:17 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  |   v8::Isolate* isolate = v8::Isolate::Allocate(); | 
					
						
							|  |  |  |   platform_->RegisterIsolate(isolate, event_loop); | 
					
						
							| 
									
										
										
										
											2020-04-27 11:38:43 -07:00
										 |  |  |   g_isolate = isolate; | 
					
						
							| 
									
										
										
										
											2018-10-06 00:10:17 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  |   return isolate; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-27 11:38:43 -07:00
										 |  |  | // static
 | 
					
						
							|  |  |  | v8::Isolate* JavascriptEnvironment::GetIsolate() { | 
					
						
							|  |  |  |   CHECK(g_isolate); | 
					
						
							|  |  |  |   return g_isolate; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-15 08:26:47 -07:00
										 |  |  | void JavascriptEnvironment::OnMessageLoopCreated() { | 
					
						
							|  |  |  |   DCHECK(!microtasks_runner_); | 
					
						
							| 
									
										
										
										
											2019-09-16 18:12:00 -04:00
										 |  |  |   microtasks_runner_ = std::make_unique<MicrotasksRunner>(isolate()); | 
					
						
							| 
									
										
										
										
											2020-07-21 22:34:34 -07:00
										 |  |  |   base::CurrentThread::Get()->AddTaskObserver(microtasks_runner_.get()); | 
					
						
							| 
									
										
										
										
											2018-10-15 08:26:47 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-06 00:10:17 +05:30
										 |  |  | void JavascriptEnvironment::OnMessageLoopDestroying() { | 
					
						
							| 
									
										
										
										
											2018-10-15 08:26:47 -07:00
										 |  |  |   DCHECK(microtasks_runner_); | 
					
						
							| 
									
										
										
										
											2020-07-20 12:13:33 -07:00
										 |  |  |   { | 
					
						
							|  |  |  |     v8::Locker locker(isolate_); | 
					
						
							|  |  |  |     v8::HandleScope scope(isolate_); | 
					
						
							|  |  |  |     gin_helper::CleanedUpAtExit::DoCleanup(); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-07-21 22:34:34 -07:00
										 |  |  |   base::CurrentThread::Get()->RemoveTaskObserver(microtasks_runner_.get()); | 
					
						
							| 
									
										
										
										
											2015-05-22 15:30:02 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-17 21:55:30 -04:00
										 |  |  | NodeEnvironment::NodeEnvironment(node::Environment* env) : env_(env) {} | 
					
						
							| 
									
										
										
										
											2017-02-28 09:56:09 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | NodeEnvironment::~NodeEnvironment() { | 
					
						
							| 
									
										
										
										
											2021-04-02 01:46:11 +02:00
										 |  |  |   auto* isolate_data = env_->isolate_data(); | 
					
						
							| 
									
										
										
										
											2017-02-28 09:56:09 +09:00
										 |  |  |   node::FreeEnvironment(env_); | 
					
						
							| 
									
										
										
										
											2021-04-02 01:46:11 +02:00
										 |  |  |   node::FreeIsolateData(isolate_data); | 
					
						
							| 
									
										
										
										
											2017-02-28 09:56:09 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-19 14:23:04 -07:00
										 |  |  | }  // namespace electron
 |