Skip to content

Commit

Permalink
fix #879: provide "kind" to "onResolve" plugins
Browse files Browse the repository at this point in the history
  • Loading branch information
evanw committed Feb 24, 2021
1 parent db38df5 commit cab83db
Show file tree
Hide file tree
Showing 11 changed files with 296 additions and 4 deletions.
34 changes: 34 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,40 @@

This release fixes an issue where esbuild could potentially crash sometimes with a concurrent map write when using injected files and entry points that were neither relative nor absolute paths. This was an edge case where esbuild's low-level file subsystem was being used without being behind a mutex lock. This regression was likely introduced in version 0.8.21. The cause of the crash has been fixed.

* Provide `kind` to `onResolve` plugins ([#879](https://github.com/evanw/esbuild/issues/879))

Plugins that add `onResolve` callbacks now have access to the `kind` parameter which tells you what kind of import is being resolved. It will be one of the following values:

* `"entry-point"` in JS (`api.ResolveEntryPoint` in Go)

An entry point provided by the user

* `"import-statement"` in JS (`api.ResolveJSImportStatement` in Go)

A JavaScript `import` or `export` statement

* `"require-call"` in JS (`api.ResolveJSRequireCall` in Go)

A JavaScript call to `require(...)` with a string argument

* `"dynamic-import"` in JS (`api.ResolveJSDynamicImport` in Go)

A JavaScript `import(...)` expression with a string argument

* `"require-resolve"` in JS (`api.ResolveJSRequireResolve` in Go)

A JavaScript call to `require.resolve(...)` with a string argument

* `"import-rule"` in JS (`api.ResolveCSSImportRule` in Go)

A CSS `@import` rule

* `"url-token"` in JS (`api.ResolveCSSURLToken` in Go)

A CSS `url(...)` token

These values are pretty much identical to the `kind` field in the JSON metadata file.

## 0.8.51

* The stderr log format now contains line numbers after file names ([#865](https://github.com/evanw/esbuild/issues/865))
Expand Down
26 changes: 26 additions & 0 deletions cmd/esbuild/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,31 @@ func (service *serviceType) convertPlugins(key int, jsPlugins interface{}) ([]ap
return result, nil
}

var kind string
switch args.Kind {
case api.ResolveEntryPoint:
kind = "entry-point"

// JS
case api.ResolveJSImportStatement:
kind = "import-statement"
case api.ResolveJSRequireCall:
kind = "require-call"
case api.ResolveJSDynamicImport:
kind = "dynamic-import"
case api.ResolveJSRequireResolve:
kind = "require-resolve"

// CSS
case api.ResolveCSSImportRule:
kind = "import-rule"
case api.ResolveCSSURLToken:
kind = "url-token"

default:
panic("Internal error")
}

response := service.sendRequest(map[string]interface{}{
"command": "resolve",
"key": key,
Expand All @@ -625,6 +650,7 @@ func (service *serviceType) convertPlugins(key int, jsPlugins interface{}) ([]ap
"importer": args.Importer,
"namespace": args.Namespace,
"resolveDir": args.ResolveDir,
"kind": kind,
"pluginData": args.PluginData,
}).(map[string]interface{})

Expand Down
8 changes: 4 additions & 4 deletions internal/ast/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@ import "github.com/evanw/esbuild/internal/logger"
type ImportKind uint8

const (
// An entry point provided by the user
ImportEntryPoint ImportKind = iota

// An ES6 import or re-export statement
ImportStmt ImportKind = iota
ImportStmt

// A call to "require()"
ImportRequire
Expand All @@ -26,9 +29,6 @@ const (

// A CSS "url(...)" token
ImportURL

// An entry point provided by the user
ImportEntryPoint
)

func (kind ImportKind) StringForMetafile() string {
Expand Down
1 change: 1 addition & 0 deletions internal/bundler/bundler.go
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,7 @@ func runOnResolvePlugins(
resolverArgs := config.OnResolveArgs{
Path: path,
ResolveDir: absResolveDir,
Kind: kind,
PluginData: pluginData,
}
applyPath := logger.Path{Text: path}
Expand Down
2 changes: 2 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"regexp"
"sync"

"github.com/evanw/esbuild/internal/ast"
"github.com/evanw/esbuild/internal/compat"
"github.com/evanw/esbuild/internal/js_ast"
"github.com/evanw/esbuild/internal/logger"
Expand Down Expand Up @@ -321,6 +322,7 @@ type OnResolveArgs struct {
Path string
Importer logger.Path
ResolveDir string
Kind ast.ImportKind
PluginData interface{}
}

Expand Down
1 change: 1 addition & 0 deletions lib/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,7 @@ export function createChannel(streamIn: StreamIn): StreamOut {
importer: request.importer,
namespace: request.namespace,
resolveDir: request.resolveDir,
kind: request.kind,
pluginData: stash.load(request.pluginData),
});

Expand Down
1 change: 1 addition & 0 deletions lib/stdio_protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ export interface OnResolveRequest {
importer: string;
namespace: string;
resolveDir: string;
kind: string;
pluginData: number;
}

Expand Down
14 changes: 14 additions & 0 deletions lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,9 +192,23 @@ export interface OnResolveArgs {
importer: string;
namespace: string;
resolveDir: string;
kind: ResolveKind;
pluginData: any;
}

export type ResolveKind =
| 'entry-point'

// JS
| 'import-statement'
| 'require-call'
| 'dynamic-import'
| 'require-resolve'

// CSS
| 'import-rule'
| 'url-token'

export interface OnResolveResult {
pluginName?: string;

Expand Down
13 changes: 13 additions & 0 deletions pkg/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,7 @@ type OnResolveArgs struct {
Importer string
Namespace string
ResolveDir string
Kind ResolveKind
PluginData interface{}
}

Expand Down Expand Up @@ -444,3 +445,15 @@ type OnLoadResult struct {
Loader Loader
PluginData interface{}
}

type ResolveKind uint8

const (
ResolveEntryPoint ResolveKind = iota
ResolveJSImportStatement
ResolveJSRequireCall
ResolveJSDynamicImport
ResolveJSRequireResolve
ResolveCSSImportRule
ResolveCSSURLToken
)
22 changes: 22 additions & 0 deletions pkg/api/api_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"sync/atomic"
"time"

"github.com/evanw/esbuild/internal/ast"
"github.com/evanw/esbuild/internal/bundler"
"github.com/evanw/esbuild/internal/cache"
"github.com/evanw/esbuild/internal/compat"
Expand Down Expand Up @@ -1117,11 +1118,32 @@ func (impl *pluginImpl) OnResolve(options OnResolveOptions, callback func(OnReso
Filter: filter,
Namespace: options.Namespace,
Callback: func(args config.OnResolveArgs) (result config.OnResolveResult) {
var kind ResolveKind
switch args.Kind {
case ast.ImportEntryPoint:
kind = ResolveEntryPoint
case ast.ImportStmt:
kind = ResolveJSImportStatement
case ast.ImportRequire:
kind = ResolveJSRequireCall
case ast.ImportDynamic:
kind = ResolveJSDynamicImport
case ast.ImportRequireResolve:
kind = ResolveJSRequireResolve
case ast.ImportAt:
kind = ResolveCSSImportRule
case ast.ImportURL:
kind = ResolveCSSURLToken
default:
panic("Internal error")
}

response, err := callback(OnResolveArgs{
Path: args.Path,
Importer: args.Importer.Text,
Namespace: args.Importer.Namespace,
ResolveDir: args.ResolveDir,
Kind: kind,
PluginData: args.PluginData,
})
result.PluginName = response.PluginName
Expand Down
Loading

0 comments on commit cab83db

Please sign in to comment.