Skip to content

Commit

Permalink
add "pluginData" to pass data between plugins (#696)
Browse files Browse the repository at this point in the history
  • Loading branch information
evanw committed Jan 30, 2021
1 parent a5cd18e commit feefbf5
Show file tree
Hide file tree
Showing 11 changed files with 189 additions and 47 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## Unreleased

* Add `pluginData` to pass data between plugins ([#696](https://github.com/evanw/esbuild/issues/696))

You can now return additional data from a plugin in the optional `pluginData` field and it will be passed to the next plugin that runs in the plugin chain. So if you return it from an `onLoad` plugin, it will be passed to the `onResolve` plugins for any imports in that file, and if you return it from an `onResolve` plugin, an arbitrary one will be passed to the `onLoad` plugin when it loads the file (it's arbitrary since the relationship is many-to-one). This is useful to pass data between different plugins without them having to coordinate directly.

## 0.8.37

* Improve ambiguous import handling ([#723](https://github.com/evanw/esbuild/issues/723))
Expand Down
18 changes: 13 additions & 5 deletions cmd/esbuild/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,7 @@ func (service *serviceType) handleBuildRequest(id uint32, request map[string]int
"importer": args.Importer,
"namespace": args.Namespace,
"resolveDir": args.ResolveDir,
"pluginData": args.PluginData,
}).(map[string]interface{})

if value, ok := response["id"]; ok {
Expand All @@ -427,6 +428,9 @@ func (service *serviceType) handleBuildRequest(id uint32, request map[string]int
if value, ok := response["external"]; ok {
result.External = value.(bool)
}
if value, ok := response["pluginData"]; ok {
result.PluginData = value.(int)
}
if value, ok := response["errors"]; ok {
result.Errors = decodeMessages(value.([]interface{}))
}
Expand All @@ -452,11 +456,12 @@ func (service *serviceType) handleBuildRequest(id uint32, request map[string]int
}

response := service.sendRequest(map[string]interface{}{
"command": "load",
"key": key,
"ids": ids,
"path": args.Path,
"namespace": args.Namespace,
"command": "load",
"key": key,
"ids": ids,
"path": args.Path,
"namespace": args.Namespace,
"pluginData": args.PluginData,
}).(map[string]interface{})

if value, ok := response["id"]; ok {
Expand All @@ -481,6 +486,9 @@ func (service *serviceType) handleBuildRequest(id uint32, request map[string]int
if value, ok := response["resolveDir"]; ok {
result.ResolveDir = value.(string)
}
if value, ok := response["pluginData"]; ok {
result.PluginData = value.(int)
}
if value, ok := response["errors"]; ok {
result.Errors = decodeMessages(value.([]interface{}))
}
Expand Down
39 changes: 28 additions & 11 deletions internal/bundler/bundler.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,11 @@ import (
)

type file struct {
source logger.Source
repr fileRepr
loader config.Loader
sourceMap *sourcemap.SourceMap
source logger.Source
repr fileRepr
loader config.Loader
sourceMap *sourcemap.SourceMap
pluginData interface{}

// The minimum number of links in the module graph to get from an entry point
// to this file
Expand Down Expand Up @@ -136,6 +137,7 @@ type parseArgs struct {
ignoreIfUnused bool
ignoreIfUnusedData *resolver.IgnoreIfUnusedData
importPathRange logger.Range
pluginData interface{}
options config.Options
results chan parseResult
inject chan config.InjectedFile
Expand All @@ -160,6 +162,7 @@ func parseFile(args parseArgs) {
var loader config.Loader
var absResolveDir string
var pluginName string
var pluginData interface{}

if stdin := args.options.Stdin; stdin != nil {
// Special-case stdin
Expand All @@ -179,6 +182,7 @@ func parseFile(args parseArgs) {
&source,
args.importSource,
args.importPathRange,
args.pluginData,
)
if !ok {
if args.inject != nil {
Expand All @@ -192,6 +196,7 @@ func parseFile(args parseArgs) {
loader = result.loader
absResolveDir = result.absResolveDir
pluginName = result.pluginName
pluginData = result.pluginData
}

_, base, ext := logger.PlatformIndependentPathDirBaseExt(source.KeyPath.Text)
Expand All @@ -203,8 +208,9 @@ func parseFile(args parseArgs) {

result := parseResult{
file: file{
source: source,
loader: loader,
source: source,
loader: loader,
pluginData: pluginData,

// Record information from "sideEffects" in "package.json"
ignoreIfUnused: args.ignoreIfUnused,
Expand Down Expand Up @@ -406,6 +412,7 @@ func parseFile(args parseArgs) {
record.Path.Text,
record.Kind,
absResolveDir,
pluginData,
)
cache[record.Path.Text] = resolveResult

Expand Down Expand Up @@ -611,10 +618,12 @@ func runOnResolvePlugins(
path string,
kind ast.ImportKind,
absResolveDir string,
pluginData interface{},
) (*resolver.ResolveResult, bool) {
resolverArgs := config.OnResolveArgs{
Path: path,
ResolveDir: absResolveDir,
PluginData: pluginData,
}
applyPath := logger.Path{Text: path}
if importSource != nil {
Expand Down Expand Up @@ -673,6 +682,7 @@ func runOnResolvePlugins(
return &resolver.ResolveResult{
PathPair: resolver.PathPair{Primary: result.Path},
IsExternal: result.External,
PluginData: result.PluginData,
}, false
}
}
Expand All @@ -687,6 +697,7 @@ type loaderPluginResult struct {
loader config.Loader
absResolveDir string
pluginName string
pluginData interface{}
}

func runOnLoadPlugins(
Expand All @@ -698,9 +709,11 @@ func runOnLoadPlugins(
source *logger.Source,
importSource *logger.Source,
importPathRange logger.Range,
pluginData interface{},
) (loaderPluginResult, bool) {
loaderArgs := config.OnLoadArgs{
Path: source.KeyPath,
Path: source.KeyPath,
PluginData: pluginData,
}

// Apply loader plugins in order until one succeeds
Expand Down Expand Up @@ -739,6 +752,7 @@ func runOnLoadPlugins(
loader: loader,
absResolveDir: result.AbsResolveDir,
pluginName: pluginName,
pluginData: result.PluginData,
}, true
}
}
Expand Down Expand Up @@ -867,6 +881,7 @@ func (s *scanner) maybeParseFile(
prettyPath string,
importSource *logger.Source,
importPathRange logger.Range,
pluginData interface{},
kind inputKind,
inject chan config.InjectedFile,
) uint32 {
Expand Down Expand Up @@ -932,6 +947,7 @@ func (s *scanner) maybeParseFile(
ignoreIfUnused: resolveResult.IgnorePrimaryIfUnused != nil,
ignoreIfUnusedData: resolveResult.IgnorePrimaryIfUnused,
importPathRange: importPathRange,
pluginData: pluginData,
options: optionsClone,
results: s.resultChannel,
inject: inject,
Expand Down Expand Up @@ -1027,7 +1043,7 @@ func (s *scanner) preprocessInjectedFiles() {
i := len(injectedFiles)
injectedFiles = append(injectedFiles, config.InjectedFile{})
channel := make(chan config.InjectedFile)
s.maybeParseFile(*resolveResult, prettyPath, nil, logger.Range{}, inputKindNormal, channel)
s.maybeParseFile(*resolveResult, prettyPath, nil, logger.Range{}, nil, inputKindNormal, channel)

// Wait for the results in parallel
injectWaitGroup.Add(1)
Expand Down Expand Up @@ -1058,7 +1074,7 @@ func (s *scanner) addEntryPoints(entryPoints []string) []uint32 {
}
}
resolveResult := resolver.ResolveResult{PathPair: resolver.PathPair{Primary: stdinPath}}
sourceIndex := s.maybeParseFile(resolveResult, s.res.PrettyPath(stdinPath), nil, logger.Range{}, inputKindStdin, nil)
sourceIndex := s.maybeParseFile(resolveResult, s.res.PrettyPath(stdinPath), nil, logger.Range{}, nil, inputKindStdin, nil)
entryPointIndices = append(entryPointIndices, sourceIndex)
}

Expand Down Expand Up @@ -1107,6 +1123,7 @@ func (s *scanner) addEntryPoints(entryPoints []string) []uint32 {
path,
ast.ImportEntryPoint,
entryPointAbsResolveDir,
nil,
)
if resolveResult != nil {
if resolveResult.IsExternal {
Expand All @@ -1133,7 +1150,7 @@ func (s *scanner) addEntryPoints(entryPoints []string) []uint32 {
for _, resolveResult := range entryPointResolveResults {
if resolveResult != nil {
prettyPath := s.res.PrettyPath(resolveResult.PathPair.Primary)
sourceIndex := s.maybeParseFile(*resolveResult, prettyPath, nil, logger.Range{}, inputKindEntryPoint, nil)
sourceIndex := s.maybeParseFile(*resolveResult, prettyPath, nil, logger.Range{}, resolveResult.PluginData, inputKindEntryPoint, nil)
if duplicateEntryPoints[sourceIndex] {
s.log.AddError(nil, logger.Loc{}, fmt.Sprintf("Duplicate entry point %q", prettyPath))
continue
Expand Down Expand Up @@ -1171,7 +1188,7 @@ func (s *scanner) scanAllDependencies() {
if !resolveResult.IsExternal {
// Handle a path within the bundle
prettyPath := s.res.PrettyPath(path)
sourceIndex := s.maybeParseFile(*resolveResult, prettyPath, &result.file.source, record.Range, inputKindNormal, nil)
sourceIndex := s.maybeParseFile(*resolveResult, prettyPath, &result.file.source, record.Range, resolveResult.PluginData, inputKindNormal, nil)
record.SourceIndex = &sourceIndex
} else {
// If the path to the external module is relative to the source
Expand Down
10 changes: 7 additions & 3 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -318,13 +318,15 @@ type OnResolveArgs struct {
Path string
Importer logger.Path
ResolveDir string
PluginData interface{}
}

type OnResolveResult struct {
PluginName string

Path logger.Path
External bool
Path logger.Path
External bool
PluginData interface{}

Msgs []logger.Msg
ThrownError error
Expand All @@ -338,7 +340,8 @@ type OnLoad struct {
}

type OnLoadArgs struct {
Path logger.Path
Path logger.Path
PluginData interface{}
}

type OnLoadResult struct {
Expand All @@ -347,6 +350,7 @@ type OnLoadResult struct {
Contents *string
AbsResolveDir string
Loader Loader
PluginData interface{}

Msgs []logger.Msg
ThrownError error
Expand Down
3 changes: 3 additions & 0 deletions internal/resolver/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ type IgnoreIfUnusedData struct {
type ResolveResult struct {
PathPair PathPair

// If this was resolved by a plugin, the plugin gets to store its data here
PluginData interface{}

// If not empty, these should override the default values
JSXFactory []string // Default if empty: "React.createElement"
JSXFragment []string // Default if empty: "React.Fragment"
Expand Down
Loading

0 comments on commit feefbf5

Please sign in to comment.