11cb0ef41Sopenharmony_ci// Copyright 2019 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "src/wasm/wasm-module-sourcemap.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include <algorithm> 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ci#include "include/v8-context.h" 101cb0ef41Sopenharmony_ci#include "include/v8-json.h" 111cb0ef41Sopenharmony_ci#include "include/v8-local-handle.h" 121cb0ef41Sopenharmony_ci#include "include/v8-object.h" 131cb0ef41Sopenharmony_ci#include "include/v8-primitive.h" 141cb0ef41Sopenharmony_ci#include "src/api/api.h" 151cb0ef41Sopenharmony_ci#include "src/base/vlq-base64.h" 161cb0ef41Sopenharmony_ci 171cb0ef41Sopenharmony_cinamespace v8 { 181cb0ef41Sopenharmony_ci 191cb0ef41Sopenharmony_ciclass String; 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_cinamespace internal { 221cb0ef41Sopenharmony_cinamespace wasm { 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_ciWasmModuleSourceMap::WasmModuleSourceMap(v8::Isolate* v8_isolate, 251cb0ef41Sopenharmony_ci v8::Local<v8::String> src_map_str) { 261cb0ef41Sopenharmony_ci v8::HandleScope scope(v8_isolate); 271cb0ef41Sopenharmony_ci v8::Local<v8::Context> context = v8::Context::New(v8_isolate); 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_ci v8::Local<v8::Value> src_map_value; 301cb0ef41Sopenharmony_ci if (!v8::JSON::Parse(context, src_map_str).ToLocal(&src_map_value)) return; 311cb0ef41Sopenharmony_ci v8::Local<v8::Object> src_map_obj = 321cb0ef41Sopenharmony_ci v8::Local<v8::Object>::Cast(src_map_value); 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_ci v8::Local<v8::Value> version_value, sources_value, mappings_value; 351cb0ef41Sopenharmony_ci bool has_valid_version = 361cb0ef41Sopenharmony_ci src_map_obj 371cb0ef41Sopenharmony_ci ->Get(context, v8::String::NewFromUtf8Literal(v8_isolate, "version")) 381cb0ef41Sopenharmony_ci .ToLocal(&version_value) && 391cb0ef41Sopenharmony_ci version_value->IsUint32(); 401cb0ef41Sopenharmony_ci uint32_t version = 0; 411cb0ef41Sopenharmony_ci if (!has_valid_version || !version_value->Uint32Value(context).To(&version) || 421cb0ef41Sopenharmony_ci version != 3u) 431cb0ef41Sopenharmony_ci return; 441cb0ef41Sopenharmony_ci 451cb0ef41Sopenharmony_ci bool has_valid_sources = 461cb0ef41Sopenharmony_ci src_map_obj 471cb0ef41Sopenharmony_ci ->Get(context, v8::String::NewFromUtf8Literal(v8_isolate, "sources")) 481cb0ef41Sopenharmony_ci .ToLocal(&sources_value) && 491cb0ef41Sopenharmony_ci sources_value->IsArray(); 501cb0ef41Sopenharmony_ci if (!has_valid_sources) return; 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_ci v8::Local<v8::Object> sources_arr = 531cb0ef41Sopenharmony_ci v8::Local<v8::Object>::Cast(sources_value); 541cb0ef41Sopenharmony_ci v8::Local<v8::Value> sources_len_value; 551cb0ef41Sopenharmony_ci if (!sources_arr 561cb0ef41Sopenharmony_ci ->Get(context, v8::String::NewFromUtf8Literal(v8_isolate, "length")) 571cb0ef41Sopenharmony_ci .ToLocal(&sources_len_value)) 581cb0ef41Sopenharmony_ci return; 591cb0ef41Sopenharmony_ci uint32_t sources_len = 0; 601cb0ef41Sopenharmony_ci if (!sources_len_value->Uint32Value(context).To(&sources_len)) return; 611cb0ef41Sopenharmony_ci 621cb0ef41Sopenharmony_ci for (uint32_t i = 0; i < sources_len; ++i) { 631cb0ef41Sopenharmony_ci v8::Local<v8::Value> file_name_value; 641cb0ef41Sopenharmony_ci if (!sources_arr->Get(context, i).ToLocal(&file_name_value) || 651cb0ef41Sopenharmony_ci !file_name_value->IsString()) 661cb0ef41Sopenharmony_ci return; 671cb0ef41Sopenharmony_ci v8::Local<v8::String> file_name = 681cb0ef41Sopenharmony_ci v8::Local<v8::String>::Cast(file_name_value); 691cb0ef41Sopenharmony_ci auto file_name_sz = file_name->Utf8Length(v8_isolate); 701cb0ef41Sopenharmony_ci std::unique_ptr<char[]> file_name_buf(new char[file_name_sz + 1]); 711cb0ef41Sopenharmony_ci file_name->WriteUtf8(v8_isolate, file_name_buf.get()); 721cb0ef41Sopenharmony_ci file_name_buf.get()[file_name_sz] = '\0'; 731cb0ef41Sopenharmony_ci filenames.emplace_back(file_name_buf.get()); 741cb0ef41Sopenharmony_ci } 751cb0ef41Sopenharmony_ci 761cb0ef41Sopenharmony_ci bool has_valid_mappings = 771cb0ef41Sopenharmony_ci src_map_obj 781cb0ef41Sopenharmony_ci ->Get(context, v8::String::NewFromUtf8Literal(v8_isolate, "mappings")) 791cb0ef41Sopenharmony_ci .ToLocal(&mappings_value) && 801cb0ef41Sopenharmony_ci mappings_value->IsString(); 811cb0ef41Sopenharmony_ci if (!has_valid_mappings) return; 821cb0ef41Sopenharmony_ci 831cb0ef41Sopenharmony_ci v8::Local<v8::String> mappings = v8::Local<v8::String>::Cast(mappings_value); 841cb0ef41Sopenharmony_ci int mappings_sz = mappings->Utf8Length(v8_isolate); 851cb0ef41Sopenharmony_ci std::unique_ptr<char[]> mappings_buf(new char[mappings_sz + 1]); 861cb0ef41Sopenharmony_ci mappings->WriteUtf8(v8_isolate, mappings_buf.get()); 871cb0ef41Sopenharmony_ci mappings_buf.get()[mappings_sz] = '\0'; 881cb0ef41Sopenharmony_ci 891cb0ef41Sopenharmony_ci valid_ = DecodeMapping(mappings_buf.get()); 901cb0ef41Sopenharmony_ci} 911cb0ef41Sopenharmony_ci 921cb0ef41Sopenharmony_cisize_t WasmModuleSourceMap::GetSourceLine(size_t wasm_offset) const { 931cb0ef41Sopenharmony_ci std::vector<std::size_t>::const_iterator up = 941cb0ef41Sopenharmony_ci std::upper_bound(offsets.begin(), offsets.end(), wasm_offset); 951cb0ef41Sopenharmony_ci CHECK_NE(offsets.begin(), up); 961cb0ef41Sopenharmony_ci size_t source_idx = up - offsets.begin() - 1; 971cb0ef41Sopenharmony_ci return source_row[source_idx]; 981cb0ef41Sopenharmony_ci} 991cb0ef41Sopenharmony_ci 1001cb0ef41Sopenharmony_cistd::string WasmModuleSourceMap::GetFilename(size_t wasm_offset) const { 1011cb0ef41Sopenharmony_ci std::vector<size_t>::const_iterator up = 1021cb0ef41Sopenharmony_ci std::upper_bound(offsets.begin(), offsets.end(), wasm_offset); 1031cb0ef41Sopenharmony_ci CHECK_NE(offsets.begin(), up); 1041cb0ef41Sopenharmony_ci size_t offset_idx = up - offsets.begin() - 1; 1051cb0ef41Sopenharmony_ci size_t filename_idx = file_idxs[offset_idx]; 1061cb0ef41Sopenharmony_ci return filenames[filename_idx]; 1071cb0ef41Sopenharmony_ci} 1081cb0ef41Sopenharmony_ci 1091cb0ef41Sopenharmony_cibool WasmModuleSourceMap::HasSource(size_t start, size_t end) const { 1101cb0ef41Sopenharmony_ci return start <= *(offsets.end() - 1) && end > *offsets.begin(); 1111cb0ef41Sopenharmony_ci} 1121cb0ef41Sopenharmony_ci 1131cb0ef41Sopenharmony_cibool WasmModuleSourceMap::HasValidEntry(size_t start, size_t addr) const { 1141cb0ef41Sopenharmony_ci std::vector<size_t>::const_iterator up = 1151cb0ef41Sopenharmony_ci std::upper_bound(offsets.begin(), offsets.end(), addr); 1161cb0ef41Sopenharmony_ci if (up == offsets.begin()) return false; 1171cb0ef41Sopenharmony_ci size_t offset_idx = up - offsets.begin() - 1; 1181cb0ef41Sopenharmony_ci size_t entry_offset = offsets[offset_idx]; 1191cb0ef41Sopenharmony_ci if (entry_offset < start) return false; 1201cb0ef41Sopenharmony_ci return true; 1211cb0ef41Sopenharmony_ci} 1221cb0ef41Sopenharmony_ci 1231cb0ef41Sopenharmony_cibool WasmModuleSourceMap::DecodeMapping(const std::string& s) { 1241cb0ef41Sopenharmony_ci size_t pos = 0, gen_col = 0, file_idx = 0, ori_line = 0; 1251cb0ef41Sopenharmony_ci int32_t qnt = 0; 1261cb0ef41Sopenharmony_ci 1271cb0ef41Sopenharmony_ci while (pos < s.size()) { 1281cb0ef41Sopenharmony_ci // Skip redundant commas. 1291cb0ef41Sopenharmony_ci if (s[pos] == ',') { 1301cb0ef41Sopenharmony_ci ++pos; 1311cb0ef41Sopenharmony_ci continue; 1321cb0ef41Sopenharmony_ci } 1331cb0ef41Sopenharmony_ci if ((qnt = base::VLQBase64Decode(s.c_str(), s.size(), &pos)) == 1341cb0ef41Sopenharmony_ci std::numeric_limits<int32_t>::min()) 1351cb0ef41Sopenharmony_ci return false; 1361cb0ef41Sopenharmony_ci gen_col += qnt; 1371cb0ef41Sopenharmony_ci if ((qnt = base::VLQBase64Decode(s.c_str(), s.size(), &pos)) == 1381cb0ef41Sopenharmony_ci std::numeric_limits<int32_t>::min()) 1391cb0ef41Sopenharmony_ci return false; 1401cb0ef41Sopenharmony_ci file_idx += qnt; 1411cb0ef41Sopenharmony_ci if ((qnt = base::VLQBase64Decode(s.c_str(), s.size(), &pos)) == 1421cb0ef41Sopenharmony_ci std::numeric_limits<int32_t>::min()) 1431cb0ef41Sopenharmony_ci return false; 1441cb0ef41Sopenharmony_ci ori_line += qnt; 1451cb0ef41Sopenharmony_ci // Column number in source file is always 0 in source map generated by 1461cb0ef41Sopenharmony_ci // Emscripten. We just decode this value without further usage of it. 1471cb0ef41Sopenharmony_ci if ((qnt = base::VLQBase64Decode(s.c_str(), s.size(), &pos)) == 1481cb0ef41Sopenharmony_ci std::numeric_limits<int32_t>::min()) 1491cb0ef41Sopenharmony_ci return false; 1501cb0ef41Sopenharmony_ci 1511cb0ef41Sopenharmony_ci if (pos < s.size() && s[pos] != ',') return false; 1521cb0ef41Sopenharmony_ci pos++; 1531cb0ef41Sopenharmony_ci 1541cb0ef41Sopenharmony_ci file_idxs.push_back(file_idx); 1551cb0ef41Sopenharmony_ci source_row.push_back(ori_line); 1561cb0ef41Sopenharmony_ci offsets.push_back(gen_col); 1571cb0ef41Sopenharmony_ci } 1581cb0ef41Sopenharmony_ci return true; 1591cb0ef41Sopenharmony_ci} 1601cb0ef41Sopenharmony_ci 1611cb0ef41Sopenharmony_ci} // namespace wasm 1621cb0ef41Sopenharmony_ci} // namespace internal 1631cb0ef41Sopenharmony_ci} // namespace v8 164