// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "extensions/renderer/module_system.h"

#include "base/bind.h"
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/timer/elapsed_timer.h"
#include "base/trace_event/trace_event.h"
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_view.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_features.h"
#include "extensions/common/extensions_client.h"
#include "extensions/renderer/console.h"
#include "extensions/renderer/safe_builtins.h"
#include "extensions/renderer/script_context.h"
#include "extensions/renderer/script_context_set.h"
#include "extensions/renderer/source_map.h"
#include "extensions/renderer/v8_helpers.h"
#include "gin/converter.h"
#include "third_party/blink/public/web/web_context_features.h"
#include "third_party/blink/public/web/web_frame.h"

namespace extensions {

using namespace v8_helpers;

namespace {

const char kModuleSystem[] = "module_system";
const char kModuleName[] = "module_name";
const char kModuleField[] = "module_field";
const char kModulesField[] = "modules";

// Logs an error for the calling context in preparation for potentially
// crashing the renderer, with some added metadata about the context:
//  - Its type (blessed, unblessed, etc).
//  - Whether it's valid.
//  - The extension ID, if one exists.
// Crashing won't happen in stable/beta releases, but is encouraged to happen
// in the less stable released to catch errors early.
void Fatal(ScriptContext* context, const std::string& message) {
  // Prepend some context metadata.
  std::string full_message = "(";
  if (!context->is_valid())
    full_message += "Invalid ";
  full_message += context->GetContextTypeDescription();
  full_message += " context";
  if (context->extension()) {
    full_message += " for ";
    full_message += context->extension()->id();
  }
  full_message += ") ";
  full_message += message;

  ExtensionsClient* client = ExtensionsClient::Get();
  if (client->ShouldSuppressFatalErrors()) {
    console::AddMessage(context, content::CONSOLE_MESSAGE_LEVEL_ERROR,
                        full_message);
    client->RecordDidSuppressFatalError();
  } else {
    console::Fatal(context, full_message);
  }
}

void Warn(v8::Isolate* isolate, const std::string& message) {
  ScriptContext* script_context =
      ScriptContextSet::GetContextByV8Context(isolate->GetCurrentContext());
  console::AddMessage(script_context, content::CONSOLE_MESSAGE_LEVEL_WARNING,
                      message);
}

// Default exception handler which logs the exception.
class DefaultExceptionHandler : public ModuleSystem::ExceptionHandler {
 public:
  explicit DefaultExceptionHandler(ScriptContext* context)
      : ModuleSystem::ExceptionHandler(context) {}

  // Fatally dumps the debug info from |try_catch| to the console.
  // Make sure this is never used for exceptions that originate in external
  // code!
  void HandleUncaughtException(const v8::TryCatch& try_catch) override {
    v8::HandleScope handle_scope(context_->isolate());
    std::string stack_trace = "<stack trace unavailable>";
    v8::Local<v8::Value> v8_stack_trace;
    if (try_catch.StackTrace(context_->v8_context()).ToLocal(&v8_stack_trace)) {
      v8::String::Utf8Value stack_value(context_->isolate(), v8_stack_trace);
      if (*stack_value)
        stack_trace.assign(*stack_value, stack_value.length());
      else
        stack_trace = "<could not convert stack trace to string>";
    }
    Fatal(context_, CreateExceptionString(try_catch) + "{" + stack_trace + "}");
  }
};

// Sets a property on the "exports" object for bindings. Called by JS with
// exports.$set(<key>, <value>).
void SetExportsProperty(
    const v8::FunctionCallbackInfo<v8::Value>& args) {
  v8::Local<v8::Object> obj = args.This();
  CHECK_EQ(2, args.Length());
  CHECK(args[0]->IsString());
  v8::Maybe<bool> result =
      obj->DefineOwnProperty(args.GetIsolate()->GetCurrentContext(),
                             args[0].As<v8::String>(), args[1], v8::ReadOnly);
  if (!result.FromMaybe(false))
    LOG(ERROR) << "Failed to set private property on the export.";
}

bool ContextNeedsMojoBindings(ScriptContext* context) {
  // Mojo is only used from JS by some APIs so a context only needs the mojo
  // bindings if at least one is available.
  //
  // Prefer to use Mojo from C++ if possible rather than adding to this list.
  static const char* const kApisRequiringMojo[] = {
      "mediaPerceptionPrivate", "mimeHandlerPrivate", "mojoPrivate",
  };

  for (const auto* api : kApisRequiringMojo) {
    if (context->GetAvailability(api).is_available())
      return true;
  }
  return false;
}

}  // namespace

std::string ModuleSystem::ExceptionHandler::CreateExceptionString(
    const v8::TryCatch& try_catch) {
  v8::Local<v8::Message> message(try_catch.Message());
  if (message.IsEmpty()) {
    return "try_catch has no message";
  }

  std::string resource_name = "<unknown resource>";
  if (!message->GetScriptOrigin().ResourceName().IsEmpty()) {
    v8::String::Utf8Value resource_name_v8(
        context_->isolate(), message->GetScriptOrigin().ResourceName());
    resource_name.assign(*resource_name_v8, resource_name_v8.length());
  }

  std::string error_message = "<no error message>";
  if (!message->Get().IsEmpty()) {
    v8::String::Utf8Value error_message_v8(context_->isolate(), message->Get());
    error_message.assign(*error_message_v8, error_message_v8.length());
  }

  int line_number = 0;
  if (context_) {  // |context_| can be null in unittests.
    auto maybe = message->GetLineNumber(context_->v8_context());
    line_number = maybe.IsJust() ? maybe.FromJust() : 0;
  }
  return base::StringPrintf("%s:%d: %s",
                            resource_name.c_str(),
                            line_number,
                            error_message.c_str());
}

ModuleSystem::ModuleSystem(ScriptContext* context, const SourceMap* source_map)
    : ObjectBackedNativeHandler(context),
      context_(context),
      source_map_(source_map),
      natives_enabled_(0),
      exception_handler_(new DefaultExceptionHandler(context)),
      lazily_initialize_handlers_(base::FeatureList::IsEnabled(
          extensions_features::kNativeCrxBindings)) {
  v8::Local<v8::Object> global(context->v8_context()->Global());
  v8::Isolate* isolate = context->isolate();
  SetPrivate(global, kModulesField, v8::Object::New(isolate));
  SetPrivate(global, kModuleSystem, v8::External::New(isolate, this));

  if (context_->GetRenderFrame() &&
      context_->context_type() == Feature::BLESSED_EXTENSION_CONTEXT &&
      ContextNeedsMojoBindings(context_)) {
    blink::WebContextFeatures::EnableMojoJS(context->v8_context(), true);
  }
}

ModuleSystem::~ModuleSystem() {
}

void ModuleSystem::AddRoutes() {
  RouteHandlerFunction("require", base::Bind(&ModuleSystem::RequireForJs,
                                             base::Unretained(this)));
  RouteHandlerFunction("requireNative", base::Bind(&ModuleSystem::RequireNative,
                                                   base::Unretained(this)));
  RouteHandlerFunction("loadScript", base::Bind(&ModuleSystem::LoadScript,
                                                base::Unretained(this)));
  RouteHandlerFunction(
      "privates", base::Bind(&ModuleSystem::Private, base::Unretained(this)));
}

void ModuleSystem::Invalidate() {
  // Clear the module system properties from the global context. It's polite,
  // and we use this as a signal in lazy handlers that we no longer exist.
  {
    v8::HandleScope scope(GetIsolate());
    v8::Local<v8::Object> global = context()->v8_context()->Global();
    DeletePrivate(global, kModulesField);
    DeletePrivate(global, kModuleSystem);
  }

  // Invalidate all active and clobbered NativeHandlers we own.
  for (const auto& handler : native_handler_map_)
    handler.second->Invalidate();
  for (const auto& clobbered_handler : clobbered_native_handlers_)
    clobbered_handler->Invalidate();

  ObjectBackedNativeHandler::Invalidate();
}

ModuleSystem::NativesEnabledScope::NativesEnabledScope(
    ModuleSystem* module_system)
    : module_system_(module_system) {
  module_system_->natives_enabled_++;
}

ModuleSystem::NativesEnabledScope::~NativesEnabledScope() {
  module_system_->natives_enabled_--;
  CHECK_GE(module_system_->natives_enabled_, 0);
}

void ModuleSystem::HandleException(const v8::TryCatch& try_catch) {
  exception_handler_->HandleUncaughtException(try_catch);
}

v8::MaybeLocal<v8::Object> ModuleSystem::Require(
    const std::string& module_name) {
  v8::Local<v8::String> v8_module_name;
  if (!ToV8String(GetIsolate(), module_name, &v8_module_name))
    return v8::MaybeLocal<v8::Object>();
  v8::EscapableHandleScope handle_scope(GetIsolate());
  v8::Local<v8::Value> value =
      RequireForJsInner(v8_module_name, true /* create */);
  if (value.IsEmpty() || !value->IsObject())
    return v8::MaybeLocal<v8::Object>();
  return handle_scope.Escape(value.As<v8::Object>());
}

void ModuleSystem::RequireForJs(
    const v8::FunctionCallbackInfo<v8::Value>& args) {
  if (!args[0]->IsString()) {
    NOTREACHED() << "require() called with a non-string argument";
    return;
  }
  v8::Local<v8::String> module_name = args[0].As<v8::String>();
  args.GetReturnValue().Set(RequireForJsInner(module_name, true /* create */));
}

v8::Local<v8::Value> ModuleSystem::RequireForJsInner(
    v8::Local<v8::String> module_name,
    bool create) {
  v8::EscapableHandleScope handle_scope(GetIsolate());
  v8::Local<v8::Context> v8_context = context()->v8_context();
  v8::Context::Scope context_scope(v8_context);

  v8::Local<v8::Object> global(context()->v8_context()->Global());

  // The module system might have been deleted. This can happen if a different
  // context keeps a reference to us, but our frame is destroyed (e.g.
  // background page keeps reference to chrome object in a closed popup).
  v8::Local<v8::Value> modules_value;
  if (!GetPrivate(global, kModulesField, &modules_value) ||
      modules_value->IsUndefined()) {
    Warn(GetIsolate(), "Extension view no longer exists");
    return v8::Undefined(GetIsolate());
  }

  v8::Local<v8::Object> modules(v8::Local<v8::Object>::Cast(modules_value));
  v8::Local<v8::Value> exports;
  if (!GetPrivateProperty(v8_context, modules, module_name, &exports) ||
      !exports->IsUndefined())
    return handle_scope.Escape(exports);

  if (!create)
    return v8::Undefined(GetIsolate());

  exports = LoadModule(*v8::String::Utf8Value(GetIsolate(), module_name));
  SetPrivateProperty(v8_context, modules, module_name, exports);
  return handle_scope.Escape(exports);
}

void ModuleSystem::CallModuleMethodSafe(const std::string& module_name,
                                        const std::string& method_name) {
  v8::HandleScope handle_scope(GetIsolate());
  v8::Local<v8::Value> no_args;
  CallModuleMethodSafe(module_name, method_name, 0, &no_args,
                       ScriptInjectionCallback::CompleteCallback());
}

void ModuleSystem::CallModuleMethodSafe(
    const std::string& module_name,
    const std::string& method_name,
    std::vector<v8::Local<v8::Value>>* args) {
  CallModuleMethodSafe(module_name, method_name, args->size(), args->data(),
                       ScriptInjectionCallback::CompleteCallback());
}

void ModuleSystem::CallModuleMethodSafe(const std::string& module_name,
                                        const std::string& method_name,
                                        int argc,
                                        v8::Local<v8::Value> argv[]) {
  CallModuleMethodSafe(module_name, method_name, argc, argv,
                       ScriptInjectionCallback::CompleteCallback());
}

void ModuleSystem::CallModuleMethodSafe(
    const std::string& module_name,
    const std::string& method_name,
    int argc,
    v8::Local<v8::Value> argv[],
    const ScriptInjectionCallback::CompleteCallback& callback) {
  TRACE_EVENT2("v8", "v8.callModuleMethodSafe", "module_name", module_name,
               "method_name", method_name);

  v8::HandleScope handle_scope(GetIsolate());
  v8::Local<v8::Context> v8_context = context()->v8_context();
  v8::Context::Scope context_scope(v8_context);

  v8::Local<v8::Function> function =
      GetModuleFunction(module_name, method_name);
  if (function.IsEmpty()) {
    // This can legitimately happen when the module hasn't been loaded in the
    // context (since GetModuleFunction() does not load an unloaded module).
    // Typically, we won't do this, but we can in the case of, e.g., dispatching
    // events (where we'll try to dispatch to each context in a process). In
    // these cases, though, we can know that there are no listeners registered,
    // since the event module hasn't been loaded.
    return;
  }

  {
    v8::TryCatch try_catch(GetIsolate());
    try_catch.SetCaptureMessage(true);
    context_->SafeCallFunction(function, argc, argv, callback);
    if (try_catch.HasCaught())
      HandleException(try_catch);
  }
}

void ModuleSystem::RegisterNativeHandler(
    const std::string& name,
    std::unique_ptr<NativeHandler> native_handler) {
  ClobberExistingNativeHandler(name);
  if (!lazily_initialize_handlers_)
    native_handler->Initialize();

  native_handler_map_[name] = std::move(native_handler);
}

void ModuleSystem::OverrideNativeHandlerForTest(const std::string& name) {
  ClobberExistingNativeHandler(name);
  overridden_native_handlers_.insert(name);
}

// static
void ModuleSystem::NativeLazyFieldGetter(
    v8::Local<v8::Name> property,
    const v8::PropertyCallbackInfo<v8::Value>& info) {
  LazyFieldGetterInner(property.As<v8::String>(), info,
                       &ModuleSystem::RequireNativeFromString);
}

// static
void ModuleSystem::LazyFieldGetter(
    v8::Local<v8::Name> property,
    const v8::PropertyCallbackInfo<v8::Value>& info) {
  LazyFieldGetterInner(property.As<v8::String>(), info, &ModuleSystem::Require);
}

// static
void ModuleSystem::LazyFieldGetterInner(
    v8::Local<v8::String> property,
    const v8::PropertyCallbackInfo<v8::Value>& info,
    RequireFunction require_function) {
  base::ElapsedTimer timer;
  CHECK(!info.Data().IsEmpty());
  CHECK(info.Data()->IsObject());
  v8::Isolate* isolate = info.GetIsolate();
  v8::HandleScope handle_scope(isolate);
  v8::Local<v8::Object> parameters = v8::Local<v8::Object>::Cast(info.Data());
  // This context should be the same as context()->v8_context().
  v8::Local<v8::Context> context = parameters->CreationContext();
  v8::Local<v8::Object> global(context->Global());
  v8::Local<v8::Value> module_system_value;
  if (!GetPrivate(context, global, kModuleSystem, &module_system_value) ||
      !module_system_value->IsExternal()) {
    // ModuleSystem has been deleted.
    // TODO(kalman): See comment in header file.
    Warn(isolate,
         "Module system has been deleted, does extension view exist?");
    return;
  }

  ModuleSystem* module_system = static_cast<ModuleSystem*>(
      v8::Local<v8::External>::Cast(module_system_value)->Value());

  v8::Local<v8::Value> v8_module_name;
  if (!GetPrivateProperty(context, parameters, kModuleName, &v8_module_name)) {
    Warn(isolate, "Cannot find module.");
    return;
  }
  std::string name = *v8::String::Utf8Value(isolate, v8_module_name);

  // As part of instantiating a module, we delete the getter and replace it with
  // the property directly. If we're trying to load the same module a second
  // time, it means something went wrong. Bail out early rather than going
  // through the initialization process again (since bindings may not expect to
  // run multiple times).
  if (!module_system->loaded_modules_.insert(name).second) {
    Warn(isolate, "Previous API instantiation failed.");
    return;
  }

  // Switch to our v8 context because we need functions created while running
  // the require()d module to belong to our context, not the current one.
  v8::Context::Scope context_scope(context);
  NativesEnabledScope natives_enabled_scope(module_system);

  v8::TryCatch try_catch(isolate);
  v8::Local<v8::Value> module_value;
  if (!(module_system->*require_function)(name).ToLocal(&module_value)) {
    module_system->HandleException(try_catch);
    return;
  }

  v8::Local<v8::Object> module = v8::Local<v8::Object>::Cast(module_value);
  v8::Local<v8::Value> field_value;
  if (!GetPrivateProperty(context, parameters, kModuleField, &field_value)) {
    module_system->HandleException(try_catch);
    return;
  }
  v8::Local<v8::String> field;
  if (!field_value->ToString(context).ToLocal(&field)) {
    module_system->HandleException(try_catch);
    return;
  }

  if (!IsTrue(module->Has(context, field))) {
    std::string field_str = *v8::String::Utf8Value(isolate, field);
    Fatal(module_system->context_,
          "Lazy require of " + name + "." + field_str + " did not set the " +
              field_str + " field");
    return;
  }

  v8::Local<v8::Value> new_field;
  if (!GetProperty(context, module, field, &new_field)) {
    module_system->HandleException(try_catch);
    return;
  }

  // Ok for it to be undefined, among other things it's how bindings signify
  // that the extension doesn't have permission to use them.
  CHECK(!new_field.IsEmpty());

  // Delete the getter and set this field to |new_field| so the same object is
  // returned every time a certain API is accessed.
  v8::Local<v8::Value> val = info.This();
  if (val->IsObject()) {
    v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(val);
    auto maybe_deleted = object->Delete(context, property);
    if (!maybe_deleted.IsJust()) {
      // In theory, deletion should never result in throwing an error. But
      // crazier things have happened.
      NOTREACHED();
      return;
    }
    if (!maybe_deleted.FromJust()) {
      // Deletion can *fail* in certain cases, such as when the script does
      // Object.freeze(chrome).
      return;
    }
    auto maybe_set = object->CreateDataProperty(context, property, new_field);
    // Setting a new value can fail in multiple scenarios. Bail out if it does.
    if (!maybe_set.IsJust() || !maybe_set.FromJust())
      return;
  } else {
    NOTREACHED();
  }
  info.GetReturnValue().Set(new_field);

  UMA_HISTOGRAM_TIMES("Extensions.ApiBindingGenerationTime", timer.Elapsed());
}

void ModuleSystem::SetLazyField(v8::Local<v8::Object> object,
                                const std::string& field,
                                const std::string& module_name,
                                const std::string& module_field) {
  SetLazyField(
      object, field, module_name, module_field, &ModuleSystem::LazyFieldGetter);
}

void ModuleSystem::SetLazyField(v8::Local<v8::Object> object,
                                const std::string& field,
                                const std::string& module_name,
                                const std::string& module_field,
                                v8::AccessorNameGetterCallback getter) {
  CHECK(field.size() < v8::String::kMaxLength);
  CHECK(module_name.size() < v8::String::kMaxLength);
  CHECK(module_field.size() < v8::String::kMaxLength);
  v8::HandleScope handle_scope(GetIsolate());
  v8::Local<v8::Object> parameters = v8::Object::New(GetIsolate());
  v8::Local<v8::Context> context = context_->v8_context();
  // Since we reset the accessor here, we remove the record of having loaded the
  // module.
  loaded_modules_.erase(module_name);
  SetPrivateProperty(context, parameters, kModuleName,
              ToV8StringUnsafe(GetIsolate(), module_name.c_str()));
  SetPrivateProperty(context, parameters, kModuleField,
              ToV8StringUnsafe(GetIsolate(), module_field.c_str()));
  auto maybe = object->SetAccessor(
      context, ToV8StringUnsafe(GetIsolate(), field.c_str()), getter, NULL,
      parameters);
  CHECK(IsTrue(maybe));
}

void ModuleSystem::SetNativeLazyField(v8::Local<v8::Object> object,
                                      const std::string& field,
                                      const std::string& module_name,
                                      const std::string& module_field) {
  SetLazyField(object,
               field,
               module_name,
               module_field,
               &ModuleSystem::NativeLazyFieldGetter);
}

void ModuleSystem::OnNativeBindingCreated(
    const std::string& api_name,
    v8::Local<v8::Value> api_bridge_value) {
  DCHECK(!get_internal_api_.IsEmpty());
  v8::HandleScope scope(GetIsolate());
  if (source_map_->Contains(api_name)) {
    // We need to load the custom bindings and store them in our modules.
    // Storing them is important so that calls through CallModuleMethod() route
    // to the proper objects, if they share the same name as an API.
    v8::Local<v8::Value> modules;
    if (!GetPrivate(context()->v8_context()->Global(), kModulesField,
                    &modules) ||
        !modules->IsObject()) {
      NOTREACHED();
      return;
    }

    NativesEnabledScope enabled(this);
    v8::Local<v8::Value> exports =
        LoadModuleWithNativeAPIBridge(api_name, api_bridge_value);
    SetPrivateProperty(context()->v8_context(), modules.As<v8::Object>(),
                       gin::StringToSymbol(GetIsolate(), api_name), exports);
  }
}

void ModuleSystem::SetGetInternalAPIHook(
    v8::Local<v8::FunctionTemplate> get_internal_api) {
  DCHECK(get_internal_api_.IsEmpty());
  get_internal_api_.Set(GetIsolate(), get_internal_api);
}

void ModuleSystem::SetJSBindingUtilGetter(const JSBindingUtilGetter& getter) {
  DCHECK(js_binding_util_getter_.is_null());
  js_binding_util_getter_ = getter;
}

v8::Local<v8::Value> ModuleSystem::RunString(v8::Local<v8::String> code,
                                             v8::Local<v8::String> name) {
  return context_->RunScript(
      name, code,
      base::Bind(&ExceptionHandler::HandleUncaughtException,
                 base::Unretained(exception_handler_.get())),
      v8::ScriptCompiler::NoCacheReason::kNoCacheBecauseExtensionModule);
}

void ModuleSystem::RequireNative(
    const v8::FunctionCallbackInfo<v8::Value>& args) {
  CHECK_EQ(1, args.Length());
  std::string native_name = *v8::String::Utf8Value(args.GetIsolate(), args[0]);
  v8::Local<v8::Object> object;
  if (RequireNativeFromString(native_name).ToLocal(&object))
    args.GetReturnValue().Set(object);
}

v8::MaybeLocal<v8::Object> ModuleSystem::RequireNativeFromString(
    const std::string& native_name) {
  if (natives_enabled_ == 0) {
    // HACK: if in test throw exception so that we can test the natives-disabled
    // logic; however, under normal circumstances, this is programmer error so
    // we could crash.
    if (exception_handler_) {
      GetIsolate()->ThrowException(
          ToV8StringUnsafe(GetIsolate(), "Natives disabled"));
      return v8::MaybeLocal<v8::Object>();
    }
    Fatal(context_, "Natives disabled for requireNative(" + native_name + ")");
    return v8::MaybeLocal<v8::Object>();
  }

  if (overridden_native_handlers_.count(native_name) > 0u) {
    v8::Local<v8::Value> value = RequireForJsInner(
        ToV8StringUnsafe(GetIsolate(), native_name.c_str()), true /* create */);
    if (value.IsEmpty() || !value->IsObject())
      return v8::MaybeLocal<v8::Object>();
    return value.As<v8::Object>();
  }

  auto i = native_handler_map_.find(native_name);
  if (i == native_handler_map_.end()) {
    Fatal(context_,
          "Couldn't find native for requireNative(" + native_name + ")");
    return v8::MaybeLocal<v8::Object>();
  }

  if (lazily_initialize_handlers_ && !i->second->IsInitialized())
    i->second->Initialize();

  return i->second->NewInstance();
}

void ModuleSystem::LoadScript(const v8::FunctionCallbackInfo<v8::Value>& args) {
  CHECK_EQ(1, args.Length());
  std::string module_name = *v8::String::Utf8Value(GetIsolate(), args[0]);

  v8::HandleScope handle_scope(GetIsolate());
  v8::Local<v8::Context> v8_context = context()->v8_context();
  v8::Context::Scope context_scope(v8_context);

  v8::Local<v8::String> source =
      source_map_->GetSource(GetIsolate(), module_name);
  if (source.IsEmpty())
    Fatal(context_, "No source for loadScript(" + module_name + ")");

  v8::Local<v8::String> v8_module_name;
  if (!ToV8String(GetIsolate(), module_name.c_str(), &v8_module_name))
    Warn(GetIsolate(), "module_name is too long");

  RunString(source, v8_module_name);
  args.GetReturnValue().Set(v8::Undefined(GetIsolate()));
}

v8::Local<v8::String> ModuleSystem::WrapSource(v8::Local<v8::String> source) {
  v8::EscapableHandleScope handle_scope(GetIsolate());
  // Keep in order with the arguments in RequireForJsInner.
  v8::Local<v8::String> left = ToV8StringUnsafe(
      GetIsolate(),
      "(function(require, requireNative, loadScript, exports, console, "
      "privates, apiBridge, bindingUtil, getInternalApi, $Array, $Function, "
      "$JSON, $Object, $RegExp, $String, $Error) {"
      "'use strict';");
  v8::Local<v8::String> right = ToV8StringUnsafe(GetIsolate(), "\n})");
  return handle_scope.Escape(v8::Local<v8::String>(v8::String::Concat(
      GetIsolate(), left, v8::String::Concat(GetIsolate(), source, right))));
}

void ModuleSystem::Private(const v8::FunctionCallbackInfo<v8::Value>& args) {
  CHECK_EQ(1, args.Length());
  if (!args[0]->IsObject() || args[0]->IsNull()) {
    GetIsolate()->ThrowException(
        v8::Exception::TypeError(ToV8StringUnsafe(GetIsolate(),
            args[0]->IsUndefined()
                ? "Method called without a valid receiver (this). "
                  "Did you forget to call .bind()?"
                : "Invalid invocation: receiver is not an object!")));
    return;
  }
  v8::Local<v8::Object> obj = args[0].As<v8::Object>();
  v8::Local<v8::Value> privates;
  if (!GetPrivate(obj, "privates", &privates) || !privates->IsObject()) {
    privates = v8::Object::New(args.GetIsolate());
    if (privates.IsEmpty()) {
      GetIsolate()->ThrowException(
          ToV8StringUnsafe(GetIsolate(), "Failed to create privates"));
      return;
    }
    v8::Maybe<bool> maybe =
        privates.As<v8::Object>()->SetPrototype(context()->v8_context(),
                                                v8::Null(args.GetIsolate()));
    CHECK(maybe.IsJust() && maybe.FromJust());
    SetPrivate(obj, "privates", privates);
  }
  args.GetReturnValue().Set(privates);
}

v8::Local<v8::Value> ModuleSystem::LoadModule(const std::string& module_name) {
  return LoadModuleWithNativeAPIBridge(module_name,
                                       v8::Undefined(GetIsolate()));
}

v8::Local<v8::Value> ModuleSystem::LoadModuleWithNativeAPIBridge(
    const std::string& module_name,
    v8::Local<v8::Value> api_bridge) {
  v8::EscapableHandleScope handle_scope(GetIsolate());
  v8::Local<v8::Context> v8_context = context()->v8_context();
  v8::Context::Scope context_scope(v8_context);

  v8::Local<v8::String> source =
      source_map_->GetSource(GetIsolate(), module_name);
  if (source.IsEmpty()) {
    Fatal(context_, "No source for require(" + module_name + ")");
    return v8::Undefined(GetIsolate());
  }
  v8::Local<v8::String> wrapped_source(WrapSource(source));
  v8::Local<v8::String> v8_module_name;
  if (!ToV8String(GetIsolate(), module_name.c_str(), &v8_module_name)) {
    NOTREACHED() << "module_name is too long";
    return v8::Undefined(GetIsolate());
  }
  // Modules are wrapped in (function(){...}) so they always return functions.
  v8::Local<v8::Value> func_as_value =
      RunString(wrapped_source, v8_module_name);
  if (func_as_value.IsEmpty() || func_as_value->IsUndefined()) {
    Fatal(context_, "Bad source for require(" + module_name + ")");
    return v8::Undefined(GetIsolate());
  }

  v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast(func_as_value);

  v8::Local<v8::Object> exports = v8::Object::New(GetIsolate());

  v8::Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New(
      GetIsolate(),
      &SetExportsProperty);
  tmpl->RemovePrototype();
  v8::Local<v8::String> v8_key;
  if (!v8_helpers::ToV8String(GetIsolate(), "$set", &v8_key)) {
    NOTREACHED();
    return v8::Undefined(GetIsolate());
  }

  v8::Local<v8::Function> function;
  if (!tmpl->GetFunction(v8_context).ToLocal(&function)) {
    NOTREACHED();
    return v8::Undefined(GetIsolate());
  }

  exports->DefineOwnProperty(v8_context, v8_key, function, v8::ReadOnly)
      .FromJust();

  v8::Local<v8::Object> natives(NewInstance());
  CHECK(!natives.IsEmpty());  // this can fail if v8 has issues

  v8::Local<v8::Value> get_internal_api;
  if (get_internal_api_.IsEmpty()) {
    get_internal_api = v8::Undefined(GetIsolate());
  } else {
    get_internal_api = get_internal_api_.Get(GetIsolate())
                           ->GetFunction(v8_context)
                           .ToLocalChecked();
  }

  v8::Local<v8::Value> binding_util;
  if (!js_binding_util_getter_.is_null()) {
    js_binding_util_getter_.Run(v8_context, &binding_util);
    if (binding_util.IsEmpty()) {
      // The NativeExtensionBindingsSystem was destroyed. This shouldn't happen,
      // but JS makes the impossible possible!
      NOTREACHED();
      return v8::Undefined(GetIsolate());
    }
  } else {
    binding_util = v8::Undefined(GetIsolate());
  }

  // These must match the argument order in WrapSource.
  v8::Local<v8::Value> args[] = {
      // CommonJS.
      GetPropertyUnsafe(v8_context, natives, "require",
                        v8::NewStringType::kInternalized),
      GetPropertyUnsafe(v8_context, natives, "requireNative",
                        v8::NewStringType::kInternalized),
      GetPropertyUnsafe(v8_context, natives, "loadScript",
                        v8::NewStringType::kInternalized),
      exports,
      // Libraries that we magically expose to every module.
      console::AsV8Object(GetIsolate()),
      GetPropertyUnsafe(v8_context, natives, "privates",
                        v8::NewStringType::kInternalized),
      api_bridge,        // exposed as apiBridge.
      binding_util,      // exposed as bindingUtil.
      get_internal_api,  // exposed as getInternalApi.
      // Each safe builtin. Keep in order with the arguments in WrapSource.
      context_->safe_builtins()->GetArray(),
      context_->safe_builtins()->GetFunction(),
      context_->safe_builtins()->GetJSON(),
      context_->safe_builtins()->GetObjekt(),
      context_->safe_builtins()->GetRegExp(),
      context_->safe_builtins()->GetString(),
      context_->safe_builtins()->GetError(),
  };
  {
    v8::TryCatch try_catch(GetIsolate());
    try_catch.SetCaptureMessage(true);
    context_->SafeCallFunction(func, base::size(args), args);
    if (try_catch.HasCaught()) {
      HandleException(try_catch);
      return v8::Undefined(GetIsolate());
    }
  }
  return handle_scope.Escape(exports);
}

void ModuleSystem::ClobberExistingNativeHandler(const std::string& name) {
  auto existing_handler = native_handler_map_.find(name);
  if (existing_handler != native_handler_map_.end()) {
    clobbered_native_handlers_.push_back(std::move(existing_handler->second));
    native_handler_map_.erase(existing_handler);
  }
}

v8::Local<v8::Function> ModuleSystem::GetModuleFunction(
    const std::string& module_name,
    const std::string& method_name) {
  v8::Local<v8::String> v8_module_name;
  v8::Local<v8::String> v8_method_name;
  if (!ToV8String(GetIsolate(), module_name.c_str(), &v8_module_name) ||
      !ToV8String(GetIsolate(), method_name.c_str(), &v8_method_name)) {
    return v8::Local<v8::Function>();
  }

  v8::Local<v8::Value> module;
  // Important: don't create the module if it doesn't exist. Doing so would
  // force a call into JS, which is something we want to avoid in case it has
  // been suspended. Additionally, we should only be calling module methods for
  // modules that have been instantiated.
  bool create = false;
  module = RequireForJsInner(v8_module_name, create);

  // RequireForJsInner() returns Undefined in the case of a module not being
  // loaded, since we don't create it here.
  if (!module.IsEmpty() && module->IsUndefined())
    return v8::Local<v8::Function>();

  if (module.IsEmpty() || !module->IsObject()) {
    Fatal(context_,
          "Failed to get module " + module_name + " to call " + method_name);
    return v8::Local<v8::Function>();
  }

  v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(module);
  v8::Local<v8::Value> value;
  if (!GetProperty(context()->v8_context(), object, v8_method_name, &value) ||
      !value->IsFunction()) {
    Fatal(context_, module_name + "." + method_name + " is not a function");
    return v8::Local<v8::Function>();
  }

  return v8::Local<v8::Function>::Cast(value);
}

}  // namespace extensions
