/*
 * 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/bindings/core/v8/v8_script_runner.h"

#include "base/feature_list.h"
#include "build/build_config.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/binding_security.h"
#include "third_party/blink/renderer/bindings/core/v8/referrer_script_info.h"
#include "third_party/blink/renderer/bindings/core/v8/script_evaluation_result.h"
#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
#include "third_party/blink/renderer/bindings/core/v8/script_source_code.h"
#include "third_party/blink/renderer/bindings/core/v8/script_streamer.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_code_cache.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_initializer.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h"
#include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h"
#include "third_party/blink/renderer/core/execution_context/agent.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/inspector/inspector_trace_events.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/classic_script.h"
#include "third_party/blink/renderer/core/script/modulator.h"
#include "third_party/blink/renderer/core/script/module_script.h"
#include "third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h"
#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
#include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h"
#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata.h"
#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h"
#include "third_party/blink/renderer/platform/scheduler/public/event_loop.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/text/text_encoding.h"

namespace blink {

namespace {

// Used to throw an exception before we exceed the C++ stack and crash.
// This limit was arrived at arbitrarily. crbug.com/449744
const int kMaxRecursionDepth = 44;

bool InDiscardExperiment() {
  return base::FeatureList::IsEnabled(
      blink::features::kDiscardCodeCacheAfterFirstUse);
}

// In order to make sure all pending messages to be processed in
// v8::Function::Call, we don't call throwStackOverflowException
// directly. Instead, we create a v8::Function of
// throwStackOverflowException and call it.
void ThrowStackOverflowException(
    const v8::FunctionCallbackInfo<v8::Value>& info) {
  V8ThrowException::ThrowRangeError(info.GetIsolate(),
                                    "Maximum call stack size exceeded.");
}

void ThrowScriptForbiddenException(v8::Isolate* isolate) {
  V8ThrowException::ThrowError(isolate, "Script execution is forbidden.");
}

v8::MaybeLocal<v8::Value> ThrowStackOverflowExceptionIfNeeded(
    v8::Isolate* isolate,
    v8::MicrotaskQueue* microtask_queue) {
  if (V8PerIsolateData::From(isolate)->IsHandlingRecursionLevelError()) {
    // If we are already handling a recursion level error, we should
    // not invoke v8::Function::Call.
    return v8::Undefined(isolate);
  }
  v8::MicrotasksScope microtasks_scope(
      isolate, microtask_queue, v8::MicrotasksScope::kDoNotRunMicrotasks);
  V8PerIsolateData::From(isolate)->SetIsHandlingRecursionLevelError(true);

  ScriptForbiddenScope::AllowUserAgentScript allow_script;
  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  v8::MaybeLocal<v8::Value> result =
      v8::Function::New(context, ThrowStackOverflowException,
                        v8::Local<v8::Value>(), 0,
                        v8::ConstructorBehavior::kThrow)
          .ToLocalChecked()
          ->Call(context, v8::Undefined(isolate), 0, nullptr);

  V8PerIsolateData::From(isolate)->SetIsHandlingRecursionLevelError(false);
  return result;
}

v8::MaybeLocal<v8::Script> CompileScriptInternal(
    v8::Isolate* isolate,
    ExecutionContext* execution_context,
    const ScriptSourceCode& source_code,
    v8::ScriptOrigin origin,
    v8::ScriptCompiler::CompileOptions compile_options,
    v8::ScriptCompiler::NoCacheReason no_cache_reason,
    inspector_compile_script_event::V8CacheResult* cache_result) {
  v8::Local<v8::String> code = V8String(isolate, source_code.Source());

  if (ScriptStreamer* streamer = source_code.Streamer()) {
    // Final compile call for a streamed compilation.
    // Streaming compilation may involve use of code cache.
    // TODO(leszeks): Add compile timer to streaming compilation.
    DCHECK(streamer->IsFinished());
    DCHECK(!streamer->IsStreamingSuppressed());
    return v8::ScriptCompiler::Compile(isolate->GetCurrentContext(),
                                       streamer->Source(), code, origin);
  }

  // Allow inspector to use its own compilation cache store.
  v8::ScriptCompiler::CachedData* inspector_data = nullptr;
  probe::ConsumeCompilationCache(execution_context, source_code,
                                 &inspector_data);
  if (inspector_data) {
    v8::ScriptCompiler::Source source(code, origin, inspector_data);
    v8::MaybeLocal<v8::Script> script =
        v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &source,
                                    v8::ScriptCompiler::kConsumeCodeCache);
    return script;
  }

  switch (compile_options) {
    case v8::ScriptCompiler::kNoCompileOptions:
    case v8::ScriptCompiler::kEagerCompile: {
      v8::ScriptCompiler::Source source(code, origin);
      return v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &source,
                                         compile_options, no_cache_reason);
    }

    case v8::ScriptCompiler::kConsumeCodeCache: {
      // Compile a script, and consume a V8 cache that was generated previously.
      SingleCachedMetadataHandler* cache_handler = source_code.CacheHandler();
      v8::ScriptCompiler::CachedData* cached_data =
          V8CodeCache::CreateCachedData(cache_handler);
      v8::ScriptCompiler::Source source(code, origin, cached_data);
      v8::MaybeLocal<v8::Script> script =
          v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &source,
                                      v8::ScriptCompiler::kConsumeCodeCache);

      if (cached_data->rejected) {
        cache_handler->ClearCachedMetadata(
            CachedMetadataHandler::kClearPersistentStorage);
      } else if (InDiscardExperiment()) {
        // Experimentally free code cache from memory after first use. See
        // http://crbug.com/1045052.
        cache_handler->ClearCachedMetadata(
            CachedMetadataHandler::kDiscardLocally);
      }
      if (cache_result) {
        cache_result->consume_result = base::make_optional(
            inspector_compile_script_event::V8CacheResult::ConsumeResult(
                v8::ScriptCompiler::kConsumeCodeCache, cached_data->length,
                cached_data->rejected));
      }
      return script;
    }
  }

  // All switch branches should return and we should never get here.
  // But some compilers aren't sure, hence this default.
  NOTREACHED();
  return v8::MaybeLocal<v8::Script>();
}

int GetMicrotasksScopeDepth(v8::Isolate* isolate,
                            v8::MicrotaskQueue* microtask_queue) {
  if (microtask_queue)
    return microtask_queue->GetMicrotasksScopeDepth();
  return v8::MicrotasksScope::GetCurrentDepth(isolate);
}

}  // namespace

v8::MaybeLocal<v8::Script> V8ScriptRunner::CompileScript(
    ScriptState* script_state,
    const ScriptSourceCode& source,
    SanitizeScriptErrors sanitize_script_errors,
    v8::ScriptCompiler::CompileOptions compile_options,
    v8::ScriptCompiler::NoCacheReason no_cache_reason,
    const ReferrerScriptInfo& referrer_info) {
  v8::Isolate* isolate = script_state->GetIsolate();
  if (source.Source().length() >= v8::String::kMaxLength) {
    V8ThrowException::ThrowError(isolate, "Source file too large.");
    return v8::Local<v8::Script>();
  }

  const String& file_name = source.Url();
  const TextPosition& script_start_position = source.StartPosition();

  constexpr const char* kTraceEventCategoryGroup = "v8,devtools.timeline";
  TRACE_EVENT_BEGIN1(kTraceEventCategoryGroup, "v8.compile", "fileName",
                     file_name.Utf8());
  ExecutionContext* execution_context = ExecutionContext::From(script_state);
  probe::V8Compile probe(execution_context, file_name,
                         script_start_position.line_.ZeroBasedInt(),
                         script_start_position.column_.ZeroBasedInt());

  // NOTE: For compatibility with WebCore, ScriptSourceCode's line starts at
  // 1, whereas v8 starts at 0.
  v8::ScriptOrigin origin(
      V8String(isolate, file_name), script_start_position.line_.ZeroBasedInt(),
      script_start_position.column_.ZeroBasedInt(),
      sanitize_script_errors == SanitizeScriptErrors::kDoNotSanitize, -1,
      V8String(isolate, source.SourceMapUrl()),
      sanitize_script_errors == SanitizeScriptErrors::kSanitize,
      false,  // is_wasm
      false,  // is_module
      referrer_info.ToV8HostDefinedOptions(isolate));

  if (!*TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(kTraceEventCategoryGroup)) {
    return CompileScriptInternal(isolate, execution_context, source, origin,
                                 compile_options, no_cache_reason, nullptr);
  }

  inspector_compile_script_event::V8CacheResult cache_result;
  v8::MaybeLocal<v8::Script> script =
      CompileScriptInternal(isolate, execution_context, source, origin,
                            compile_options, no_cache_reason, &cache_result);
  TRACE_EVENT_END1(kTraceEventCategoryGroup, "v8.compile", "data",
                   inspector_compile_script_event::Data(
                       file_name, script_start_position, cache_result,
                       source.Streamer(), source.NotStreamingReason()));
  return script;
}

v8::MaybeLocal<v8::Module> V8ScriptRunner::CompileModule(
    v8::Isolate* isolate,
    const ModuleScriptCreationParams& params,
    const TextPosition& start_position,
    v8::ScriptCompiler::CompileOptions compile_options,
    v8::ScriptCompiler::NoCacheReason no_cache_reason,
    const ReferrerScriptInfo& referrer_info) {
  const String file_name = params.SourceURL();
  constexpr const char* kTraceEventCategoryGroup = "v8,devtools.timeline";
  TRACE_EVENT_BEGIN1(kTraceEventCategoryGroup, "v8.compileModule", "fileName",
                     file_name.Utf8());

  // |resource_is_shared_cross_origin| is always true and |resource_is_opaque|
  // is always false because CORS is enforced to module scripts.
  v8::ScriptOrigin origin(V8String(isolate, file_name),
                          start_position.line_.ZeroBasedInt(),
                          start_position.column_.ZeroBasedInt(),
                          true,  // resource_is_shared_cross_origin
                          -1,    // script id
                          v8::String::Empty(isolate),  // source_map_url
                          false,                   // resource_is_opaque
                          false,                   // is_wasm
                          true,                    // is_module
                          referrer_info.ToV8HostDefinedOptions(isolate));

  v8::Local<v8::String> code = V8String(isolate, params.GetSourceText());
  inspector_compile_script_event::V8CacheResult cache_result;
  v8::MaybeLocal<v8::Module> script;
  ScriptStreamer* streamer = params.GetScriptStreamer();
  if (streamer) {
    // Final compile call for a streamed compilation.
    // Streaming compilation may involve use of code cache.
    // TODO(leszeks): Add compile timer to streaming compilation.
    DCHECK(streamer->IsFinished());
    DCHECK(!streamer->IsStreamingSuppressed());
    script = v8::ScriptCompiler::CompileModule(
        isolate->GetCurrentContext(), streamer->Source(), code, origin);
  } else {
    switch (compile_options) {
      case v8::ScriptCompiler::kNoCompileOptions:
      case v8::ScriptCompiler::kEagerCompile: {
        v8::ScriptCompiler::Source source(code, origin);
        script = v8::ScriptCompiler::CompileModule(
            isolate, &source, compile_options, no_cache_reason);
        break;
      }

      case v8::ScriptCompiler::kConsumeCodeCache: {
        // Compile a script, and consume a V8 cache that was generated
        // previously.
        SingleCachedMetadataHandler* cache_handler = params.CacheHandler();
        DCHECK(cache_handler);
        v8::ScriptCompiler::CachedData* cached_data =
            V8CodeCache::CreateCachedData(cache_handler);
        v8::ScriptCompiler::Source source(code, origin, cached_data);
        script = v8::ScriptCompiler::CompileModule(
            isolate, &source, compile_options, no_cache_reason);
        if (cached_data->rejected) {
          cache_handler->ClearCachedMetadata(
              CachedMetadataHandler::kClearPersistentStorage);
        } else if (InDiscardExperiment()) {
          // Experimentally free code cache from memory after first use. See
          // http://crbug.com/1045052.
          cache_handler->ClearCachedMetadata(
              CachedMetadataHandler::kDiscardLocally);
        }
        cache_result.consume_result = base::make_optional(
            inspector_compile_script_event::V8CacheResult::ConsumeResult(
                compile_options, cached_data->length, cached_data->rejected));
        break;
      }
    }
  }

  TRACE_EVENT_END1(kTraceEventCategoryGroup, "v8.compileModule", "data",
                   inspector_compile_script_event::Data(
                       file_name, start_position, cache_result, streamer,
                       params.NotStreamingReason()));
  return script;
}

v8::MaybeLocal<v8::Value> V8ScriptRunner::RunCompiledScript(
    v8::Isolate* isolate,
    v8::Local<v8::Script> script,
    ExecutionContext* context) {
  DCHECK(!script.IsEmpty());
  LocalDOMWindow* window = DynamicTo<LocalDOMWindow>(context);
  ScopedFrameBlamer frame_blamer(window ? window->GetFrame() : nullptr);

  v8::Local<v8::Value> script_name =
      script->GetUnboundScript()->GetScriptName();
  TRACE_EVENT1("v8", "v8.run", "fileName",
               TRACE_STR_COPY(*v8::String::Utf8Value(isolate, script_name)));
  RuntimeCallStatsScopedTracer rcs_scoped_tracer(isolate);
  RUNTIME_CALL_TIMER_SCOPE(isolate, RuntimeCallStats::CounterId::kV8);

  v8::MicrotaskQueue* microtask_queue = ToMicrotaskQueue(context);
  if (GetMicrotasksScopeDepth(isolate, microtask_queue) > kMaxRecursionDepth)
    return ThrowStackOverflowExceptionIfNeeded(isolate, microtask_queue);

  CHECK(!context->ContextLifecycleObserverSet().IsIteratingOverObservers());

  // Run the script and keep track of the current recursion depth.
  v8::MaybeLocal<v8::Value> result;
  {
    if (ScriptForbiddenScope::IsScriptForbidden()) {
      ThrowScriptForbiddenException(isolate);
      return v8::MaybeLocal<v8::Value>();
    }

    v8::Isolate::SafeForTerminationScope safe_for_termination(isolate);
    v8::MicrotasksScope microtasks_scope(isolate, microtask_queue,
                                         v8::MicrotasksScope::kRunMicrotasks);
    v8::Local<v8::String> script_url;
    if (!script_name->ToString(isolate->GetCurrentContext())
             .ToLocal(&script_url))
      return result;

    // ToCoreString here should be zero copy due to externalized string
    // unpacked.
    probe::ExecuteScript probe(context, ToCoreString(script_url),
                               script->GetUnboundScript()->GetId());
    result = script->Run(isolate->GetCurrentContext());
  }

  CHECK(!isolate->IsDead());
  return result;
}

ScriptEvaluationResult V8ScriptRunner::CompileAndRunScript(
    ScriptState* script_state,
    ClassicScript* classic_script,
    ExecuteScriptPolicy policy,
    RethrowErrorsOption rethrow_errors) {
  if (!script_state)
    return ScriptEvaluationResult::FromClassicNotRun();

  // |script_state->GetContext()| must be initialized here already, typically
  // due to a WindowProxy() call inside ToScriptState*() that is used to get the
  // ScriptState.

  ExecutionContext* execution_context = ExecutionContext::From(script_state);
  DCHECK(execution_context->IsContextThread());

  if (policy == ExecuteScriptPolicy::kDoNotExecuteScriptWhenScriptsDisabled &&
      !execution_context->CanExecuteScripts(kAboutToExecuteScript)) {
    return ScriptEvaluationResult::FromClassicNotRun();
  }

  v8::Isolate* isolate = script_state->GetIsolate();
  const ScriptSourceCode& source = classic_script->GetScriptSourceCode();
  const SanitizeScriptErrors sanitize_script_errors =
      classic_script->GetSanitizeScriptErrors();

  LocalDOMWindow* window = DynamicTo<LocalDOMWindow>(execution_context);
  WorkerOrWorkletGlobalScope* worker_or_worklet_global_scope =
      DynamicTo<WorkerOrWorkletGlobalScope>(execution_context);
  LocalFrame* frame = window ? window->GetFrame() : nullptr;

  if (window && window->document()->IsInitialEmptyDocument()) {
    window->GetFrame()->Loader().DidAccessInitialDocument();
  } else if (worker_or_worklet_global_scope) {
    DCHECK_EQ(
        script_state,
        worker_or_worklet_global_scope->ScriptController()->GetScriptState());
    DCHECK(worker_or_worklet_global_scope->ScriptController()
               ->IsContextInitialized());
    DCHECK(worker_or_worklet_global_scope->ScriptController()
               ->IsReadyToEvaluate());
  }

  v8::Context::Scope scope(script_state->GetContext());

  TRACE_EVENT1("devtools.timeline", "EvaluateScript", "data",
               inspector_evaluate_script_event::Data(
                   frame, source.Url().GetString(), source.StartPosition()));

  // Scope for |v8::TryCatch|.
  {
    v8::TryCatch try_catch(isolate);
    // Step 8.3. Otherwise, rethrow errors is false. Perform the following
    // steps: [spec text]
    // Step 8.3.1. Report the exception given by evaluationStatus.[[Value]]
    // for script. [spec text]
    //
    // This will be done inside V8 by setting TryCatch::SetVerbose(true) here.
    if (!rethrow_errors.ShouldRethrow()) {
      try_catch.SetVerbose(true);
    }

    // Omit storing base URL if it is same as source URL.
    // Note: This improves chance of getting into a fast path in
    //       ReferrerScriptInfo::ToV8HostDefinedOptions.
    const KURL base_url = classic_script->BaseURL();
    KURL stored_base_url = (base_url == source.Url()) ? KURL() : base_url;

    // TODO(hiroshige): Remove this code and related use counters once the
    // measurement is done.
    ReferrerScriptInfo::BaseUrlSource base_url_source =
        ReferrerScriptInfo::BaseUrlSource::kOther;
    if (source.SourceLocationType() ==
            ScriptSourceLocationType::kExternalFile &&
        !base_url.IsNull()) {
      switch (sanitize_script_errors) {
        case SanitizeScriptErrors::kDoNotSanitize:
          base_url_source =
              ReferrerScriptInfo::BaseUrlSource::kClassicScriptCORSSameOrigin;
          break;
        case SanitizeScriptErrors::kSanitize:
          base_url_source =
              ReferrerScriptInfo::BaseUrlSource::kClassicScriptCORSCrossOrigin;
          break;
      }
    }
    const ReferrerScriptInfo referrer_info(
        stored_base_url, classic_script->FetchOptions(), base_url_source);

    v8::Local<v8::Script> script;

    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(execution_context->GetV8CacheOptions(),
                                       source);

    v8::MaybeLocal<v8::Value> maybe_result;
    if (V8ScriptRunner::CompileScript(script_state, source,
                                      sanitize_script_errors, compile_options,
                                      no_cache_reason, referrer_info)
            .ToLocal(&script)) {
      maybe_result =
          V8ScriptRunner::RunCompiledScript(isolate, script, execution_context);
      probe::ProduceCompilationCache(probe::ToCoreProbeSink(execution_context),
                                     source, script);
      V8CodeCache::ProduceCache(isolate, script, source, produce_cache_options);
    }

    // TODO(crbug/1114601): Investigate whether to check CanContinue() in other
    // script evaluation code paths.
    if (!try_catch.CanContinue()) {
      if (worker_or_worklet_global_scope)
        worker_or_worklet_global_scope->ScriptController()->ForbidExecution();
      return ScriptEvaluationResult::FromClassicAborted();
    }

    if (!try_catch.HasCaught()) {
      // Step 10. If evaluationStatus is a normal completion, then return
      // evaluationStatus. [spec text]
      v8::Local<v8::Value> result;
      bool success = maybe_result.ToLocal(&result);
      DCHECK(success);
      return ScriptEvaluationResult::FromClassicSuccess(result);
    }

    DCHECK(maybe_result.IsEmpty());

    if (rethrow_errors.ShouldRethrow() &&
        sanitize_script_errors == SanitizeScriptErrors::kDoNotSanitize) {
      // Step 8.1. If rethrow errors is true and script's muted errors is
      // false, then: [spec text]
      //
      // Step 8.1.2. Rethrow evaluationStatus.[[Value]]. [spec text]
      //
      // We rethrow exceptions reported from importScripts() here. The
      // original filename/lineno/colno information (which points inside of
      // imported scripts) is kept through ReThrow(), and will be eventually
      // reported to WorkerGlobalScope.onerror via `TryCatch::SetVerbose(true)`
      // called at top-level worker script evaluation.
      try_catch.ReThrow();
      return ScriptEvaluationResult::FromClassicException();
    }
  }
  // |v8::TryCatch| is (and should be) exited, before ThrowException() below.

  if (rethrow_errors.ShouldRethrow()) {
    // kDoNotSanitize case is processed and early-exited above.
    DCHECK_EQ(sanitize_script_errors, SanitizeScriptErrors::kSanitize);

    // Step 8.2. If rethrow errors is true and script's muted errors is
    // true, then: [spec text]
    //
    // Step 8.2.2. Throw a "NetworkError" DOMException. [spec text]
    //
    // We don't supply any message here to avoid leaking details of muted
    // errors.
    V8ThrowException::ThrowException(
        isolate, V8ThrowDOMException::CreateOrEmpty(
                     isolate, DOMExceptionCode::kNetworkError,
                     rethrow_errors.Message()));
    return ScriptEvaluationResult::FromClassicException();
  }

  // #report-the-error for rethrow errors == true is already handled via
  // |TryCatch::SetVerbose(true)| above.
  return ScriptEvaluationResult::FromClassicException();
}

v8::MaybeLocal<v8::Value> V8ScriptRunner::CompileAndRunInternalScript(
    v8::Isolate* isolate,
    ScriptState* script_state,
    const ScriptSourceCode& source_code) {
  DCHECK_EQ(isolate, script_state->GetIsolate());

  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(mojom::blink::V8CacheOptions::kDefault,
                                     source_code);
  // Currently internal scripts don't have cache handlers. So we should not
  // produce cache for them.
  DCHECK_EQ(produce_cache_options,
            V8CodeCache::ProduceCacheOptions::kNoProduceCache);
  v8::Local<v8::Script> script;
  // Use default ScriptReferrerInfo here:
  // - nonce: empty for internal script, and
  // - parser_state: always "not parser inserted" for internal scripts.
  if (!V8ScriptRunner::CompileScript(
           script_state, source_code, SanitizeScriptErrors::kDoNotSanitize,
           compile_options, no_cache_reason, ReferrerScriptInfo())
           .ToLocal(&script))
    return v8::MaybeLocal<v8::Value>();

  TRACE_EVENT0("v8", "v8.run");
  RuntimeCallStatsScopedTracer rcs_scoped_tracer(isolate);
  RUNTIME_CALL_TIMER_SCOPE(isolate, RuntimeCallStats::CounterId::kV8);
  v8::Isolate::SafeForTerminationScope safe_for_termination(isolate);
  v8::MicrotasksScope microtasks_scope(
      isolate, ToMicrotaskQueue(script_state),
      v8::MicrotasksScope::kDoNotRunMicrotasks);
  v8::MaybeLocal<v8::Value> result = script->Run(isolate->GetCurrentContext());
  CHECK(!isolate->IsDead());
  return result;
}

v8::MaybeLocal<v8::Value> V8ScriptRunner::CallAsConstructor(
    v8::Isolate* isolate,
    v8::Local<v8::Object> constructor,
    ExecutionContext* context,
    int argc,
    v8::Local<v8::Value> argv[]) {
  TRACE_EVENT0("v8", "v8.callAsConstructor");
  RUNTIME_CALL_TIMER_SCOPE(isolate, RuntimeCallStats::CounterId::kV8);

  v8::MicrotaskQueue* microtask_queue = ToMicrotaskQueue(context);
  int depth = GetMicrotasksScopeDepth(isolate, microtask_queue);
  if (depth >= kMaxRecursionDepth)
    return ThrowStackOverflowExceptionIfNeeded(isolate, microtask_queue);

  CHECK(!context->ContextLifecycleObserverSet().IsIteratingOverObservers());

  if (ScriptForbiddenScope::IsScriptForbidden()) {
    ThrowScriptForbiddenException(isolate);
    return v8::MaybeLocal<v8::Value>();
  }

  // TODO(dominicc): When inspector supports tracing object
  // invocation, change this to use v8::Object instead of
  // v8::Function. All callers use functions because
  // CustomElementRegistry#define's IDL signature is Function.
  CHECK(constructor->IsFunction());
  v8::Local<v8::Function> function = constructor.As<v8::Function>();

  v8::Isolate::SafeForTerminationScope safe_for_termination(isolate);
  v8::MicrotasksScope microtasks_scope(isolate, ToMicrotaskQueue(context),
                                       v8::MicrotasksScope::kRunMicrotasks);
  probe::CallFunction probe(context, function, depth);

  if (!depth) {
    TRACE_EVENT_BEGIN1("devtools.timeline", "FunctionCall", "data",
                       inspector_function_call_event::Data(context, function));
  }

  v8::MaybeLocal<v8::Value> result =
      constructor->CallAsConstructor(isolate->GetCurrentContext(), argc, argv);
  CHECK(!isolate->IsDead());

  if (!depth)
    TRACE_EVENT_END0("devtools.timeline", "FunctionCall");

  return result;
}

v8::MaybeLocal<v8::Value> V8ScriptRunner::CallFunction(
    v8::Local<v8::Function> function,
    ExecutionContext* context,
    v8::Local<v8::Value> receiver,
    int argc,
    v8::Local<v8::Value> args[],
    v8::Isolate* isolate) {
  LocalDOMWindow* window = DynamicTo<LocalDOMWindow>(context);
  LocalFrame* frame = window ? window->GetFrame() : nullptr;
  ScopedFrameBlamer frame_blamer(frame);
  TRACE_EVENT0("v8", "v8.callFunction");
  RuntimeCallStatsScopedTracer rcs_scoped_tracer(isolate);
  RUNTIME_CALL_TIMER_SCOPE(isolate, RuntimeCallStats::CounterId::kV8);

  v8::MicrotaskQueue* microtask_queue = ToMicrotaskQueue(context);
  int depth = GetMicrotasksScopeDepth(isolate, microtask_queue);
  if (depth >= kMaxRecursionDepth)
    return ThrowStackOverflowExceptionIfNeeded(isolate, microtask_queue);

  CHECK(!context->ContextLifecycleObserverSet().IsIteratingOverObservers());

  if (ScriptForbiddenScope::IsScriptForbidden()) {
    ThrowScriptForbiddenException(isolate);
    return v8::MaybeLocal<v8::Value>();
  }

  DCHECK(!frame || BindingSecurity::ShouldAllowAccessToFrame(
                       ToLocalDOMWindow(function->CreationContext()), frame,
                       BindingSecurity::ErrorReportOption::kDoNotReport));
  v8::Isolate::SafeForTerminationScope safe_for_termination(isolate);
  v8::MicrotasksScope microtasks_scope(isolate, microtask_queue,
                                       v8::MicrotasksScope::kRunMicrotasks);
  if (!depth) {
    TRACE_EVENT_BEGIN1("devtools.timeline", "FunctionCall", "data",
                       inspector_function_call_event::Data(context, function));
  }

  probe::CallFunction probe(context, function, depth);
  v8::MaybeLocal<v8::Value> result =
      function->Call(isolate->GetCurrentContext(), receiver, argc, args);
  CHECK(!isolate->IsDead());

  if (!depth)
    TRACE_EVENT_END0("devtools.timeline", "FunctionCall");

  return result;
}

class ModuleEvaluationRejectionCallback final : public ScriptFunction {
 public:
  explicit ModuleEvaluationRejectionCallback(ScriptState* script_state)
      : ScriptFunction(script_state) {}

  static v8::Local<v8::Function> CreateFunction(ScriptState* script_state) {
    ModuleEvaluationRejectionCallback* self =
        MakeGarbageCollected<ModuleEvaluationRejectionCallback>(script_state);
    return self->BindToV8Function();
  }

 private:
  ScriptValue Call(ScriptValue value) override {
    ModuleRecord::ReportException(GetScriptState(), value.V8Value());
    return ScriptValue();
  }
};

// <specdef href="https://html.spec.whatwg.org/C/#run-a-module-script">
// Spec with TLA: https://github.com/whatwg/html/pull/4352
ScriptEvaluationResult V8ScriptRunner::EvaluateModule(
    ModuleScript* module_script,
    RethrowErrorsOption rethrow_errors) {
  // <spec step="1">If rethrow errors is not given, let it be false.</spec>

  // <spec step="2">Let settings be the settings object of script.</spec>
  //
  // The settings object is |module_script->SettingsObject()|.
  ScriptState* script_state = module_script->SettingsObject()->GetScriptState();
  DCHECK_EQ(Modulator::From(script_state), module_script->SettingsObject());
  ExecutionContext* execution_context = ExecutionContext::From(script_state);
  v8::Isolate* isolate = script_state->GetIsolate();

  // TODO(crbug.com/1151165): Ideally v8::Context should be entered before
  // CanExecuteScripts().
  v8::Context::Scope scope(script_state->GetContext());

  // <spec step="3">Check if we can run script with settings. If this returns
  // "do not run" then return NormalCompletion(empty).</spec>
  if (!execution_context->CanExecuteScripts(kAboutToExecuteScript)) {
    return ScriptEvaluationResult::FromModuleNotRun();
  }

  // <spec step="4">Prepare to run script given settings.</spec>
  //
  // These are placed here to also cover ModuleRecord::ReportException().
  v8::MicrotasksScope microtasks_scope(isolate,
                                       ToMicrotaskQueue(execution_context),
                                       v8::MicrotasksScope::kRunMicrotasks);

  // Without TLA: <spec step="5">Let evaluationStatus be null.</spec>
  ScriptEvaluationResult result = ScriptEvaluationResult::FromModuleNotRun();

  // <spec step="6">If script's error to rethrow is not null, ...</spec>
  if (module_script->HasErrorToRethrow()) {
    // Without TLA: <spec step="6">... then set evaluationStatus to Completion
    //     { [[Type]]: throw, [[Value]]: script's error to rethrow,
    //       [[Target]]: empty }.</spec>
    // With TLA:    <spec step="5">If script's error to rethrow is not null,
    //     then let valuationPromise be a promise rejected with script's error
    //     to rethrow.</spec>
    result = ScriptEvaluationResult::FromModuleException(
        module_script->CreateErrorToRethrow().V8Value());
  } else {
    // <spec step="7">Otherwise:</spec>

    // <spec step="7.1">Let record be script's record.</spec>
    v8::Local<v8::Module> record = module_script->V8Module();
    CHECK(!record.IsEmpty());

    // <spec step="7.2">Set evaluationStatus to record.Evaluate(). ...</spec>

    // Isolate exceptions that occur when executing the code. These exceptions
    // should not interfere with javascript code we might evaluate from C++
    // when returning from here.
    v8::TryCatch try_catch(isolate);

    // Script IDs are not available on errored modules or on non-source text
    // modules, so we give them a default value.
    probe::ExecuteScript probe(execution_context, module_script->SourceURL(),
                               record->GetStatus() != v8::Module::kErrored &&
                                       record->IsSourceTextModule()
                                   ? record->ScriptId()
                                   : v8::UnboundScript::kNoScriptId);

    TRACE_EVENT0("v8,devtools.timeline", "v8.evaluateModule");
    RUNTIME_CALL_TIMER_SCOPE(isolate, RuntimeCallStats::CounterId::kV8);
    v8::Isolate::SafeForTerminationScope safe_for_termination(isolate);

    // Do not perform a microtask checkpoint here. A checkpoint is performed
    // only after module error handling to ensure proper timing with and
    // without top-level await.

    v8::MaybeLocal<v8::Value> maybe_result =
        record->Evaluate(script_state->GetContext());

    if (!try_catch.CanContinue())
      return ScriptEvaluationResult::FromModuleAborted();

    v8::Local<v8::Value> v8_result;
    if (!maybe_result.ToLocal(&v8_result)) {
      DCHECK(try_catch.HasCaught());
      result =
          ScriptEvaluationResult::FromModuleException(try_catch.Exception());
    } else {
      DCHECK(!try_catch.HasCaught());
      result = ScriptEvaluationResult::FromModuleSuccess(v8_result);
    }

    // <spec step="7.2">... If Evaluate fails to complete as a result of the
    // user agent aborting the running script, then set evaluationStatus to
    // Completion { [[Type]]: throw, [[Value]]: a new "QuotaExceededError"
    // DOMException, [[Target]]: empty }.</spec>
  }

  // [not specced] Store V8 code cache on successful evaluation.
  if (result.GetResultType() == ScriptEvaluationResult::ResultType::kSuccess) {
    execution_context->GetTaskRunner(TaskType::kNetworking)
        ->PostTask(FROM_HERE,
                   WTF::Bind(&Modulator::ProduceCacheModuleTreeTopLevel,
                             WrapWeakPersistent(Modulator::From(script_state)),
                             WrapWeakPersistent(module_script)));
  }

  if (!rethrow_errors.ShouldRethrow()) {
    if (base::FeatureList::IsEnabled(features::kTopLevelAwait)) {
      // <spec step="7"> If report errors is true, then upon rejection of
      // evaluationPromise with reason, report the exception given by reason
      // for script.</spec>
      v8::Local<v8::Function> callback_failure =
          ModuleEvaluationRejectionCallback::CreateFunction(script_state);
      // Add a rejection handler to report back errors once the result
      // promise is rejected.
      result.GetPromise(script_state)
          .Then(v8::Local<v8::Function>(), callback_failure);
    } else {
      // <spec step="8">If evaluationStatus is an abrupt completion,
      // then:</spec>
      if (result.GetResultType() ==
          ScriptEvaluationResult::ResultType::kException) {
        // <spec step="8.2">Otherwise, report the exception given by
        // evaluationStatus.[[Value]] for script.</spec>
        ModuleRecord::ReportException(script_state,
                                      result.GetExceptionForModule());
      }
    }
  }

  // <spec step="8">Clean up after running script with settings.</spec>
  // Partially implemented in MicrotaskScope destructor and the
  // v8::Context::Scope destructor.
  return result;
}

void V8ScriptRunner::ReportException(v8::Isolate* isolate,
                                     v8::Local<v8::Value> exception) {
  DCHECK(!exception.IsEmpty());

  // https://html.spec.whatwg.org/C/#report-the-error
  v8::Local<v8::Message> message =
      v8::Exception::CreateMessage(isolate, exception);
  if (IsMainThread())
    V8Initializer::MessageHandlerInMainThread(message, exception);
  else
    V8Initializer::MessageHandlerInWorker(message, exception);
}

}  // namespace blink
