Skip to content

Commit 844c5db

Browse files
committed
runtime: Include call column into position key, in addition to line.
This prevents pc collision when minified and virtually all calls and functions are on the same line. This change resolves `testing.TestTBHelper` test failure in Go 1.18.
1 parent dfcddff commit 844c5db

File tree

2 files changed

+19
-14
lines changed

2 files changed

+19
-14
lines changed

compiler/natives/src/runtime/runtime.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,8 @@ var (
107107
positionCounters = []*Func{}
108108
)
109109

110-
func registerPosition(funcName string, file string, line int) uintptr {
111-
key := file + ":" + itoa(line)
110+
func registerPosition(funcName string, file string, line int, col int) uintptr {
111+
key := file + ":" + itoa(line) + ":" + itoa(col)
112112
if pc, found := knownPositions[key]; found {
113113
return pc
114114
}
@@ -135,6 +135,7 @@ type basicFrame struct {
135135
FuncName string
136136
File string
137137
Line int
138+
Col int
138139
}
139140

140141
func callstack(skip, limit int) []basicFrame {
@@ -189,6 +190,7 @@ func ParseCallFrame(info *js.Object) basicFrame {
189190
return basicFrame{
190191
File: parts.Call("slice", 1, parts.Length()-2).Call("join", ":").String(),
191192
Line: parts.Index(parts.Length() - 2).Int(),
193+
Col: parts.Index(parts.Length() - 1).Int(),
192194
FuncName: parts.Index(0).String(),
193195
}
194196
}
@@ -202,12 +204,13 @@ func ParseCallFrame(info *js.Object) basicFrame {
202204
File: parts.Call("slice", 0, parts.Length()-2).Call("join", ":").
203205
Call("replace", js.Global.Get("RegExp").New(`^\s*at `), "").String(),
204206
Line: parts.Index(parts.Length() - 2).Int(),
207+
Col: parts.Index(parts.Length() - 1).Int(),
205208
FuncName: "<none>",
206209
}
207210
}
208211

209212
var file, funcName string
210-
var line int
213+
var line, col int
211214

212215
pos := info.Call("substring", openIdx+1, info.Call("indexOf", ")").Int())
213216
parts := pos.Call("split", ":")
@@ -217,6 +220,7 @@ func ParseCallFrame(info *js.Object) basicFrame {
217220
} else {
218221
file = parts.Call("slice", 0, parts.Length()-2).Call("join", ":").String()
219222
line = parts.Index(parts.Length() - 2).Int()
223+
col = parts.Index(parts.Length() - 1).Int()
220224
}
221225
fn := info.Call("substring", info.Call("indexOf", "at ").Int()+3, info.Call("indexOf", " (").Int())
222226
if idx := fn.Call("indexOf", "[as ").Int(); idx > 0 {
@@ -227,6 +231,7 @@ func ParseCallFrame(info *js.Object) basicFrame {
227231
return basicFrame{
228232
File: file,
229233
Line: line,
234+
Col: col,
230235
FuncName: funcName,
231236
}
232237
}
@@ -237,7 +242,7 @@ func Caller(skip int) (pc uintptr, file string, line int, ok bool) {
237242
if len(frames) != 1 {
238243
return 0, "", 0, false
239244
}
240-
pc = registerPosition(frames[0].FuncName, frames[0].File, frames[0].Line)
245+
pc = registerPosition(frames[0].FuncName, frames[0].File, frames[0].Line, frames[0].Col)
241246
return pc, frames[0].File, frames[0].Line, true
242247
}
243248

@@ -261,7 +266,7 @@ func Caller(skip int) (pc uintptr, file string, line int, ok bool) {
261266
func Callers(skip int, pc []uintptr) int {
262267
frames := callstack(skip, len(pc))
263268
for i, frame := range frames {
264-
pc[i] = registerPosition(frame.FuncName, frame.File, frame.Line)
269+
pc[i] = registerPosition(frame.FuncName, frame.File, frame.Line, frame.Col)
265270
}
266271
return len(frames)
267272
}

tests/runtime_test.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,50 +20,50 @@ func Test_parseCallFrame(t *testing.T) {
2020
{
2121
name: "Chrome 96.0.4664.110 on Linux #1",
2222
input: "at foo (eval at $b (https://gopherjs.github.io/playground/playground.js:102:11836), <anonymous>:25887:60)",
23-
want: "foo https://gopherjs.github.io/playground/playground.js 102",
23+
want: "foo https://gopherjs.github.io/playground/playground.js 102 11836",
2424
},
2525
{
2626
name: "Chrome 96, anonymous eval",
2727
input: " at eval (<anonymous>)",
28-
want: "eval <anonymous> 0",
28+
want: "eval <anonymous> 0 0",
2929
},
3030
{
3131
name: "Chrome 96, anonymous Array.forEach",
3232
input: " at Array.forEach (<anonymous>)",
33-
want: "Array.forEach <anonymous> 0",
33+
want: "Array.forEach <anonymous> 0 0",
3434
},
3535
{
3636
name: "Chrome 96, file location only",
3737
input: "at https://ajax.googleapis.com/ajax/libs/angularjs/1.2.18/angular.min.js:31:225",
38-
want: "<none> https://ajax.googleapis.com/ajax/libs/angularjs/1.2.18/angular.min.js 31",
38+
want: "<none> https://ajax.googleapis.com/ajax/libs/angularjs/1.2.18/angular.min.js 31 225",
3939
},
4040
{
4141
name: "Chrome 96, aliased function",
4242
input: "at k.e.$externalizeWrapper.e.$externalizeWrapper [as run] (https://gopherjs.github.io/playground/playground.js:5:30547)",
43-
want: "run https://gopherjs.github.io/playground/playground.js 5",
43+
want: "run https://gopherjs.github.io/playground/playground.js 5 30547",
4444
},
4545
{
4646
name: "Node.js v12.22.5",
4747
input: " at Script.runInThisContext (vm.js:120:18)",
48-
want: "Script.runInThisContext vm.js 120",
48+
want: "Script.runInThisContext vm.js 120 18",
4949
},
5050
{
5151
name: "Node.js v12.22.5, aliased function",
5252
input: "at REPLServer.runBound [as eval] (domain.js:440:12)",
53-
want: "eval domain.js 440",
53+
want: "eval domain.js 440 12",
5454
},
5555
{
5656
name: "Firefox 78.15.0esr Linux",
5757
input: "getEvalResult@resource://devtools/server/actors/webconsole/eval-with-debugger.js:231:24",
58-
want: "getEvalResult resource://devtools/server/actors/webconsole/eval-with-debugger.js 231",
58+
want: "getEvalResult resource://devtools/server/actors/webconsole/eval-with-debugger.js 231 24",
5959
},
6060
}
6161

6262
for _, tt := range tests {
6363
t.Run(tt.name, func(t *testing.T) {
6464
lines := js.Global.Get("String").New(tt.input)
6565
frame := runtime.ParseCallFrame(lines)
66-
got := fmt.Sprintf("%v %v %v", frame.FuncName, frame.File, frame.Line)
66+
got := fmt.Sprintf("%v %v %v %v", frame.FuncName, frame.File, frame.Line, frame.Col)
6767
if tt.want != got {
6868
t.Errorf("Unexpected result: %s", got)
6969
}

0 commit comments

Comments
 (0)