// Copyright 2017 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 "third_party/blink/renderer/bindings/core/v8/module_record.h"
#include "base/feature_list.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/v8_cache_options.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/boxed_v8_module.h"
#include "third_party/blink/renderer/bindings/core/v8/referrer_script_info.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_script_runner.h"
#include "third_party/blink/renderer/core/loader/modulescript/module_script_creation_params.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/core/script/modulator.h"
#include "third_party/blink/renderer/core/script/module_record_resolver.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/text/text_position.h"
#include "third_party/blink/renderer/platform/wtf/wtf.h"

namespace blink {

ModuleRecordProduceCacheData::ModuleRecordProduceCacheData(
    v8::Isolate* isolate,
    SingleCachedMetadataHandler* cache_handler,
    V8CodeCache::ProduceCacheOptions produce_cache_options,
    v8::Local<v8::Module> module)
    : cache_handler_(cache_handler),
      produce_cache_options_(produce_cache_options) {
  v8::HandleScope scope(isolate);

  if (produce_cache_options ==
          V8CodeCache::ProduceCacheOptions::kProduceCodeCache &&
      module->GetStatus() == v8::Module::kUninstantiated) {
    v8::Local<v8::UnboundModuleScript> unbound_script =
        module->GetUnboundModuleScript();
    if (!unbound_script.IsEmpty())
      unbound_script_.Set(isolate, unbound_script);
  }
}

void ModuleRecordProduceCacheData::Trace(Visitor* visitor) const {
  visitor->Trace(cache_handler_);
  visitor->Trace(unbound_script_.UnsafeCast<v8::Value>());
}

v8::Local<v8::Module> ModuleRecord::Compile(
    v8::Isolate* isolate,
    const ModuleScriptCreationParams& params,
    const ScriptFetchOptions& options,
    const TextPosition& text_position,
    ExceptionState& exception_state,
    mojom::blink::V8CacheOptions v8_cache_options,
    ModuleRecordProduceCacheData** out_produce_cache_data) {
  v8::TryCatch try_catch(isolate);
  v8::Local<v8::Module> module;

  // Module scripts currently don't support |kEagerCompile| which can be
  // used for |mojom::blink::V8CacheOptions::kFullCodeWithoutHeatCheck|, so use
  // |mojom::blink::V8CacheOptions::kCodeWithoutHeatCheck| instead.
  if (v8_cache_options ==
      mojom::blink::V8CacheOptions::kFullCodeWithoutHeatCheck) {
    v8_cache_options = mojom::blink::V8CacheOptions::kCodeWithoutHeatCheck;
  }

  v8::ScriptCompiler::CompileOptions compile_options;
  V8CodeCache::ProduceCacheOptions produce_cache_options;
  v8::ScriptCompiler::NoCacheReason no_cache_reason;
  std::tie(compile_options, produce_cache_options, no_cache_reason) =
      V8CodeCache::GetCompileOptions(v8_cache_options, params.CacheHandler(),
                                     params.GetSourceText().length(),
                                     params.SourceLocationType());

  if (!V8ScriptRunner::CompileModule(
           isolate, params, text_position, compile_options, no_cache_reason,
           ReferrerScriptInfo(params.BaseURL(), options,
                              ReferrerScriptInfo::BaseUrlSource::kOther))
           .ToLocal(&module)) {
    DCHECK(try_catch.HasCaught());
    exception_state.RethrowV8Exception(try_catch.Exception());
    return v8::Local<v8::Module>();
  }
  DCHECK(!try_catch.HasCaught());

  if (out_produce_cache_data) {
    *out_produce_cache_data =
        MakeGarbageCollected<ModuleRecordProduceCacheData>(
            isolate, params.CacheHandler(), produce_cache_options, module);
  }

  return module;
}

ScriptValue ModuleRecord::Instantiate(ScriptState* script_state,
                                      v8::Local<v8::Module> record,
                                      const KURL& source_url) {
  v8::Isolate* isolate = script_state->GetIsolate();
  v8::TryCatch try_catch(isolate);
  try_catch.SetVerbose(true);

  DCHECK(!record.IsEmpty());
  v8::Local<v8::Context> context = script_state->GetContext();

  // Script IDs are not available on errored modules or on non-source text
  // modules, so we give them a default value.
  probe::ExecuteScript probe(ExecutionContext::From(script_state), source_url,
                             record->GetStatus() != v8::Module::kErrored &&
                                     record->IsSourceTextModule()
                                 ? record->ScriptId()
                                 : v8::UnboundScript::kNoScriptId);
  bool success;
  if (!record->InstantiateModule(context, &ResolveModuleCallback)
           .To(&success) ||
      !success) {
    DCHECK(try_catch.HasCaught());
    return ScriptValue(isolate, try_catch.Exception());
  }
  DCHECK(!try_catch.HasCaught());
  return ScriptValue();
}

void ModuleRecord::ReportException(ScriptState* script_state,
                                   v8::Local<v8::Value> exception) {
  V8ScriptRunner::ReportException(script_state->GetIsolate(), exception);
}

Vector<ModuleRequest> ModuleRecord::ModuleRequests(
    ScriptState* script_state,
    v8::Local<v8::Module> record) {
  if (record.IsEmpty())
    return Vector<ModuleRequest>();

  v8::Local<v8::FixedArray> v8_module_requests = record->GetModuleRequests();
  int length = v8_module_requests->Length();
  Vector<ModuleRequest> requests;
  requests.ReserveInitialCapacity(length);
  bool needs_text_position =
      !WTF::IsMainThread() ||
      probe::ToCoreProbeSink(ExecutionContext::From(script_state))
          ->HasDevToolsSessions();

  for (int i = 0; i < length; ++i) {
    v8::Local<v8::ModuleRequest> v8_module_request =
        v8_module_requests->Get(script_state->GetContext(), i)
            .As<v8::ModuleRequest>();
    v8::Local<v8::String> v8_specifier = v8_module_request->GetSpecifier();
    TextPosition position = TextPosition::MinimumPosition();
    if (needs_text_position) {
      // The source position is only used by DevTools for module requests and
      // only visible if devtools is open when the request is initiated.
      // Calculating the source position is not free and V8 has to initialize
      // the line end information for the complete module, thus we try to
      // avoid this additional work here if DevTools is closed.
      int source_offset = v8_module_request->GetSourceOffset();
      v8::Location v8_loc = record->SourceOffsetToLocation(source_offset);
      position = TextPosition(
          OrdinalNumber::FromZeroBasedInt(v8_loc.GetLineNumber()),
          OrdinalNumber::FromZeroBasedInt(v8_loc.GetColumnNumber()));
    }
    Vector<ImportAssertion> import_assertions =
        ModuleRecord::ToBlinkImportAssertions(
            script_state->GetContext(), record,
            v8_module_request->GetImportAssertions(),
            /*v8_import_assertions_has_positions=*/true);

    requests.emplace_back(ToCoreString(v8_specifier), position,
                          import_assertions);
  }

  return requests;
}

v8::Local<v8::Value> ModuleRecord::V8Namespace(v8::Local<v8::Module> record) {
  DCHECK(!record.IsEmpty());
  return record->GetModuleNamespace();
}

v8::MaybeLocal<v8::Module> ModuleRecord::ResolveModuleCallback(
    v8::Local<v8::Context> context,
    v8::Local<v8::String> specifier,
    v8::Local<v8::FixedArray> import_assertions,
    v8::Local<v8::Module> referrer) {
  v8::Isolate* isolate = context->GetIsolate();
  Modulator* modulator = Modulator::From(ScriptState::From(context));
  DCHECK(modulator);

  ModuleRequest module_request(
      ToCoreStringWithNullCheck(specifier), TextPosition(),
      ModuleRecord::ToBlinkImportAssertions(
          context, referrer, import_assertions,
          /*v8_import_assertions_has_positions=*/true));

  ExceptionState exception_state(isolate, ExceptionState::kExecutionContext,
                                 "ModuleRecord", "resolveModuleCallback");
  v8::Local<v8::Module> resolved =
      modulator->GetModuleRecordResolver()->Resolve(module_request, referrer,
                                                    exception_state);
  DCHECK(!resolved.IsEmpty());
  DCHECK(!exception_state.HadException());

  return resolved;
}

Vector<ImportAssertion> ModuleRecord::ToBlinkImportAssertions(
    v8::Local<v8::Context> context,
    v8::Local<v8::Module> record,
    v8::Local<v8::FixedArray> v8_import_assertions,
    bool v8_import_assertions_has_positions) {
  // If v8_import_assertions_has_positions == true then v8_import_assertions has
  // source position information and is given in the form [key1, value1,
  // source_offset1, key2, value2, source_offset2, ...]. Otherwise if
  // v8_import_assertions_has_positions == false, then v8_import_assertions is
  // in the form [key1, value1, key2, value2, ...].
  const int kV8AssertionEntrySize = v8_import_assertions_has_positions ? 3 : 2;

  Vector<ImportAssertion> import_assertions;
  int number_of_import_assertions =
      v8_import_assertions->Length() / kV8AssertionEntrySize;
  import_assertions.ReserveInitialCapacity(number_of_import_assertions);
  for (int i = 0; i < number_of_import_assertions; ++i) {
    v8::Local<v8::String> v8_assertion_key =
        v8_import_assertions->Get(context, i * kV8AssertionEntrySize)
            .As<v8::String>();
    v8::Local<v8::String> v8_assertion_value =
        v8_import_assertions->Get(context, (i * kV8AssertionEntrySize) + 1)
            .As<v8::String>();
    TextPosition assertion_position;
    if (v8_import_assertions_has_positions) {
      int32_t v8_assertion_source_offset =
          v8_import_assertions->Get(context, (i * kV8AssertionEntrySize) + 2)
              .As<v8::Int32>()
              ->Value();
      v8::Location v8_assertion_loc =
          record->SourceOffsetToLocation(v8_assertion_source_offset);
      assertion_position = TextPosition(
          OrdinalNumber::FromZeroBasedInt(v8_assertion_loc.GetLineNumber()),
          OrdinalNumber::FromZeroBasedInt(v8_assertion_loc.GetColumnNumber()));
    }

    import_assertions.emplace_back(ToCoreString(v8_assertion_key),
                                   ToCoreString(v8_assertion_value),
                                   assertion_position);
  }

  return import_assertions;
}

}  // namespace blink
