// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. #ifndef INTERNAL_H_ #define INTERNAL_H_ #include #include #include #include #include "deno.h" #include "third_party/v8/include/v8.h" #include "third_party/v8/src/base/logging.h" namespace deno { struct ModuleInfo { bool main; std::string name; v8::Persistent handle; std::vector import_specifiers; ModuleInfo(v8::Isolate* isolate, v8::Local module, bool main_, const char* name_, std::vector import_specifiers_) : main(main_), name(name_), import_specifiers(import_specifiers_) { handle.Reset(isolate, module); } }; // deno_s = Wrapped Isolate. class DenoIsolate { public: explicit DenoIsolate(deno_config config) : isolate_(nullptr), locker_(nullptr), shared_(config.shared), current_args_(nullptr), snapshot_creator_(nullptr), global_import_buf_ptr_(nullptr), recv_cb_(config.recv_cb), next_zero_copy_id_(1), // zero_copy_id must not be zero. user_data_(nullptr), resolve_cb_(nullptr) { array_buffer_allocator_ = v8::ArrayBuffer::Allocator::NewDefaultAllocator(); if (config.load_snapshot.data_ptr) { snapshot_.data = reinterpret_cast(config.load_snapshot.data_ptr); snapshot_.raw_size = static_cast(config.load_snapshot.data_len); } } ~DenoIsolate() { shared_ab_.Reset(); if (locker_) { delete locker_; } if (snapshot_creator_) { delete snapshot_creator_; } else { isolate_->Dispose(); } delete array_buffer_allocator_; } static inline DenoIsolate* FromIsolate(v8::Isolate* isolate) { return static_cast(isolate->GetData(0)); } void AddIsolate(v8::Isolate* isolate); deno_mod RegisterModule(bool main, const char* name, const char* source); void ClearModules(); ModuleInfo* GetModuleInfo(deno_mod id) { if (id == 0) { return nullptr; } auto it = mods_.find(id); if (it != mods_.end()) { return &it->second; } else { return nullptr; } } void DeleteZeroCopyRef(size_t zero_copy_id) { DCHECK_NE(zero_copy_id, 0); // Delete persistent reference to data ArrayBuffer. auto it = zero_copy_map_.find(zero_copy_id); if (it != zero_copy_map_.end()) { it->second.Reset(); zero_copy_map_.erase(it); } } void AddZeroCopyRef(size_t zero_copy_id, v8::Local zero_copy_v) { zero_copy_map_.emplace(std::piecewise_construct, std::make_tuple(zero_copy_id), std::make_tuple(isolate_, zero_copy_v)); } v8::Isolate* isolate_; v8::Locker* locker_; v8::ArrayBuffer::Allocator* array_buffer_allocator_; deno_buf shared_; const v8::FunctionCallbackInfo* current_args_; v8::SnapshotCreator* snapshot_creator_; void* global_import_buf_ptr_; deno_recv_cb recv_cb_; size_t next_zero_copy_id_; void* user_data_; std::map mods_; std::map mods_by_name_; deno_resolve_cb resolve_cb_; v8::Persistent context_; std::map> zero_copy_map_; std::map> pending_promise_map_; std::string last_exception_; v8::Persistent recv_; v8::StartupData snapshot_; v8::Persistent global_import_buf_; v8::Persistent shared_ab_; }; class UserDataScope { DenoIsolate* deno_; void* prev_data_; void* data_; // Not necessary; only for sanity checking. public: UserDataScope(DenoIsolate* deno, void* data) : deno_(deno), data_(data) { CHECK(deno->user_data_ == nullptr || deno->user_data_ == data_); prev_data_ = deno->user_data_; deno->user_data_ = data; } ~UserDataScope() { CHECK(deno_->user_data_ == data_); deno_->user_data_ = prev_data_; } }; struct InternalFieldData { uint32_t data; }; static inline v8::Local v8_str(const char* x) { return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), x, v8::NewStringType::kNormal) .ToLocalChecked(); } void Print(const v8::FunctionCallbackInfo& args); void Recv(const v8::FunctionCallbackInfo& args); void Send(const v8::FunctionCallbackInfo& args); void EvalContext(const v8::FunctionCallbackInfo& args); void ErrorToJSON(const v8::FunctionCallbackInfo& args); void Shared(v8::Local property, const v8::PropertyCallbackInfo& info); void MessageCallback(v8::Local message, v8::Local data); static intptr_t external_references[] = { reinterpret_cast(Print), reinterpret_cast(Recv), reinterpret_cast(Send), reinterpret_cast(EvalContext), reinterpret_cast(ErrorToJSON), reinterpret_cast(Shared), reinterpret_cast(MessageCallback), 0}; static const deno_buf empty_buf = {nullptr, 0, nullptr, 0, 0}; static const deno_snapshot empty_snapshot = {nullptr, 0}; Deno* NewFromSnapshot(void* user_data, deno_recv_cb cb); void InitializeContext(v8::Isolate* isolate, v8::Local context); void DeserializeInternalFields(v8::Local holder, int index, v8::StartupData payload, void* data); v8::StartupData SerializeInternalFields(v8::Local holder, int index, void* data); v8::Local ImportBuf(DenoIsolate* d, deno_buf buf); bool Execute(v8::Local context, const char* js_filename, const char* js_source); bool ExecuteMod(v8::Local context, const char* js_filename, const char* js_source, bool resolve_only); } // namespace deno extern "C" { // This is just to workaround the linker. struct deno_s { deno::DenoIsolate isolate; }; } #endif // INTERNAL_H_