1// +build js
2
3package gls
4
5// This file is used for GopherJS builds, which don't have normal runtime
6// stack trace support
7
8import (
9	"strconv"
10	"strings"
11
12	"github.com/gopherjs/gopherjs/js"
13)
14
15const (
16	jsFuncNamePrefix = "github_com_jtolds_gls_mark"
17)
18
19func jsMarkStack() (f []uintptr) {
20	lines := strings.Split(
21		js.Global.Get("Error").New().Get("stack").String(), "\n")
22	f = make([]uintptr, 0, len(lines))
23	for i, line := range lines {
24		line = strings.TrimSpace(line)
25		if line == "" {
26			continue
27		}
28		if i == 0 {
29			if line != "Error" {
30				panic("didn't understand js stack trace")
31			}
32			continue
33		}
34		fields := strings.Fields(line)
35		if len(fields) < 2 || fields[0] != "at" {
36			panic("didn't understand js stack trace")
37		}
38
39		pos := strings.Index(fields[1], jsFuncNamePrefix)
40		if pos < 0 {
41			continue
42		}
43		pos += len(jsFuncNamePrefix)
44		if pos >= len(fields[1]) {
45			panic("didn't understand js stack trace")
46		}
47		char := string(fields[1][pos])
48		switch char {
49		case "S":
50			f = append(f, uintptr(0))
51		default:
52			val, err := strconv.ParseUint(char, 16, 8)
53			if err != nil {
54				panic("didn't understand js stack trace")
55			}
56			f = append(f, uintptr(val)+1)
57		}
58	}
59	return f
60}
61
62// variables to prevent inlining
63var (
64	findPtr = func() uintptr {
65		funcs := jsMarkStack()
66		if len(funcs) == 0 {
67			panic("failed to find function pointer")
68		}
69		return funcs[0]
70	}
71
72	getStack = func(offset, amount int) (stack []uintptr, next_offset int) {
73		return jsMarkStack(), 0
74	}
75)
76