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

#include "bindings/core/v8/BindingSecurity.h"
#include "bindings/core/v8/ScriptSourceCode.h"
#include "bindings/core/v8/ScriptStreamer.h"
#include "bindings/core/v8/V8BindingForCore.h"
#include "bindings/core/v8/V8GCController.h"
#include "bindings/core/v8/V8ThrowException.h"
#include "core/dom/Document.h"
#include "core/dom/ExecutionContext.h"
#include "core/frame/LocalDOMWindow.h"
#include "core/frame/LocalFrame.h"
#include "core/inspector/InspectorTraceEvents.h"
#include "core/inspector/ThreadDebugger.h"
#include "core/loader/resource/ScriptResource.h"
#include "core/probe/CoreProbes.h"
#include "platform/Histogram.h"
#include "platform/ScriptForbiddenScope.h"
#include "platform/instrumentation/tracing/TraceEvent.h"
#include "platform/loader/fetch/CachedMetadata.h"
#include "platform/wtf/CurrentTime.h"
#include "public/platform/Platform.h"

#if OS(WIN)
#include <malloc.h>
#else
#include <alloca.h>
#endif

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;

class V8CompileHistogram {
 public:
  enum Cacheability { kCacheable, kNoncacheable, kInlineScript };
  explicit V8CompileHistogram(Cacheability);
  ~V8CompileHistogram();

 private:
  Cacheability cacheability_;
  double time_stamp_;
};

V8CompileHistogram::V8CompileHistogram(
    V8CompileHistogram::Cacheability cacheability)
    : cacheability_(cacheability), time_stamp_(WTF::CurrentTime()) {}

V8CompileHistogram::~V8CompileHistogram() {
  int64_t elapsed_micro_seconds =
      static_cast<int64_t>((WTF::CurrentTime() - time_stamp_) * 1000000);
  switch (cacheability_) {
    case kCacheable: {
      DEFINE_THREAD_SAFE_STATIC_LOCAL(
          CustomCountHistogram, compile_cacheable_histogram,
          new CustomCountHistogram("V8.CompileCacheableMicroSeconds", 0,
                                   1000000, 50));
      compile_cacheable_histogram.Count(elapsed_micro_seconds);
      break;
    }
    case kNoncacheable: {
      DEFINE_THREAD_SAFE_STATIC_LOCAL(
          CustomCountHistogram, compile_non_cacheable_histogram,
          new CustomCountHistogram("V8.CompileNoncacheableMicroSeconds", 0,
                                   1000000, 50));
      compile_non_cacheable_histogram.Count(elapsed_micro_seconds);
      break;
    }
    case kInlineScript: {
      DEFINE_THREAD_SAFE_STATIC_LOCAL(
          CustomCountHistogram, compile_inline_histogram,
          new CustomCountHistogram("V8.CompileInlineScriptMicroSeconds", 0,
                                   1000000, 50));
      compile_inline_histogram.Count(elapsed_micro_seconds);
      break;
    }
  }
}

// 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::Local<v8::Value> ThrowStackOverflowExceptionIfNeeded(v8::Isolate* isolate) {
  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, v8::MicrotasksScope::kDoNotRunMicrotasks);
  V8PerIsolateData::From(isolate)->SetIsHandlingRecursionLevelError(true);
  v8::Local<v8::Value> result =
      v8::Function::New(isolate->GetCurrentContext(),
                        ThrowStackOverflowException, v8::Local<v8::Value>(), 0,
                        v8::ConstructorBehavior::kThrow)
          .ToLocalChecked()
          ->Call(v8::Undefined(isolate), 0, 0);
  V8PerIsolateData::From(isolate)->SetIsHandlingRecursionLevelError(false);
  return result;
}

// Compile a script without any caching or compile options.
v8::MaybeLocal<v8::Script> CompileWithoutOptions(
    V8CompileHistogram::Cacheability cacheability,
    v8::Isolate* isolate,
    v8::Local<v8::String> code,
    v8::ScriptOrigin origin) {
  V8CompileHistogram histogram_scope(cacheability);
  v8::ScriptCompiler::Source source(code, origin);
  return v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &source,
                                     v8::ScriptCompiler::kNoCompileOptions);
}

// Compile a script, and consume a V8 cache that was generated previously.
static v8::MaybeLocal<v8::Script> CompileAndConsumeCache(
    CachedMetadataHandler* cache_handler,
    PassRefPtr<CachedMetadata> cached_metadata,
    v8::ScriptCompiler::CompileOptions compile_options,
    v8::Isolate* isolate,
    v8::Local<v8::String> code,
    v8::ScriptOrigin origin) {
  V8CompileHistogram histogram_scope(V8CompileHistogram::kCacheable);
  const char* data = cached_metadata->Data();
  int length = cached_metadata->size();
  v8::ScriptCompiler::CachedData* cached_data =
      new v8::ScriptCompiler::CachedData(
          reinterpret_cast<const uint8_t*>(data), length,
          v8::ScriptCompiler::CachedData::BufferNotOwned);
  v8::ScriptCompiler::Source source(code, origin, cached_data);
  v8::MaybeLocal<v8::Script> script = v8::ScriptCompiler::Compile(
      isolate->GetCurrentContext(), &source, compile_options);
  if (cached_data->rejected)
    cache_handler->ClearCachedMetadata(CachedMetadataHandler::kSendToPlatform);
  return script;
}

// Compile a script, and produce a V8 cache for future use.
v8::MaybeLocal<v8::Script> CompileAndProduceCache(
    CachedMetadataHandler* cache_handler,
    uint32_t tag,
    v8::ScriptCompiler::CompileOptions compile_options,
    CachedMetadataHandler::CacheType cache_type,
    v8::Isolate* isolate,
    v8::Local<v8::String> code,
    v8::ScriptOrigin origin) {
  V8CompileHistogram histogram_scope(V8CompileHistogram::kCacheable);
  v8::ScriptCompiler::Source source(code, origin);
  v8::MaybeLocal<v8::Script> script = v8::ScriptCompiler::Compile(
      isolate->GetCurrentContext(), &source, compile_options);
  const v8::ScriptCompiler::CachedData* cached_data = source.GetCachedData();
  if (cached_data) {
    const char* data = reinterpret_cast<const char*>(cached_data->data);
    int length = cached_data->length;
    if (length > 1024) {
      // Omit histogram samples for small cache data to avoid outliers.
      int cache_size_ratio = static_cast<int>(100.0 * length / code->Length());
      DEFINE_THREAD_SAFE_STATIC_LOCAL(
          CustomCountHistogram, code_cache_size_histogram,
          new CustomCountHistogram("V8.CodeCacheSizeRatio", 0, 10000, 50));
      code_cache_size_histogram.Count(cache_size_ratio);
    }
    cache_handler->ClearCachedMetadata(CachedMetadataHandler::kCacheLocally);
    cache_handler->SetCachedMetadata(tag, data, length, cache_type);
  }
  return script;
}

// Compile a script, and consume or produce a V8 Cache, depending on whether the
// given resource already has cached data available.
v8::MaybeLocal<v8::Script> CompileAndConsumeOrProduce(
    CachedMetadataHandler* cache_handler,
    uint32_t tag,
    v8::ScriptCompiler::CompileOptions consume_options,
    v8::ScriptCompiler::CompileOptions produce_options,
    CachedMetadataHandler::CacheType cache_type,
    v8::Isolate* isolate,
    v8::Local<v8::String> code,
    v8::ScriptOrigin origin) {
  RefPtr<CachedMetadata> code_cache(cache_handler->GetCachedMetadata(tag));
  return code_cache.Get()
             ? CompileAndConsumeCache(cache_handler, code_cache,
                                      consume_options, isolate, code, origin)
             : CompileAndProduceCache(cache_handler, tag, produce_options,
                                      cache_type, isolate, code, origin);
}

enum CacheTagKind {
  kCacheTagParser = 0,
  kCacheTagCode = 1,
  kCacheTagTimeStamp = 3,
  kCacheTagLast
};

static const int kCacheTagKindSize = 2;

uint32_t CacheTag(CacheTagKind kind, CachedMetadataHandler* cache_handler) {
  static_assert((1 << kCacheTagKindSize) >= kCacheTagLast,
                "CacheTagLast must be large enough");

  static uint32_t v8_cache_data_version =
      v8::ScriptCompiler::CachedDataVersionTag() << kCacheTagKindSize;

  // A script can be (successfully) interpreted with different encodings,
  // depending on the page it appears in. The cache doesn't know anything
  // about encodings, but the cached data is specific to one encoding. If we
  // later load the script from the cache and interpret it with a different
  // encoding, the cached data is not valid for that encoding.
  return (v8_cache_data_version | kind) +
         StringHash::GetHash(cache_handler->Encoding());
}

// Check previously stored timestamp.
bool IsResourceHotForCaching(CachedMetadataHandler* cache_handler,
                             int hot_hours) {
  const double cache_within_seconds = hot_hours * 60 * 60;
  uint32_t tag = CacheTag(kCacheTagTimeStamp, cache_handler);
  RefPtr<CachedMetadata> cached_metadata =
      cache_handler->GetCachedMetadata(tag);
  if (!cached_metadata)
    return false;
  double time_stamp;
  const int size = sizeof(time_stamp);
  DCHECK_EQ(cached_metadata->size(), static_cast<unsigned long>(size));
  memcpy(&time_stamp, cached_metadata->Data(), size);
  return (WTF::CurrentTime() - time_stamp) < cache_within_seconds;
}

// Final compile call for a streamed compilation. Most decisions have already
// been made, but we need to write back data into the cache.
v8::MaybeLocal<v8::Script> PostStreamCompile(
    V8CacheOptions cache_options,
    CachedMetadataHandler* cache_handler,
    ScriptStreamer* streamer,
    v8::Isolate* isolate,
    v8::Local<v8::String> code,
    v8::ScriptOrigin origin) {
  V8CompileHistogram histogram_scope(V8CompileHistogram::kNoncacheable);
  v8::MaybeLocal<v8::Script> script = v8::ScriptCompiler::Compile(
      isolate->GetCurrentContext(), streamer->Source(), code, origin);

  if (!cache_handler)
    return script;

  // If the non-streaming compiler uses the parser cache, retrieve and store
  // the cache data. If the code cache uses time stamp as heuristic, set that
  // time stamp.
  switch (cache_options) {
    case kV8CacheOptionsParse: {
      const v8::ScriptCompiler::CachedData* new_cached_data =
          streamer->Source()->GetCachedData();
      if (!new_cached_data)
        break;
      CachedMetadataHandler::CacheType cache_type =
          (cache_options == kV8CacheOptionsParse)
              ? CachedMetadataHandler::kSendToPlatform
              : CachedMetadataHandler::kCacheLocally;
      cache_handler->ClearCachedMetadata(cache_type);
      cache_handler->SetCachedMetadata(
          CacheTag(kCacheTagParser, cache_handler),
          reinterpret_cast<const char*>(new_cached_data->data),
          new_cached_data->length, cache_type);
      break;
    }

    case kV8CacheOptionsDefault:
    case kV8CacheOptionsCode:
      V8ScriptRunner::SetCacheTimeStamp(cache_handler);
      break;

    case kV8CacheOptionsAlways:
      // Currently V8CacheOptionsAlways doesn't support streaming.
      NOTREACHED();
    case kV8CacheOptionsNone:
      break;
  }
  return script;
}

typedef Function<v8::MaybeLocal<v8::Script>(v8::Isolate*,
                                            v8::Local<v8::String>,
                                            v8::ScriptOrigin)>
    CompileFn;

// A notation convenience: WTF::bind<...> needs to be given the right argument
// types. We have an awful lot of bind calls below, all with the same types, so
// this local bind lets WTF::bind to all the work, but 'knows' the right
// parameter types.
// This version isn't quite as smart as the real WTF::bind, though, so you
// sometimes may still have to call the original.
template <typename... A>
std::unique_ptr<CompileFn> Bind(const A&... args) {
  return WTF::Bind(args...);
}

// Select a compile function from any of the above, mainly depending on
// cacheOptions.
static std::unique_ptr<CompileFn> SelectCompileFunction(
    V8CacheOptions cache_options,
    CachedMetadataHandler* cache_handler,
    PassRefPtr<CachedMetadata> code_cache,
    v8::Local<v8::String> code,
    V8CompileHistogram::Cacheability cacheability_if_no_handler) {
  static const int kMinimalCodeLength = 1024;
  static const int kHotHours = 72;

  // Caching is not available in this case.
  if (!cache_handler)
    return Bind(CompileWithoutOptions, cacheability_if_no_handler);

  if (cache_options == kV8CacheOptionsNone)
    return Bind(CompileWithoutOptions, V8CompileHistogram::kCacheable);

  // Caching is not worthwhile for small scripts.  Do not use caching
  // unless explicitly expected, indicated by the cache option.
  if (code->Length() < kMinimalCodeLength)
    return Bind(CompileWithoutOptions, V8CompileHistogram::kCacheable);

  // The cacheOptions will guide our strategy:
  switch (cache_options) {
    case kV8CacheOptionsParse:
      // Use parser-cache; in-memory only.
      return Bind(CompileAndConsumeOrProduce, WrapPersistent(cache_handler),
                  CacheTag(kCacheTagParser, cache_handler),
                  v8::ScriptCompiler::kConsumeParserCache,
                  v8::ScriptCompiler::kProduceParserCache,
                  CachedMetadataHandler::kCacheLocally);
      break;

    case kV8CacheOptionsDefault:
    case kV8CacheOptionsCode:
    case kV8CacheOptionsAlways: {
      // Use code caching for recently seen resources.
      // Use compression depending on the cache option.
      if (code_cache) {
        return Bind(CompileAndConsumeCache, WrapPersistent(cache_handler),
                    std::move(code_cache),
                    v8::ScriptCompiler::kConsumeCodeCache);
      }
      if (cache_options != kV8CacheOptionsAlways &&
          !IsResourceHotForCaching(cache_handler, kHotHours)) {
        V8ScriptRunner::SetCacheTimeStamp(cache_handler);
        return Bind(CompileWithoutOptions, V8CompileHistogram::kCacheable);
      }
      uint32_t code_cache_tag = CacheTag(kCacheTagCode, cache_handler);
      return Bind(CompileAndProduceCache, WrapPersistent(cache_handler),
                  code_cache_tag, v8::ScriptCompiler::kProduceCodeCache,
                  CachedMetadataHandler::kSendToPlatform);
      break;
    }

    case kV8CacheOptionsNone:
      // Shouldn't happen, as this is handled above.
      // Case is here so that compiler can check all cases are handled.
      NOTREACHED();
      break;
  }

  // All switch branches should return and we should never get here.
  // But some compilers aren't sure, hence this default.
  NOTREACHED();
  return Bind(CompileWithoutOptions, V8CompileHistogram::kCacheable);
}

// Select a compile function for a streaming compile.
std::unique_ptr<CompileFn> SelectCompileFunction(V8CacheOptions cache_options,
                                                 ScriptResource* resource,
                                                 ScriptStreamer* streamer) {
  // We don't stream scripts which don't have a Resource.
  DCHECK(resource);
  // Failed resources should never get this far.
  DCHECK(!resource->ErrorOccurred());
  DCHECK(streamer->IsFinished());
  DCHECK(!streamer->StreamingSuppressed());
  return WTF::Bind(PostStreamCompile, cache_options,
                   WrapPersistent(resource->CacheHandler()),
                   WrapPersistent(streamer));
}
}  // namespace

v8::MaybeLocal<v8::Script> V8ScriptRunner::CompileScript(
    const ScriptSourceCode& source,
    v8::Isolate* isolate,
    AccessControlStatus access_control_status,
    V8CacheOptions cache_options) {
  if (source.Source().length() >= v8::String::kMaxLength) {
    V8ThrowException::ThrowError(isolate, "Source file too large.");
    return v8::Local<v8::Script>();
  }
  return CompileScript(
      V8String(isolate, source.Source()), source.Url(), source.SourceMapUrl(),
      source.StartPosition(), isolate, source.GetResource(), source.Streamer(),
      source.GetResource() ? source.GetResource()->CacheHandler() : nullptr,
      access_control_status, cache_options);
}

v8::MaybeLocal<v8::Script> V8ScriptRunner::CompileScript(
    const String& code,
    const String& file_name,
    const String& source_map_url,
    const TextPosition& text_position,
    v8::Isolate* isolate,
    CachedMetadataHandler* cache_metadata_handler,
    AccessControlStatus access_control_status,
    V8CacheOptions v8_cache_options) {
  if (code.length() >= v8::String::kMaxLength) {
    V8ThrowException::ThrowError(isolate, "Source file too large.");
    return v8::Local<v8::Script>();
  }
  return CompileScript(V8String(isolate, code), file_name, source_map_url,
                       text_position, isolate, nullptr, nullptr,
                       cache_metadata_handler, access_control_status,
                       v8_cache_options);
}

v8::MaybeLocal<v8::Script> V8ScriptRunner::CompileScript(
    v8::Local<v8::String> code,
    const String& file_name,
    const String& source_map_url,
    const TextPosition& script_start_position,
    v8::Isolate* isolate,
    ScriptResource* resource,
    ScriptStreamer* streamer,
    CachedMetadataHandler* cache_handler,
    AccessControlStatus access_control_status,
    V8CacheOptions cache_options) {
  TRACE_EVENT2(
      "v8,devtools.timeline", "v8.compile", "fileName", file_name.Utf8(),
      "data",
      InspectorCompileScriptEvent::Data(file_name, script_start_position));

  DCHECK(!streamer || resource);
  DCHECK(!resource || resource->CacheHandler() == cache_handler);

  // NOTE: For compatibility with WebCore, ScriptSourceCode's line starts at
  // 1, whereas v8 starts at 0.
  v8::ScriptOrigin origin(
      V8String(isolate, file_name),
      v8::Integer::New(isolate, script_start_position.line_.ZeroBasedInt()),
      v8::Integer::New(isolate, script_start_position.column_.ZeroBasedInt()),
      v8::Boolean::New(isolate, access_control_status == kSharableCrossOrigin),
      v8::Local<v8::Integer>(), V8String(isolate, source_map_url),
      v8::Boolean::New(isolate, access_control_status == kOpaqueResource));

  V8CompileHistogram::Cacheability cacheability_if_no_handler =
      V8CompileHistogram::Cacheability::kNoncacheable;
  if (!cache_handler && (script_start_position.line_.ZeroBasedInt() == 0) &&
      (script_start_position.column_.ZeroBasedInt() == 0))
    cacheability_if_no_handler =
        V8CompileHistogram::Cacheability::kInlineScript;

  RefPtr<CachedMetadata> code_cache(
      cache_handler ? cache_handler->GetCachedMetadata(
                          CacheTag(kCacheTagCode, cache_handler))
                    : nullptr);
  std::unique_ptr<CompileFn> compile_fn =
      streamer ? SelectCompileFunction(cache_options, resource, streamer)
               : SelectCompileFunction(cache_options, cache_handler, code_cache,
                                       code, cacheability_if_no_handler);

  return (*compile_fn)(isolate, code, origin);
}

v8::MaybeLocal<v8::Module> V8ScriptRunner::CompileModule(
    v8::Isolate* isolate,
    const String& source,
    const String& file_name,
    AccessControlStatus access_control_status) {
  TRACE_EVENT1("v8", "v8.compileModule", "fileName", file_name.Utf8());
  // TODO(adamk): Add Inspector integration?
  // TODO(adamk): Pass more info into ScriptOrigin.
  v8::ScriptOrigin origin(
      V8String(isolate, file_name),
      v8::Integer::New(isolate, 0),  // line_offset
      v8::Integer::New(isolate, 0),  // col_offset
      v8::Boolean::New(isolate, access_control_status == kSharableCrossOrigin),
      v8::Local<v8::Integer>(),    // script id
      v8::String::Empty(isolate),  // source_map_url
      v8::Boolean::New(isolate, access_control_status == kOpaqueResource),
      v8::False(isolate),  // is_wasm
      v8::True(isolate));  // is_module

  v8::ScriptCompiler::Source script_source(V8String(isolate, source), origin);
  return v8::ScriptCompiler::CompileModule(isolate, &script_source);
}

void V8ScriptRunner::ReportExceptionForModule(v8::Isolate* isolate,
                                              v8::Local<v8::Value> exception,
                                              const String& file_name) {
  // |origin| is for compiling a fragment that throws |exception|.
  // Therefore |is_module| is false and |access_control_status| is
  // kSharableCrossOrigin.
  AccessControlStatus access_control_status = kSharableCrossOrigin;
  v8::ScriptOrigin origin(
      V8String(isolate, file_name),
      v8::Integer::New(isolate, 0),  // line_offset
      v8::Integer::New(isolate, 0),  // col_offset
      v8::Boolean::New(isolate, access_control_status == kSharableCrossOrigin),
      v8::Local<v8::Integer>(),    // script id
      v8::String::Empty(isolate),  // source_map_url
      v8::Boolean::New(isolate, access_control_status == kOpaqueResource),
      v8::False(isolate),   // is_wasm
      v8::False(isolate));  // is_module

  ThrowException(isolate, exception, origin);
}

v8::MaybeLocal<v8::Value> V8ScriptRunner::RunCompiledScript(
    v8::Isolate* isolate,
    v8::Local<v8::Script> script,
    ExecutionContext* context) {
  DCHECK(!script.IsEmpty());
  ScopedFrameBlamer frame_blamer(
      context->IsDocument() ? ToDocument(context)->GetFrame() : nullptr);
  TRACE_EVENT1("v8", "v8.run", "fileName",
               TRACE_STR_COPY(*v8::String::Utf8Value(
                   script->GetUnboundScript()->GetScriptName())));

  if (v8::MicrotasksScope::GetCurrentDepth(isolate) >= kMaxRecursionDepth)
    return ThrowStackOverflowExceptionIfNeeded(isolate);

  CHECK(!context->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::MicrotasksScope microtasks_scope(isolate,
                                         v8::MicrotasksScope::kRunMicrotasks);
    probe::ExecuteScript probe(context);
    result = script->Run(isolate->GetCurrentContext());
  }

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

v8::MaybeLocal<v8::Value> V8ScriptRunner::CompileAndRunInternalScript(
    v8::Local<v8::String> source,
    v8::Isolate* isolate,
    const String& file_name,
    const TextPosition& script_start_position) {
  v8::Local<v8::Script> script;
  if (!V8ScriptRunner::CompileScript(
           source, file_name, String(), script_start_position, isolate, nullptr,
           nullptr, nullptr, kSharableCrossOrigin, kV8CacheOptionsDefault)
           .ToLocal(&script))
    return v8::MaybeLocal<v8::Value>();

  TRACE_EVENT0("v8", "v8.run");
  v8::MicrotasksScope microtasks_scope(
      isolate, v8::MicrotasksScope::kDoNotRunMicrotasks);
  v8::MaybeLocal<v8::Value> result = script->Run(isolate->GetCurrentContext());
  CHECK(!isolate->IsDead());
  return result;
}

v8::MaybeLocal<v8::Value> V8ScriptRunner::RunCompiledInternalScript(
    v8::Isolate* isolate,
    v8::Local<v8::Script> script) {
  TRACE_EVENT0("v8", "v8.run");
  v8::MicrotasksScope microtasks_scope(
      isolate, 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");

  int depth = v8::MicrotasksScope::GetCurrentDepth(isolate);
  if (depth >= kMaxRecursionDepth)
    return v8::MaybeLocal<v8::Value>(
        ThrowStackOverflowExceptionIfNeeded(isolate));

  CHECK(!context->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::MicrotasksScope microtasks_scope(isolate,
                                       v8::MicrotasksScope::kRunMicrotasks);
  probe::CallFunction probe(context, function, depth);
  v8::MaybeLocal<v8::Value> result =
      constructor->CallAsConstructor(isolate->GetCurrentContext(), argc, argv);
  CHECK(!isolate->IsDead());
  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) {
  LocalFrame* frame =
      context->IsDocument() ? ToDocument(context)->GetFrame() : nullptr;
  ScopedFrameBlamer frame_blamer(frame);
  TRACE_EVENT0("v8", "v8.callFunction");

  int depth = v8::MicrotasksScope::GetCurrentDepth(isolate);
  if (depth >= kMaxRecursionDepth)
    return v8::MaybeLocal<v8::Value>(
        ThrowStackOverflowExceptionIfNeeded(isolate));

  CHECK(!context->IsIteratingOverObservers());

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

  DCHECK(!frame || BindingSecurity::ShouldAllowAccessToFrame(
                       ToLocalDOMWindow(function->CreationContext()), frame,
                       BindingSecurity::ErrorReportOption::kDoNotReport));
  CHECK(!ThreadState::Current()->IsWrapperTracingForbidden());
  v8::MicrotasksScope microtasks_scope(isolate,
                                       v8::MicrotasksScope::kRunMicrotasks);
  probe::CallFunction probe(context, function, depth);
  v8::MaybeLocal<v8::Value> result =
      function->Call(isolate->GetCurrentContext(), receiver, argc, args);
  CHECK(!isolate->IsDead());

  return result;
}

v8::MaybeLocal<v8::Value> V8ScriptRunner::CallInternalFunction(
    v8::Local<v8::Function> function,
    v8::Local<v8::Value> receiver,
    int argc,
    v8::Local<v8::Value> args[],
    v8::Isolate* isolate) {
  TRACE_EVENT0("v8", "v8.callFunction");
  CHECK(!ThreadState::Current()->IsWrapperTracingForbidden());
  v8::MicrotasksScope microtasks_scope(
      isolate, v8::MicrotasksScope::kDoNotRunMicrotasks);
  v8::MaybeLocal<v8::Value> result =
      function->Call(isolate->GetCurrentContext(), receiver, argc, args);
  CHECK(!isolate->IsDead());
  return result;
}

v8::MaybeLocal<v8::Value> V8ScriptRunner::EvaluateModule(
    v8::Local<v8::Module> module,
    v8::Local<v8::Context> context,
    v8::Isolate* isolate) {
  TRACE_EVENT0("v8", "v8.evaluateModule");
  v8::MicrotasksScope microtasks_scope(isolate,
                                       v8::MicrotasksScope::kRunMicrotasks);
  return module->Evaluate(context);
}

uint32_t V8ScriptRunner::TagForParserCache(
    CachedMetadataHandler* cache_handler) {
  return CacheTag(kCacheTagParser, cache_handler);
}

uint32_t V8ScriptRunner::TagForCodeCache(CachedMetadataHandler* cache_handler) {
  return CacheTag(kCacheTagCode, cache_handler);
}

// Store a timestamp to the cache as hint.
void V8ScriptRunner::SetCacheTimeStamp(CachedMetadataHandler* cache_handler) {
  double now = WTF::CurrentTime();
  uint32_t tag = CacheTag(kCacheTagTimeStamp, cache_handler);
  cache_handler->ClearCachedMetadata(CachedMetadataHandler::kCacheLocally);
  cache_handler->SetCachedMetadata(tag, reinterpret_cast<char*>(&now),
                                   sizeof(now),
                                   CachedMetadataHandler::kSendToPlatform);
}

void V8ScriptRunner::ThrowException(v8::Isolate* isolate,
                                    v8::Local<v8::Value> exception,
                                    const v8::ScriptOrigin& origin) {
  // In order for the current TryCatch to catch this exception and
  // call MessageCallback when SetVerbose(true), create a v8::Function
  // that calls isolate->throwException().
  // Unlike throwStackOverflowExceptionIfNeeded(), create a temporary Script
  // with the specified ScriptOrigin. When the exception was created but not
  // thrown yet, the ScriptOrigin of the thrower is set to the exception.
  // v8::Function::New() has empty ScriptOrigin, and thus the exception will
  // be "muted" (sanitized in our terminology) if CORS does not allow.
  // https://html.spec.whatwg.org/multipage/webappapis.html#report-the-error
  // Avoid compile and run scripts when API is available: crbug.com/639739
  v8::Local<v8::Script> script =
      CompileWithoutOptions(
          V8CompileHistogram::Cacheability::kNoncacheable, isolate,
          V8AtomicString(isolate, "((e) => { throw e; })"), origin)
          .ToLocalChecked();
  v8::Local<v8::Function> thrower = RunCompiledInternalScript(isolate, script)
                                        .ToLocalChecked()
                                        .As<v8::Function>();
  v8::Local<v8::Value> args[] = {exception};
  CallInternalFunction(thrower, thrower, WTF_ARRAY_LENGTH(args), args, isolate);
}

v8::MaybeLocal<v8::Value> V8ScriptRunner::CallExtraHelper(
    ScriptState* script_state,
    const char* name,
    size_t num_args,
    v8::Local<v8::Value>* args) {
  v8::Isolate* isolate = script_state->GetIsolate();
  v8::Local<v8::Value> function_value;
  v8::Local<v8::Context> context = script_state->GetContext();
  if (!context->GetExtrasBindingObject()
           ->Get(context, V8AtomicString(isolate, name))
           .ToLocal(&function_value))
    return v8::MaybeLocal<v8::Value>();
  v8::Local<v8::Function> function = function_value.As<v8::Function>();
  return V8ScriptRunner::CallInternalFunction(function, v8::Undefined(isolate),
                                              num_args, args, isolate);
}

}  // namespace blink
