Diff
Modified: trunk/LayoutTests/ChangeLog (194250 => 194251)
--- trunk/LayoutTests/ChangeLog 2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/LayoutTests/ChangeLog 2015-12-18 01:09:13 UTC (rev 194251)
@@ -1,3 +1,28 @@
+2015-12-17 Joseph Pecoraro <[email protected]>
+
+ Provide a way to distinguish a nested lexical block from a function's lexical block
+ https://bugs.webkit.org/show_bug.cgi?id=152361
+
+ Reviewed by Saam Barati.
+
+ * inspector/debugger/breakpoint-scope-expected.txt:
+ We will soon remove the backend sending a "Local" scope.
+ The backend was just marking the first closure scope as local.
+ The frontend can do this itself and do a better job of it.
+
+ * inspector/model/resources/all-scopes.js: Added.
+ (testAllScopes.innerScope):
+ (testAllScopes):
+ * inspector/model/resources/block-scopes.js: Added.
+ (testBlockScopes):
+ (testBlockScopes.method):
+ * inspector/model/resources/function-name-scopes.js: Added.
+ (testFunctionNameScope1):
+ * inspector/model/scope-chain-node-expected.txt: Added.
+ * inspector/model/scope-chain-node.html: Added.
+ Tests for ways to get all the different scope types and
+ specific cases of certain scope types.
+
2015-12-17 Keith Miller <[email protected]>
[ES6] Add support for Symbol.hasInstance
Modified: trunk/LayoutTests/inspector/debugger/breakpoint-scope-expected.txt (194250 => 194251)
--- trunk/LayoutTests/inspector/debugger/breakpoint-scope-expected.txt 2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/LayoutTests/inspector/debugger/breakpoint-scope-expected.txt 2015-12-18 01:09:13 UTC (rev 194251)
@@ -3,12 +3,12 @@
Starting Test
Hit breakpoint at line: 4, column: 8
-scope-chain-type-local properties:
+scope-chain-type-closure properties:
resolve
reject
scope-chain-type-closure properties:
p
-scope-chain-type-globalLexicalEnvironment properties:
+scope-chain-type-global-lexical-environment properties:
lexicalVariable
scope-chain-type-global (properties not listed)
Tests done
Added: trunk/LayoutTests/inspector/model/resources/all-scopes.js (0 => 194251)
--- trunk/LayoutTests/inspector/model/resources/all-scopes.js (rev 0)
+++ trunk/LayoutTests/inspector/model/resources/all-scopes.js 2015-12-18 01:09:13 UTC (rev 194251)
@@ -0,0 +1,55 @@
+// Global
+var globalVariable = 1;
+
+// GlobalLexicalEnvironment
+let lexicalGlobalVariable = 2;
+
+function testAllScopes() {
+ // Closure
+ var closureVariable1 = 3;
+ let closureVariable2 = 4;
+
+ function innerScope() {
+ // Closure
+ var innerClosureVariable1 = 5;
+ let innerClosureVariable2 = 6;
+
+ // With (the object)
+ with ({withObjectProperty: 7, __proto__: null}) {
+ // Block
+ let withBlockVariable = 8;
+
+ // Catch (the `e` object)
+ try {
+ throw 9;
+ } catch (exceptionVariable) {
+ // Block
+ let catchBlockVariable = 10;
+
+ // Function Name
+ (function functionName() {
+
+ // Closure ("Local")
+ var localVariable1 = 11;
+ let localVariable2 = 12;
+
+ console.log("Variables",
+ globalVariable,
+ lexicalGlobalVariable,
+ closureVariable1, closureVariable2,
+ innerClosureVariable1, innerClosureVariable2,
+ withBlockVariable,
+ exceptionVariable,
+ catchBlockVariable,
+ functionName.name,
+ localVariable1, localVariable2);
+
+ // Pause.
+ debugger;
+ })();
+ }
+ }
+ }
+
+ innerScope();
+}
Added: trunk/LayoutTests/inspector/model/resources/block-scopes.js (0 => 194251)
--- trunk/LayoutTests/inspector/model/resources/block-scopes.js (rev 0)
+++ trunk/LayoutTests/inspector/model/resources/block-scopes.js 2015-12-18 01:09:13 UTC (rev 194251)
@@ -0,0 +1,147 @@
+function testBlockScopes() {
+ // Normal (not Block)
+ let a = 1;
+ console.log("normal", a);
+ debugger; // 1
+
+ // If
+ if (true) {
+ let a = 990;
+ console.log("if", a);
+ debugger; // 2
+ }
+
+ // Else
+ if (false) {}
+ else {
+ let a = 991;
+ console.log("else", a);
+ debugger; // 3
+ }
+
+ // While
+ while (true) {
+ let a = 992;
+ console.log("while", a);
+ debugger; // 4
+ break;
+ }
+
+ // Do/While
+ do {
+ let a = 993;
+ console.log("do", a);
+ debugger; // 5
+ } while (false);
+
+ // For
+ for (let a = 994; true; ++a) {
+ console.log("for", a);
+ debugger; // 6
+ break;
+ }
+
+ // ForIn
+ for (let a in ({"995":1})) {
+ console.log("for-in", a);
+ debugger; // 7
+ break;
+ }
+
+ // ForOf
+ for (let a of [996]) {
+ console.log("for-of", a);
+ debugger; // 8
+ break;
+ }
+
+ // Switch
+ switch ("test") {
+ case "test":
+ let a = 997;
+ console.log("case", a);
+ debugger; // 9
+ // fallthrough
+ default:
+ a += 0.5;
+ console.log("default", a);
+ debugger; // 10
+ break;
+ }
+
+ // Try
+ try {
+ let a = 998;
+ console.log("try", a);
+ debugger; // 11
+ } catch (e) {}
+
+ // Catch
+ try {
+ throw "Error";
+ } catch (e) {
+ let a = 999;
+ console.log("catch", a);
+ debugger; // 12
+ }
+
+ // Finally
+ try {}
+ finally {
+ let a = 1000;
+ console.log("finally", a);
+ debugger; // 13
+ }
+
+ // Anonymous block.
+ {
+ let a = 1001;
+ console.log("block", a);
+ debugger; // 14
+ }
+
+ // With block.
+ with ({something:true,__proto__:null}) {
+ let a = 1002;
+ console.log("with", a);
+ debugger; // 15
+ }
+
+ // Nested blocks.
+ {
+ let a = 1003;
+ {
+ let a = 1004;
+ {
+ let a = 1005;
+ {
+ let a = 1006;
+ console.log("nested blocks", a);
+ debugger; // 16
+ }
+ }
+ }
+ }
+
+ // Class (method)
+ (new (class MyClass {
+ method() {
+ // Block Variable scope containing the Class identifier `MyClass`.
+ console.log("class (method)");
+ debugger; // 17
+ }
+ })).method();
+
+ // Class (static method)
+ (class MyClassWithStaticMethod {
+ static staticMethod() {
+ // Block Variable scope containing the Class identifier `MyClass`.
+ console.log("class (static)");
+ debugger; // 18
+ }
+ }).staticMethod();
+
+ // Normal (not Block)
+ console.log("normal", a);
+ debugger; // 19
+}
Added: trunk/LayoutTests/inspector/model/resources/function-name-scopes.js (0 => 194251)
--- trunk/LayoutTests/inspector/model/resources/function-name-scopes.js (rev 0)
+++ trunk/LayoutTests/inspector/model/resources/function-name-scopes.js 2015-12-18 01:09:13 UTC (rev 194251)
@@ -0,0 +1,13 @@
+function testFunctionNameScope1() {
+ (function functionName() {
+ debugger;
+ })();
+}
+
+function testFunctionNameScope2() {
+ (class MyClass {
+ static staticMethod() {
+ debugger;
+ }
+ }).staticMethod();
+}
Added: trunk/LayoutTests/inspector/model/scope-chain-node-expected.txt (0 => 194251)
--- trunk/LayoutTests/inspector/model/scope-chain-node-expected.txt (rev 0)
+++ trunk/LayoutTests/inspector/model/scope-chain-node-expected.txt 2015-12-18 01:09:13 UTC (rev 194251)
@@ -0,0 +1,136 @@
+CONSOLE MESSAGE: line 36: Variables
+CONSOLE MESSAGE: line 4: normal
+CONSOLE MESSAGE: line 10: if
+CONSOLE MESSAGE: line 18: else
+CONSOLE MESSAGE: line 25: while
+CONSOLE MESSAGE: line 33: do
+CONSOLE MESSAGE: line 39: for
+CONSOLE MESSAGE: line 46: for-in
+CONSOLE MESSAGE: line 53: for-of
+CONSOLE MESSAGE: line 62: case
+CONSOLE MESSAGE: line 67: default
+CONSOLE MESSAGE: line 75: try
+CONSOLE MESSAGE: line 84: catch
+CONSOLE MESSAGE: line 92: finally
+CONSOLE MESSAGE: line 99: block
+CONSOLE MESSAGE: line 106: with
+CONSOLE MESSAGE: line 119: nested blocks
+CONSOLE MESSAGE: line 130: class (method)
+CONSOLE MESSAGE: line 139: class (static)
+CONSOLE MESSAGE: line 145: normal
+Tests for the WebInspector.ScopeChainNode model object.
+
+
+== Running test suite: WebInspector.ScopeChainNode
+-- Running test case: WebInspector.ScopeChainNode.AllTypes
+PASS: ScopeChain should have 13 scopes.
+SCOPE CHAIN:
+ Closure
+ - localVariable2: 12
+ Closure
+ - localVariable1: 11
+ FunctionName
+ - functionName: function functionName() {
+ Block
+ - catchBlockVariable: 10
+ Catch
+ - exceptionVariable: 9
+ Block
+ - withBlockVariable: 8
+ With
+ - withObjectProperty: 7
+ Closure
+ - innerClosureVariable2: 6
+ Closure
+ - innerClosureVariable1: 5
+ Closure
+ - closureVariable2: 4
+ Closure
+ - closureVariable1: 3
+ - innerScope: function innerScope() {
+ GlobalLexicalEnvironment
+ - lexicalGlobalVariable: 2
+ Global
+
+-- Running test case: WebInspector.ScopeChainNode.FunctionNameInFunctionExpression
+SCOPE CHAIN:
+ Closure
+ FunctionName
+ - functionName: function functionName() {
+ Closure
+ GlobalLexicalEnvironment
+ - lexicalGlobalVariable: 2
+ Global
+
+-- Running test case: WebInspector.ScopeChainNode.FunctionNameInClassMethod
+SCOPE CHAIN:
+ Closure
+ FunctionName
+ - staticMethod: function staticMethod() {
+ Block
+ - MyClass: class MyClass
+ Closure
+ GlobalLexicalEnvironment
+ - lexicalGlobalVariable: 2
+ Global
+
+-- Running test case: WebInspector.ScopeChainNode.BlockScopes
+PASS: Pause #1 - Top scope should be normal function Closure/Local scope.
+PASS: Pause #2 - Top scope should be Block scope.
+PASS: Pause #3 - Top scope should be Block scope.
+PASS: Pause #4 - Top scope should be Block scope.
+PASS: Pause #5 - Top scope should be Block scope.
+PASS: Pause #6 - Top scope should be Block scope.
+PASS: Pause #7 - Top scope should be Block scope.
+PASS: Pause #8 - Top scope should be Block scope.
+PASS: Pause #9 - Top scope should be Block scope.
+PASS: Pause #10 - Top scope should be Block scope.
+PASS: Pause #11 - Top scope should be Block scope.
+PASS: Pause #12 - Top scope should be Block scope.
+PASS: Pause #13 - Top scope should be Block scope.
+PASS: Pause #14 - Top scope should be Block scope.
+PASS: Pause #15 - Top scope should be Block scope.
+PASS: Pause #16 - Contains a Block scope.
+SCOPE CHAIN:
+ Block
+ - a: 1006
+ Block
+ - a: 1005
+ Block
+ - a: 1004
+ Block
+ - a: 1003
+ Closure
+ - a: 1
+ Closure
+ GlobalLexicalEnvironment
+ - lexicalGlobalVariable: 2
+ Global
+PASS: Pause #17 - Contains a Block scope.
+SCOPE CHAIN:
+ Closure
+ FunctionName
+ - method: function method() {
+ Block
+ - MyClass: class MyClass
+ Closure
+ - a: 1
+ Closure
+ GlobalLexicalEnvironment
+ - lexicalGlobalVariable: 2
+ Global
+PASS: Pause #18 - Contains a Block scope.
+SCOPE CHAIN:
+ Closure
+ FunctionName
+ - staticMethod: function staticMethod() {
+ Block
+ - MyClassWithStaticMethod: class MyClassWithStaticMethod
+ Closure
+ - a: 1
+ Closure
+ GlobalLexicalEnvironment
+ - lexicalGlobalVariable: 2
+ Global
+PASS: Pause #19 - Top scope should be normal function Closure/Local scope.
+
Added: trunk/LayoutTests/inspector/model/scope-chain-node.html (0 => 194251)
--- trunk/LayoutTests/inspector/model/scope-chain-node.html (rev 0)
+++ trunk/LayoutTests/inspector/model/scope-chain-node.html 2015-12-18 01:09:13 UTC (rev 194251)
@@ -0,0 +1,160 @@
+<!doctype html>
+<html>
+<head>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+<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 WebInspector.ScopeChainNode.Type) {
+ if (WebInspector.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 === WebInspector.ScopeChainNode.Type.Global)
+ resolve({scope, propertyDescriptors: []});
+ else {
+ scope.object.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 !== WebInspector.ScopeChainNode.Type.Global) {
+ for (let descriptor of propertyDescriptors)
+ InspectorTest.log(` - ${descriptor.name}: ${firstLine(descriptor.value.description)}`);
+ }
+ }
+ return results;
+ });
+ }
+
+
+ let suite = InspectorTest.createAsyncSuite("WebInspector.ScopeChainNode");
+
+ InspectorTest.dumpActivityToSystemConsole = true;
+ InspectorBackend.dumpInspectorProtocolMessages = true;
+
+ suite.addTestCase({
+ name: "WebInspector.ScopeChainNode.AllTypes",
+ description: "Tests for each of the different scope chain node types.",
+ test: (resolve, reject) => {
+ InspectorTest.evaluateInPage("setTimeout(testAllScopes)");
+ WebInspector.debuggerManager.singleFireEventListener(WebInspector.DebuggerManager.Event.CallFramesDidChange, (event) => {
+ let scopeChain = WebInspector.debuggerManager.activeCallFrame.scopeChain;
+ InspectorTest.expectThat(scopeChain.length === 13, "ScopeChain should have 13 scopes.");
+ logScopeChain(scopeChain).then((result) => {
+ WebInspector.debuggerManager.resume();
+ resolve();
+ });
+ });
+ }
+ });
+
+ suite.addTestCase({
+ name: "WebInspector.ScopeChainNode.FunctionNameInFunctionExpression",
+ description: "Tests that there should be a FunctionName scope inside a function _expression_.",
+ test: (resolve, reject) => {
+ InspectorTest.evaluateInPage("setTimeout(testFunctionNameScope1)");
+ WebInspector.debuggerManager.singleFireEventListener(WebInspector.DebuggerManager.Event.CallFramesDidChange, (event) => {
+ let scopeChain = WebInspector.debuggerManager.activeCallFrame.scopeChain;
+ logScopeChain(scopeChain).then((result) => {
+ WebInspector.debuggerManager.resume();
+ resolve();
+ });
+ });
+ }
+ });
+
+ suite.addTestCase({
+ name: "WebInspector.ScopeChainNode.FunctionNameInClassMethod",
+ description: "Tests that there should be a FunctionName scope inside a class method.",
+ test: (resolve, reject) => {
+ InspectorTest.evaluateInPage("setTimeout(testFunctionNameScope2)");
+ WebInspector.debuggerManager.singleFireEventListener(WebInspector.DebuggerManager.Event.CallFramesDidChange, (event) => {
+ let scopeChain = WebInspector.debuggerManager.activeCallFrame.scopeChain;
+ logScopeChain(scopeChain).then((result) => {
+ WebInspector.debuggerManager.resume();
+ resolve();
+ });
+ });
+ }
+ });
+
+ suite.addTestCase({
+ name: "WebInspector.ScopeChainNode.BlockScopes",
+ description: "Tests for a Block scope inside all the different types of blocks.",
+ test: (resolve, reject) => {
+ InspectorTest.evaluateInPage("setTimeout(testBlockScopes)");
+ WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.ActiveCallFrameDidChange, callFramesDidChangeListener);
+
+ let pauseCount = 0;
+ let pauseEventsExpected = 19;
+ function callFramesDidChangeListener(event) {
+ pauseCount++;
+ let scopeChain = WebInspector.debuggerManager.activeCallFrame.scopeChain;
+
+ // First, normal function scope.
+ if (pauseCount === 1) {
+ InspectorTest.expectThat(scopeChain[0].type === WebInspector.ScopeChainNode.Type.Closure, "Pause #1 - Top scope should be normal function Closure/Local scope.");
+ WebInspector.debuggerManager.resume();
+ return;
+ }
+
+ // Last, normal function scope.
+ if (pauseCount === pauseEventsExpected) {
+ InspectorTest.expectThat(scopeChain[0].type === WebInspector.ScopeChainNode.Type.Closure, `Pause #${pauseCount} - Top scope should be normal function Closure/Local scope.`);
+ WebInspector.debuggerManager.removeEventListener(WebInspector.DebuggerManager.Event.ActiveCallFrameDidChange, callFramesDidChangeListener);
+ WebInspector.debuggerManager.resume();
+ resolve();
+ return;
+ }
+
+ // The first 15 cases the top scope should be a Block scope.
+ if (pauseCount <= 15) {
+ InspectorTest.expectThat(scopeChain[0].type === WebInspector.ScopeChainNode.Type.Block, `Pause #${pauseCount} - Top scope should be Block scope.`);
+ WebInspector.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 === WebInspector.ScopeChainNode.Type.Block), `Pause #${pauseCount} - Contains a Block scope.`);
+ logScopeChain(scopeChain).then((result) => {
+ WebInspector.debuggerManager.resume();
+ });
+ }
+ }
+ });
+
+ suite.runTestCasesAndFinish();
+}
+</script>
+</head>
+<body _onload_="runTest()">
+<p>Tests for the WebInspector.ScopeChainNode model object.</p>
+</body>
+</html>
Modified: trunk/Source/_javascript_Core/ChangeLog (194250 => 194251)
--- trunk/Source/_javascript_Core/ChangeLog 2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/_javascript_Core/ChangeLog 2015-12-18 01:09:13 UTC (rev 194251)
@@ -1,5 +1,57 @@
2015-12-17 Joseph Pecoraro <[email protected]>
+ Provide a way to distinguish a nested lexical block from a function's lexical block
+ https://bugs.webkit.org/show_bug.cgi?id=152361
+
+ Reviewed by Saam Barati.
+
+ * bytecompiler/BytecodeGenerator.h:
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::initializeDefaultParameterValuesAndSetupFunctionScopeStack):
+ (JSC::BytecodeGenerator::initializeArrowFunctionContextScopeIfNeeded):
+ (JSC::BytecodeGenerator::emitPushFunctionNameScope):
+ (JSC::BytecodeGenerator::emitPushCatchScope):
+ Each of these are specialized scopes. They are not nested lexical scopes.
+
+ (JSC::BytecodeGenerator::pushLexicalScope):
+ (JSC::BytecodeGenerator::pushLexicalScopeInternal):
+ Include an extra parameter to mark the SymbolTable as a nested lexical or not.
+
+ * bytecompiler/NodesCodegen.cpp:
+ (JSC::BlockNode::emitBytecode):
+ (JSC::ForNode::emitBytecode):
+ (JSC::ForInNode::emitMultiLoopBytecode):
+ (JSC::ForOfNode::emitBytecode):
+ (JSC::SwitchNode::emitBytecode):
+ (JSC::ClassExprNode::emitBytecode):
+ Each of these are cases of non-function nested lexical scopes.
+ So mark the SymbolTable as nested.
+
+ * inspector/protocol/Debugger.json:
+ * inspector/InjectedScriptSource.js:
+ Include a new scope type.
+
+ * inspector/JSJavaScriptCallFrame.h:
+ * inspector/JSJavaScriptCallFrame.cpp:
+ (Inspector::JSJavaScriptCallFrame::scopeType):
+ Use the new "NestedLexical" scope type for nested, non-function,
+ lexical scopes. The Inspector can use this to better describe
+ this scope in the frontend.
+
+ * debugger/DebuggerScope.cpp:
+ (JSC::DebuggerScope::isNestedLexicalScope):
+ * debugger/DebuggerScope.h:
+ * runtime/JSScope.cpp:
+ (JSC::JSScope::isNestedLexicalScope):
+ * runtime/JSScope.h:
+ * runtime/SymbolTable.cpp:
+ (JSC::SymbolTable::SymbolTable):
+ (JSC::SymbolTable::cloneScopePart):
+ * runtime/SymbolTable.h:
+ Access the isNestedLexicalScope bit.
+
+2015-12-17 Joseph Pecoraro <[email protected]>
+
Unreviewed EFL Build Fix after r194247.
* interpreter/CallFrame.cpp:
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (194250 => 194251)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2015-12-18 01:09:13 UTC (rev 194251)
@@ -809,7 +809,7 @@
}
// This implements step 25 of section 9.2.12.
- pushLexicalScopeInternal(environment, true, nullptr, TDZRequirement::UnderTDZ, ScopeType::LetConstScope, ScopeRegisterType::Block);
+ pushLexicalScopeInternal(environment, true, false, nullptr, TDZRequirement::UnderTDZ, ScopeType::LetConstScope, ScopeRegisterType::Block);
RefPtr<RegisterID> temp = newTemporary();
for (unsigned i = 0; i < parameters.size(); i++) {
@@ -927,7 +927,7 @@
}
size_t size = m_symbolTableStack.size();
- pushLexicalScopeInternal(environment, true, nullptr, TDZRequirement::UnderTDZ, ScopeType::LetConstScope, ScopeRegisterType::Block);
+ pushLexicalScopeInternal(environment, true, false, nullptr, TDZRequirement::UnderTDZ, ScopeType::LetConstScope, ScopeRegisterType::Block);
ASSERT_UNUSED(size, m_symbolTableStack.size() == size + 1);
@@ -1797,13 +1797,13 @@
}
}
-void BytecodeGenerator::pushLexicalScope(VariableEnvironmentNode* node, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult)
+void BytecodeGenerator::pushLexicalScope(VariableEnvironmentNode* node, bool canOptimizeTDZChecks, bool isNestedLexicalScope, RegisterID** constantSymbolTableResult)
{
VariableEnvironment& environment = node->lexicalVariables();
- pushLexicalScopeInternal(environment, canOptimizeTDZChecks, constantSymbolTableResult, TDZRequirement::UnderTDZ, ScopeType::LetConstScope, ScopeRegisterType::Block);
+ pushLexicalScopeInternal(environment, canOptimizeTDZChecks, isNestedLexicalScope, constantSymbolTableResult, TDZRequirement::UnderTDZ, ScopeType::LetConstScope, ScopeRegisterType::Block);
}
-void BytecodeGenerator::pushLexicalScopeInternal(VariableEnvironment& environment, bool canOptimizeTDZChecks,
+void BytecodeGenerator::pushLexicalScopeInternal(VariableEnvironment& environment, bool canOptimizeTDZChecks, bool isNestedLexicalScope,
RegisterID** constantSymbolTableResult, TDZRequirement tdzRequirement, ScopeType scopeType, ScopeRegisterType scopeRegisterType)
{
if (!environment.size())
@@ -1825,6 +1825,9 @@
break;
}
+ if (isNestedLexicalScope)
+ symbolTable->markIsNestedLexicalScope();
+
auto lookUpVarKind = [] (UniquedStringImpl*, const VariableEnvironmentEntry& entry) -> VarKind {
return entry.isCaptured() ? VarKind::Scope : VarKind::Stack;
};
@@ -3563,7 +3566,7 @@
addResult.iterator->value.setIsCaptured();
addResult.iterator->value.setIsConst(); // The function name scope name acts like a const variable.
unsigned numVars = m_codeBlock->m_numVars;
- pushLexicalScopeInternal(nameScopeEnvironment, true, nullptr, TDZRequirement::NotUnderTDZ, ScopeType::FunctionNameScope, ScopeRegisterType::Var);
+ pushLexicalScopeInternal(nameScopeEnvironment, true, false, nullptr, TDZRequirement::NotUnderTDZ, ScopeType::FunctionNameScope, ScopeRegisterType::Var);
ASSERT_UNUSED(numVars, m_codeBlock->m_numVars == static_cast<int>(numVars + 1)); // Should have only created one new "var" for the function name scope.
bool shouldTreatAsLexicalVariable = isStrictMode();
Variable functionVar = variableForLocalEntry(property, m_symbolTableStack.last().m_symbolTable->get(property.impl()), m_symbolTableStack.last().m_symbolTableConstantIndex, shouldTreatAsLexicalVariable);
@@ -3589,7 +3592,7 @@
void BytecodeGenerator::emitPushCatchScope(const Identifier& property, RegisterID* exceptionValue, VariableEnvironment& environment)
{
RELEASE_ASSERT(environment.contains(property.impl()));
- pushLexicalScopeInternal(environment, true, nullptr, TDZRequirement::NotUnderTDZ, ScopeType::CatchScope, ScopeRegisterType::Block);
+ pushLexicalScopeInternal(environment, true, false, nullptr, TDZRequirement::NotUnderTDZ, ScopeType::CatchScope, ScopeRegisterType::Block);
Variable exceptionVar = variable(property);
RELEASE_ASSERT(exceptionVar.isResolved());
RefPtr<RegisterID> scope = emitResolveScope(nullptr, exceptionVar);
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (194250 => 194251)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2015-12-18 01:09:13 UTC (rev 194251)
@@ -704,7 +704,7 @@
enum class TDZRequirement { UnderTDZ, NotUnderTDZ };
enum class ScopeType { CatchScope, LetConstScope, FunctionNameScope };
enum class ScopeRegisterType { Var, Block };
- void pushLexicalScopeInternal(VariableEnvironment&, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult, TDZRequirement, ScopeType, ScopeRegisterType);
+ void pushLexicalScopeInternal(VariableEnvironment&, bool canOptimizeTDZChecks, bool isNestedLexicalScope, RegisterID** constantSymbolTableResult, TDZRequirement, ScopeType, ScopeRegisterType);
void popLexicalScopeInternal(VariableEnvironment&, TDZRequirement);
template<typename LookUpVarKindFunctor>
bool instantiateLexicalVariables(const VariableEnvironment&, SymbolTable*, ScopeRegisterType, LookUpVarKindFunctor);
@@ -715,7 +715,7 @@
void emitNewFunctionExpressionCommon(RegisterID*, BaseFuncExprNode*);
public:
- void pushLexicalScope(VariableEnvironmentNode*, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult = nullptr);
+ void pushLexicalScope(VariableEnvironmentNode*, bool canOptimizeTDZChecks, bool isNestedLexicalScope = false, RegisterID** constantSymbolTableResult = nullptr);
void popLexicalScope(VariableEnvironmentNode*);
void prepareLexicalScopeForNextForLoopIteration(VariableEnvironmentNode*, RegisterID* loopSymbolTable);
int labelScopeDepth() const;
Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (194250 => 194251)
--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2015-12-18 01:09:13 UTC (rev 194251)
@@ -2049,7 +2049,7 @@
{
if (!m_statements)
return;
- generator.pushLexicalScope(this, true);
+ generator.pushLexicalScope(this, true, true);
m_statements->emitBytecode(generator, dst);
generator.popLexicalScope(this);
}
@@ -2254,7 +2254,7 @@
LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
RegisterID* forLoopSymbolTable = nullptr;
- generator.pushLexicalScope(this, true, &forLoopSymbolTable);
+ generator.pushLexicalScope(this, true, true, &forLoopSymbolTable);
generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
@@ -2382,7 +2382,7 @@
RefPtr<Label> end = generator.newLabel();
RegisterID* forLoopSymbolTable = nullptr;
- generator.pushLexicalScope(this, true, &forLoopSymbolTable);
+ generator.pushLexicalScope(this, true, true, &forLoopSymbolTable);
generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
@@ -2532,7 +2532,7 @@
}
RegisterID* forLoopSymbolTable = nullptr;
- generator.pushLexicalScope(this, true, &forLoopSymbolTable);
+ generator.pushLexicalScope(this, true, true, &forLoopSymbolTable);
generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
auto extractor = [this, dst](BytecodeGenerator& generator, RegisterID* value)
{
@@ -2848,7 +2848,7 @@
RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
- generator.pushLexicalScope(this, false);
+ generator.pushLexicalScope(this, false, true);
m_block->emitBytecodeForBlock(generator, r0.get(), dst);
generator.popLexicalScope(this);
@@ -3181,7 +3181,7 @@
RegisterID* ClassExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
if (!m_name.isNull())
- generator.pushLexicalScope(this, true);
+ generator.pushLexicalScope(this, true, true);
RefPtr<RegisterID> superclass;
if (m_classHeritage) {
Modified: trunk/Source/_javascript_Core/debugger/DebuggerScope.cpp (194250 => 194251)
--- trunk/Source/_javascript_Core/debugger/DebuggerScope.cpp 2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/_javascript_Core/debugger/DebuggerScope.cpp 2015-12-18 01:09:13 UTC (rev 194251)
@@ -197,6 +197,11 @@
return m_scope->isVarScope() || m_scope->isLexicalScope();
}
+bool DebuggerScope::isNestedLexicalScope() const
+{
+ return m_scope->isNestedLexicalScope();
+}
+
JSValue DebuggerScope::caughtValue(ExecState* exec) const
{
ASSERT(isCatchScope());
Modified: trunk/Source/_javascript_Core/debugger/DebuggerScope.h (194250 => 194251)
--- trunk/Source/_javascript_Core/debugger/DebuggerScope.h 2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/_javascript_Core/debugger/DebuggerScope.h 2015-12-18 01:09:13 UTC (rev 194251)
@@ -91,6 +91,7 @@
bool isGlobalScope() const;
bool isClosureScope() const;
bool isGlobalLexicalEnvironment() const;
+ bool isNestedLexicalScope() const;
JSValue caughtValue(ExecState*) const;
Modified: trunk/Source/_javascript_Core/inspector/InjectedScriptSource.js (194250 => 194251)
--- trunk/Source/_javascript_Core/inspector/InjectedScriptSource.js 2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/_javascript_Core/inspector/InjectedScriptSource.js 2015-12-18 01:09:13 UTC (rev 194251)
@@ -1369,6 +1369,7 @@
4: "catch", // CATCH_SCOPE
5: "functionName", // FUNCTION_NAME_SCOPE
6: "globalLexicalEnvironment", // GLOBAL_LEXICAL_ENVIRONMENT_SCOPE
+ 7: "nestedLexical", // NESTED_LEXICAL_SCOPE
}
InjectedScript.CallFrameProxy._createScopeJson = function(scopeTypeCode, scopeObject, groupId)
Modified: trunk/Source/_javascript_Core/inspector/JSJavaScriptCallFrame.cpp (194250 => 194251)
--- trunk/Source/_javascript_Core/inspector/JSJavaScriptCallFrame.cpp 2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/_javascript_Core/inspector/JSJavaScriptCallFrame.cpp 2015-12-18 01:09:13 UTC (rev 194251)
@@ -95,17 +95,9 @@
DebuggerScope* scopeChain = impl().scopeChain();
DebuggerScope::iterator end = scopeChain->end();
- bool foundLocalScope = false;
for (DebuggerScope::iterator iter = scopeChain->begin(); iter != end; ++iter) {
DebuggerScope* scope = iter.get();
- if (!foundLocalScope && scope->isClosureScope()) {
- // First closure scope is the local scope, each successive one is a true closure.
- if (!index)
- return jsNumber(JSJavaScriptCallFrame::LOCAL_SCOPE);
- foundLocalScope = true;
- }
-
if (!index) {
if (scope->isCatchScope())
return jsNumber(JSJavaScriptCallFrame::CATCH_SCOPE);
@@ -113,6 +105,8 @@
return jsNumber(JSJavaScriptCallFrame::FUNCTION_NAME_SCOPE);
if (scope->isWithScope())
return jsNumber(JSJavaScriptCallFrame::WITH_SCOPE);
+ if (scope->isNestedLexicalScope())
+ return jsNumber(JSJavaScriptCallFrame::NESTED_LEXICAL_SCOPE);
if (scope->isGlobalLexicalEnvironment())
return jsNumber(JSJavaScriptCallFrame::GLOBAL_LEXICAL_ENVIRONMENT_SCOPE);
if (scope->isGlobalScope()) {
Modified: trunk/Source/_javascript_Core/inspector/JSJavaScriptCallFrame.h (194250 => 194251)
--- trunk/Source/_javascript_Core/inspector/JSJavaScriptCallFrame.h 2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/_javascript_Core/inspector/JSJavaScriptCallFrame.h 2015-12-18 01:09:13 UTC (rev 194251)
@@ -78,6 +78,7 @@
static const unsigned short CATCH_SCOPE = 4;
static const unsigned short FUNCTION_NAME_SCOPE = 5;
static const unsigned short GLOBAL_LEXICAL_ENVIRONMENT_SCOPE = 6;
+ static const unsigned short NESTED_LEXICAL_SCOPE = 7;
protected:
void finishCreation(JSC::VM&);
Modified: trunk/Source/_javascript_Core/inspector/protocol/Debugger.json (194250 => 194251)
--- trunk/Source/_javascript_Core/inspector/protocol/Debugger.json 2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/_javascript_Core/inspector/protocol/Debugger.json 2015-12-18 01:09:13 UTC (rev 194251)
@@ -81,7 +81,7 @@
"id": "Scope",
"type": "object",
"properties": [
- { "name": "type", "type": "string", "enum": ["global", "local", "with", "closure", "catch", "functionName", "globalLexicalEnvironment"], "description": "Scope type." },
+ { "name": "type", "type": "string", "enum": ["global", "local", "with", "closure", "catch", "functionName", "globalLexicalEnvironment", "nestedLexical"], "description": "Scope type." },
{ "name": "object", "$ref": "Runtime.RemoteObject", "description": "Object representing the scope. For <code>global</code> and <code>with</code> scopes it represents the actual object; for the rest of the scopes, it is artificial transient object enumerating scope variables as its properties." }
],
"description": "Scope description."
Modified: trunk/Source/_javascript_Core/runtime/JSScope.cpp (194250 => 194251)
--- trunk/Source/_javascript_Core/runtime/JSScope.cpp 2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/_javascript_Core/runtime/JSScope.cpp 2015-12-18 01:09:13 UTC (rev 194251)
@@ -286,6 +286,13 @@
return isScopeType<JSGlobalLexicalEnvironment, SymbolTable::ScopeType::GlobalLexicalScope>(this);
}
+bool JSScope::isNestedLexicalScope()
+{
+ if (JSLexicalEnvironment* environment = jsDynamicCast<JSLexicalEnvironment*>(this))
+ return environment->symbolTable()->isNestedLexicalScope();
+ return false;
+}
+
JSScope* JSScope::constantScopeForCodeBlock(ResolveType type, CodeBlock* codeBlock)
{
switch (type) {
Modified: trunk/Source/_javascript_Core/runtime/JSScope.h (194250 => 194251)
--- trunk/Source/_javascript_Core/runtime/JSScope.h 2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/_javascript_Core/runtime/JSScope.h 2015-12-18 01:09:13 UTC (rev 194251)
@@ -62,6 +62,8 @@
bool isCatchScope();
bool isFunctionNameScopeObject();
+ bool isNestedLexicalScope();
+
ScopeChainIterator begin();
ScopeChainIterator end();
JSScope* next();
Modified: trunk/Source/_javascript_Core/runtime/SymbolTable.cpp (194250 => 194251)
--- trunk/Source/_javascript_Core/runtime/SymbolTable.cpp 2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/_javascript_Core/runtime/SymbolTable.cpp 2015-12-18 01:09:13 UTC (rev 194251)
@@ -84,6 +84,7 @@
SymbolTable::SymbolTable(VM& vm)
: JSCell(vm, vm.symbolTableStructure.get())
, m_usesNonStrictEval(false)
+ , m_nestedLexicalScope(false)
, m_scopeType(VarScope)
{
}
@@ -142,6 +143,7 @@
SymbolTable* result = SymbolTable::create(vm);
result->m_usesNonStrictEval = m_usesNonStrictEval;
+ result->m_nestedLexicalScope = m_nestedLexicalScope;
result->m_scopeType = m_scopeType;
for (auto iter = m_map.begin(), end = m_map.end(); iter != end; ++iter) {
Modified: trunk/Source/_javascript_Core/runtime/SymbolTable.h (194250 => 194251)
--- trunk/Source/_javascript_Core/runtime/SymbolTable.h 2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/_javascript_Core/runtime/SymbolTable.h 2015-12-18 01:09:13 UTC (rev 194251)
@@ -646,9 +646,12 @@
RefPtr<TypeSet> globalTypeSetForOffset(const ConcurrentJITLocker&, VarOffset, VM&);
RefPtr<TypeSet> globalTypeSetForVariable(const ConcurrentJITLocker&, UniquedStringImpl* key, VM&);
- bool usesNonStrictEval() { return m_usesNonStrictEval; }
+ bool usesNonStrictEval() const { return m_usesNonStrictEval; }
void setUsesNonStrictEval(bool usesNonStrictEval) { m_usesNonStrictEval = usesNonStrictEval; }
+ bool isNestedLexicalScope() const { return m_nestedLexicalScope; }
+ void markIsNestedLexicalScope() { ASSERT(scopeType() == LexicalScope); m_nestedLexicalScope = true; }
+
enum ScopeType {
VarScope,
GlobalLexicalScope,
@@ -686,6 +689,7 @@
std::unique_ptr<TypeProfilingRareData> m_typeProfilingRareData;
bool m_usesNonStrictEval : 1;
+ bool m_nestedLexicalScope : 1; // Non-function LexicalScope.
unsigned m_scopeType : 3; // ScopeType
WriteBarrier<ScopedArgumentsTable> m_arguments;
Modified: trunk/Source/WebInspectorUI/ChangeLog (194250 => 194251)
--- trunk/Source/WebInspectorUI/ChangeLog 2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/WebInspectorUI/ChangeLog 2015-12-18 01:09:13 UTC (rev 194251)
@@ -1,5 +1,24 @@
2015-12-17 Joseph Pecoraro <[email protected]>
+ Provide a way to distinguish a nested lexical block from a function's lexical block
+ https://bugs.webkit.org/show_bug.cgi?id=152361
+
+ Reviewed by Saam Barati.
+
+ * Localizations/en.lproj/localizedStrings.js:
+ * UserInterface/Views/ScopeChainDetailsSidebarPanel.js:
+ (WebInspector.ScopeChainDetailsSidebarPanel.prototype._generateCallFramesSection):
+ New "Block Variables" string.
+
+ * UserInterface/Models/ScopeChainNode.js:
+ New "Block" scope type, and update existing types.
+
+ * UserInterface/Controllers/DebuggerManager.js:
+ (WebInspector.DebuggerManager.prototype._scopeChainNodeFromPayload):
+ Parse the protocol type to frontend types. Use the protocol generated enum.
+
+2015-12-17 Joseph Pecoraro <[email protected]>
+
Web Inspector: Improve names in Debugger Call Stack section when paused
https://bugs.webkit.org/show_bug.cgi?id=152398
Modified: trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js (194250 => 194251)
--- trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js 2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js 2015-12-18 01:09:13 UTC (rev 194251)
@@ -95,6 +95,7 @@
localizedStrings["Background"] = "Background";
localizedStrings["Basis"] = "Basis";
localizedStrings["Begin Capturing"] = "Begin Capturing";
+localizedStrings["Block Variables"] = "Block Variables";
localizedStrings["Blur"] = "Blur";
localizedStrings["Border"] = "Border";
localizedStrings["Bottom"] = "Bottom";
Modified: trunk/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js (194250 => 194251)
--- trunk/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js 2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js 2015-12-18 01:09:13 UTC (rev 194251)
@@ -585,25 +585,28 @@
{
var type = null;
switch (payload.type) {
- case "local":
+ case DebuggerAgent.ScopeType.Local:
type = WebInspector.ScopeChainNode.Type.Local;
break;
- case "global":
+ case DebuggerAgent.ScopeType.Global:
type = WebInspector.ScopeChainNode.Type.Global;
break;
- case "with":
+ case DebuggerAgent.ScopeType.With:
type = WebInspector.ScopeChainNode.Type.With;
break;
- case "closure":
+ case DebuggerAgent.ScopeType.Closure:
type = WebInspector.ScopeChainNode.Type.Closure;
break;
- case "catch":
+ case DebuggerAgent.ScopeType.Catch:
type = WebInspector.ScopeChainNode.Type.Catch;
break;
- case "functionName":
+ case DebuggerAgent.ScopeType.FunctionName:
type = WebInspector.ScopeChainNode.Type.FunctionName;
break;
- case "globalLexicalEnvironment":
+ case DebuggerAgent.ScopeType.NestedLexical:
+ type = WebInspector.ScopeChainNode.Type.Block;
+ break;
+ case DebuggerAgent.ScopeType.GlobalLexicalEnvironment:
type = WebInspector.ScopeChainNode.Type.GlobalLexicalEnvironment;
break;
default:
Modified: trunk/Source/WebInspectorUI/UserInterface/Models/ScopeChainNode.js (194250 => 194251)
--- trunk/Source/WebInspectorUI/UserInterface/Models/ScopeChainNode.js 2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/ScopeChainNode.js 2015-12-18 01:09:13 UTC (rev 194251)
@@ -55,9 +55,10 @@
WebInspector.ScopeChainNode.Type = {
Local: "scope-chain-type-local",
Global: "scope-chain-type-global",
+ GlobalLexicalEnvironment: "scope-chain-type-global-lexical-environment",
With: "scope-chain-type-with",
Closure: "scope-chain-type-closure",
Catch: "scope-chain-type-catch",
- FunctionName: "scope-chain-type-functionName",
- GlobalLexicalEnvironment: "scope-chain-type-globalLexicalEnvironment",
+ FunctionName: "scope-chain-type-function-name",
+ Block: "scope-chain-type-block",
};
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ScopeChainDetailsSidebarPanel.js (194250 => 194251)
--- trunk/Source/WebInspectorUI/UserInterface/Views/ScopeChainDetailsSidebarPanel.js 2015-12-18 01:09:00 UTC (rev 194250)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ScopeChainDetailsSidebarPanel.js 2015-12-18 01:09:13 UTC (rev 194251)
@@ -184,6 +184,11 @@
extraPropertyDescriptor = new WebInspector.PropertyDescriptor({name: "this", value: callFrame.thisObject});
break;
+ case WebInspector.ScopeChainNode.Type.Block:
+ title = WebInspector.UIString("Block Variables");
+ collapsedByDefault = false;
+ break;
+
case WebInspector.ScopeChainNode.Type.Closure:
title = WebInspector.UIString("Closure Variables");
collapsedByDefault = false;