diff options
Diffstat (limited to 'vendor/gopkg.in/sourcemap.v1/consumer.go')
-rw-r--r-- | vendor/gopkg.in/sourcemap.v1/consumer.go | 312 |
1 files changed, 312 insertions, 0 deletions
diff --git a/vendor/gopkg.in/sourcemap.v1/consumer.go b/vendor/gopkg.in/sourcemap.v1/consumer.go new file mode 100644 index 000000000..b66761a6c --- /dev/null +++ b/vendor/gopkg.in/sourcemap.v1/consumer.go @@ -0,0 +1,312 @@ +package sourcemap // import "gopkg.in/sourcemap.v1" + +import ( + "encoding/json" + "errors" + "fmt" + "io" + "net/url" + "path" + "sort" + "strconv" + "strings" + + "gopkg.in/sourcemap.v1/base64vlq" +) + +type Consumer struct { + sourceRootURL *url.URL + smap *sourceMap + mappings []mapping +} + +func Parse(mapURL string, b []byte) (*Consumer, error) { + smap := new(sourceMap) + err := json.Unmarshal(b, smap) + if err != nil { + return nil, err + } + + if smap.Version != 3 { + return nil, errors.New("sourcemap: only 3rd version is supported") + } + + var sourceRootURL *url.URL + if smap.SourceRoot != "" { + u, err := url.Parse(smap.SourceRoot) + if err != nil { + return nil, err + } + if u.IsAbs() { + sourceRootURL = u + } + } else if mapURL != "" { + u, err := url.Parse(mapURL) + if err != nil { + return nil, err + } + if u.IsAbs() { + u.Path = path.Dir(u.Path) + sourceRootURL = u + } + } + + mappings, err := parseMappings(smap.Mappings) + if err != nil { + return nil, err + } + // Free memory. + smap.Mappings = "" + + return &Consumer{ + sourceRootURL: sourceRootURL, + smap: smap, + mappings: mappings, + }, nil +} + +func (c *Consumer) File() string { + return c.smap.File +} + +func (c *Consumer) Source(genLine, genCol int) (source, name string, line, col int, ok bool) { + i := sort.Search(len(c.mappings), func(i int) bool { + m := &c.mappings[i] + if m.genLine == genLine { + return m.genCol >= genCol + } + return m.genLine >= genLine + }) + + // Mapping not found. + if i == len(c.mappings) { + return + } + + match := &c.mappings[i] + + // Fuzzy match. + if match.genCol > genCol && i > 0 { + match = &c.mappings[i-1] + } + + if match.sourcesInd >= 0 { + source = c.absSource(c.smap.Sources[match.sourcesInd]) + } + if match.namesInd >= 0 { + iv := c.smap.Names[match.namesInd] + switch v := iv.(type) { + case string: + name = v + case float64: + name = strconv.FormatFloat(v, 'f', -1, 64) + default: + name = fmt.Sprint(iv) + } + } + line = match.sourceLine + col = match.sourceCol + ok = true + return +} + +func (c *Consumer) absSource(source string) string { + if path.IsAbs(source) { + return source + } + + if u, err := url.Parse(source); err == nil && u.IsAbs() { + return source + } + + if c.sourceRootURL != nil { + u := *c.sourceRootURL + u.Path = path.Join(c.sourceRootURL.Path, source) + return u.String() + } + + if c.smap.SourceRoot != "" { + return path.Join(c.smap.SourceRoot, source) + } + + return source +} + +func (c *Consumer) SourceName(genLine, genCol int, genName string) (name string, ok bool) { + ind := sort.Search(len(c.mappings), func(i int) bool { + m := c.mappings[i] + if m.genLine == genLine { + return m.genCol >= genCol + } + return m.genLine >= genLine + }) + + // Mapping not found. + if ind == len(c.mappings) { + return "", false + } + + for i := ind; i >= 0; i-- { + m := c.mappings[i] + if m.namesInd == -1 { + continue + } + if c.smap.Names[m.namesInd] == "" { + + } + } + + return +} + +type fn func() (fn, error) + +type sourceMap struct { + Version int `json:"version"` + File string `json:"file"` + SourceRoot string `json:"sourceRoot"` + Sources []string `json:"sources"` + Names []interface{} `json:"names"` + Mappings string `json:"mappings"` +} + +type mapping struct { + genLine int + genCol int + sourcesInd int + sourceLine int + sourceCol int + namesInd int +} + +type mappings struct { + rd *strings.Reader + dec *base64vlq.Decoder + + genLine int + genCol int + sourcesInd int + sourceLine int + sourceCol int + namesInd int + + value mapping + values []mapping +} + +func parseMappings(s string) ([]mapping, error) { + rd := strings.NewReader(s) + m := &mappings{ + rd: rd, + dec: base64vlq.NewDecoder(rd), + + genLine: 1, + sourceLine: 1, + } + m.zeroValue() + err := m.parse() + if err != nil { + return nil, err + } + return m.values, nil +} + +func (m *mappings) parse() error { + next := m.parseGenCol + for { + c, err := m.rd.ReadByte() + if err == io.EOF { + m.pushValue() + return nil + } else if err != nil { + return err + } + + switch c { + case ',': + m.pushValue() + next = m.parseGenCol + case ';': + m.pushValue() + + m.genLine++ + m.genCol = 0 + + next = m.parseGenCol + default: + m.rd.UnreadByte() + + var err error + next, err = next() + if err != nil { + return err + } + } + } +} + +func (m *mappings) parseGenCol() (fn, error) { + n, err := m.dec.Decode() + if err != nil { + return nil, err + } + m.genCol += n + m.value.genCol = m.genCol + return m.parseSourcesInd, nil +} + +func (m *mappings) parseSourcesInd() (fn, error) { + n, err := m.dec.Decode() + if err != nil { + return nil, err + } + m.sourcesInd += n + m.value.sourcesInd = m.sourcesInd + return m.parseSourceLine, nil +} + +func (m *mappings) parseSourceLine() (fn, error) { + n, err := m.dec.Decode() + if err != nil { + return nil, err + } + m.sourceLine += n + m.value.sourceLine = m.sourceLine + return m.parseSourceCol, nil +} + +func (m *mappings) parseSourceCol() (fn, error) { + n, err := m.dec.Decode() + if err != nil { + return nil, err + } + m.sourceCol += n + m.value.sourceCol = m.sourceCol + return m.parseNamesInd, nil +} + +func (m *mappings) parseNamesInd() (fn, error) { + n, err := m.dec.Decode() + if err != nil { + return nil, err + } + m.namesInd += n + m.value.namesInd = m.namesInd + return m.parseGenCol, nil +} + +func (m *mappings) zeroValue() { + m.value = mapping{ + genLine: m.genLine, + genCol: 0, + sourcesInd: -1, + sourceLine: 0, + sourceCol: 0, + namesInd: -1, + } +} + +func (m *mappings) pushValue() { + m.values = append(m.values, m.value) + m.zeroValue() +} |