Changeset 202659 in webkit
- Timestamp:
- Jun 29, 2016 4:59:35 PM (8 years ago)
- Location:
- trunk
- Files:
-
- 5 added
- 21 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r202649 r202659 1 2016-06-29 Joseph Pecoraro <pecoraro@apple.com> 2 3 Web Inspector: Wrong function name next to scope 4 https://bugs.webkit.org/show_bug.cgi?id=158210 5 <rdar://problem/26543093> 6 7 Reviewed by Brian Burg. 8 9 * inspector/debugger/paused-scopes-expected.txt: Added. 10 * inspector/debugger/paused-scopes.html: Added. 11 * inspector/debugger/resources/paused-scopes.js: Added. 12 Test dumps the call frames and scope chains for each call frame 13 when pausing at different locations in a program. Outputting 14 the hashes we can see even identically named functions have 15 different hashes because their location is different. 16 1 17 2016-06-29 Ryan Haddad <ryanhaddad@apple.com> 2 18 -
trunk/Source/JavaScriptCore/CMakeLists.txt
r202435 r202659 240 240 debugger/Debugger.cpp 241 241 debugger/DebuggerCallFrame.cpp 242 debugger/DebuggerLocation.cpp 242 243 debugger/DebuggerScope.cpp 243 244 -
trunk/Source/JavaScriptCore/ChangeLog
r202654 r202659 1 2016-06-29 Joseph Pecoraro <pecoraro@apple.com> 2 3 Web Inspector: Wrong function name next to scope 4 https://bugs.webkit.org/show_bug.cgi?id=158210 5 <rdar://problem/26543093> 6 7 Reviewed by Brian Burg. 8 9 * CMakeLists.txt: 10 * JavaScriptCore.xcodeproj/project.pbxproj: 11 Add DebuggerLocation. A helper for describing a unique location. 12 13 * bytecode/CodeBlock.cpp: 14 (JSC::CodeBlock::setConstantRegisters): 15 When compiled with debug info, add a SymbolTable rare data pointer 16 back to the CodeBlock. This will be used later to get JSScope debug 17 info if Web Inspector pauses. 18 19 * runtime/SymbolTable.h: 20 * runtime/SymbolTable.cpp: 21 (JSC::SymbolTable::cloneScopePart): 22 (JSC::SymbolTable::prepareForTypeProfiling): 23 (JSC::SymbolTable::uniqueIDForVariable): 24 (JSC::SymbolTable::uniqueIDForOffset): 25 (JSC::SymbolTable::globalTypeSetForOffset): 26 (JSC::SymbolTable::globalTypeSetForVariable): 27 Rename rareData and include a CodeBlock pointer. 28 29 (JSC::SymbolTable::rareDataCodeBlock): 30 (JSC::SymbolTable::setRareDataCodeBlock): 31 Setter and getter for the rare data. It should only be set once. 32 33 (JSC::SymbolTable::visitChildren): 34 Visit the rare data code block if we have one. 35 36 * debugger/DebuggerLocation.cpp: Added. 37 (JSC::DebuggerLocation::DebuggerLocation): 38 * debugger/DebuggerLocation.h: Added. 39 (JSC::DebuggerLocation::DebuggerLocation): 40 Construction from a ScriptExecutable. 41 42 * runtime/JSScope.cpp: 43 (JSC::JSScope::symbolTable): 44 * runtime/JSScope.h: 45 * debugger/DebuggerScope.h: 46 * debugger/DebuggerScope.cpp: 47 (JSC::DebuggerScope::name): 48 (JSC::DebuggerScope::location): 49 Name and location for a scope. This uses: 50 JSScope -> SymbolTable -> CodeBlock -> Executable 51 52 * inspector/protocol/Debugger.json: 53 * inspector/InjectedScriptSource.js: 54 (InjectedScript.CallFrameProxy.prototype._wrapScopeChain): 55 (InjectedScript.CallFrameProxy._createScopeJson): 56 * inspector/JSJavaScriptCallFrame.cpp: 57 (Inspector::valueForScopeType): 58 (Inspector::valueForScopeLocation): 59 (Inspector::JSJavaScriptCallFrame::scopeDescriptions): 60 (Inspector::JSJavaScriptCallFrame::scopeType): Deleted. 61 * inspector/JSJavaScriptCallFrame.h: 62 * inspector/JSJavaScriptCallFramePrototype.cpp: 63 (Inspector::JSJavaScriptCallFramePrototype::finishCreation): 64 (Inspector::jsJavaScriptCallFramePrototypeFunctionScopeDescriptions): 65 (Inspector::jsJavaScriptCallFramePrototypeFunctionScopeType): Deleted. 66 Simplify this code to build the objects we will send across the protocol 67 to descript a Scope. 68 1 69 2016-06-29 Saam barati <sbarati@apple.com> 2 70 -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r202502 r202659 1646 1646 A5EF9B181A1D440600702E90 /* generate_cpp_protocol_types_header.py in Headers */ = {isa = PBXBuildFile; fileRef = C4F4B6D51A05C76F005CAB76 /* generate_cpp_protocol_types_header.py */; settings = {ATTRIBUTES = (Private, ); }; }; 1647 1647 A5EF9B191A1D440700702E90 /* generate_cpp_protocol_types_implementation.py in Headers */ = {isa = PBXBuildFile; fileRef = C4F4B6D61A05C76F005CAB76 /* generate_cpp_protocol_types_implementation.py */; settings = {ATTRIBUTES = (Private, ); }; }; 1648 A5FC84B21D1DDAD6006B5C46 /* DebuggerLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = A5FC84B11D1DDAC8006B5C46 /* DebuggerLocation.h */; }; 1649 A5FC84B31D1DDAD9006B5C46 /* DebuggerLocation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5FC84B01D1DDAC8006B5C46 /* DebuggerLocation.cpp */; }; 1648 1650 A5FD0067189AFE9C00633231 /* ScriptArguments.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5FD0065189AFE9C00633231 /* ScriptArguments.cpp */; }; 1649 1651 A5FD0068189AFE9C00633231 /* ScriptArguments.h in Headers */ = {isa = PBXBuildFile; fileRef = A5FD0066189AFE9C00633231 /* ScriptArguments.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 3866 3868 A5EA70F819F6DE5A0098F5EC /* objc_generator.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = objc_generator.py; sourceTree = "<group>"; }; 3867 3869 A5EA710D19F6DF810098F5EC /* InspectorAlternateBackendDispatchers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorAlternateBackendDispatchers.h; sourceTree = "<group>"; }; 3870 A5FC84B01D1DDAC8006B5C46 /* DebuggerLocation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DebuggerLocation.cpp; sourceTree = "<group>"; }; 3871 A5FC84B11D1DDAC8006B5C46 /* DebuggerLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebuggerLocation.h; sourceTree = "<group>"; }; 3868 3872 A5FD0065189AFE9C00633231 /* ScriptArguments.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScriptArguments.cpp; sourceTree = "<group>"; }; 3869 3873 A5FD0066189AFE9C00633231 /* ScriptArguments.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScriptArguments.h; sourceTree = "<group>"; }; … … 5343 5347 1480DB9B0DDC227F003CFDF2 /* DebuggerCallFrame.h */, 5344 5348 6AD2CB4C19B9140100065719 /* DebuggerEvalEnabler.h */, 5349 A5FC84B01D1DDAC8006B5C46 /* DebuggerLocation.cpp */, 5350 A5FC84B11D1DDAC8006B5C46 /* DebuggerLocation.h */, 5345 5351 FEA0861F182B7A0400F6D851 /* DebuggerPrimitives.h */, 5346 5352 0F2D4DDB19832D34007D4B19 /* DebuggerScope.cpp */, … … 7692 7698 978801411471AD920041B016 /* JSDateMath.h in Headers */, 7693 7699 C2A7F688160432D400F76B98 /* JSDestructibleObject.h in Headers */, 7700 A5FC84B21D1DDAD6006B5C46 /* DebuggerLocation.h in Headers */, 7694 7701 FE384EE61ADDB7AD0055DE2C /* JSDollarVM.h in Headers */, 7695 7702 FE384EE81ADDB7AD0055DE2C /* JSDollarVMPrototype.h in Headers */, … … 8771 8778 52B717B51A0597E1007AF4F3 /* ControlFlowProfiler.cpp in Sources */, 8772 8779 0FBADF541BD1F4B800E073C1 /* CopiedBlock.cpp in Sources */, 8780 A5FC84B31D1DDAD9006B5C46 /* DebuggerLocation.cpp in Sources */, 8773 8781 C240305514B404E60079EB64 /* CopiedSpace.cpp in Sources */, 8774 8782 0F6183301C45BF070072450B /* AirLowerMacros.cpp in Sources */, -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r202633 r202659 2478 2478 symbolTable->prepareForTypeProfiling(locker); 2479 2479 } 2480 constant = symbolTable->cloneScopePart(*m_vm); 2480 2481 SymbolTable* clone = symbolTable->cloneScopePart(*m_vm); 2482 if (wasCompiledWithDebuggingOpcodes()) 2483 clone->setRareDataCodeBlock(this); 2484 2485 constant = clone; 2481 2486 } 2482 2487 } -
trunk/Source/JavaScriptCore/debugger/DebuggerScope.cpp
r200430 r202659 211 211 } 212 212 213 String DebuggerScope::name() const 214 { 215 SymbolTable* symbolTable = m_scope->symbolTable(); 216 if (!symbolTable) 217 return String(); 218 219 CodeBlock* codeBlock = symbolTable->rareDataCodeBlock(); 220 if (!codeBlock) 221 return String(); 222 223 return String::fromUTF8(codeBlock->inferredName()); 224 } 225 226 DebuggerLocation DebuggerScope::location() const 227 { 228 SymbolTable* symbolTable = m_scope->symbolTable(); 229 if (!symbolTable) 230 return DebuggerLocation(); 231 232 CodeBlock* codeBlock = symbolTable->rareDataCodeBlock(); 233 if (!codeBlock) 234 return DebuggerLocation(); 235 236 ScriptExecutable* executable = codeBlock->ownerScriptExecutable(); 237 return DebuggerLocation(executable); 238 } 239 213 240 JSValue DebuggerScope::caughtValue(ExecState* exec) const 214 241 { -
trunk/Source/JavaScriptCore/debugger/DebuggerScope.h
r200430 r202659 27 27 #define DebuggerScope_h 28 28 29 #include "DebuggerLocation.h" 29 30 #include "JSObject.h" 30 31 … … 89 90 bool isNestedLexicalScope() const; 90 91 92 String name() const; 93 DebuggerLocation location() const; 94 91 95 JSValue caughtValue(ExecState*) const; 92 96 -
trunk/Source/JavaScriptCore/inspector/InjectedScriptSource.js
r202568 r202659 1307 1307 { 1308 1308 var scopeChain = callFrame.scopeChain; 1309 var scopeDescriptions = callFrame.scopeDescriptions(); 1310 1309 1311 var scopeChainProxy = []; 1310 1312 for (var i = 0; i < scopeChain.length; i++) 1311 scopeChainProxy[i] = InjectedScript.CallFrameProxy._createScopeJson( callFrame.scopeType(i), scopeChain[i], "backtrace");1313 scopeChainProxy[i] = InjectedScript.CallFrameProxy._createScopeJson(scopeChain[i], scopeDescriptions[i], "backtrace"); 1312 1314 return scopeChainProxy; 1313 1315 } … … 1322 1324 5: "globalLexicalEnvironment", // GLOBAL_LEXICAL_ENVIRONMENT_SCOPE 1323 1325 6: "nestedLexical", // NESTED_LEXICAL_SCOPE 1324 } 1325 1326 InjectedScript.CallFrameProxy._createScopeJson = function( scopeTypeCode, scopeObject, groupId)1326 }; 1327 1328 InjectedScript.CallFrameProxy._createScopeJson = function(object, {name, type, location}, groupId) 1327 1329 { 1328 return{1329 object: injectedScript._wrapObject( scopeObject, groupId),1330 type: InjectedScript.CallFrameProxy._scopeTypeNames[ scopeTypeCode]1330 var scope = { 1331 object: injectedScript._wrapObject(object, groupId), 1332 type: InjectedScript.CallFrameProxy._scopeTypeNames[type], 1331 1333 }; 1334 1335 if (name) 1336 scope.name = name; 1337 if (location) 1338 scope.location = location; 1339 1340 return scope; 1332 1341 } 1333 1342 -
trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.cpp
r200981 r202659 29 29 #include "DebuggerScope.h" 30 30 #include "Error.h" 31 #include "IdentifierInlines.h" 31 32 #include "JSCJSValue.h" 32 33 #include "JSCellInlines.h" 33 34 #include "JSJavaScriptCallFramePrototype.h" 35 #include "ObjectConstructor.h" 34 36 #include "StructureInlines.h" 35 37 … … 93 95 } 94 96 95 JSValue JSJavaScriptCallFrame::scopeType(ExecState* exec) 96 { 97 if (!impl().scopeChain()) 97 static JSValue valueForScopeType(DebuggerScope* scope) 98 { 99 if (scope->isCatchScope()) 100 return jsNumber(JSJavaScriptCallFrame::CATCH_SCOPE); 101 if (scope->isFunctionNameScope()) 102 return jsNumber(JSJavaScriptCallFrame::FUNCTION_NAME_SCOPE); 103 if (scope->isWithScope()) 104 return jsNumber(JSJavaScriptCallFrame::WITH_SCOPE); 105 if (scope->isNestedLexicalScope()) 106 return jsNumber(JSJavaScriptCallFrame::NESTED_LEXICAL_SCOPE); 107 if (scope->isGlobalLexicalEnvironment()) 108 return jsNumber(JSJavaScriptCallFrame::GLOBAL_LEXICAL_ENVIRONMENT_SCOPE); 109 if (scope->isGlobalScope()) 110 return jsNumber(JSJavaScriptCallFrame::GLOBAL_SCOPE); 111 112 ASSERT(scope->isClosureScope()); 113 return jsNumber(JSJavaScriptCallFrame::CLOSURE_SCOPE); 114 } 115 116 static JSValue valueForScopeLocation(ExecState* exec, const DebuggerLocation& location) 117 { 118 if (location.sourceID == noSourceID) 119 return jsNull(); 120 121 // Debugger.Location protocol object. 122 JSObject* result = constructEmptyObject(exec); 123 result->putDirect(exec->vm(), Identifier::fromString(exec, "scriptId"), jsString(exec, String::number(location.sourceID))); 124 result->putDirect(exec->vm(), Identifier::fromString(exec, "lineNumber"), jsNumber(location.line)); 125 result->putDirect(exec->vm(), Identifier::fromString(exec, "columnNumber"), jsNumber(location.column)); 126 return result; 127 } 128 129 JSValue JSJavaScriptCallFrame::scopeDescriptions(ExecState* exec) 130 { 131 DebuggerScope* scopeChain = impl().scopeChain(); 132 if (!scopeChain) 98 133 return jsUndefined(); 99 134 100 if (!exec->argument(0).isInt32()) 101 return jsUndefined(); 102 int index = exec->argument(0).asInt32(); 103 104 DebuggerScope* scopeChain = impl().scopeChain(); 135 int index = 0; 136 JSArray* array = constructEmptyArray(exec, nullptr); 137 105 138 DebuggerScope::iterator end = scopeChain->end(); 106 107 139 for (DebuggerScope::iterator iter = scopeChain->begin(); iter != end; ++iter) { 108 140 DebuggerScope* scope = iter.get(); 109 110 if (!index) { 111 if (scope->isCatchScope()) 112 return jsNumber(JSJavaScriptCallFrame::CATCH_SCOPE); 113 if (scope->isFunctionNameScope()) 114 return jsNumber(JSJavaScriptCallFrame::FUNCTION_NAME_SCOPE); 115 if (scope->isWithScope()) 116 return jsNumber(JSJavaScriptCallFrame::WITH_SCOPE); 117 if (scope->isNestedLexicalScope()) 118 return jsNumber(JSJavaScriptCallFrame::NESTED_LEXICAL_SCOPE); 119 if (scope->isGlobalLexicalEnvironment()) 120 return jsNumber(JSJavaScriptCallFrame::GLOBAL_LEXICAL_ENVIRONMENT_SCOPE); 121 if (scope->isGlobalScope()) { 122 ASSERT(++iter == end); 123 return jsNumber(JSJavaScriptCallFrame::GLOBAL_SCOPE); 124 } 125 ASSERT(scope->isClosureScope()); 126 return jsNumber(JSJavaScriptCallFrame::CLOSURE_SCOPE); 127 } 128 129 --index; 141 JSObject* description = constructEmptyObject(exec); 142 description->putDirect(exec->vm(), Identifier::fromString(exec, "type"), valueForScopeType(scope)); 143 description->putDirect(exec->vm(), Identifier::fromString(exec, "name"), jsString(exec, scope->name())); 144 description->putDirect(exec->vm(), Identifier::fromString(exec, "location"), valueForScopeLocation(exec, scope->location())); 145 array->putDirectIndex(exec, index++, description); 130 146 } 131 147 132 ASSERT_NOT_REACHED(); 133 return jsUndefined(); 148 return array; 134 149 } 135 150 -
trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.h
r200981 r202659 59 59 // Functions. 60 60 JSC::JSValue evaluateWithScopeExtension(JSC::ExecState*); 61 JSC::JSValue scope Type(JSC::ExecState*);61 JSC::JSValue scopeDescriptions(JSC::ExecState*); 62 62 63 63 // Attributes. -
trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFramePrototype.cpp
r200981 r202659 40 40 // Functions. 41 41 static EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFramePrototypeFunctionEvaluateWithScopeExtension(ExecState*); 42 static EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFramePrototypeFunctionScope Type(ExecState*);42 static EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFramePrototypeFunctionScopeDescriptions(ExecState*); 43 43 44 44 // Attributes. … … 62 62 63 63 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("evaluateWithScopeExtension", jsJavaScriptCallFramePrototypeFunctionEvaluateWithScopeExtension, DontEnum, 1); 64 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("scope Type", jsJavaScriptCallFramePrototypeFunctionScopeType, DontEnum, 1);64 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("scopeDescriptions", jsJavaScriptCallFramePrototypeFunctionScopeDescriptions, DontEnum, 0); 65 65 66 66 JSC_NATIVE_GETTER("caller", jsJavaScriptCallFrameAttributeCaller, DontEnum | Accessor); … … 85 85 } 86 86 87 EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFramePrototypeFunctionScope Type(ExecState* exec)87 EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFramePrototypeFunctionScopeDescriptions(ExecState* exec) 88 88 { 89 89 JSValue thisValue = exec->thisValue(); … … 92 92 return throwVMTypeError(exec); 93 93 94 return JSValue::encode(castedThis->scope Type(exec));94 return JSValue::encode(castedThis->scopeDescriptions(exec)); 95 95 } 96 96 -
trunk/Source/JavaScriptCore/inspector/protocol/Debugger.json
r200981 r202659 82 82 "type": "object", 83 83 "properties": [ 84 { "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." }, 84 85 { "name": "type", "type": "string", "enum": ["global", "with", "closure", "catch", "functionName", "globalLexicalEnvironment", "nestedLexical"], "description": "Scope type." }, 85 { "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." } 86 { "name": "name", "type": "string", "optional": true, "description": "Name associated with the scope." }, 87 { "name": "location", "$ref": "Location", "optional": true, "description": "Location if available of the scope definition." } 86 88 ], 87 89 "description": "Scope description." -
trunk/Source/JavaScriptCore/runtime/JSScope.cpp
r201266 r202659 341 341 } 342 342 343 SymbolTable* JSScope::symbolTable() 344 { 345 if (JSSymbolTableObject* symbolTableObject = jsDynamicCast<JSSymbolTableObject*>(this)) 346 return symbolTableObject->symbolTable(); 347 348 return nullptr; 349 } 350 343 351 } // namespace JSC -
trunk/Source/JavaScriptCore/runtime/JSScope.h
r198989 r202659 33 33 34 34 class ScopeChainIterator; 35 class SymbolTable; 36 class VariableEnvironment; 35 37 class WatchpointSet; 36 class VariableEnvironment;37 38 38 39 class JSScope : public JSNonFinalObject { … … 71 72 VM* vm(); 72 73 JSObject* globalThis(); 74 75 SymbolTable* symbolTable(); 73 76 74 77 protected: -
trunk/Source/JavaScriptCore/runtime/SymbolTable.cpp
r194251 r202659 105 105 visitor.append(&thisSymbolTable->m_singletonScope); 106 106 107 if (thisSymbolTable->m_rareData) 108 visitor.append(&thisSymbolTable->m_rareData->m_codeBlock); 109 107 110 // Save some memory. This is O(n) to rebuild and we do so on the fly. 108 111 ConcurrentJITLocker locker(thisSymbolTable->m_lock); … … 160 163 result->m_arguments.set(vm, result, arguments); 161 164 162 if (m_ typeProfilingRareData) {163 result->m_ typeProfilingRareData = std::make_unique<TypeProfilingRareData>();165 if (m_rareData) { 166 result->m_rareData = std::make_unique<SymbolTableRareData>(); 164 167 165 168 { 166 auto iter = m_ typeProfilingRareData->m_uniqueIDMap.begin();167 auto end = m_ typeProfilingRareData->m_uniqueIDMap.end();169 auto iter = m_rareData->m_uniqueIDMap.begin(); 170 auto end = m_rareData->m_uniqueIDMap.end(); 168 171 for (; iter != end; ++iter) 169 result->m_ typeProfilingRareData->m_uniqueIDMap.set(iter->key, iter->value);172 result->m_rareData->m_uniqueIDMap.set(iter->key, iter->value); 170 173 } 171 174 172 175 { 173 auto iter = m_ typeProfilingRareData->m_offsetToVariableMap.begin();174 auto end = m_ typeProfilingRareData->m_offsetToVariableMap.end();176 auto iter = m_rareData->m_offsetToVariableMap.begin(); 177 auto end = m_rareData->m_offsetToVariableMap.end(); 175 178 for (; iter != end; ++iter) 176 result->m_ typeProfilingRareData->m_offsetToVariableMap.set(iter->key, iter->value);179 result->m_rareData->m_offsetToVariableMap.set(iter->key, iter->value); 177 180 } 178 181 179 182 { 180 auto iter = m_ typeProfilingRareData->m_uniqueTypeSetMap.begin();181 auto end = m_ typeProfilingRareData->m_uniqueTypeSetMap.end();183 auto iter = m_rareData->m_uniqueTypeSetMap.begin(); 184 auto end = m_rareData->m_uniqueTypeSetMap.end(); 182 185 for (; iter != end; ++iter) 183 result->m_ typeProfilingRareData->m_uniqueTypeSetMap.set(iter->key, iter->value);186 result->m_rareData->m_uniqueTypeSetMap.set(iter->key, iter->value); 184 187 } 185 188 } … … 190 193 void SymbolTable::prepareForTypeProfiling(const ConcurrentJITLocker&) 191 194 { 192 if (m_ typeProfilingRareData)195 if (m_rareData) 193 196 return; 194 197 195 m_ typeProfilingRareData = std::make_unique<TypeProfilingRareData>();198 m_rareData = std::make_unique<SymbolTableRareData>(); 196 199 197 200 for (auto iter = m_map.begin(), end = m_map.end(); iter != end; ++iter) { 198 m_typeProfilingRareData->m_uniqueIDMap.set(iter->key, TypeProfilerNeedsUniqueIDGeneration); 199 m_typeProfilingRareData->m_offsetToVariableMap.set(iter->value.varOffset(), iter->key); 200 } 201 m_rareData->m_uniqueIDMap.set(iter->key, TypeProfilerNeedsUniqueIDGeneration); 202 m_rareData->m_offsetToVariableMap.set(iter->value.varOffset(), iter->key); 203 } 204 } 205 206 CodeBlock* SymbolTable::rareDataCodeBlock() 207 { 208 if (!m_rareData) 209 return nullptr; 210 211 return m_rareData->m_codeBlock.get(); 212 } 213 214 void SymbolTable::setRareDataCodeBlock(CodeBlock* codeBlock) 215 { 216 if (!m_rareData) 217 m_rareData = std::make_unique<SymbolTableRareData>(); 218 219 ASSERT(!m_rareData->m_codeBlock); 220 m_rareData->m_codeBlock.set(*codeBlock->vm(), this, codeBlock); 201 221 } 202 222 203 223 GlobalVariableID SymbolTable::uniqueIDForVariable(const ConcurrentJITLocker&, UniquedStringImpl* key, VM& vm) 204 224 { 205 RELEASE_ASSERT(m_ typeProfilingRareData);206 207 auto iter = m_ typeProfilingRareData->m_uniqueIDMap.find(key);208 auto end = m_ typeProfilingRareData->m_uniqueIDMap.end();225 RELEASE_ASSERT(m_rareData); 226 227 auto iter = m_rareData->m_uniqueIDMap.find(key); 228 auto end = m_rareData->m_uniqueIDMap.end(); 209 229 if (iter == end) 210 230 return TypeProfilerNoGlobalIDExists; … … 213 233 if (id == TypeProfilerNeedsUniqueIDGeneration) { 214 234 id = vm.typeProfiler()->getNextUniqueVariableID(); 215 m_ typeProfilingRareData->m_uniqueIDMap.set(key, id);216 m_ typeProfilingRareData->m_uniqueTypeSetMap.set(key, TypeSet::create()); // Make a new global typeset for this corresponding ID.235 m_rareData->m_uniqueIDMap.set(key, id); 236 m_rareData->m_uniqueTypeSetMap.set(key, TypeSet::create()); // Make a new global typeset for this corresponding ID. 217 237 } 218 238 … … 222 242 GlobalVariableID SymbolTable::uniqueIDForOffset(const ConcurrentJITLocker& locker, VarOffset offset, VM& vm) 223 243 { 224 RELEASE_ASSERT(m_ typeProfilingRareData);225 226 auto iter = m_ typeProfilingRareData->m_offsetToVariableMap.find(offset);227 auto end = m_ typeProfilingRareData->m_offsetToVariableMap.end();244 RELEASE_ASSERT(m_rareData); 245 246 auto iter = m_rareData->m_offsetToVariableMap.find(offset); 247 auto end = m_rareData->m_offsetToVariableMap.end(); 228 248 if (iter == end) 229 249 return TypeProfilerNoGlobalIDExists; … … 234 254 RefPtr<TypeSet> SymbolTable::globalTypeSetForOffset(const ConcurrentJITLocker& locker, VarOffset offset, VM& vm) 235 255 { 236 RELEASE_ASSERT(m_ typeProfilingRareData);256 RELEASE_ASSERT(m_rareData); 237 257 238 258 uniqueIDForOffset(locker, offset, vm); // Lazily create the TypeSet if necessary. 239 259 240 auto iter = m_ typeProfilingRareData->m_offsetToVariableMap.find(offset);241 auto end = m_ typeProfilingRareData->m_offsetToVariableMap.end();260 auto iter = m_rareData->m_offsetToVariableMap.find(offset); 261 auto end = m_rareData->m_offsetToVariableMap.end(); 242 262 if (iter == end) 243 263 return nullptr; … … 248 268 RefPtr<TypeSet> SymbolTable::globalTypeSetForVariable(const ConcurrentJITLocker& locker, UniquedStringImpl* key, VM& vm) 249 269 { 250 RELEASE_ASSERT(m_ typeProfilingRareData);270 RELEASE_ASSERT(m_rareData); 251 271 252 272 uniqueIDForVariable(locker, key, vm); // Lazily create the TypeSet if necessary. 253 273 254 auto iter = m_ typeProfilingRareData->m_uniqueTypeSetMap.find(key);255 auto end = m_ typeProfilingRareData->m_uniqueTypeSetMap.end();274 auto iter = m_rareData->m_uniqueTypeSetMap.find(key); 275 auto end = m_rareData->m_uniqueTypeSetMap.end(); 256 276 if (iter == end) 257 277 return nullptr; -
trunk/Source/JavaScriptCore/runtime/SymbolTable.h
r202588 r202659 680 680 681 681 void prepareForTypeProfiling(const ConcurrentJITLocker&); 682 683 CodeBlock* rareDataCodeBlock(); 684 void setRareDataCodeBlock(CodeBlock*); 682 685 683 686 InferredValue* singletonScope() { return m_singletonScope.get(); } … … 696 699 ScopeOffset m_maxScopeOffset; 697 700 698 struct TypeProfilingRareData {701 struct SymbolTableRareData { 699 702 UniqueIDMap m_uniqueIDMap; 700 703 OffsetToVariableMap m_offsetToVariableMap; 701 704 UniqueTypeSetMap m_uniqueTypeSetMap; 705 WriteBarrier<CodeBlock> m_codeBlock; 702 706 }; 703 std::unique_ptr< TypeProfilingRareData> m_typeProfilingRareData;707 std::unique_ptr<SymbolTableRareData> m_rareData; 704 708 705 709 bool m_usesNonStrictEval : 1; -
trunk/Source/WebInspectorUI/ChangeLog
r202657 r202659 1 2016-06-29 Joseph Pecoraro <pecoraro@apple.com> 2 3 Web Inspector: Wrong function name next to scope 4 https://bugs.webkit.org/show_bug.cgi?id=158210 5 <rdar://problem/26543093> 6 7 Reviewed by Brian Burg. 8 9 * UserInterface/Controllers/DebuggerManager.js: 10 (WebInspector.DebuggerManager.prototype._scopeChainNodeFromPayload): 11 Include new payload data in the construction call. 12 All the new data is optional, so we gracefully handle 13 legacy backends. 14 15 * UserInterface/Models/ScopeChainNode.js: 16 (WebInspector.ScopeChainNode): 17 (WebInspector.ScopeChainNode.prototype.get type): 18 (WebInspector.ScopeChainNode.prototype.get objects): 19 (WebInspector.ScopeChainNode.prototype.get name): 20 (WebInspector.ScopeChainNode.prototype.get location): 21 (WebInspector.ScopeChainNode.prototype.get hash): 22 Hash is a rough (name:sourceId:line:column) string for quick comparisons. 23 24 (WebInspector.ScopeChainNode.prototype.makeLocalScope): 25 Make this an action you take on a scope, to avoid having to 26 do it at construction time, or making it a generic setting. 27 28 * UserInterface/Views/ScopeChainDetailsSidebarPanel.js: 29 (WebInspector.ScopeChainDetailsSidebarPanel.prototype._generateCallFramesSection): 30 This was wrong before. Move the work to CallFrame 31 and change it to be correct. 32 33 * UserInterface/CallFrame.js: 34 (WebInspector.CallFrame.prototype.mergedScopeChain): 35 36 This transforms the scope chain for a call frame from: 37 38 scope1 scope2 scope3 scope4 scope5 scope6 scope7 39 foo foo foo bar bar - - 40 Block Closure Closure Closure Closure GLE GBL 41 42 To: 43 scope1 scope2&3 scope4&5 scope6 scope7 44 foo foo* bar* - - 45 Block Local Closure GLE GBL 46 47 Doing a few things: 48 49 - Merge the first two Closure scopes sharing a location. 50 These are the "var" and "let" Closure scopes in a function, 51 and it is better to present these together in the UI. 52 53 - Mark the first Closure scope within a function (*). When 54 this is displayed in the UI, we can provide the name of 55 the function: "Closure Scope (name)", and we even have 56 location information that we can use to display a goto 57 arrow if needed. 58 59 - Make the first Closure scope the Local scope if it 60 matches the Call Frame's function name. This lets us 61 display the section as "Local Variables". 62 1 63 2016-06-29 Brian Burg <bburg@apple.com> 2 64 -
trunk/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js
r201211 r202659 663 663 664 664 var object = WebInspector.RemoteObject.fromPayload(payload.object); 665 return new WebInspector.ScopeChainNode(type, [object] );665 return new WebInspector.ScopeChainNode(type, [object], payload.name, payload.location); 666 666 } 667 667 -
trunk/Source/WebInspectorUI/UserInterface/Models/CallFrame.js
r200981 r202659 46 46 // Public 47 47 48 get id() 49 { 50 return this._id; 51 } 52 53 get sourceCodeLocation() 54 { 55 return this._sourceCodeLocation; 56 } 57 58 get functionName() 59 { 60 return this._functionName; 61 } 62 63 get nativeCode() 64 { 65 return this._nativeCode; 66 } 67 68 get programCode() 69 { 70 return this._programCode; 71 } 72 73 get thisObject() 74 { 75 return this._thisObject; 76 } 77 78 get scopeChain() 79 { 80 return this._scopeChain; 81 } 82 83 get isTailDeleted() 84 { 85 return this._isTailDeleted; 86 } 48 get id() { return this._id; } 49 get sourceCodeLocation() { return this._sourceCodeLocation; } 50 get functionName() { return this._functionName; } 51 get nativeCode() { return this._nativeCode; } 52 get programCode() { return this._programCode; } 53 get thisObject() { return this._thisObject; } 54 get scopeChain() { return this._scopeChain; } 55 get isTailDeleted() { return this._isTailDeleted; } 87 56 88 57 saveIdentityToCookie() … … 111 80 for (var i = 0; i < this._scopeChain.length; ++i) 112 81 this._scopeChain[i].objects[0].deprecatedGetAllProperties(propertiesCollected); 82 } 83 84 mergedScopeChain() 85 { 86 let mergedScopes = []; 87 88 // Scopes list goes from top/local (1) to bottom/global (5) 89 // [scope1, scope2, scope3, scope4, scope5] 90 let scopes = this._scopeChain.slice(); 91 92 // Merge similiar scopes. Some function call frames may have multiple 93 // top level closure scopes (one for `var`s one for `let`s) that can be 94 // combined to a single scope of variables. Go in reverse order so we 95 // merge the first two closure scopes with the same name. Also mark 96 // the first time we see a new name, so we know the base for the name. 97 // [scope1&2, scope3, scope4, scope5] 98 // foo bar GLE global 99 let lastMarkedHash = null; 100 function markAsBaseIfNeeded(scope) { 101 if (!scope.hash) 102 return false; 103 if (scope.type !== WebInspector.ScopeChainNode.Type.Closure) 104 return false; 105 if (scope.hash === lastMarkedHash) 106 return false; 107 lastMarkedHash = scope.hash; 108 scope.__baseClosureScope = true; 109 return true; 110 } 111 112 function shouldMergeClosureScopes(youngScope, oldScope, lastMerge) { 113 if (!youngScope || !oldScope) 114 return false; 115 116 // Don't merge unknown locations. 117 if (!youngScope.hash || !oldScope.hash) 118 return false; 119 120 // Only merge closure scopes. 121 if (youngScope.type !== WebInspector.ScopeChainNode.Type.Closure) 122 return false; 123 if (oldScope.type !== WebInspector.ScopeChainNode.Type.Closure) 124 return false; 125 126 // Don't merge if they are not the same. 127 if (youngScope.hash !== oldScope.hash) 128 return false; 129 130 // Don't merge if there was already a merge. 131 if (lastMerge && youngScope.hash === lastMerge.hash) 132 return false; 133 134 return true; 135 } 136 137 let lastScope = null; 138 let lastMerge = null; 139 for (let i = scopes.length - 1; i >= 0; --i) { 140 let scope = scopes[i]; 141 markAsBaseIfNeeded(scope); 142 if (shouldMergeClosureScopes(scope, lastScope, lastMerge)) { 143 console.assert(lastScope.__baseClosureScope); 144 let type = WebInspector.ScopeChainNode.Type.Closure; 145 let objects = lastScope.objects.concat(scope.objects); 146 let merged = new WebInspector.ScopeChainNode(type, objects, scope.name, scope.location); 147 merged.__baseClosureScope = true; 148 console.assert(objects.length === 2); 149 150 mergedScopes.pop(); // Remove the last. 151 mergedScopes.push(merged); // Add the merged scope. 152 153 lastMerge = merged; 154 lastScope = null; 155 } else { 156 mergedScopes.push(scope); 157 158 lastMerge = null; 159 lastScope = scope; 160 } 161 } 162 163 mergedScopes = mergedScopes.reverse(); 164 165 // Mark the first Closure as Local if the name matches this call frame. 166 for (let scope of mergedScopes) { 167 if (scope.type === WebInspector.ScopeChainNode.Type.Closure) { 168 if (scope.name === this._functionName) 169 scope.convertToLocalScope(); 170 break; 171 } 172 } 173 174 return mergedScopes; 113 175 } 114 176 -
trunk/Source/WebInspectorUI/UserInterface/Models/ScopeChainNode.js
r201630 r202659 26 26 WebInspector.ScopeChainNode = class ScopeChainNode extends WebInspector.Object 27 27 { 28 constructor(type, objects )28 constructor(type, objects, name, location) 29 29 { 30 30 super(); … … 38 38 this._type = type || null; 39 39 this._objects = objects || []; 40 this._name = name || ""; 41 this._location = location || null; 40 42 } 41 43 42 44 // Public 43 45 44 get type() 46 get type() { return this._type; } 47 get objects() { return this._objects; } 48 get name() { return this._name; } 49 get location() { return this._location; } 50 51 get hash() 45 52 { 46 return this._type; 53 if (this._hash) 54 return this._hash; 55 56 this._hash = this._name; 57 if (this._location) 58 this._hash += `:${this._location.scriptId}:${this._location.lineNumber}:${this._location.columnNumber}`; 59 return this._hash; 47 60 } 48 61 49 get objects()62 convertToLocalScope() 50 63 { 51 return this._objects;64 this._type = WebInspector.ScopeChainNode.Type.Local; 52 65 } 53 66 }; -
trunk/Source/WebInspectorUI/UserInterface/Views/ScopeChainDetailsSidebarPanel.js
r201855 r202659 165 165 sectionCountByType.set(WebInspector.ScopeChainNode.Type[type], 0); 166 166 167 // Scopes list goes from top/local (1) to bottom/global (5) 168 // Call frames list goes from top/local (1) to bottom/global (2) 169 // [scope1, scope2, scope3, scope4, scope5] 170 // [CallFrame1, CallFrame2] 171 let scopeChain = callFrame.scopeChain; 172 let callFrames = WebInspector.debuggerManager.callFrames; 173 174 // Group scopes with the call frame containing them. 175 // Creating a map that looks like: 176 // CallFrame2 => [scope5, scope4] 177 // CallFrame1 => [scope3, scope2, scope1] 178 let reversedScopeChain = scopeChain.slice().reverse(); 179 let callFrameScopes = new Map; 180 let lastLength = 0; 181 for (let i = callFrames.length - 1; i >= 0; --i) { 182 let nextCallFrame = callFrames[i]; 183 console.assert(nextCallFrame.scopeChain.length > lastLength); 184 callFrameScopes.set(nextCallFrame, reversedScopeChain.slice(lastLength, nextCallFrame.scopeChain.length)); 185 lastLength = nextCallFrame.scopeChain.length; 186 if (nextCallFrame === callFrame) { 187 console.assert(lastLength === scopeChain.length); 167 let scopeChain = callFrame.mergedScopeChain(); 168 for (let scope of scopeChain) { 169 let title = null; 170 let extraPropertyDescriptor = null; 171 let collapsedByDefault = false; 172 173 let count = sectionCountByType.get(scope.type); 174 sectionCountByType.set(scope.type, ++count); 175 176 switch (scope.type) { 177 case WebInspector.ScopeChainNode.Type.Local: 178 foundLocalScope = true; 179 collapsedByDefault = false; 180 title = WebInspector.UIString("Local Variables"); 181 if (callFrame.thisObject) 182 extraPropertyDescriptor = new WebInspector.PropertyDescriptor({name: "this", value: callFrame.thisObject}); 183 break; 184 185 case WebInspector.ScopeChainNode.Type.Closure: 186 if (scope.__baseClosureScope && scope.name) 187 title = WebInspector.UIString("Closure Variables (%s)").format(scope.name); 188 else 189 title = WebInspector.UIString("Closure Variables"); 190 collapsedByDefault = false; 191 break; 192 193 case WebInspector.ScopeChainNode.Type.Block: 194 title = WebInspector.UIString("Block Variables"); 195 collapsedByDefault = false; 196 break; 197 198 case WebInspector.ScopeChainNode.Type.Catch: 199 title = WebInspector.UIString("Catch Variables"); 200 collapsedByDefault = false; 201 break; 202 203 case WebInspector.ScopeChainNode.Type.FunctionName: 204 title = WebInspector.UIString("Function Name Variable"); 205 collapsedByDefault = true; 206 break; 207 208 case WebInspector.ScopeChainNode.Type.With: 209 title = WebInspector.UIString("With Object Properties"); 210 collapsedByDefault = foundLocalScope; 211 break; 212 213 case WebInspector.ScopeChainNode.Type.Global: 214 title = WebInspector.UIString("Global Variables"); 215 collapsedByDefault = true; 216 break; 217 218 case WebInspector.ScopeChainNode.Type.GlobalLexicalEnvironment: 219 title = WebInspector.UIString("Global Lexical Environment"); 220 collapsedByDefault = true; 188 221 break; 189 222 } 190 } 191 192 // Now that we have this map we can merge some of the scopes within an individual 193 // call frame. In particular, function call frames may have multiple top level 194 // closure scopes (one for `var`s one for `let`s) that can be combined to a 195 // single scope of variables. 196 // This modifies the Map, resulting in: 197 // CallFrame2 => [scope4, scope5] 198 // CallFrame1 => [scope1, scope2&3] 199 for (let [currentCallFrame, scopes] of callFrameScopes) { 200 let firstClosureScope = null; 201 for (let scope of scopes) { 202 // Reached a non-closure scope. Bail. 203 let isClosureScope = scope.type === WebInspector.ScopeChainNode.Type.Closure; 204 if (!isClosureScope && firstClosureScope) 205 break; 206 207 // Found first closure scope. Mark it so we can provide the function name later in the UI. 208 if (isClosureScope && !firstClosureScope) { 209 firstClosureScope = scope; 210 firstClosureScope[WebInspector.ScopeChainDetailsSidebarPanel.CallFrameBaseClosureScopeSymbol] = true; 211 continue; 223 224 let detailsSectionIdentifier = scope.type + "-" + sectionCountByType.get(scope.type); 225 226 // FIXME: This just puts two ObjectTreeViews next to each other, but that means 227 // that properties are not nicely sorted between the two separate lists. 228 229 let rows = []; 230 for (let object of scope.objects) { 231 let scopePropertyPath = WebInspector.PropertyPath.emptyPropertyPathForScope(object); 232 let objectTree = new WebInspector.ObjectTreeView(object, WebInspector.ObjectTreeView.Mode.Properties, scopePropertyPath); 233 234 objectTree.showOnlyProperties(); 235 236 if (extraPropertyDescriptor) { 237 objectTree.appendExtraPropertyDescriptor(extraPropertyDescriptor); 238 extraPropertyDescriptor = null; 212 239 } 213 240 214 // Found 2 sequential top level closure scopes. Merge and mark it so we can provide the function name later in the UI. 215 if (isClosureScope && firstClosureScope) { 216 let type = currentCallFrame === callFrame ? WebInspector.ScopeChainNode.Type.Local : WebInspector.ScopeChainNode.Type.Closure; 217 let objects = firstClosureScope.objects.concat(scope.objects); 218 let merged = new WebInspector.ScopeChainNode(type, objects); 219 merged[WebInspector.ScopeChainDetailsSidebarPanel.CallFrameBaseClosureScopeSymbol] = true; 220 console.assert(objects.length === 2); 221 222 let index = scopes.indexOf(firstClosureScope); 223 scopes.splice(index, 1); // Remove one of them. 224 scopes[index] = merged; // Replace the remaining with the merged. 225 break; 226 } 241 let treeOutline = objectTree.treeOutline; 242 treeOutline.addEventListener(WebInspector.TreeOutline.Event.ElementAdded, this._treeElementAdded.bind(this, detailsSectionIdentifier), this); 243 treeOutline.addEventListener(WebInspector.TreeOutline.Event.ElementDisclosureDidChanged, this._treeElementDisclosureDidChange.bind(this, detailsSectionIdentifier), this); 244 245 // FIXME: <https://webkit.org/b/140567> Web Inspector: Do not request Scope Chain lists if section is collapsed (mainly Global Variables) 246 // This autoexpands the ObjectTreeView and fetches all properties. Should wait to see if we are collapsed or not. 247 rows.push(new WebInspector.DetailsSectionPropertiesRow(objectTree)); 227 248 } 228 scopes.reverse(); 229 } 230 231 // Now we can walk the list of call frames and their scopes. 232 // We walk in top -> down order: 233 // CallFrame1 => [scope1, scope2&3] 234 // CallFrame2 => [scope5, scope4] 235 for (let [call, scopes] of [...callFrameScopes.entries()].reverse()) { 236 for (let scope of scopes) { 237 let title = null; 238 let extraPropertyDescriptor = null; 239 let collapsedByDefault = false; 240 241 let count = sectionCountByType.get(scope.type); 242 sectionCountByType.set(scope.type, ++count); 243 244 switch (scope.type) { 245 case WebInspector.ScopeChainNode.Type.Local: 246 foundLocalScope = true; 247 collapsedByDefault = false; 248 title = WebInspector.UIString("Local Variables"); 249 if (call.thisObject) 250 extraPropertyDescriptor = new WebInspector.PropertyDescriptor({name: "this", value: call.thisObject}); 251 break; 252 253 case WebInspector.ScopeChainNode.Type.Closure: 254 if (scope[WebInspector.ScopeChainDetailsSidebarPanel.CallFrameBaseClosureScopeSymbol] && call.functionName) 255 title = WebInspector.UIString("Closure Variables (%s)").format(call.functionName); 256 else 257 title = WebInspector.UIString("Closure Variables"); 258 collapsedByDefault = false; 259 break; 260 261 case WebInspector.ScopeChainNode.Type.Block: 262 title = WebInspector.UIString("Block Variables"); 263 collapsedByDefault = false; 264 break; 265 266 case WebInspector.ScopeChainNode.Type.Catch: 267 title = WebInspector.UIString("Catch Variables"); 268 collapsedByDefault = false; 269 break; 270 271 case WebInspector.ScopeChainNode.Type.FunctionName: 272 title = WebInspector.UIString("Function Name Variable"); 273 collapsedByDefault = true; 274 break; 275 276 case WebInspector.ScopeChainNode.Type.With: 277 title = WebInspector.UIString("With Object Properties"); 278 collapsedByDefault = foundLocalScope; 279 break; 280 281 case WebInspector.ScopeChainNode.Type.Global: 282 title = WebInspector.UIString("Global Variables"); 283 collapsedByDefault = true; 284 break; 285 286 case WebInspector.ScopeChainNode.Type.GlobalLexicalEnvironment: 287 title = WebInspector.UIString("Global Lexical Environment"); 288 collapsedByDefault = true; 289 break; 290 } 291 292 let detailsSectionIdentifier = scope.type + "-" + sectionCountByType.get(scope.type); 293 294 // FIXME: This just puts two ObjectTreeViews next to eachother, but that means 295 // that properties are not nicely sorted between the two separate lists. 296 297 let rows = []; 298 for (let object of scope.objects) { 299 let scopePropertyPath = WebInspector.PropertyPath.emptyPropertyPathForScope(object); 300 let objectTree = new WebInspector.ObjectTreeView(object, WebInspector.ObjectTreeView.Mode.Properties, scopePropertyPath); 301 302 objectTree.showOnlyProperties(); 303 304 if (extraPropertyDescriptor) { 305 objectTree.appendExtraPropertyDescriptor(extraPropertyDescriptor); 306 extraPropertyDescriptor = null; 307 } 308 309 let treeOutline = objectTree.treeOutline; 310 treeOutline.addEventListener(WebInspector.TreeOutline.Event.ElementAdded, this._treeElementAdded.bind(this, detailsSectionIdentifier), this); 311 treeOutline.addEventListener(WebInspector.TreeOutline.Event.ElementDisclosureDidChanged, this._treeElementDisclosureDidChange.bind(this, detailsSectionIdentifier), this); 312 313 rows.push(new WebInspector.DetailsSectionPropertiesRow(objectTree)); 314 } 315 316 let detailsSection = new WebInspector.DetailsSection(detailsSectionIdentifier, title, null, null, collapsedByDefault); 317 detailsSection.groups[0].rows = rows; 318 detailsSections.push(detailsSection); 319 } 249 250 let detailsSection = new WebInspector.DetailsSection(detailsSectionIdentifier, title, null, null, collapsedByDefault); 251 detailsSection.groups[0].rows = rows; 252 detailsSections.push(detailsSection); 320 253 } 321 254 … … 546 479 WebInspector.ScopeChainDetailsSidebarPanel._autoExpandProperties = new Set; 547 480 WebInspector.ScopeChainDetailsSidebarPanel.WatchExpressionsObjectGroupName = "watch-expressions"; 548 WebInspector.ScopeChainDetailsSidebarPanel.CallFrameBaseClosureScopeSymbol = Symbol("scope-chain-call-frame-base-closure-scope");
Note: See TracChangeset
for help on using the changeset viewer.