userland: add archive tools and pinned GoAWK, esbuild, and QuickJS

This commit is contained in:
2026-11-07 10:56:29 +00:00
parent 7e7e49bfa2
commit d79b2bc2e1
1798 changed files with 562969 additions and 1 deletions
+100
View File
@@ -0,0 +1,100 @@
// This API exposes the command-line interface for esbuild. It can be used to
// run esbuild from Go without the overhead of creating a child process.
//
// Example usage:
//
// package main
//
// import (
// "os"
//
// "github.com/evanw/esbuild/pkg/cli"
// )
//
// func main() {
// os.Exit(cli.Run(os.Args[1:]))
// }
package cli
import (
"errors"
"github.com/evanw/esbuild/pkg/api"
)
// This function invokes the esbuild CLI. It takes an array of command-line
// arguments (excluding the executable argument itself) and returns an exit
// code. There are some minor differences between this CLI and the actual
// "esbuild" executable such as the lack of auxiliary flags (e.g. "--help" and
// "--version") but it is otherwise exactly the same code.
func Run(osArgs []string) int {
return runImpl(osArgs, []api.Plugin{})
}
// This is similar to "Run()" but also takes an array of plugins to be used
// during the build process.
func RunWithPlugins(osArgs []string, plugins []api.Plugin) int {
return runImpl(osArgs, plugins)
}
// This parses an array of strings into an options object suitable for passing
// to "api.Build()". Use this if you need to reuse the same argument parsing
// logic as the esbuild CLI.
//
// Example usage:
//
// options, err := cli.ParseBuildOptions([]string{
// "input.js",
// "--bundle",
// "--minify",
// })
//
// result := api.Build(options)
func ParseBuildOptions(osArgs []string) (options api.BuildOptions, err error) {
options = newBuildOptions()
_, errWithNote := parseOptionsImpl(osArgs, &options, nil, kindExternal)
if errWithNote != nil {
err = errors.New(errWithNote.Text)
}
return
}
// This parses an array of strings into an options object suitable for passing
// to "api.Transform()". Use this if you need to reuse the same argument
// parsing logic as the esbuild CLI.
//
// Example usage:
//
// options, err := cli.ParseTransformOptions([]string{
// "--minify",
// "--loader=tsx",
// "--define:DEBUG=false",
// })
//
// result := api.Transform(input, options)
func ParseTransformOptions(osArgs []string) (options api.TransformOptions, err error) {
options = newTransformOptions()
_, errWithNote := parseOptionsImpl(osArgs, nil, &options, kindExternal)
if errWithNote != nil {
err = errors.New(errWithNote.Text)
}
return
}
// This parses an array of strings into an options object suitable for passing
// to "api.Serve()". The remaining non-serve arguments are returned in another
// array to then be passed to "api.ParseBuildOptions()". Use this if you need
// to reuse the same argument parsing logic as the esbuild CLI.
//
// Example usage:
//
// serveOptions, args, err := cli.ParseServeOptions([]string{
// "--serve=8000",
// })
//
// buildOptions, err := cli.ParseBuildOptions(args)
//
// result := api.Serve(serveOptions, buildOptions)
func ParseServeOptions(osArgs []string) (options api.ServeOptions, remainingArgs []string, err error) {
return parseServeOptionsImpl(osArgs)
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,19 @@
// This file was automatically generated by "js_table.ts"
package cli
import "github.com/evanw/esbuild/pkg/api"
var validEngines = map[string]api.EngineName{
"chrome": api.EngineChrome,
"deno": api.EngineDeno,
"edge": api.EngineEdge,
"firefox": api.EngineFirefox,
"hermes": api.EngineHermes,
"ie": api.EngineIE,
"ios": api.EngineIOS,
"node": api.EngineNode,
"opera": api.EngineOpera,
"rhino": api.EngineRhino,
"safari": api.EngineSafari,
}
@@ -0,0 +1,154 @@
package cli
// The mangle cache is a JSON file that remembers esbuild's property renaming
// decisions. It's a flat map where the keys are strings and the values are
// either strings or the boolean value "false". This is the case both in JSON
// and in Go (so the "interface{}" values are also either strings or "false").
import (
"fmt"
"sort"
"strings"
"syscall"
"github.com/evanw/esbuild/internal/fs"
"github.com/evanw/esbuild/internal/helpers"
"github.com/evanw/esbuild/internal/js_ast"
"github.com/evanw/esbuild/internal/js_lexer"
"github.com/evanw/esbuild/internal/js_parser"
"github.com/evanw/esbuild/internal/logger"
"github.com/evanw/esbuild/internal/resolver"
)
func parseMangleCache(osArgs []string, fs fs.FS, absPath string) (map[string]interface{}, []string) {
// Log problems with the mangle cache to stderr
log := logger.NewStderrLog(logger.OutputOptionsForArgs(osArgs))
defer log.Done()
// Try to read the existing file
prettyPath := absPath
if rel, ok := fs.Rel(fs.Cwd(), absPath); ok {
prettyPath = rel
}
prettyPath = strings.ReplaceAll(prettyPath, "\\", "/")
bytes, err, originalError := fs.ReadFile(absPath)
if err != nil {
// It's ok if it's just missing
if err == syscall.ENOENT {
return make(map[string]interface{}), []string{}
}
// Otherwise, report the error
log.AddError(nil, logger.Range{},
fmt.Sprintf("Failed to read from mangle cache file %q: %s", prettyPath, originalError.Error()))
return nil, nil
}
// Use our JSON parser so we get pretty-printed error messages
keyPath := logger.Path{Text: absPath, Namespace: "file"}
source := logger.Source{
KeyPath: keyPath,
PrettyPaths: resolver.MakePrettyPaths(fs, keyPath),
Contents: string(bytes),
}
result, ok := js_parser.ParseJSON(log, source, js_parser.JSONOptions{})
if !ok || log.HasErrors() {
// Stop if there were any errors so we don't continue and then overwrite this file
return nil, nil
}
tracker := logger.MakeLineColumnTracker(&source)
// Validate the top-level object
root, ok := result.Data.(*js_ast.EObject)
if !ok {
log.AddError(&tracker, logger.Range{Loc: result.Loc},
"Expected a top-level object in mangle cache file")
return nil, nil
}
mangleCache := make(map[string]interface{}, len(root.Properties))
order := make([]string, 0, len(root.Properties))
for _, property := range root.Properties {
key := helpers.UTF16ToString(property.Key.Data.(*js_ast.EString).Value)
order = append(order, key)
switch v := property.ValueOrNil.Data.(type) {
case *js_ast.EBoolean:
if v.Value {
log.AddError(&tracker, js_lexer.RangeOfIdentifier(source, property.ValueOrNil.Loc),
fmt.Sprintf("Expected %q in mangle cache file to map to either a string or false", key))
} else {
mangleCache[key] = false
}
case *js_ast.EString:
mangleCache[key] = helpers.UTF16ToString(v.Value)
default:
log.AddError(&tracker, logger.Range{Loc: property.ValueOrNil.Loc},
fmt.Sprintf("Expected %q in mangle cache file to map to either a string or false", key))
}
}
if log.HasErrors() {
return nil, nil
}
return mangleCache, order
}
func printMangleCache(mangleCache map[string]interface{}, originalOrder []string, asciiOnly bool) []byte {
j := helpers.Joiner{}
j.AddString("{")
// Determine the order to print the keys in
order := originalOrder
if len(mangleCache) > len(order) {
order = make([]string, 0, len(mangleCache))
if sort.StringsAreSorted(originalOrder) {
// If they came sorted, keep them sorted
for key := range mangleCache {
order = append(order, key)
}
sort.Strings(order)
} else {
// Otherwise add all new keys to the end, and only sort the new keys
originalKeys := make(map[string]bool, len(originalOrder))
for _, key := range originalOrder {
originalKeys[key] = true
}
order = append(order, originalOrder...)
for key := range mangleCache {
if !originalKeys[key] {
order = append(order, key)
}
}
sort.Strings(order[len(originalOrder):])
}
}
// Print the JSON while preserving the existing order of the keys
for i, key := range order {
// Print the key
if i > 0 {
j.AddString(",\n ")
} else {
j.AddString("\n ")
}
j.AddBytes(helpers.QuoteForJSON(key, asciiOnly))
// Print the value
if value := mangleCache[key]; value != false {
j.AddString(": ")
j.AddBytes(helpers.QuoteForJSON(value.(string), asciiOnly))
} else {
j.AddString(": false")
}
}
if len(order) > 0 {
j.AddString("\n")
}
j.AddString("}\n")
return j.Done()
}