Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ const (

type options struct {
disableSourceMaps bool
skipEmptySourceMaps bool
sourceMapLoader func(path string) ([]byte, error)
}

Expand All @@ -66,6 +67,13 @@ func WithDisableSourceMaps(opts *options) {
opts.disableSourceMaps = true
}

// WithSkipEmptySourceMaps is an option to ignore source maps that are empty rather than fail parsing.
// This is particulary useful for code compiled from TypeScript. The TypeScript compiler outputs empty
// source maps for files containing only type definitions.
func WithSkipEmptySourceMaps(opts *options) {
opts.skipEmptySourceMaps = true
}

// WithSourceMapLoader is an option to set a custom source map loader. The loader will be given a path or a
// URL from the sourceMappingURL. If sourceMappingURL is not absolute it is resolved relatively to the name
// of the file being parsed. Any error returned by the loader will fail the parsing.
Expand Down
19 changes: 19 additions & 0 deletions parser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1235,6 +1235,25 @@ var x = {};
is(err, nil)
is(count, 1)
is(requestedPath, "https://site.com/delme.js.map")

// Checks related to empty source maps.
emptySourceMapLoader := func(p string) ([]byte, error) {
count++
requestedPath = p
emptySourceMap := `{"version":3,"file":"delme.js","sourceRoot":"","sources":["../src/delme.ts"],"names":[],"mappings":""}`
return []byte(emptySourceMap), nil
}

// First, ensure that the expected error is produced for an empty source map.
_, err = ParseFile(nil, "delme.js", src, 0, WithSourceMapLoader(emptySourceMapLoader))
is(true, strings.Contains(err.Error(), errSourceMapEmptyString))

// Then, ensure WithSkipEmptySourceMaps bypasses the error.
count = 0
_, err = ParseFile(nil, "delme.js", src, 0, WithSourceMapLoader(emptySourceMapLoader), WithSkipEmptySourceMaps)
is(err, nil)
is(count, 1)
is(requestedPath, "delme.js.map")
})
}

Expand Down
7 changes: 7 additions & 0 deletions parser/statement.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ import (
"github.com/go-sourcemap/sourcemap"
)

const (
// Copied from https://github.com/go-sourcemap/sourcemap/blob/794171861aeb0f83fcd66eeb0415a5062594cde6/mappings.go#L35
errSourceMapEmptyString = "sourcemap: mappings are empty"
)

func (self *_parser) parseBlockStatement() *ast.BlockStatement {
node := &ast.BlockStatement{}
node.LeftBrace = self.expect(token.LEFT_BRACE)
Expand Down Expand Up @@ -950,6 +955,8 @@ func (self *_parser) parseSourceMap() *sourcemap.Consumer {

if sm, err := sourcemap.Parse(self.file.Name(), data); err == nil {
return sm
} else if self.opts.skipEmptySourceMaps && strings.Contains(err.Error(), errSourceMapEmptyString) {
return nil
} else {
self.error(file.Idx(0), "Could not parse source map: %v", err)
}
Expand Down