| <!DOCTYPE html> |
| <html> |
| <head> |
| <script src="../../http/tests/inspector/resources/inspector-test.js"></script> |
| <script src="resources/paused-scopes.js"></script> |
| <script> |
| function test() |
| { |
| function scopeTypeName(type) { |
| switch (type) { |
| case WI.ScopeChainNode.Type.Local: return "Local"; |
| case WI.ScopeChainNode.Type.Global: return "Global"; |
| case WI.ScopeChainNode.Type.GlobalLexicalEnvironment: return "GlobalLexicalEnvironment"; |
| case WI.ScopeChainNode.Type.With: return "With"; |
| case WI.ScopeChainNode.Type.Closure: return "Closure"; |
| case WI.ScopeChainNode.Type.Catch: return "Catch"; |
| case WI.ScopeChainNode.Type.FunctionName: return "FunctionName"; |
| case WI.ScopeChainNode.Type.Block: return "Block"; |
| default: return "Unknown!"; |
| }; |
| } |
| |
| function sanitizeHash(hash) { |
| return hash.replace(/:(.*?):/, ":<sourceID>:"); |
| } |
| |
| function collectScopeChainProperties(scopeChain) { |
| let scopeChainData = []; |
| |
| let promises = []; |
| for (let scope of scopeChain) { |
| let data = {scope, properties: []}; |
| scopeChainData.push(data); |
| if (scope.type === WI.ScopeChainNode.Type.Global) |
| continue; |
| |
| for (let scopeObject of scope.objects) { |
| promises.push(new Promise((resolve, reject) => { |
| scopeObject.getPropertyDescriptors((propertyDescriptors) => { |
| data.properties = data.properties.concat(propertyDescriptors); |
| resolve(); |
| }); |
| })); |
| } |
| } |
| |
| return Promise.all(promises) |
| .then(() => scopeChainData); |
| } |
| |
| function dumpScopeChainData(scopeChainData) { |
| for (let {scope, properties} of scopeChainData) { |
| InspectorTest.log(` SCOPE: Name (${scope.name}) - Type (${scopeTypeName(scope.type)}) - Hash (${sanitizeHash(scope.hash)})`); |
| for (let propertyDescriptor of properties) |
| InspectorTest.log(` - ${propertyDescriptor.name}`); |
| } |
| } |
| |
| function dumpCallFrame(callFrame) { |
| return Promise.all([ |
| collectScopeChainProperties(callFrame.scopeChain), |
| collectScopeChainProperties(callFrame.mergedScopeChain()), |
| ]).then((results) => { |
| let [scopeChainData, mergedScopeChainData] = results; |
| InspectorTest.log(`CALLFRAME: ${callFrame.functionName}`); |
| InspectorTest.log("\n---- Scope Chain ----"); |
| dumpScopeChainData(scopeChainData); |
| InspectorTest.log("\n---- Merged Scope Chain ----"); |
| dumpScopeChainData(mergedScopeChainData); |
| InspectorTest.log(""); |
| }); |
| } |
| |
| function dumpCallFrames() { |
| let targetData = WI.debuggerManager.dataForTarget(WI.debuggerManager.activeCallFrame.target); |
| let callFrames = targetData.callFrames; |
| let chain = Promise.resolve(); |
| for (let callFrame of callFrames) |
| chain = chain.then(() => dumpCallFrame(callFrame)); |
| return chain; |
| } |
| |
| |
| let suite = InspectorTest.createAsyncSuite("PausedCallFrameScope"); |
| |
| suite.addTestCase({ |
| name: "PausedCallFrameScope.TriggerFirstPause", |
| description: "Dump CallFrames and Scopes with the first pause.", |
| test(resolve, reject) { |
| InspectorTest.evaluateInPage("setTimeout(entry)"); |
| WI.debuggerManager.singleFireEventListener(WI.DebuggerManager.Event.Paused, (event) => { |
| dumpCallFrames().then(resolve, reject); |
| }); |
| } |
| }); |
| |
| suite.addTestCase({ |
| name: "PausedCallFrameScope.TriggerSecondPause", |
| description: "Dump CallFrames and Scopes with the second pause.", |
| test(resolve, reject) { |
| WI.debuggerManager.resume(); |
| WI.debuggerManager.singleFireEventListener(WI.DebuggerManager.Event.Paused, (event) => { |
| dumpCallFrames().then(resolve, reject); |
| }); |
| } |
| }); |
| |
| suite.addTestCase({ |
| name: "PausedCallFrameScope.TriggerThirdPause", |
| description: "Dump CallFrames and Scopes with the third pause.", |
| test(resolve, reject) { |
| WI.debuggerManager.resume(); |
| WI.debuggerManager.singleFireEventListener(WI.DebuggerManager.Event.Paused, (event) => { |
| dumpCallFrames().then(resolve, reject); |
| }); |
| } |
| }); |
| |
| suite.addTestCase({ |
| name: "PausedCallFrameScope.Complete", |
| test(resolve, reject) { |
| WI.debuggerManager.resume().then(resolve, reject); |
| } |
| }); |
| |
| suite.runTestCasesAndFinish(); |
| } |
| </script> |
| </head> |
| <body onload="runTest()"> |
| <p>Check scope chains for different call frames at different pauses.</p> |
| </body> |
| </html> |