<html>
<head>
<script src="../../http/tests/inspector/resources/protocol-test.js"></script>
<script src="resources/breakpoint.js"></script>

<script>
// Put this here instead of on <body onload> to prevent an extra Debugger.scriptParsed event.
window.onload = runTest;

function test()
{
    // This test setting a breakpoints in DFG compiled functions callee and then modify
    // and examine a global and local via the DFG frame.

    InspectorProtocol.sendCommand("Debugger.enable", {});
    InspectorProtocol.sendCommand("Debugger.setBreakpointsActive", {active: true});

    var breakpointId = null;
    var scriptId = 0;
    var startLine = 0;

    InspectorProtocol.eventHandler["Debugger.scriptParsed"] = function(messageObject)
    {
        if (/resources\/breakpoint\.js$/.test(messageObject.params.url)) {
            ProtocolTest.log("Found breakpoint.js");
            scriptId = messageObject.params.scriptId;
            startLine = messageObject.params.startLine;

            InspectorProtocol.sendCommand("Runtime.evaluate", {
                expression: "dfgWithoutInline3();"
            }, function(responseObject) {
                ProtocolTest.log("dfg function warmed up\n");

                var location1 = {scriptId: scriptId, lineNumber: 2, columnNumber: 0};

                InspectorProtocol.sendCommand("Debugger.setBreakpoint", {location: location1}, function(responseObject) {
                    InspectorProtocol.checkForError(responseObject);
                    ProtocolTest.log("Breakpoint set in breakpointBasic()");

                    breakpointId = responseObject.result.breakpointId;
                    InspectorProtocol.sendCommand("Runtime.evaluate", {
                        expression: "dfgWithoutInline3();"
                    });
                });
            });
        }
    }

    InspectorProtocol.eventHandler["Debugger.paused"] = function(messageObject)
    {
        function dumpResponse(response)
        {
            try {
                if (response.result.wasThrown) {
                    ProtocolTest.log("Exception thrown processing request");
                    return false;
                }
                ProtocolTest.log("Response value is " + response.result.result.value);
                return true;
            } catch (e) {
                return false;
            }
        }

        function resumeFromBreakpoint()
        {
            InspectorProtocol.sendCommand("Debugger.resume", {}, function(responseObject) {
                ProtocolTest.log("Resumed from breakpoint");
            });
        }

        ProtocolTest.log("Hit Breakpoint!");
        var callFrames = messageObject.params.callFrames;
        if (callFrames.length < 3) {
            ProtocolTest.log("FAIL: too few frames in stack trace");
            resumeFromBreakpoint();
            return;
        }
        var callFrameId = callFrames[2].callFrameId;
        ProtocolTest.log("Evaluating in DFG frame at frame[2]: 'globalVal3 = 30;'");
        InspectorProtocol.sendCommand("Debugger.evaluateOnCallFrame", { callFrameId: callFrameId, expression: "globalVal3 = 30;" }, function(responseObject) {
            if (!dumpResponse(responseObject)) {
                resumeFromBreakpoint();
                return;
            }
            ProtocolTest.log("Evaluating in DFG frame at frame[2]: 'localVal3 = 12;'");
            InspectorProtocol.sendCommand("Debugger.evaluateOnCallFrame", { callFrameId: callFrameId, expression: "localVal3 = 12;" }, function(responseObject) {
                if (!dumpResponse(responseObject)) {
                    resumeFromBreakpoint();
                    return;
                }
                ProtocolTest.log("Evaluating in DFG frame at frame[2]: 'localVal3'");
                InspectorProtocol.sendCommand("Debugger.evaluateOnCallFrame", { callFrameId: callFrameId, expression: "localVal3" }, function(responseObject) {
                    if (!dumpResponse(responseObject)) {
                        resumeFromBreakpoint();
                        return;
                    }
                    InspectorProtocol.awaitEvent({event: "Debugger.resumed"}).then(() => {
                        ProtocolTest.log("Resumed from breakpoint");
                        ProtocolTest.log("Test complete");
                        ProtocolTest.completeTest();
                    });
                    InspectorProtocol.sendCommand("Debugger.resume");
                });
            });
        });
    }
}
</script>
</head>
<body>
<p>Debugger.evaluateOnCallFrame in a DFG compiled function from a breakpoint in a non-DFG callee.</p>
</body>
</html>
