Commit c2f30c2b authored by Benedikt Meurer's avatar Benedikt Meurer Committed by V8 LUCI CQ

[inspector] Fix positions for inline scripts with #sourceURL.

For inline scripts that have a `// #sourceURL=foo.js` annotation, the
V8 inspector (and by extension `Error.stack`) currently operates in
terms of the `foo.js`, i.e. doesn't give any hint about the actual
source, except for the line/column offsets reported upon scriptParsed.
However in case of stack frames (i.e. as part of `Error.stack` or as
part of the call frames reported via CDP), the line/column offsets are
relative to the actual source instead of relative to the `foo.js` part,
which - besides other things - makes post-processing of recorded stack
traces tricky (sometimes impossible).

This change adjusts the source positions reported for (inline) scripts
with sourceURL annotations to be relative to the (inline) script instead
of the surrounding document.

Bug: chromium:1183990
Fixed: chromium:578269
Change-Id: I74f2b93c22ec43ca796b6b51faa9df5b99cf03f9
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3069289
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Auto-Submit: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: 's avatarSimon Zünd <szuend@chromium.org>
Cr-Commit-Position: refs/heads/master@{#76097}
parent 1b1b4572
...@@ -175,6 +175,10 @@ bool Script::HasValidSource() { ...@@ -175,6 +175,10 @@ bool Script::HasValidSource() {
return true; return true;
} }
bool Script::HasSourceURLComment() const {
return source_url().IsString() && String::cast(source_url()).length() != 0;
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
......
...@@ -142,6 +142,9 @@ class Script : public TorqueGeneratedScript<Script, Struct> { ...@@ -142,6 +142,9 @@ class Script : public TorqueGeneratedScript<Script, Struct> {
// resource is accessible. Otherwise, always return true. // resource is accessible. Otherwise, always return true.
inline bool HasValidSource(); inline bool HasValidSource();
// If the script has a non-empty sourceURL comment.
inline bool HasSourceURLComment() const;
Object GetNameOrSourceURL(); Object GetNameOrSourceURL();
// Retrieve source position from where eval was called. // Retrieve source position from where eval was called.
......
...@@ -68,7 +68,11 @@ int StackFrameInfo::GetLineNumber(Handle<StackFrameInfo> info) { ...@@ -68,7 +68,11 @@ int StackFrameInfo::GetLineNumber(Handle<StackFrameInfo> info) {
Handle<Script> script; Handle<Script> script;
if (GetScript(isolate, info).ToHandle(&script)) { if (GetScript(isolate, info).ToHandle(&script)) {
int position = GetSourcePosition(info); int position = GetSourcePosition(info);
return Script::GetLineNumber(script, position) + 1; int line_number = Script::GetLineNumber(script, position) + 1;
if (script->HasSourceURLComment()) {
line_number -= script->line_offset();
}
return line_number;
} }
return Message::kNoLineNumberInfo; return Message::kNoLineNumberInfo;
} }
...@@ -84,7 +88,13 @@ int StackFrameInfo::GetColumnNumber(Handle<StackFrameInfo> info) { ...@@ -84,7 +88,13 @@ int StackFrameInfo::GetColumnNumber(Handle<StackFrameInfo> info) {
#endif // V8_ENABLE_WEBASSEMBLY #endif // V8_ENABLE_WEBASSEMBLY
Handle<Script> script; Handle<Script> script;
if (GetScript(isolate, info).ToHandle(&script)) { if (GetScript(isolate, info).ToHandle(&script)) {
return Script::GetColumnNumber(script, position) + 1; int column_number = Script::GetColumnNumber(script, position) + 1;
if (script->HasSourceURLComment()) {
if (Script::GetLineNumber(script, position) == script->line_offset()) {
column_number -= script->column_offset();
}
}
return column_number;
} }
return Message::kNoColumnInfo; return Message::kNoColumnInfo;
} }
......
...@@ -9,12 +9,12 @@ test (test.js:21:2) ...@@ -9,12 +9,12 @@ test (test.js:21:2)
foo (test.js:10:2) foo (test.js:10:2)
-- Promise.then -- -- Promise.then --
test (test.js:19:14) test (test.js:12:14)
(anonymous) (expr1.js:0:0) (anonymous) (expr1.js:0:0)
foo (test.js:12:2) foo (test.js:12:2)
-- Promise.then -- -- Promise.then --
test (test.js:19:14) test (test.js:12:14)
(anonymous) (expr1.js:0:0) (anonymous) (expr1.js:0:0)
......
Checks async stack for late .then handlers with gc Checks async stack for late .then handlers with gc
foo1 (test.js:11:2) foo1 (test.js:11:2)
-- Promise.then -- -- Promise.then --
test (test.js:18:14) test (test.js:10:14)
(anonymous) (expr.js:0:0) (anonymous) (expr.js:0:0)
foo1 (test.js:11:2) foo1 (test.js:11:2)
-- Promise.then -- -- Promise.then --
test (test.js:22:14) test (test.js:14:14)
(anonymous) (expr.js:0:0) (anonymous) (expr.js:0:0)
foo1 (test.js:11:2) foo1 (test.js:11:2)
-- Promise.then -- -- Promise.then --
test (test.js:24:14) test (test.js:16:14)
(anonymous) (expr.js:0:0) (anonymous) (expr.js:0:0)
...@@ -2,10 +2,10 @@ Checks that async stack contains setTimeout ...@@ -2,10 +2,10 @@ Checks that async stack contains setTimeout
inner1 (test.js:11:4) inner1 (test.js:11:4)
foo1 (test.js:14:2) foo1 (test.js:14:2)
-- setTimeout -- -- setTimeout --
inner2 (test.js:18:4) inner2 (test.js:11:4)
foo2 (test.js:20:2) foo2 (test.js:13:2)
-- setTimeout -- -- setTimeout --
inner3 (test.js:25:4) inner3 (test.js:18:4)
foo3 (test.js:27:2) foo3 (test.js:20:2)
(anonymous) (expr.js:0:0) (anonymous) (expr.js:0:0)
...@@ -3,78 +3,78 @@ Checks created frame for async call chain ...@@ -3,78 +3,78 @@ Checks created frame for async call chain
Running test: testPromise Running test: testPromise
foo1 (test.js:10:2) foo1 (test.js:10:2)
-- Promise.then -- -- Promise.then --
promise (test.js:20:14) promise (test.js:12:14)
(anonymous) (expr.js:0:0) (anonymous) (expr.js:0:0)
Running test: testPromiseThen Running test: testPromiseThen
foo1 (test.js:10:2) foo1 (test.js:10:2)
-- Promise.then -- -- Promise.then --
promiseThen (test.js:28:14) promiseThen (test.js:20:14)
(anonymous) (expr.js:0:0) (anonymous) (expr.js:0:0)
foo2 (test.js:14:2) foo2 (test.js:14:2)
-- Promise.then -- -- Promise.then --
promiseThen (test.js:29:14) promiseThen (test.js:21:14)
(anonymous) (expr.js:0:0) (anonymous) (expr.js:0:0)
Running test: testPromiseThenThen Running test: testPromiseThenThen
foo1 (test.js:10:2) foo1 (test.js:10:2)
-- Promise.then -- -- Promise.then --
promiseThenThen (test.js:37:14) promiseThenThen (test.js:29:14)
(anonymous) (expr.js:0:0) (anonymous) (expr.js:0:0)
foo1 (test.js:10:2) foo1 (test.js:10:2)
-- Promise.then -- -- Promise.then --
promiseThenThen (test.js:38:14) promiseThenThen (test.js:30:14)
(anonymous) (expr.js:0:0) (anonymous) (expr.js:0:0)
foo2 (test.js:14:2) foo2 (test.js:14:2)
-- Promise.then -- -- Promise.then --
promiseThenThen (test.js:37:25) promiseThenThen (test.js:29:25)
(anonymous) (expr.js:0:0) (anonymous) (expr.js:0:0)
Running test: testPromiseResolve Running test: testPromiseResolve
foo1 (test.js:10:2) foo1 (test.js:10:2)
-- Promise.then -- -- Promise.then --
promiseResolve (test.js:44:27) promiseResolve (test.js:36:27)
(anonymous) (expr.js:0:0) (anonymous) (expr.js:0:0)
Running test: testPromiseReject Running test: testPromiseReject
foo1 (test.js:10:2) foo1 (test.js:10:2)
-- Promise.catch -- -- Promise.catch --
promiseReject (test.js:48:31) promiseReject (test.js:40:31)
(anonymous) (expr.js:0:0) (anonymous) (expr.js:0:0)
Running test: testPromiseAll Running test: testPromiseAll
foo1 (test.js:10:2) foo1 (test.js:10:2)
-- Promise.then -- -- Promise.then --
promiseAll (test.js:52:44) promiseAll (test.js:44:44)
(anonymous) (expr.js:0:0) (anonymous) (expr.js:0:0)
Running test: testPromiseRace Running test: testPromiseRace
foo1 (test.js:10:2) foo1 (test.js:10:2)
-- Promise.then -- -- Promise.then --
promiseRace (test.js:56:45) promiseRace (test.js:48:45)
(anonymous) (expr.js:0:0) (anonymous) (expr.js:0:0)
Running test: testThenableJob1 Running test: testThenableJob1
foo1 (test.js:10:2) foo1 (test.js:10:2)
-- Promise.then -- -- Promise.then --
thenableJob1 (test.js:60:72) thenableJob1 (test.js:52:72)
(anonymous) (expr.js:0:0) (anonymous) (expr.js:0:0)
Running test: testThenableJob2 Running test: testThenableJob2
foo1 (test.js:10:2) foo1 (test.js:10:2)
-- Promise.then -- -- Promise.then --
thenableJob2 (test.js:64:57) thenableJob2 (test.js:56:57)
(anonymous) (expr.js:0:0) (anonymous) (expr.js:0:0)
...@@ -82,10 +82,10 @@ Running test: testSetTimeouts ...@@ -82,10 +82,10 @@ Running test: testSetTimeouts
foo1 (test.js:10:2) foo1 (test.js:10:2)
(anonymous) (test.js:72:25) (anonymous) (test.js:72:25)
-- setTimeout -- -- setTimeout --
(anonymous) (test.js:72:6) (anonymous) (test.js:64:6)
-- setTimeout -- -- setTimeout --
(anonymous) (test.js:71:4) (anonymous) (test.js:63:4)
-- setTimeout -- -- setTimeout --
setTimeouts (test.js:70:2) setTimeouts (test.js:62:2)
(anonymous) (expr.js:0:0) (anonymous) (expr.js:0:0)
...@@ -3,94 +3,94 @@ Checks that async chains for promises are correct. ...@@ -3,94 +3,94 @@ Checks that async chains for promises are correct.
Running test: testPromise Running test: testPromise
foo1 (test.js:9:2) foo1 (test.js:9:2)
-- Promise.then -- -- Promise.then --
promise (test.js:19:14) promise (test.js:12:14)
(anonymous) (testPromise.js:0:0) (anonymous) (testPromise.js:0:0)
Running test: testPromiseResolvedBySetTimeout Running test: testPromiseResolvedBySetTimeout
foo1 (test.js:9:2) foo1 (test.js:9:2)
-- Promise.then -- -- Promise.then --
promiseResolvedBySetTimeout (test.js:27:14) promiseResolvedBySetTimeout (test.js:20:14)
(anonymous) (testPromiseResolvedBySetTimeout.js:0:0) (anonymous) (testPromiseResolvedBySetTimeout.js:0:0)
Running test: testPromiseAll Running test: testPromiseAll
foo1 (test.js:9:2) foo1 (test.js:9:2)
-- Promise.then -- -- Promise.then --
promiseAll (test.js:37:35) promiseAll (test.js:30:35)
(anonymous) (testPromiseAll.js:0:0) (anonymous) (testPromiseAll.js:0:0)
Running test: testPromiseAllReverseOrder Running test: testPromiseAllReverseOrder
foo1 (test.js:9:2) foo1 (test.js:9:2)
-- Promise.then -- -- Promise.then --
promiseAllReverseOrder (test.js:48:35) promiseAllReverseOrder (test.js:41:35)
(anonymous) (testPromiseAllReverseOrder.js:0:0) (anonymous) (testPromiseAllReverseOrder.js:0:0)
Running test: testPromiseRace Running test: testPromiseRace
foo1 (test.js:9:2) foo1 (test.js:9:2)
-- Promise.then -- -- Promise.then --
promiseRace (test.js:59:36) promiseRace (test.js:52:36)
(anonymous) (testPromiseRace.js:0:0) (anonymous) (testPromiseRace.js:0:0)
Running test: testTwoChainedCallbacks Running test: testTwoChainedCallbacks
foo1 (test.js:9:2) foo1 (test.js:9:2)
-- Promise.then -- -- Promise.then --
twoChainedCallbacks (test.js:68:14) twoChainedCallbacks (test.js:61:14)
(anonymous) (testTwoChainedCallbacks.js:0:0) (anonymous) (testTwoChainedCallbacks.js:0:0)
foo2 (test.js:13:2) foo2 (test.js:13:2)
-- Promise.then -- -- Promise.then --
twoChainedCallbacks (test.js:68:25) twoChainedCallbacks (test.js:61:25)
(anonymous) (testTwoChainedCallbacks.js:0:0) (anonymous) (testTwoChainedCallbacks.js:0:0)
Running test: testPromiseResolve Running test: testPromiseResolve
foo1 (test.js:9:2) foo1 (test.js:9:2)
-- Promise.then -- -- Promise.then --
promiseResolve (test.js:74:27) promiseResolve (test.js:67:27)
(anonymous) (testPromiseResolve.js:0:0) (anonymous) (testPromiseResolve.js:0:0)
foo2 (test.js:13:2) foo2 (test.js:13:2)
-- Promise.then -- -- Promise.then --
promiseResolve (test.js:74:38) promiseResolve (test.js:67:38)
(anonymous) (testPromiseResolve.js:0:0) (anonymous) (testPromiseResolve.js:0:0)
Running test: testThenableJobResolvedInSetTimeout Running test: testThenableJobResolvedInSetTimeout
foo1 (test.js:9:2) foo1 (test.js:9:2)
-- Promise.then -- -- Promise.then --
thenableJobResolvedInSetTimeout (test.js:86:40) thenableJobResolvedInSetTimeout (test.js:79:40)
(anonymous) (testThenableJobResolvedInSetTimeout.js:0:0) (anonymous) (testThenableJobResolvedInSetTimeout.js:0:0)
Running test: testThenableJobResolvedInSetTimeoutWithStack Running test: testThenableJobResolvedInSetTimeoutWithStack
foo1 (test.js:9:2) foo1 (test.js:9:2)
-- Promise.then -- -- Promise.then --
thenableJobResolvedInSetTimeoutWithStack (test.js:104:40) thenableJobResolvedInSetTimeoutWithStack (test.js:97:40)
(anonymous) (testThenableJobResolvedInSetTimeoutWithStack.js:0:0) (anonymous) (testThenableJobResolvedInSetTimeoutWithStack.js:0:0)
Running test: testThenableJobResolvedByPromise Running test: testThenableJobResolvedByPromise
foo1 (test.js:9:2) foo1 (test.js:9:2)
-- Promise.then -- -- Promise.then --
thenableJobResolvedByPromise (test.js:118:40) thenableJobResolvedByPromise (test.js:111:40)
(anonymous) (testThenableJobResolvedByPromise.js:0:0) (anonymous) (testThenableJobResolvedByPromise.js:0:0)
Running test: testThenableJobResolvedByPromiseWithStack Running test: testThenableJobResolvedByPromiseWithStack
foo1 (test.js:9:2) foo1 (test.js:9:2)
-- Promise.then -- -- Promise.then --
thenableJobResolvedByPromiseWithStack (test.js:136:40) thenableJobResolvedByPromiseWithStack (test.js:129:40)
(anonymous) (testThenableJobResolvedByPromiseWithStack.js:0:0) (anonymous) (testThenableJobResolvedByPromiseWithStack.js:0:0)
Running test: testLateThenCallback Running test: testLateThenCallback
foo1 (test.js:9:2) foo1 (test.js:9:2)
-- Promise.then -- -- Promise.then --
lateThenCallback (test.js:145:12) lateThenCallback (test.js:138:12)
(anonymous) (testLateThenCallback.js:0:0) (anonymous) (testLateThenCallback.js:0:0)
...@@ -98,36 +98,36 @@ Running test: testComplex ...@@ -98,36 +98,36 @@ Running test: testComplex
inner1 (test.js:154:6) inner1 (test.js:154:6)
foo1 (test.js:156:4) foo1 (test.js:156:4)
-- Promise.then -- -- Promise.then --
complex (test.js:202:5) complex (test.js:195:5)
(anonymous) (testComplex.js:0:0) (anonymous) (testComplex.js:0:0)
(anonymous) (test.js:207:8) (anonymous) (test.js:207:8)
-- Promise.then -- -- Promise.then --
(anonymous) (test.js:206:8) (anonymous) (test.js:199:8)
-- Promise.then -- -- Promise.then --
(anonymous) (test.js:205:6) (anonymous) (test.js:198:6)
-- setTimeout -- -- setTimeout --
complex (test.js:204:2) complex (test.js:197:2)
(anonymous) (testComplex.js:0:0) (anonymous) (testComplex.js:0:0)
Running test: testReject Running test: testReject
foo1 (test.js:9:2) foo1 (test.js:9:2)
-- Promise.catch -- -- Promise.catch --
reject (test.js:217:31) reject (test.js:210:31)
(anonymous) (testReject.js:0:0) (anonymous) (testReject.js:0:0)
Running test: testFinally1 Running test: testFinally1
foo1 (test.js:9:2) foo1 (test.js:9:2)
-- Promise.finally -- -- Promise.finally --
finally1 (test.js:221:33) finally1 (test.js:214:33)
(anonymous) (testFinally1.js:0:0) (anonymous) (testFinally1.js:0:0)
Running test: testFinally2 Running test: testFinally2
foo1 (test.js:9:2) foo1 (test.js:9:2)
-- Promise.finally -- -- Promise.finally --
finally2 (test.js:225:34) finally2 (test.js:218:34)
(anonymous) (testFinally2.js:0:0) (anonymous) (testFinally2.js:0:0)
...@@ -8,10 +8,10 @@ asyncFact (test.js:9:2) ...@@ -8,10 +8,10 @@ asyncFact (test.js:9:2)
asyncFact (test.js:11:2) asyncFact (test.js:11:2)
-- async function -- -- async function --
asyncFact (test.js:10:20) asyncFact (test.js:3:20)
asyncFact (test.js:10:20) asyncFact (test.js:3:20)
asyncFact (test.js:10:20) asyncFact (test.js:3:20)
asyncFact (test.js:10:20) asyncFact (test.js:3:20)
(anonymous) (expr.js:0:0) (anonymous) (expr.js:0:0)
...@@ -23,7 +23,7 @@ asyncFact (test.js:9:2) ...@@ -23,7 +23,7 @@ asyncFact (test.js:9:2)
asyncFact (test.js:11:2) asyncFact (test.js:11:2)
-- async function -- -- async function --
asyncFact (test.js:10:20) asyncFact (test.js:3:20)
(anonymous) (expr.js:0:0) (anonymous) (expr.js:0:0)
......
...@@ -164,7 +164,7 @@ Runtime.evaluate compiled script with stack trace ...@@ -164,7 +164,7 @@ Runtime.evaluate compiled script with stack trace
[0] : { [0] : {
columnNumber : 2 columnNumber : 2
functionName : fooTop functionName : fooTop
lineNumber : 10 lineNumber : 2
scriptId : <scriptId> scriptId : <scriptId>
url : top-frame.js url : top-frame.js
} }
...@@ -247,7 +247,7 @@ Runtime.evaluate compile script error with stack trace ...@@ -247,7 +247,7 @@ Runtime.evaluate compile script error with stack trace
[0] : { [0] : {
columnNumber : 2 columnNumber : 2
functionName : fooTopFail functionName : fooTopFail
lineNumber : 20 lineNumber : 2
scriptId : <scriptId> scriptId : <scriptId>
url : top-frame-fail.js url : top-frame-fail.js
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment