v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
wasm-module-sourcemap.cc
Go to the documentation of this file.
1// Copyright 2019 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
7#include <algorithm>
8
10#include "include/v8-json.h"
12#include "include/v8-object.h"
14#include "src/base/vlq-base64.h"
16
17namespace v8 {
18
19class String;
20
21namespace internal {
22namespace wasm {
23
25 v8::Local<v8::String> src_map_str) {
26 v8::HandleScope scope(v8_isolate);
27 v8::Local<v8::Context> context = v8::Context::New(v8_isolate);
28
29 v8::Local<v8::Value> src_map_value;
30 if (!v8::JSON::Parse(context, src_map_str).ToLocal(&src_map_value)) return;
31 v8::Local<v8::Object> src_map_obj =
32 v8::Local<v8::Object>::Cast(src_map_value);
33
34 v8::Local<v8::Value> version_value, sources_value, mappings_value;
35 bool has_valid_version =
36 src_map_obj
37 ->Get(context, v8::String::NewFromUtf8Literal(v8_isolate, "version"))
38 .ToLocal(&version_value) &&
39 version_value->IsUint32();
40 uint32_t version = 0;
41 if (!has_valid_version || !version_value->Uint32Value(context).To(&version) ||
42 version != 3u)
43 return;
44
45 bool has_valid_sources =
46 src_map_obj
47 ->Get(context, v8::String::NewFromUtf8Literal(v8_isolate, "sources"))
48 .ToLocal(&sources_value) &&
49 sources_value->IsArray();
50 if (!has_valid_sources) return;
51
52 v8::Local<v8::Object> sources_arr =
53 v8::Local<v8::Object>::Cast(sources_value);
54 v8::Local<v8::Value> sources_len_value;
55 if (!sources_arr
56 ->Get(context, v8::String::NewFromUtf8Literal(v8_isolate, "length"))
57 .ToLocal(&sources_len_value))
58 return;
59 uint32_t sources_len = 0;
60 if (!sources_len_value->Uint32Value(context).To(&sources_len)) return;
61
62 for (uint32_t i = 0; i < sources_len; ++i) {
63 v8::Local<v8::Value> file_name_value;
64 if (!sources_arr->Get(context, i).ToLocal(&file_name_value) ||
65 !file_name_value->IsString())
66 return;
67 v8::Local<v8::String> file_name =
68 v8::Local<v8::String>::Cast(file_name_value);
69 size_t file_name_sz = file_name->Utf8LengthV2(v8_isolate) + 1;
70 std::unique_ptr<char[]> file_name_buf(new char[file_name_sz]);
71 file_name->WriteUtf8V2(v8_isolate, file_name_buf.get(), file_name_sz,
73 filenames.emplace_back(file_name_buf.get());
74 }
75
76 bool has_valid_mappings =
77 src_map_obj
78 ->Get(context, v8::String::NewFromUtf8Literal(v8_isolate, "mappings"))
79 .ToLocal(&mappings_value) &&
80 mappings_value->IsString();
81 if (!has_valid_mappings) return;
82
83 v8::Local<v8::String> mappings = v8::Local<v8::String>::Cast(mappings_value);
84 size_t mappings_sz = mappings->Utf8LengthV2(v8_isolate) + 1;
85 std::unique_ptr<char[]> mappings_buf(new char[mappings_sz]);
86 mappings->WriteUtf8V2(v8_isolate, mappings_buf.get(), mappings_sz,
88
89 valid_ = DecodeMapping(mappings_buf.get());
90}
91
92size_t WasmModuleSourceMap::GetSourceLine(size_t wasm_offset) const {
93 std::vector<std::size_t>::const_iterator up =
94 std::upper_bound(offsets.begin(), offsets.end(), wasm_offset);
95 CHECK_NE(offsets.begin(), up);
96 size_t source_idx = up - offsets.begin() - 1;
97 return source_row[source_idx];
98}
99
100std::string WasmModuleSourceMap::GetFilename(size_t wasm_offset) const {
101 std::vector<size_t>::const_iterator up =
102 std::upper_bound(offsets.begin(), offsets.end(), wasm_offset);
103 CHECK_NE(offsets.begin(), up);
104 size_t offset_idx = up - offsets.begin() - 1;
105 size_t filename_idx = file_idxs[offset_idx];
106 return filenames[filename_idx];
107}
108
109bool WasmModuleSourceMap::HasSource(size_t start, size_t end) const {
110 return start <= *(offsets.end() - 1) && end > *offsets.begin();
111}
112
113bool WasmModuleSourceMap::HasValidEntry(size_t start, size_t addr) const {
114 std::vector<size_t>::const_iterator up =
115 std::upper_bound(offsets.begin(), offsets.end(), addr);
116 if (up == offsets.begin()) return false;
117 size_t offset_idx = up - offsets.begin() - 1;
118 size_t entry_offset = offsets[offset_idx];
119 if (entry_offset < start) return false;
120 return true;
121}
122
123bool WasmModuleSourceMap::DecodeMapping(const std::string& s) {
124 size_t pos = 0, gen_col = 0, file_idx = 0, ori_line = 0;
125 int32_t qnt = 0;
126
127 while (pos < s.size()) {
128 // Skip redundant commas.
129 if (s[pos] == ',') {
130 ++pos;
131 continue;
132 }
133 if ((qnt = base::VLQBase64Decode(s.c_str(), s.size(), &pos)) ==
134 std::numeric_limits<int32_t>::min())
135 return false;
136 gen_col += qnt;
137 if ((qnt = base::VLQBase64Decode(s.c_str(), s.size(), &pos)) ==
138 std::numeric_limits<int32_t>::min())
139 return false;
140 file_idx += qnt;
141 if ((qnt = base::VLQBase64Decode(s.c_str(), s.size(), &pos)) ==
142 std::numeric_limits<int32_t>::min())
143 return false;
144 ori_line += qnt;
145 // Column number in source file is always 0 in source map generated by
146 // Emscripten. We just decode this value without further usage of it.
147 if ((qnt = base::VLQBase64Decode(s.c_str(), s.size(), &pos)) ==
148 std::numeric_limits<int32_t>::min())
149 return false;
150
151 if (pos < s.size() && s[pos] != ',') return false;
152 pos++;
153
154 file_idxs.push_back(file_idx);
155 source_row.push_back(ori_line);
156 offsets.push_back(gen_col);
157 }
158 return true;
159}
160
163 size_t result = sizeof(WasmModuleSourceMap);
166 for (const std::string& s : filenames) {
167 result += s.length();
168 }
171 return result;
172}
173
174} // namespace wasm
175} // namespace internal
176} // namespace v8
SourcePosition pos
static Local< Context > New(Isolate *isolate, ExtensionConfiguration *extensions=nullptr, MaybeLocal< ObjectTemplate > global_template=MaybeLocal< ObjectTemplate >(), MaybeLocal< Value > global_object=MaybeLocal< Value >(), DeserializeInternalFieldsCallback internal_fields_deserializer=DeserializeInternalFieldsCallback(), MicrotaskQueue *microtask_queue=nullptr, DeserializeContextDataCallback context_data_deserializer=DeserializeContextDataCallback(), DeserializeAPIWrapperCallback api_wrapper_deserializer=DeserializeAPIWrapperCallback())
Definition api.cc:6778
static V8_WARN_UNUSED_RESULT MaybeLocal< Value > Parse(Local< Context > context, Local< String > json_string)
Definition api.cc:3172
static V8_INLINE Local< T > Cast(Local< S > that)
static V8_WARN_UNUSED_RESULT Local< String > NewFromUtf8Literal(Isolate *isolate, const char(&literal)[N], NewStringType type=NewStringType::kNormal)
size_t GetSourceLine(size_t wasm_offset) const
bool HasValidEntry(size_t start, size_t addr) const
bool HasSource(size_t start, size_t end) const
WasmModuleSourceMap(v8::Isolate *v8_isolate, v8::Local< v8::String > src_map_str)
std::string GetFilename(size_t wasm_offset) const
int start
int end
ZoneVector< RpoNumber > & result
int32_t VLQBase64Decode(const char *start, size_t sz, size_t *pos)
Definition vlq-base64.cc:37
size_t ContentSize(const std::vector< T > &vector)
WireBytesRef Get(const NameMap &map, uint32_t index)
v8_inspector::String16 String
Definition string-util.h:26
bool ToLocal(v8::internal::MaybeDirectHandle< v8::internal::Object > maybe, Local< T > *local)
Definition api.h:303
Definition c-api.cc:87
#define CHECK_NE(lhs, rhs)
#define UPDATE_WHEN_CLASS_CHANGES(classname, size)