| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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_); | 
					
						
							| 
									
										
										
										
											2019-01-22 02:13:53 +05:30
										 |  |  |   gin::IsolateHolder::Initialize(gin::IsolateHolder::kNonStrictMode, | 
					
						
							|  |  |  |                                  gin::ArrayBufferAllocator::SharedInstance(), | 
					
						
							|  |  |  |                                  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() { | 
					
						
							|  |  |  |   node::FreeEnvironment(env_); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-19 14:23:04 -07:00
										 |  |  | }  // namespace electron
 |