[debug] Fix scope for class member initializer
This CL removes the bailout when trying to collect the scope info for the class member initializer function. While this might not have worked previously, now we only need to tweak the scope search slightly to fix this. Class member initializer functions never have their own context but instead us the class context. That means that most of the logic in debug-scopes.cc doesn't really matter and we only need to initialize the ScopeIterator properly with the class context and the member initializer JSFunction. Note that this still does not fully fix bug 1350842. That is because we still run into a DCHECk when paused at a `new class { ... }` statement. We'll fix that in a separate CL. R=bmeurer@chromium.org Bug: chromium:1350842 Change-Id: Id128b10676a5aa8a77309735e755e485f2c14446 Fixed: chromium:1246889 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3825881 Commit-Queue: Simon Zünd <szuend@chromium.org> Reviewed-by: Benedikt Meurer <bmeurer@chromium.org> Cr-Commit-Position: refs/heads/main@{#82387}
This commit is contained in:
parent
606e7022b8
commit
aa101ca18f
@ -132,7 +132,13 @@ class ScopeChainRetriever {
|
||||
}
|
||||
|
||||
bool RetrieveClosureScope(Scope* scope) {
|
||||
if (break_scope_start_ == scope->start_position() &&
|
||||
// The closure scope is the scope that matches exactly the function we
|
||||
// paused in. There is one quirk though, member initializder functions have
|
||||
// the same source position as their class scope, so when looking for the
|
||||
// declaration scope of the member initializer, we need to skip the
|
||||
// corresponding class scope and keep looking.
|
||||
if (!scope->is_class_scope() &&
|
||||
break_scope_start_ == scope->start_position() &&
|
||||
break_scope_end_ == scope->end_position()) {
|
||||
closure_scope_ = scope->AsDeclarationScope();
|
||||
return true;
|
||||
@ -194,16 +200,6 @@ void ScopeIterator::TryParseAndRetrieveScopes(ReparseStrategy strategy) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Class fields initializer functions don't have any scope
|
||||
// information. We short circuit the parsing of the class literal
|
||||
// and return an empty context here.
|
||||
if (IsClassMembersInitializerFunction(shared_info->kind())) {
|
||||
current_scope_ = closure_scope_ = nullptr;
|
||||
context_ = Handle<Context>();
|
||||
function_ = Handle<JSFunction>();
|
||||
return;
|
||||
}
|
||||
|
||||
bool ignore_nested_scopes = false;
|
||||
if (shared_info->HasBreakInfo() && frame_inspector_ != nullptr) {
|
||||
// The source position at return is always the end of the function,
|
||||
|
@ -198,6 +198,55 @@ Running test: testScopesPaused
|
||||
scriptId : <scriptId>
|
||||
}
|
||||
scopeChain : [
|
||||
[0] : {
|
||||
endLocation : {
|
||||
columnNumber : 3
|
||||
lineNumber : 15
|
||||
scriptId : <scriptId>
|
||||
}
|
||||
name : <instance_members_initializer>
|
||||
object : {
|
||||
className : Object
|
||||
description : Object
|
||||
objectId : <objectId>
|
||||
type : object
|
||||
}
|
||||
startLocation : {
|
||||
columnNumber : 2
|
||||
lineNumber : 11
|
||||
scriptId : <scriptId>
|
||||
}
|
||||
type : local
|
||||
}
|
||||
[1] : {
|
||||
endLocation : {
|
||||
columnNumber : 1
|
||||
lineNumber : 19
|
||||
scriptId : <scriptId>
|
||||
}
|
||||
name : run
|
||||
object : {
|
||||
className : Object
|
||||
description : Object
|
||||
objectId : <objectId>
|
||||
type : object
|
||||
}
|
||||
startLocation : {
|
||||
columnNumber : 12
|
||||
lineNumber : 1
|
||||
scriptId : <scriptId>
|
||||
}
|
||||
type : closure
|
||||
}
|
||||
[2] : {
|
||||
object : {
|
||||
className : global
|
||||
description : global
|
||||
objectId : <objectId>
|
||||
type : object
|
||||
}
|
||||
type : global
|
||||
}
|
||||
]
|
||||
this : {
|
||||
className : X
|
||||
@ -383,6 +432,55 @@ Running test: testScopesPaused
|
||||
scriptId : <scriptId>
|
||||
}
|
||||
scopeChain : [
|
||||
[0] : {
|
||||
endLocation : {
|
||||
columnNumber : 3
|
||||
lineNumber : 15
|
||||
scriptId : <scriptId>
|
||||
}
|
||||
name : <instance_members_initializer>
|
||||
object : {
|
||||
className : Object
|
||||
description : Object
|
||||
objectId : <objectId>
|
||||
type : object
|
||||
}
|
||||
startLocation : {
|
||||
columnNumber : 2
|
||||
lineNumber : 11
|
||||
scriptId : <scriptId>
|
||||
}
|
||||
type : local
|
||||
}
|
||||
[1] : {
|
||||
endLocation : {
|
||||
columnNumber : 1
|
||||
lineNumber : 19
|
||||
scriptId : <scriptId>
|
||||
}
|
||||
name : run
|
||||
object : {
|
||||
className : Object
|
||||
description : Object
|
||||
objectId : <objectId>
|
||||
type : object
|
||||
}
|
||||
startLocation : {
|
||||
columnNumber : 12
|
||||
lineNumber : 1
|
||||
scriptId : <scriptId>
|
||||
}
|
||||
type : closure
|
||||
}
|
||||
[2] : {
|
||||
object : {
|
||||
className : global
|
||||
description : global
|
||||
objectId : <objectId>
|
||||
type : object
|
||||
}
|
||||
type : global
|
||||
}
|
||||
]
|
||||
this : {
|
||||
className : X
|
||||
@ -568,6 +666,55 @@ Running test: testScopesPaused
|
||||
scriptId : <scriptId>
|
||||
}
|
||||
scopeChain : [
|
||||
[0] : {
|
||||
endLocation : {
|
||||
columnNumber : 3
|
||||
lineNumber : 15
|
||||
scriptId : <scriptId>
|
||||
}
|
||||
name : <instance_members_initializer>
|
||||
object : {
|
||||
className : Object
|
||||
description : Object
|
||||
objectId : <objectId>
|
||||
type : object
|
||||
}
|
||||
startLocation : {
|
||||
columnNumber : 2
|
||||
lineNumber : 11
|
||||
scriptId : <scriptId>
|
||||
}
|
||||
type : local
|
||||
}
|
||||
[1] : {
|
||||
endLocation : {
|
||||
columnNumber : 1
|
||||
lineNumber : 19
|
||||
scriptId : <scriptId>
|
||||
}
|
||||
name : run
|
||||
object : {
|
||||
className : Object
|
||||
description : Object
|
||||
objectId : <objectId>
|
||||
type : object
|
||||
}
|
||||
startLocation : {
|
||||
columnNumber : 12
|
||||
lineNumber : 1
|
||||
scriptId : <scriptId>
|
||||
}
|
||||
type : closure
|
||||
}
|
||||
[2] : {
|
||||
object : {
|
||||
className : global
|
||||
description : global
|
||||
objectId : <objectId>
|
||||
type : object
|
||||
}
|
||||
type : global
|
||||
}
|
||||
]
|
||||
this : {
|
||||
className : X
|
||||
@ -826,6 +973,55 @@ Running test: testScopesPaused
|
||||
scriptId : <scriptId>
|
||||
}
|
||||
scopeChain : [
|
||||
[0] : {
|
||||
endLocation : {
|
||||
columnNumber : 3
|
||||
lineNumber : 15
|
||||
scriptId : <scriptId>
|
||||
}
|
||||
name : <instance_members_initializer>
|
||||
object : {
|
||||
className : Object
|
||||
description : Object
|
||||
objectId : <objectId>
|
||||
type : object
|
||||
}
|
||||
startLocation : {
|
||||
columnNumber : 2
|
||||
lineNumber : 11
|
||||
scriptId : <scriptId>
|
||||
}
|
||||
type : local
|
||||
}
|
||||
[1] : {
|
||||
endLocation : {
|
||||
columnNumber : 1
|
||||
lineNumber : 19
|
||||
scriptId : <scriptId>
|
||||
}
|
||||
name : run
|
||||
object : {
|
||||
className : Object
|
||||
description : Object
|
||||
objectId : <objectId>
|
||||
type : object
|
||||
}
|
||||
startLocation : {
|
||||
columnNumber : 12
|
||||
lineNumber : 1
|
||||
scriptId : <scriptId>
|
||||
}
|
||||
type : closure
|
||||
}
|
||||
[2] : {
|
||||
object : {
|
||||
className : global
|
||||
description : global
|
||||
objectId : <objectId>
|
||||
type : object
|
||||
}
|
||||
type : global
|
||||
}
|
||||
]
|
||||
this : {
|
||||
className : X
|
||||
|
21
test/inspector/regress/regress-crbug-1350842-expected.txt
Normal file
21
test/inspector/regress/regress-crbug-1350842-expected.txt
Normal file
@ -0,0 +1,21 @@
|
||||
Don't crash when evaluating `this` in class instance initializer
|
||||
{
|
||||
id : <messageId>
|
||||
result : {
|
||||
result : {
|
||||
className : tmpName
|
||||
description : tmpName
|
||||
objectId : <objectId>
|
||||
type : object
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
id : <messageId>
|
||||
result : {
|
||||
result : {
|
||||
type : string
|
||||
value : tmpName
|
||||
}
|
||||
}
|
||||
}
|
42
test/inspector/regress/regress-crbug-1350842.js
Normal file
42
test/inspector/regress/regress-crbug-1350842.js
Normal file
@ -0,0 +1,42 @@
|
||||
// Copyright 2022 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
const {contextGroup, Protocol} = InspectorTest.start('Don\'t crash when evaluating `this` in class instance initializer');
|
||||
|
||||
const script = `
|
||||
(function foo() {
|
||||
function identity(v) {
|
||||
return v;
|
||||
}
|
||||
|
||||
debugger;
|
||||
|
||||
class tmpName {
|
||||
#thisWorks = this.constructor.name;
|
||||
#thisFails = identity(this.constructor.name);
|
||||
};
|
||||
new tmpName;
|
||||
})();
|
||||
`;
|
||||
|
||||
(async () => {
|
||||
Protocol.Debugger.enable();
|
||||
|
||||
contextGroup.addScript(script, 0, 0, 'test.js');
|
||||
|
||||
await Protocol.Debugger.oncePaused();
|
||||
|
||||
Protocol.Debugger.stepInto({});
|
||||
await Protocol.Debugger.oncePaused();
|
||||
|
||||
Protocol.Debugger.stepInto({});
|
||||
const { params: { callFrames } } = await Protocol.Debugger.oncePaused();
|
||||
|
||||
InspectorTest.logMessage(
|
||||
await Protocol.Debugger.evaluateOnCallFrame({ callFrameId: callFrames[0].callFrameId, expression: "this" }));
|
||||
InspectorTest.logMessage(
|
||||
await Protocol.Debugger.evaluateOnCallFrame({ callFrameId: callFrames[0].callFrameId, expression: "this.constructor.name" }));
|
||||
|
||||
InspectorTest.completeTest();
|
||||
})();
|
Loading…
Reference in New Issue
Block a user