blob: 1569b27a2a63c4b8337d8e351a2c95000b30dc64 [file] [edit]
<!DOCTYPE html>
<html>
<head>
<script src="../../http/tests/inspector/resources/protocol-test.js"></script>
<script>
let sharedNativeModule;
let sharedNativeInstances = [];
function createSharedNativeModule()
{
return new WebAssembly.Module(new Uint8Array([
0, 97, 115, 109, 1, 0, 0, 0,
1, 6, 1, 96, 1, 127, 1, 127,
3, 3, 2, 0, 0,
7, 18, 2, 5, 102, 105, 114, 115, 116, 0, 0, 6, 115, 101, 99, 111, 110, 100, 0, 1,
10, 17, 2, 7, 0, 32, 0, 65, 1, 106, 11, 7, 0, 32, 0, 65, 2, 106, 11,
]));
}
function prepareSharedNativeFunctions()
{
sharedNativeModule = createSharedNativeModule();
sharedNativeInstances = [
new WebAssembly.Instance(sharedNativeModule),
new WebAssembly.Instance(sharedNativeModule),
];
return document.getElementById("native-result").textContent;
}
function runSharedNativeFunctions()
{
let values = [];
for (let index = 0; index < sharedNativeInstances.length; ++index) {
let {first, second} = sharedNativeInstances[index].exports;
values.push(first((index + 1) * 10), second((index + 1) * 10));
}
document.getElementById("native-result").textContent = values.join(", ");
return JSON.stringify(values);
}
function test()
{
let suite = ProtocolTest.createAsyncSuite("Debugger.SymbolicBreakpoint.SharedNativeCode");
async function evaluate(expression)
{
let response = await InspectorProtocol.awaitCommand({
method: "Runtime.evaluate",
params: {expression, returnByValue: true},
});
ProtocolTest.assert(!response.wasThrown, "The real page operation should not throw.");
return response.result.value;
}
function addBreakpoint(symbol)
{
return InspectorProtocol.awaitCommand({
method: "Debugger.addSymbolicBreakpoint",
params: {symbol, isRegex: true},
});
}
function removeBreakpoint(symbol)
{
return InspectorProtocol.awaitCommand({
method: "Debugger.removeSymbolicBreakpoint",
params: {symbol, isRegex: true},
});
}
suite.addTestCase({
name: "Debugger.SymbolicBreakpoint.SharedNativeCode.Prepare",
async test() {
await InspectorProtocol.awaitCommand({method: "Runtime.enable"});
await InspectorProtocol.awaitCommand({method: "Debugger.enable"});
await InspectorProtocol.awaitCommand({method: "Debugger.setBreakpointsActive", params: {active: false}});
ProtocolTest.expectEqual(await evaluate("prepareSharedNativeFunctions()"), "Ready", "The actual page should compile both exports and materialize a DOM native method.");
ProtocolTest.expectEqual(await evaluate("runSharedNativeFunctions()"), "[11,12,21,22]", "Both real instances should return their own export results.");
},
});
suite.addTestCase({
name: "Debugger.SymbolicBreakpoint.SharedNativeCode.Install",
async test() {
await addBreakpoint(".*");
ProtocolTest.expectEqual(await evaluate("runSharedNativeFunctions()"), "[11,12,21,22]", "A broad native hook should preserve both shared instances.");
ProtocolTest.expectEqual(await evaluate("document.getElementById('native-result').textContent"), "11, 12, 21, 22", "The hooked DOM native method should still read the actual page output.");
},
});
suite.addTestCase({
name: "Debugger.SymbolicBreakpoint.SharedNativeCode.NewExports",
async test() {
await evaluate("sharedNativeInstances.push(new WebAssembly.Instance(sharedNativeModule), new WebAssembly.Instance(createSharedNativeModule())); GCController.collect()");
ProtocolTest.expectEqual(await evaluate("runSharedNativeFunctions()"), "[11,12,21,22,31,32,41,42]", "Exports created while hooks are active should retain correct code through collection.");
},
});
suite.addTestCase({
name: "Debugger.SymbolicBreakpoint.SharedNativeCode.OverlappingOwners",
async test() {
await addBreakpoint(".+");
await removeBreakpoint(".*");
ProtocolTest.expectEqual(await evaluate("runSharedNativeFunctions()"), "[11,12,21,22,31,32,41,42]", "Removing one symbolic owner should preserve the other owner's native hooks.");
},
});
suite.addTestCase({
name: "Debugger.SymbolicBreakpoint.SharedNativeCode.Restore",
async test() {
await removeBreakpoint(".+");
ProtocolTest.expectEqual(await evaluate("runSharedNativeFunctions()"), "[11,12,21,22,31,32,41,42]", "Removing all hooks should restore every real export.");
ProtocolTest.expectEqual(await evaluate("document.getElementById('native-result').textContent"), "11, 12, 21, 22, 31, 32, 41, 42", "Restoring native code should preserve DOM method behavior.");
},
});
suite.addTestCase({
name: "Debugger.SymbolicBreakpoint.SharedNativeCode.Repeat",
async test() {
for (let index = 0; index < 3; ++index) {
await addBreakpoint(".*");
await evaluate("runSharedNativeFunctions()");
await removeBreakpoint(".*");
}
ProtocolTest.expectEqual(await evaluate("runSharedNativeFunctions()"), "[11,12,21,22,31,32,41,42]", "Repeated native hook installation should leave no stale entry points.");
await InspectorProtocol.awaitCommand({method: "Debugger.setBreakpointsActive", params: {active: true}});
await InspectorProtocol.awaitCommand({method: "Debugger.disable"});
await evaluate("GCController.collect()");
ProtocolTest.expectEqual(await evaluate("runSharedNativeFunctions()"), "[11,12,21,22,31,32,41,42]", "Disabling the debugger should leave every shared export executable after collection.");
await evaluate("document.getElementById('native-result').remove()");
},
});
suite.runTestCasesAndFinish();
}
</script>
</head>
<body onload="runTest()">
<p>Tests symbolic breakpoint hooks on real exports that share native JIT code.</p>
<output id="native-result">Ready</output>
</body>
</html>