// Copyright 2016 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 "bindings/core/v8/SourceLocation.h"

#include "bindings/core/v8/V8BindingMacros.h"
#include "bindings/core/v8/V8PerIsolateData.h"
#include "core/dom/Document.h"
#include "core/dom/ExecutionContext.h"
#include "core/dom/ScriptableDocumentParser.h"
#include "core/html/HTMLFrameOwnerElement.h"
#include "core/inspector/ThreadDebugger.h"
#include "core/inspector/V8InspectorString.h"
#include "platform/ScriptForbiddenScope.h"
#include "platform/instrumentation/tracing/TracedValue.h"
#include "wtf/PtrUtil.h"
#include <memory>

namespace blink {

namespace {

std::unique_ptr<v8_inspector::V8StackTrace> captureStackTrace(bool full) {
  v8::Isolate* isolate = v8::Isolate::GetCurrent();
  ThreadDebugger* debugger = ThreadDebugger::from(isolate);
  if (!debugger || !isolate->InContext())
    return nullptr;
  ScriptForbiddenScope::AllowUserAgentScript allowScripting;
  return debugger->v8Inspector()->captureStackTrace(full);
}
}

// static
std::unique_ptr<SourceLocation> SourceLocation::capture(const String& url,
                                                        unsigned lineNumber,
                                                        unsigned columnNumber) {
  std::unique_ptr<v8_inspector::V8StackTrace> stackTrace =
      captureStackTrace(false);
  if (stackTrace && !stackTrace->isEmpty())
    return SourceLocation::createFromNonEmptyV8StackTrace(std::move(stackTrace),
                                                          0);
  return SourceLocation::create(url, lineNumber, columnNumber,
                                std::move(stackTrace));
}

// static
std::unique_ptr<SourceLocation> SourceLocation::capture(
    ExecutionContext* executionContext) {
  std::unique_ptr<v8_inspector::V8StackTrace> stackTrace =
      captureStackTrace(false);
  if (stackTrace && !stackTrace->isEmpty())
    return SourceLocation::createFromNonEmptyV8StackTrace(std::move(stackTrace),
                                                          0);

  Document* document = executionContext && executionContext->isDocument()
                           ? toDocument(executionContext)
                           : nullptr;
  if (document) {
    unsigned lineNumber = 0;
    if (document->scriptableDocumentParser() &&
        !document->isInDocumentWrite()) {
      if (document->scriptableDocumentParser()->isParsingAtLineNumber())
        lineNumber =
            document->scriptableDocumentParser()->lineNumber().oneBasedInt();
    }
    return SourceLocation::create(document->url().getString(), lineNumber, 0,
                                  std::move(stackTrace));
  }

  return SourceLocation::create(
      executionContext ? executionContext->url().getString() : String(), 0, 0,
      std::move(stackTrace));
}

// static
std::unique_ptr<SourceLocation> SourceLocation::fromMessage(
    v8::Isolate* isolate,
    v8::Local<v8::Message> message,
    ExecutionContext* executionContext) {
  v8::Local<v8::StackTrace> stack = message->GetStackTrace();
  std::unique_ptr<v8_inspector::V8StackTrace> stackTrace = nullptr;
  ThreadDebugger* debugger = ThreadDebugger::from(isolate);
  if (debugger)
    stackTrace = debugger->v8Inspector()->createStackTrace(stack);

  int scriptId = message->GetScriptOrigin().ScriptID()->Value();
  if (!stack.IsEmpty() && stack->GetFrameCount() > 0) {
    int topScriptId = stack->GetFrame(0)->GetScriptId();
    if (topScriptId == scriptId)
      scriptId = 0;
  }

  int lineNumber = 0;
  int columnNumber = 0;
  if (v8Call(message->GetLineNumber(isolate->GetCurrentContext()),
             lineNumber) &&
      v8Call(message->GetStartColumn(isolate->GetCurrentContext()),
             columnNumber))
    ++columnNumber;

  if ((!scriptId || !lineNumber) && stackTrace && !stackTrace->isEmpty())
    return SourceLocation::createFromNonEmptyV8StackTrace(std::move(stackTrace),
                                                          0);

  String url = toCoreStringWithUndefinedOrNullCheck(
      message->GetScriptOrigin().ResourceName());
  if (url.isNull())
    url = executionContext->url();
  return SourceLocation::create(url, lineNumber, columnNumber,
                                std::move(stackTrace), scriptId);
}

// static
std::unique_ptr<SourceLocation> SourceLocation::create(
    const String& url,
    unsigned lineNumber,
    unsigned columnNumber,
    std::unique_ptr<v8_inspector::V8StackTrace> stackTrace,
    int scriptId) {
  return WTF::wrapUnique(new SourceLocation(url, lineNumber, columnNumber,
                                            std::move(stackTrace), scriptId));
}

// static
std::unique_ptr<SourceLocation> SourceLocation::createFromNonEmptyV8StackTrace(
    std::unique_ptr<v8_inspector::V8StackTrace> stackTrace,
    int scriptId) {
  // Retrieve the data before passing the ownership to SourceLocation.
  String url = toCoreString(stackTrace->topSourceURL());
  unsigned lineNumber = stackTrace->topLineNumber();
  unsigned columnNumber = stackTrace->topColumnNumber();
  return WTF::wrapUnique(new SourceLocation(url, lineNumber, columnNumber,
                                            std::move(stackTrace), scriptId));
}

// static
std::unique_ptr<SourceLocation> SourceLocation::fromFunction(
    v8::Local<v8::Function> function) {
  if (!function.IsEmpty())
    return SourceLocation::create(
        toCoreStringWithUndefinedOrNullCheck(
            function->GetScriptOrigin().ResourceName()),
        function->GetScriptLineNumber() + 1,
        function->GetScriptColumnNumber() + 1, nullptr, function->ScriptId());
  return SourceLocation::create(String(), 0, 0, nullptr, 0);
}

// static
std::unique_ptr<SourceLocation> SourceLocation::captureWithFullStackTrace() {
  std::unique_ptr<v8_inspector::V8StackTrace> stackTrace =
      captureStackTrace(true);
  if (stackTrace && !stackTrace->isEmpty())
    return SourceLocation::createFromNonEmptyV8StackTrace(std::move(stackTrace),
                                                          0);
  return SourceLocation::create(String(), 0, 0, nullptr, 0);
}

SourceLocation::SourceLocation(
    const String& url,
    unsigned lineNumber,
    unsigned columnNumber,
    std::unique_ptr<v8_inspector::V8StackTrace> stackTrace,
    int scriptId)
    : m_url(url),
      m_lineNumber(lineNumber),
      m_columnNumber(columnNumber),
      m_stackTrace(std::move(stackTrace)),
      m_scriptId(scriptId) {}

SourceLocation::~SourceLocation() {}

void SourceLocation::toTracedValue(TracedValue* value, const char* name) const {
  if (!m_stackTrace || m_stackTrace->isEmpty())
    return;
  value->beginArray(name);
  value->beginDictionary();
  value->setString("functionName",
                   toCoreString(m_stackTrace->topFunctionName()));
  value->setString("scriptId", toCoreString(m_stackTrace->topScriptId()));
  value->setString("url", toCoreString(m_stackTrace->topSourceURL()));
  value->setInteger("lineNumber", m_stackTrace->topLineNumber());
  value->setInteger("columnNumber", m_stackTrace->topColumnNumber());
  value->endDictionary();
  value->endArray();
}

std::unique_ptr<SourceLocation> SourceLocation::clone() const {
  return WTF::wrapUnique(new SourceLocation(
      m_url.isolatedCopy(), m_lineNumber, m_columnNumber,
      m_stackTrace ? m_stackTrace->clone() : nullptr, m_scriptId));
}

std::unique_ptr<v8_inspector::protocol::Runtime::API::StackTrace>
SourceLocation::buildInspectorObject() const {
  return m_stackTrace ? m_stackTrace->buildInspectorObject() : nullptr;
}

String SourceLocation::toString() const {
  if (!m_stackTrace)
    return String();
  return toCoreString(m_stackTrace->toString());
}

}  // namespace blink
