blob: 78c26b314fdfa47e378ece69513990c3f249f9ab [file] [log] [blame]
<!doctype html>
<html>
<head>
<script src="../../http/tests/inspector/resources/inspector-test.js"></script>
<script src="resources/all-scopes.js"></script>
<script src="resources/function-name-scopes.js"></script>
<script src="resources/block-scopes.js"></script>
<script>
function test()
{
function firstLine(str) {
let newlineIndex = str.indexOf("\n");
if (newlineIndex !== -1)
return str.substr(0, newlineIndex);
return str;
}
function scopeTypeToString(type) {
for (let key in WI.ScopeChainNode.Type) {
if (WI.ScopeChainNode.Type[key] === type)
return key;
}
return "Unexpected Scope Type";
}
function harvestScopeChain(scopeChain) {
let promises = [];
for (let scope of scopeChain) {
promises.push(new Promise((resolve, reject) => {
if (scope.type === WI.ScopeChainNode.Type.Global)
resolve({scope, propertyDescriptors: []});
else {
scope.objects[0].getDisplayablePropertyDescriptors((propertyDescriptors) => {
resolve({scope, propertyDescriptors});
});
}
}));
}
return Promise.all(promises);
}
function logScopeChain(scopeChain) {
return harvestScopeChain(scopeChain)
.then((results) => {
InspectorTest.log("SCOPE CHAIN:");
for (let {scope, propertyDescriptors} of results) {
InspectorTest.log(` ${scopeTypeToString(scope.type)}`);
if (scope.type === WI.ScopeChainNode.Type.Global)
continue;
if (!propertyDescriptors.length) {
InspectorTest.assert(scope.empty, "Scope should be empty if there are no property descriptors.");
InspectorTest.log(" (empty)");
continue;
}
for (let descriptor of propertyDescriptors)
InspectorTest.log(` - ${descriptor.name}: ${firstLine(descriptor.value.description)}`);
}
return results;
});
}
let suite = InspectorTest.createAsyncSuite("WI.ScopeChainNode");
suite.addTestCase({
name: "WI.ScopeChainNode.AllTypes",
description: "Tests for each of the different scope chain node types.",
test(resolve, reject) {
WI.debuggerManager.awaitEvent(WI.DebuggerManager.Event.CallFramesDidChange)
.then((event) => {
let scopeChain = WI.debuggerManager.activeCallFrame.scopeChain;
InspectorTest.expectThat(scopeChain.length === 13, "ScopeChain should have 13 scopes.");
return logScopeChain(scopeChain);
})
.then((result) => {
let promise = WI.debuggerManager.awaitEvent(WI.DebuggerManager.Event.Resumed);
WI.debuggerManager.resume();
return promise;
})
.then(resolve, reject);
InspectorTest.evaluateInPage("setTimeout(testAllScopes)");
}
});
suite.addTestCase({
name: "WI.ScopeChainNode.FunctionNameInFunctionExpression",
description: "Tests that there should be a FunctionName scope inside a function expression.",
test(resolve, reject) {
WI.debuggerManager.awaitEvent(WI.DebuggerManager.Event.CallFramesDidChange)
.then((event) => {
let scopeChain = WI.debuggerManager.activeCallFrame.scopeChain;
return logScopeChain(scopeChain);
})
.then((result) => {
let promise = WI.debuggerManager.awaitEvent(WI.DebuggerManager.Event.Resumed);
WI.debuggerManager.resume();
return promise;
})
.then(resolve, reject);
InspectorTest.evaluateInPage("setTimeout(testFunctionNameScope1)");
}
});
suite.addTestCase({
name: "WI.ScopeChainNode.FunctionNameInClassMethod",
description: "Tests that there should be a FunctionName scope inside a class method.",
test(resolve, reject) {
WI.debuggerManager.awaitEvent(WI.DebuggerManager.Event.CallFramesDidChange)
.then((event) => {
let scopeChain = WI.debuggerManager.activeCallFrame.scopeChain;
return logScopeChain(scopeChain);
})
.then((result) => {
let promise = WI.debuggerManager.awaitEvent(WI.DebuggerManager.Event.Resumed);
WI.debuggerManager.resume();
return promise;
})
.then(resolve, reject);
InspectorTest.evaluateInPage("setTimeout(testFunctionNameScope2)");
}
});
suite.addTestCase({
name: "WI.ScopeChainNode.BlockScopes",
description: "Tests for a Block scope inside all the different types of blocks.",
test(resolve, reject) {
let pauseCount = 0;
let pauseEventsExpected = 19;
function callFramesDidChangeListener(event) {
if (!WI.debuggerManager.activeCallFrame)
return;
pauseCount++;
let scopeChain = WI.debuggerManager.activeCallFrame.scopeChain;
// First, normal function scope.
if (pauseCount === 1) {
InspectorTest.expectThat(scopeChain[0].type === WI.ScopeChainNode.Type.Closure, "Pause #1 - Top scope should be normal function Closure/Local scope.");
WI.debuggerManager.resume();
return;
}
// Last, normal function scope.
if (pauseCount === pauseEventsExpected) {
InspectorTest.expectThat(scopeChain[0].type === WI.ScopeChainNode.Type.Closure, `Pause #${pauseCount} - Top scope should be normal function Closure/Local scope.`);
WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.ActiveCallFrameDidChange, callFramesDidChangeListener);
WI.debuggerManager.resume();
resolve();
return;
}
// The first 15 cases the top scope should be a Block scope.
if (pauseCount <= 15) {
InspectorTest.expectThat(scopeChain[0].type === WI.ScopeChainNode.Type.Block, `Pause #${pauseCount} - Top scope should be Block scope.`);
WI.debuggerManager.resume();
return;
}
// Print out the full scope of the last few where there are nested or buried block scopes.
InspectorTest.expectThat(scopeChain.some((scopeChain) => scopeChain.type === WI.ScopeChainNode.Type.Block), `Pause #${pauseCount} - Contains a Block scope.`);
logScopeChain(scopeChain)
.then((result) => {
WI.debuggerManager.resume();
});
}
WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.ActiveCallFrameDidChange, callFramesDidChangeListener);
InspectorTest.evaluateInPage("setTimeout(testBlockScopes)");
}
});
suite.runTestCasesAndFinish();
}
</script>
</head>
<body onload="runTest()">
<p>Tests for the WI.ScopeChainNode model object.</p>
</body>
</html>