blob: c80eb018e6c0817153e5b6421cf8bc56403c1338 [file] [log] [blame]
<!DOCTYPE html>
<html>
<head>
<script src="../../http/tests/inspector/resources/inspector-test.js"></script>
<script>
var varGlobalVariable = 1;
let letGlobalVariable = 2;
const constGlobalVariable = 3;
function foo(a, b) {
var c = a + b + arguments[2];
var keys = 123;
bar(c, keys, -129);
}
function bar(a, b) {
"use strict";
let c = b + a + arguments[2];
debugger;
return c;
}
function triggerPause() {
foo.call("my-this-object", 1, 2, 3);
}
function test()
{
const objectGroup = "test";
const includeCommandLineAPI = true;
const returnByValue = true;
function testEvaluateOnCallFrame(callFrame, expression, callback) {
let callFrameId = callFrame.id;
DebuggerAgent.evaluateOnCallFrame.invoke({callFrameId, expression, objectGroup, includeCommandLineAPI, returnByValue}, (error, resultValue, wasThrown) => {
InspectorTest.assert(!error, "Should not be a protocol error.");
InspectorTest.assert(!wasThrown, "Should not be a runtime error.");
if (callback)
callback(resultValue.value);
});
}
function testEvaluateOnCallFrameThrows(callFrame, expression, callback) {
let callFrameId = callFrame.id;
DebuggerAgent.evaluateOnCallFrame.invoke({callFrameId, expression, objectGroup, includeCommandLineAPI, returnByValue}, (error, resultValue, wasThrown) => {
InspectorTest.assert(!error, "Should not be a protocol error.");
InspectorTest.assert(wasThrown, "Should be a runtime error.");
if (callback)
callback(wasThrown);
});
}
function testEvaluateOnStrictCallFrame(expression, callback) {
let callFrame = WI.debuggerManager.activeCallFrame; // bar
testEvaluateOnCallFrame(callFrame, expression, callback);
}
function testEvaluateOnStrictCallFrameThrows(expression, callback) {
let callFrame = WI.debuggerManager.activeCallFrame; // bar
testEvaluateOnCallFrameThrows(callFrame, expression, callback);
}
function testEvaluateOnNonStrictCallFrame(expression, callback) {
let targetData = WI.debuggerManager.dataForTarget(WI.debuggerManager.activeCallFrame.target);
let callFrame = targetData.callFrames[1]; // foo
testEvaluateOnCallFrame(callFrame, expression, callback);
}
function testEvaluateOnNonStrictCallFrameThrows(expression, callback) {
let targetData = WI.debuggerManager.dataForTarget(WI.debuggerManager.activeCallFrame.target);
let callFrame = targetData.callFrames[1]; // foo
testEvaluateOnCallFrameThrows(callFrame, expression, callback);
}
let suite = InspectorTest.createAsyncSuite("Debugger.evaluateOnCallFrame.CommandLineAPI");
suite.addTestCase({
name: "ValidateCallFrames",
description: "Test evaluate can access CommandLineAPI methods.",
test(resolve, reject) {
let targetData = WI.debuggerManager.dataForTarget(WI.debuggerManager.activeCallFrame.target);
InspectorTest.expectThat(WI.debuggerManager.activeCallFrame.functionName === "bar", "Strict call frame is `bar`.");
InspectorTest.expectThat(targetData.callFrames[1].functionName === "foo", "Non-strict call frame is `foo`.");
testEvaluateOnStrictCallFrame("a", (x) => { InspectorTest.expectThat(x === 6, "`a` should be 5 in `bar`."); });
testEvaluateOnStrictCallFrame("b", (x) => { InspectorTest.expectThat(x === 123, "`b` should be 123 in `bar`."); });
testEvaluateOnStrictCallFrame("c", (x) => { InspectorTest.expectThat(x === 0, "`c` should be 0 in `bar`."); });
testEvaluateOnStrictCallFrame("this", (x) => { InspectorTest.expectThat(x === undefined, "`this` should be undefined in `bar`."); });
testEvaluateOnNonStrictCallFrame("a", (x) => { InspectorTest.expectThat(x === 1, "`a` should be 1 in `foo`."); });
testEvaluateOnNonStrictCallFrame("b", (x) => { InspectorTest.expectThat(x === 2, "`b` should be 2 in `foo`."); });
testEvaluateOnNonStrictCallFrame("c", (x) => { InspectorTest.expectThat(x === 6, "`c` should be 6 in `foo`."); });
testEvaluateOnNonStrictCallFrame("this.toString()", (x) => { InspectorTest.expectThat(x === "my-this-object", "`this` should be 'my-this-object' in `foo`."); resolve(); });
}
});
suite.addTestCase({
name: "AccessCommandLineAPI",
description: "Test evaluate can access CommandLineAPI methods.",
test(resolve, reject) {
testEvaluateOnStrictCallFrame("keys.toString()", (resultValue) => {
InspectorTest.expectThat(resultValue.includes("[Command Line API]"), "CommandLineAPI `keys` can be accessed in the `bar` strict call frame.");
});
testEvaluateOnNonStrictCallFrame("dir.toString()", (resultValue) => {
InspectorTest.expectThat(resultValue.includes("[Command Line API]"), "CommandLineAPI `keys` can be accessed in the `foo` non-strict call frame.");
});
testEvaluateOnStrictCallFrame("keys({a:1, b:2})", (resultValue) => {
InspectorTest.expectThat(resultValue.length === 2 && resultValue[0] === "a" && resultValue[1] === "b", "CommandLineAPI `keys` should work with a simple object.");
resolve();
});
}
});
suite.addTestCase({
name: "AccessGlobalVariable",
description: "Test evaluate can access global variables.",
test(resolve, reject) {
testEvaluateOnStrictCallFrame("varGlobalVariable", (x) => { InspectorTest.expectThat(x === 1, "Should be able to access var in global scope in strict call frame."); });
testEvaluateOnStrictCallFrame("letGlobalVariable", (x) => { InspectorTest.expectThat(x === 2, "Should be able to access let in global scope in strict call frame."); });
testEvaluateOnStrictCallFrame("constGlobalVariable", (x) => { InspectorTest.expectThat(x === 3, "Should be able to access const in global scope in strict call frame."); });
testEvaluateOnNonStrictCallFrame("varGlobalVariable", (x) => { InspectorTest.expectThat(x === 1, "Should be able to access var in global scope in non-strict call frame."); });
testEvaluateOnNonStrictCallFrame("letGlobalVariable", (x) => { InspectorTest.expectThat(x === 2, "Should be able to access let in global scope in non-strict call frame."); });
testEvaluateOnNonStrictCallFrame("constGlobalVariable", (x) => { InspectorTest.expectThat(x === 3, "Should be able to access const in global scope in non-strict call frame."); resolve(); });
}
});
suite.addTestCase({
name: "NoVariablesCreatedOnCallFrame",
description: "Test evaluate may not create new local variables.",
test(resolve, reject) {
testEvaluateOnStrictCallFrame(`
var createdVarLocalVariable = 1;
let createdLetLocalVariable = 2;
const createdConstLocalVariable = 3;
`);
testEvaluateOnStrictCallFrameThrows("createdVarLocalVariable", (wasThrown) => { InspectorTest.expectThat(wasThrown, "Should not be able to access local var created in earlier eval on strict call frame."); });
testEvaluateOnStrictCallFrameThrows("createdLetLocalVariable", (wasThrown) => { InspectorTest.expectThat(wasThrown, "Should not be able to access local let created in earlier eval on strict call frame."); });
testEvaluateOnStrictCallFrameThrows("createdConstLocalVariable", (wasThrown) => { InspectorTest.expectThat(wasThrown, "Should not be able to access local const created in earlier eval on strict call frame."); });
testEvaluateOnNonStrictCallFrame(`
var createdVarLocalVariable = 1;
let createdLetLocalVariable = 2;
const createdConstLocalVariable = 3;
`);
testEvaluateOnNonStrictCallFrame("createdVarLocalVariable", (resultValue) => { InspectorTest.expectThat(resultValue === 1, "Should be able to access local var created in earlier eval on non-strict call frame."); });
testEvaluateOnNonStrictCallFrameThrows("createdLetLocalVariable", (wasThrown) => { InspectorTest.expectThat(wasThrown, "Should not be able to access local let created in earlier eval on non-strict call frame."); });
testEvaluateOnNonStrictCallFrameThrows("createdConstLocalVariable", (wasThrown) => { InspectorTest.expectThat(wasThrown, "Should not be able to access local const created in earlier eval on non-strict call frame."); resolve(); });
}
});
suite.addTestCase({
name: "NonStrictAndStrictEvaluations",
description: "Test evaluate can run strict and non-strict programs.",
test(resolve, reject) {
// Non strict, this is okay.
testEvaluateOnNonStrictCallFrame("arguments.callee.name", (resultValue) => {
InspectorTest.expectThat(resultValue === "foo", "Non-strict evaluation. Should be able to access arguments.callee.");
});
// Strict, this throw an exception.
testEvaluateOnStrictCallFrameThrows("arguments.callee.name", (wasThrown) => {
InspectorTest.expectThat(wasThrown, "Strict evaluation. Should not be able to access arguments.callee.");
resolve();
});
}
});
suite.addTestCase({
name: "CommandLineAPIDoesNotShadowLocalVariables",
description: "Test CommandLineAPI does not shadow local variables.",
test(resolve, reject) {
testEvaluateOnNonStrictCallFrame("keys", (resultValue) => {
InspectorTest.expectThat(resultValue === 123, "Local variable `keys` should not be shadowed by CommandLineAPI `keys` function in call frame for `foo`.");
resolve();
});
}
});
suite.addTestCase({
name: "CommandLineAPIDoesNotShadowGlobalVariables",
description: "Test CommandLineAPI does not shadow global variables.",
test(resolve, reject) {
testEvaluateOnStrictCallFrame("keys.toString()", (resultValue) => {
InspectorTest.expectThat(resultValue.includes("[Command Line API]"), "CommandLineAPI `keys` can be accessed in the `bar` strict call frame.");
});
testEvaluateOnStrictCallFrame("window.keys = 999", (resultValue) => {
InspectorTest.expectThat(resultValue === 999, "Global assignment to `keys` should be okay.");
});
testEvaluateOnStrictCallFrame("keys", (resultValue) => {
InspectorTest.expectThat(resultValue === 999, "Global variable `keys` should not be shadowed by CommandLineAPI `keys` function in call frame for `bar`.");
});
testEvaluateOnStrictCallFrame("delete window.keys");
testEvaluateOnStrictCallFrame("keys.toString()", (resultValue) => {
InspectorTest.expectThat(resultValue.includes("[Command Line API]"), "CommandLineAPI `keys` can be accessed in the `bar` strict call frame after deleting global variable `keys`.");
resolve();
});
}
});
suite.addTestCase({
name: "CommandLineAPIDoesNotShadowGlobalObjectProperties",
description: "Test CommandLineAPI does not shadow global object properties.",
test(resolve, reject) {
testEvaluateOnStrictCallFrame("values.toString()", (resultValue) => {
InspectorTest.expectThat(resultValue === "[object HTMLDivElement]", "`values` should be `window.values` and not shadowed by CommandLineAPI `values` function in strict call frame.");
});
testEvaluateOnNonStrictCallFrame("values.toString()", (resultValue) => {
InspectorTest.expectThat(resultValue === "[object HTMLDivElement]", "`values` should be `window.values` and not shadowed by CommandLineAPI `values` function in non-strict call frame.");
resolve();
});
}
});
suite.addTestCase({
name: "Complete",
test(resolve, reject) {
WI.debuggerManager.resume();
resolve();
}
})
InspectorTest.evaluateInPage("triggerPause()");
WI.debuggerManager.singleFireEventListener(WI.DebuggerManager.Event.Paused, (event) => {
suite.runTestCasesAndFinish();
});
}
</script>
</head>
<body onload="runTest()">
<div id="values"></div> <!-- This introduces the named property `window.values` on the window global object. -->
<p>Tests for the Debugger.evaluateOnCallFrame with the Command Line API.</p>
</body>
</html>