// Copyright 2019 the V8 project 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 "src/wasm/wasm-module-sourcemap.h"

#include <algorithm>

#include "include/v8.h"
#include "src/api/api.h"
#include "src/base/vlq-base64.h"

namespace v8 {
namespace internal {
namespace wasm {

WasmModuleSourceMap::WasmModuleSourceMap(v8::Isolate* v8_isolate,
                                         v8::Local<v8::String> src_map_str) {
  v8::HandleScope scope(v8_isolate);
  v8::Local<v8::Context> context = v8::Context::New(v8_isolate);

  v8::Local<v8::Value> src_map_value;
  if (!v8::JSON::Parse(context, src_map_str).ToLocal(&src_map_value)) return;
  v8::Local<v8::Object> src_map_obj =
      v8::Local<v8::Object>::Cast(src_map_value);

  v8::Local<v8::Value> version_value, sources_value, mappings_value;
  bool has_valid_version =
      src_map_obj
          ->Get(context, v8::String::NewFromUtf8Literal(v8_isolate, "version"))
          .ToLocal(&version_value) &&
      version_value->IsUint32();
  uint32_t version = 0;
  if (!has_valid_version || !version_value->Uint32Value(context).To(&version) ||
      version != 3u)
    return;

  bool has_valid_sources =
      src_map_obj
          ->Get(context, v8::String::NewFromUtf8Literal(v8_isolate, "sources"))
          .ToLocal(&sources_value) &&
      sources_value->IsArray();
  if (!has_valid_sources) return;

  v8::Local<v8::Object> sources_arr =
      v8::Local<v8::Object>::Cast(sources_value);
  v8::Local<v8::Value> sources_len_value;
  if (!sources_arr
           ->Get(context, v8::String::NewFromUtf8Literal(v8_isolate, "length"))
           .ToLocal(&sources_len_value))
    return;
  uint32_t sources_len = 0;
  if (!sources_len_value->Uint32Value(context).To(&sources_len)) return;

  for (uint32_t i = 0; i < sources_len; ++i) {
    v8::Local<v8::Value> file_name_value;
    if (!sources_arr->Get(context, i).ToLocal(&file_name_value) ||
        !file_name_value->IsString())
      return;
    v8::Local<v8::String> file_name =
        v8::Local<v8::String>::Cast(file_name_value);
    auto file_name_sz = file_name->Utf8Length(v8_isolate);
    std::unique_ptr<char[]> file_name_buf(new char[file_name_sz + 1]);
    file_name->WriteUtf8(v8_isolate, file_name_buf.get());
    file_name_buf.get()[file_name_sz] = '\0';
    filenames.emplace_back(file_name_buf.get());
  }

  bool has_valid_mappings =
      src_map_obj
          ->Get(context, v8::String::NewFromUtf8Literal(v8_isolate, "mappings"))
          .ToLocal(&mappings_value) &&
      mappings_value->IsString();
  if (!has_valid_mappings) return;

  v8::Local<v8::String> mappings = v8::Local<v8::String>::Cast(mappings_value);
  int mappings_sz = mappings->Utf8Length(v8_isolate);
  std::unique_ptr<char[]> mappings_buf(new char[mappings_sz + 1]);
  mappings->WriteUtf8(v8_isolate, mappings_buf.get());
  mappings_buf.get()[mappings_sz] = '\0';

  valid_ = DecodeMapping(mappings_buf.get());
}

size_t WasmModuleSourceMap::GetSourceLine(size_t wasm_offset) const {
  std::vector<std::size_t>::const_iterator up =
      std::upper_bound(offsets.begin(), offsets.end(), wasm_offset);
  CHECK_NE(offsets.begin(), up);
  size_t source_idx = up - offsets.begin() - 1;
  return source_row[source_idx];
}

std::string WasmModuleSourceMap::GetFilename(size_t wasm_offset) const {
  std::vector<size_t>::const_iterator up =
      std::upper_bound(offsets.begin(), offsets.end(), wasm_offset);
  CHECK_NE(offsets.begin(), up);
  size_t offset_idx = up - offsets.begin() - 1;
  size_t filename_idx = file_idxs[offset_idx];
  return filenames[filename_idx];
}

bool WasmModuleSourceMap::HasSource(size_t start, size_t end) const {
  return start <= *(offsets.end() - 1) && end > *offsets.begin();
}

bool WasmModuleSourceMap::HasValidEntry(size_t start, size_t addr) const {
  std::vector<size_t>::const_iterator up =
      std::upper_bound(offsets.begin(), offsets.end(), addr);
  if (up == offsets.begin()) return false;
  size_t offset_idx = up - offsets.begin() - 1;
  size_t entry_offset = offsets[offset_idx];
  if (entry_offset < start) return false;
  return true;
}

bool WasmModuleSourceMap::DecodeMapping(const std::string& s) {
  size_t pos = 0, gen_col = 0, file_idx = 0, ori_line = 0;
  int32_t qnt = 0;

  while (pos < s.size()) {
    // Skip redundant commas.
    if (s[pos] == ',') {
      ++pos;
      continue;
    }
    if ((qnt = base::VLQBase64Decode(s.c_str(), s.size(), &pos)) ==
        std::numeric_limits<int32_t>::min())
      return false;
    gen_col += qnt;
    if ((qnt = base::VLQBase64Decode(s.c_str(), s.size(), &pos)) ==
        std::numeric_limits<int32_t>::min())
      return false;
    file_idx += qnt;
    if ((qnt = base::VLQBase64Decode(s.c_str(), s.size(), &pos)) ==
        std::numeric_limits<int32_t>::min())
      return false;
    ori_line += qnt;
    // Column number in source file is always 0 in source map generated by
    // Emscripten. We just decode this value without further usage of it.
    if ((qnt = base::VLQBase64Decode(s.c_str(), s.size(), &pos)) ==
        std::numeric_limits<int32_t>::min())
      return false;

    if (pos < s.size() && s[pos] != ',') return false;
    pos++;

    file_idxs.push_back(file_idx);
    source_row.push_back(ori_line);
    offsets.push_back(gen_col);
  }
  return true;
}

}  // namespace wasm
}  // namespace internal
}  // namespace v8
