1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
|
// Copyright 2016 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.
// Flags: --expose-wasm
InspectorTest.log("Tests how wasm scripts are reported");
let contextGroup = new InspectorTest.ContextGroup();
let sessions = [
// Main session.
trackScripts(),
// Extra session to verify that all inspectors get same messages.
// See https://bugs.chromium.org/p/v8/issues/detail?id=9725.
trackScripts(),
];
utils.load('test/mjsunit/wasm/wasm-module-builder.js');
// Create module with given custom sections.
function createModule(...customSections) {
var builder = new WasmModuleBuilder();
builder.addFunction('nopFunction', kSig_v_v).addBody([kExprNop]);
builder.addFunction('main', kSig_v_v)
.addBody([kExprBlock, kWasmStmt, kExprI32Const, 2, kExprDrop, kExprEnd])
.exportAs('main');
for (var { name, value } of customSections) {
builder.addCustomSection(name, value);
}
return builder.toArray();
}
function testFunction(bytes) {
// Compilation triggers registration of wasm scripts.
new WebAssembly.Module(new Uint8Array(bytes));
}
// Generate stable IDs.
let scriptIds = {};
function nextStableId(id) {
if (!(id in scriptIds)) {
scriptIds[id] = Object.keys(scriptIds).length;
}
return scriptIds[id];
}
contextGroup.addScript(testFunction.toString(), 0, 0, 'v8://test/testFunction');
InspectorTest.log(
'Check that each inspector gets a wasm script at module creation time.');
// Sample .debug_info section.
// Content doesn't matter, as we don't try to parse it in V8,
// but should be non-empty to check that we're skipping it correctly.
const embeddedDWARFSection = {
name: '.debug_info',
value: [1, 2, 3, 4, 5]
};
// Sample external_debug_info section set to "abc".
const externalDWARFSection = {
name: '.external_debug_info',
value: [3, 97, 98, 99]
};
// Sample sourceMappingURL section set to "abc".
const sourceMapSection = {
name: 'sourceMappingURL',
value: [3, 97, 98, 99]
};
sessions[0]
.Protocol.Runtime
.evaluate({
'expression': `//# sourceURL=v8://test/runTestRunction
// no debug info
testFunction([${createModule()}]);
// shared script for identical modules
testFunction([${createModule()}]);
// External DWARF
testFunction([${createModule(externalDWARFSection)}]);
// Embedded DWARF
testFunction([${createModule(embeddedDWARFSection)}]);
// Source map
testFunction([${createModule(sourceMapSection)}]);
// SourceMap + External DWARF
testFunction([${createModule(sourceMapSection, externalDWARFSection)}]);
// External DWARF + SourceMap (different order)
testFunction([${createModule(externalDWARFSection, sourceMapSection)}]);
// Embedded DWARF + External DWARF
testFunction([${
createModule(embeddedDWARFSection, externalDWARFSection)}]);
// External + Embedded DWARF (different order)
testFunction([${
createModule(externalDWARFSection, embeddedDWARFSection)}]);
// Embedded DWARF + source map
testFunction([${createModule(embeddedDWARFSection, sourceMapSection)}]);
// Source map + Embedded DWARF (different order)
testFunction([${createModule(sourceMapSection, embeddedDWARFSection)}]);
`
})
.then(
() => (
// At this point all scripts were parsed.
// Stop tracking and wait for script sources in each session.
Promise.all(sessions.map(session => session.getScripts()))))
.catch(err => {
InspectorTest.log(err.stack);
})
.then(() => InspectorTest.completeTest());
function trackScripts(debuggerParams) {
let {id: sessionId, Protocol} = contextGroup.connect();
let scripts = [];
Protocol.Debugger.enable(debuggerParams);
Protocol.Debugger.onScriptParsed(handleScriptParsed);
async function loadScript({
url,
scriptId,
sourceMapURL,
startColumn,
endColumn,
codeOffset,
debugSymbols
}) {
let stableId = nextStableId(scriptId);
InspectorTest.log(`Session #${sessionId}: Script #${
scripts.length} parsed. URL: ${url}. Script ID: ${
stableId}, Source map URL: ${sourceMapURL}, debug symbols: ${
debugSymbols.type}:${debugSymbols.externalURL}. module begin: ${
startColumn}, module end: ${endColumn}, code offset: ${codeOffset}`);
let {result: {scriptSource, bytecode}} =
await Protocol.Debugger.getScriptSource({scriptId});
if (bytecode) {
if (scriptSource) {
InspectorTest.log('Unexpected scriptSource with bytecode: ');
InspectorTest.log(scriptSource);
}
// Binary value is represented as base64 in JSON, decode it.
bytecode = InspectorTest.decodeBase64(bytecode);
// Check that it can be parsed back to a WebAssembly module.
let module = new WebAssembly.Module(bytecode);
scriptSource =
`
Raw: ${Array.from(bytecode, b => ('0' + b.toString(16)).slice(-2)).join(' ')}
Imports: [${
WebAssembly.Module.imports(module)
.map(i => `${i.name}: ${i.kind} from "${i.module}"`)
.join(', ')}]
Exports: [${
WebAssembly.Module.exports(module)
.map(e => `${e.name}: ${e.kind}`)
.join(', ')}]
`.trim();
}
InspectorTest.log(`Session #${sessionId}: Source for ${url}:`);
InspectorTest.log(scriptSource);
}
function handleScriptParsed({params}) {
if (params.url.startsWith('wasm://')) {
scripts.push(loadScript(params));
}
}
return {
Protocol,
getScripts: () => Promise.all(scripts),
};
}
|