/*
 * Copyright (C) 2009 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"

#include <memory>
#include <utility>

#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_thread.h"
#include "third_party/blink/public/web/blink.h"
#include "third_party/blink/renderer/platform/bindings/active_script_wrappable_base.h"
#include "third_party/blink/renderer/platform/bindings/dom_data_store.h"
#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
#include "third_party/blink/renderer/platform/bindings/v8_object_constructor.h"
#include "third_party/blink/renderer/platform/bindings/v8_private_property.h"
#include "third_party/blink/renderer/platform/bindings/v8_value_cache.h"
#include "third_party/blink/renderer/platform/wtf/leak_annotations.h"
#include "v8/include/v8.h"

namespace blink {

// Wrapper function defined in WebKit.h
v8::Isolate* MainThreadIsolate() {
  return V8PerIsolateData::MainThreadIsolate();
}

static V8PerIsolateData* g_main_thread_per_isolate_data = nullptr;

static void BeforeCallEnteredCallback(v8::Isolate* isolate) {
  CHECK(!ScriptForbiddenScope::IsScriptForbidden());
}

static void MicrotasksCompletedCallback(v8::Isolate* isolate) {
  V8PerIsolateData::From(isolate)->RunEndOfScopeTasks();
}

V8PerIsolateData::V8PerIsolateData(
    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
    V8ContextSnapshotMode v8_context_snapshot_mode)
    : v8_context_snapshot_mode_(v8_context_snapshot_mode),
      isolate_holder_(task_runner,
                      gin::IsolateHolder::kSingleThread,
                      IsMainThread() ? gin::IsolateHolder::kDisallowAtomicsWait
                                     : gin::IsolateHolder::kAllowAtomicsWait),
      interface_template_map_for_v8_context_snapshot_(GetIsolate()),
      string_cache_(std::make_unique<StringCache>(GetIsolate())),
      private_property_(V8PrivateProperty::Create()),
      constructor_mode_(ConstructorMode::kCreateNewObject),
      use_counter_disabled_(false),
      is_handling_recursion_level_error_(false),
      is_reporting_exception_(false),
      runtime_call_stats_(base::DefaultTickClock::GetInstance()),
      handled_near_v8_heap_limit_(false) {
  // FIXME: Remove once all v8::Isolate::GetCurrent() calls are gone.
  GetIsolate()->Enter();
  GetIsolate()->AddBeforeCallEnteredCallback(&BeforeCallEnteredCallback);
  GetIsolate()->AddMicrotasksCompletedCallback(&MicrotasksCompletedCallback);
  if (IsMainThread())
    g_main_thread_per_isolate_data = this;
}

// This constructor is used for creating a V8 context snapshot. It must run on
// the main thread.
V8PerIsolateData::V8PerIsolateData()
    : v8_context_snapshot_mode_(V8ContextSnapshotMode::kTakeSnapshot),
      isolate_holder_(Platform::Current()->MainThread()->GetTaskRunner(),
                      gin::IsolateHolder::kSingleThread,
                      gin::IsolateHolder::kAllowAtomicsWait,
                      gin::IsolateHolder::IsolateCreationMode::kCreateSnapshot),
      interface_template_map_for_v8_context_snapshot_(GetIsolate()),
      string_cache_(std::make_unique<StringCache>(GetIsolate())),
      private_property_(V8PrivateProperty::Create()),
      constructor_mode_(ConstructorMode::kCreateNewObject),
      use_counter_disabled_(false),
      is_handling_recursion_level_error_(false),
      is_reporting_exception_(false),
      runtime_call_stats_(base::DefaultTickClock::GetInstance()),
      handled_near_v8_heap_limit_(false) {
  CHECK(IsMainThread());

  // SnapshotCreator enters the isolate, so we don't call Isolate::Enter() here.
  g_main_thread_per_isolate_data = this;
}

V8PerIsolateData::~V8PerIsolateData() = default;

v8::Isolate* V8PerIsolateData::MainThreadIsolate() {
  DCHECK(g_main_thread_per_isolate_data);
  return g_main_thread_per_isolate_data->GetIsolate();
}

v8::Isolate* V8PerIsolateData::Initialize(
    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
    V8ContextSnapshotMode context_mode) {
  V8PerIsolateData* data = nullptr;
  if (context_mode == V8ContextSnapshotMode::kTakeSnapshot) {
    data = new V8PerIsolateData();
  } else {
    data = new V8PerIsolateData(task_runner, context_mode);
  }
  DCHECK(data);

  v8::Isolate* isolate = data->GetIsolate();
  isolate->SetData(gin::kEmbedderBlink, data);
  return isolate;
}

void V8PerIsolateData::EnableIdleTasks(
    v8::Isolate* isolate,
    std::unique_ptr<gin::V8IdleTaskRunner> task_runner) {
  From(isolate)->isolate_holder_.EnableIdleTasks(std::move(task_runner));
}

// willBeDestroyed() clear things that should be cleared before
// ThreadState::detach() gets called.
void V8PerIsolateData::WillBeDestroyed(v8::Isolate* isolate) {
  V8PerIsolateData* data = From(isolate);

  data->thread_debugger_.reset();
  // Clear any data that may have handles into the heap,
  // prior to calling ThreadState::detach().
  data->ClearEndOfScopeTasks();

  data->active_script_wrappables_.Clear();

  // Detach V8's garbage collector.
  isolate->SetEmbedderHeapTracer(nullptr);
  if (data->script_wrappable_visitor_->WrapperTracingInProgress())
    data->script_wrappable_visitor_->AbortTracing();
  data->script_wrappable_visitor_.reset();
}

// destroy() clear things that should be cleared after ThreadState::detach()
// gets called but before the Isolate exits.
void V8PerIsolateData::Destroy(v8::Isolate* isolate) {
  isolate->RemoveBeforeCallEnteredCallback(&BeforeCallEnteredCallback);
  isolate->RemoveMicrotasksCompletedCallback(&MicrotasksCompletedCallback);
  V8PerIsolateData* data = From(isolate);

  // Clear everything before exiting the Isolate.
  if (data->script_regexp_script_state_)
    data->script_regexp_script_state_->DisposePerContextData();
  data->private_property_.reset();
  data->string_cache_->Dispose();
  data->string_cache_.reset();
  data->interface_template_map_for_non_main_world_.clear();
  data->interface_template_map_for_main_world_.clear();
  data->operation_template_map_for_non_main_world_.clear();
  data->operation_template_map_for_main_world_.clear();
  if (IsMainThread())
    g_main_thread_per_isolate_data = nullptr;

  // FIXME: Remove once all v8::Isolate::GetCurrent() calls are gone.
  isolate->Exit();
  delete data;
}

V8PerIsolateData::V8FunctionTemplateMap&
V8PerIsolateData::SelectInterfaceTemplateMap(const DOMWrapperWorld& world) {
  return world.IsMainWorld() ? interface_template_map_for_main_world_
                             : interface_template_map_for_non_main_world_;
}

V8PerIsolateData::V8FunctionTemplateMap&
V8PerIsolateData::SelectOperationTemplateMap(const DOMWrapperWorld& world) {
  return world.IsMainWorld() ? operation_template_map_for_main_world_
                             : operation_template_map_for_non_main_world_;
}

v8::Local<v8::FunctionTemplate> V8PerIsolateData::FindOrCreateOperationTemplate(
    const DOMWrapperWorld& world,
    const void* key,
    v8::FunctionCallback callback,
    v8::Local<v8::Value> data,
    v8::Local<v8::Signature> signature,
    int length) {
  auto& map = SelectOperationTemplateMap(world);
  auto result = map.find(key);
  if (result != map.end())
    return result->value.Get(GetIsolate());

  v8::Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(
      GetIsolate(), callback, data, signature, length);
  templ->RemovePrototype();
  map.insert(key, v8::Eternal<v8::FunctionTemplate>(GetIsolate(), templ));
  return templ;
}

v8::Local<v8::FunctionTemplate> V8PerIsolateData::FindInterfaceTemplate(
    const DOMWrapperWorld& world,
    const void* key) {
  if (GetV8ContextSnapshotMode() == V8ContextSnapshotMode::kTakeSnapshot) {
    const WrapperTypeInfo* type = reinterpret_cast<const WrapperTypeInfo*>(key);
    return interface_template_map_for_v8_context_snapshot_.Get(type);
  }

  auto& map = SelectInterfaceTemplateMap(world);
  auto result = map.find(key);
  if (result != map.end())
    return result->value.Get(GetIsolate());
  return v8::Local<v8::FunctionTemplate>();
}

void V8PerIsolateData::SetInterfaceTemplate(
    const DOMWrapperWorld& world,
    const void* key,
    v8::Local<v8::FunctionTemplate> value) {
  if (GetV8ContextSnapshotMode() == V8ContextSnapshotMode::kTakeSnapshot) {
    auto& map = interface_template_map_for_v8_context_snapshot_;
    const WrapperTypeInfo* type = reinterpret_cast<const WrapperTypeInfo*>(key);
    map.Set(type, value);
  } else {
    auto& map = SelectInterfaceTemplateMap(world);
    map.insert(key, v8::Eternal<v8::FunctionTemplate>(GetIsolate(), value));
  }
}

void V8PerIsolateData::ClearPersistentsForV8ContextSnapshot() {
  interface_template_map_for_v8_context_snapshot_.Clear();
  private_property_.reset();
}

const v8::Eternal<v8::Name>* V8PerIsolateData::FindOrCreateEternalNameCache(
    const void* lookup_key,
    const char* const names[],
    size_t count) {
  auto it = eternal_name_cache_.find(lookup_key);
  const Vector<v8::Eternal<v8::Name>>* vector = nullptr;
  if (UNLIKELY(it == eternal_name_cache_.end())) {
    v8::Isolate* isolate = this->GetIsolate();
    Vector<v8::Eternal<v8::Name>> new_vector(count);
    std::transform(
        names, names + count, new_vector.begin(), [isolate](const char* name) {
          return v8::Eternal<v8::Name>(isolate, V8AtomicString(isolate, name));
        });
    vector = &eternal_name_cache_.Set(lookup_key, std::move(new_vector))
                  .stored_value->value;
  } else {
    vector = &it->value;
  }
  DCHECK_EQ(vector->size(), count);
  return vector->data();
}

v8::Local<v8::Context> V8PerIsolateData::EnsureScriptRegexpContext() {
  if (!script_regexp_script_state_) {
    LEAK_SANITIZER_DISABLED_SCOPE;
    v8::Local<v8::Context> context(v8::Context::New(GetIsolate()));
    script_regexp_script_state_ = ScriptState::Create(
        context, DOMWrapperWorld::Create(GetIsolate(),
                                         DOMWrapperWorld::WorldType::kRegExp));
  }
  return script_regexp_script_state_->GetContext();
}

void V8PerIsolateData::ClearScriptRegexpContext() {
  if (script_regexp_script_state_)
    script_regexp_script_state_->DisposePerContextData();
  script_regexp_script_state_ = nullptr;
}

bool V8PerIsolateData::HasInstance(
    const WrapperTypeInfo* untrusted_wrapper_type_info,
    v8::Local<v8::Value> value) {
  RUNTIME_CALL_TIMER_SCOPE(GetIsolate(),
                           RuntimeCallStats::CounterId::kHasInstance);
  return HasInstance(untrusted_wrapper_type_info, value,
                     interface_template_map_for_main_world_) ||
         HasInstance(untrusted_wrapper_type_info, value,
                     interface_template_map_for_non_main_world_);
}

bool V8PerIsolateData::HasInstance(
    const WrapperTypeInfo* untrusted_wrapper_type_info,
    v8::Local<v8::Value> value,
    V8FunctionTemplateMap& map) {
  auto result = map.find(untrusted_wrapper_type_info);
  if (result == map.end())
    return false;
  v8::Local<v8::FunctionTemplate> templ = result->value.Get(GetIsolate());
  return templ->HasInstance(value);
}

v8::Local<v8::Object> V8PerIsolateData::FindInstanceInPrototypeChain(
    const WrapperTypeInfo* info,
    v8::Local<v8::Value> value) {
  v8::Local<v8::Object> wrapper = FindInstanceInPrototypeChain(
      info, value, interface_template_map_for_main_world_);
  if (!wrapper.IsEmpty())
    return wrapper;
  return FindInstanceInPrototypeChain(
      info, value, interface_template_map_for_non_main_world_);
}

v8::Local<v8::Object> V8PerIsolateData::FindInstanceInPrototypeChain(
    const WrapperTypeInfo* info,
    v8::Local<v8::Value> value,
    V8FunctionTemplateMap& map) {
  if (value.IsEmpty() || !value->IsObject())
    return v8::Local<v8::Object>();
  auto result = map.find(info);
  if (result == map.end())
    return v8::Local<v8::Object>();
  v8::Local<v8::FunctionTemplate> templ = result->value.Get(GetIsolate());
  return v8::Local<v8::Object>::Cast(value)->FindInstanceInPrototypeChain(
      templ);
}

void V8PerIsolateData::AddEndOfScopeTask(base::OnceClosure task) {
  end_of_scope_tasks_.push_back(std::move(task));
}

void V8PerIsolateData::RunEndOfScopeTasks() {
  Vector<base::OnceClosure> tasks;
  tasks.swap(end_of_scope_tasks_);
  for (auto& task : tasks)
    std::move(task).Run();
  DCHECK(end_of_scope_tasks_.IsEmpty());
}

void V8PerIsolateData::ClearEndOfScopeTasks() {
  end_of_scope_tasks_.clear();
}

void V8PerIsolateData::SetThreadDebugger(
    std::unique_ptr<V8PerIsolateData::Data> thread_debugger) {
  DCHECK(!thread_debugger_);
  thread_debugger_ = std::move(thread_debugger);
}

V8PerIsolateData::Data* V8PerIsolateData::ThreadDebugger() {
  return thread_debugger_.get();
}

void V8PerIsolateData::AddActiveScriptWrappable(
    ActiveScriptWrappableBase* wrappable) {
  if (!active_script_wrappables_)
    active_script_wrappables_ = new ActiveScriptWrappableSet();

  active_script_wrappables_->insert(wrappable);
}

void V8PerIsolateData::TemporaryScriptWrappableVisitorScope::
    SwapWithV8PerIsolateDataVisitor(
        std::unique_ptr<ScriptWrappableMarkingVisitor>& visitor) {
  ScriptWrappableMarkingVisitor* current = CurrentVisitor();
  if (current)
    ScriptWrappableMarkingVisitor::PerformCleanup(isolate_);

  V8PerIsolateData::From(isolate_)->script_wrappable_visitor_.swap(
      saved_visitor_);
  isolate_->SetEmbedderHeapTracer(CurrentVisitor());
}

}  // namespace blink
