From dc5e7503e48ca80125e94383ecea6b9b533b916c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=80=E4=B8=9D?= Date: Fri, 31 Oct 2025 12:14:30 +0800 Subject: [PATCH 01/12] feat: add CSS `@view-transition` (#4313) MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/@view-transition --- CHANGELOG.md | 14 ++++++++++++++ internal/css_parser/css_parser.go | 4 ++++ internal/css_parser/css_parser_test.go | 4 ++++ 3 files changed, 22 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e070d6c44de..491c9f6c614 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +* Add support for the new `@view-transition` CSS at rule ([#4313](https://github.com/evanw/esbuild/pull/4313)) + + ```css + /* Original code */ + @view-transition { + navigation: auto; + types: check; + } + /* Output */ + @view-transition{navigation:auto;types:check} + ``` + + This was contributed by [@yisibl](https://github.com/yisibl). + ## 0.25.11 * Add support for `with { type: 'bytes' }` imports ([#4292](https://github.com/evanw/esbuild/issues/4292)) diff --git a/internal/css_parser/css_parser.go b/internal/css_parser/css_parser.go index b45bc08aa52..3f6ca6dc19b 100644 --- a/internal/css_parser/css_parser.go +++ b/internal/css_parser/css_parser.go @@ -1109,6 +1109,10 @@ var specialAtRules = map[string]atRuleKind{ // Anchor Positioning // Reference: https://drafts.csswg.org/css-anchor-position-1/#at-ruledef-position-try "position-try": atRuleDeclarations, + + // @view-transition + // Reference: https://drafts.csswg.org/css-view-transitions-2/#view-transition-rule + "view-transition": atRuleDeclarations, } var atKnownRuleCanBeRemovedIfEmpty = map[string]bool{ diff --git a/internal/css_parser/css_parser_test.go b/internal/css_parser/css_parser_test.go index 8b76e801cdd..5061e027f12 100644 --- a/internal/css_parser/css_parser_test.go +++ b/internal/css_parser/css_parser_test.go @@ -1516,6 +1516,10 @@ func TestAtRule(t *testing.T) { } } }`, "@supports (container-type: size){@container (width <= 150px){#inner{background-color:#87ceeb}}}", "") + expectPrintedMinify(t, `@view-transition { + navigation: auto; + types: check; +}`, "@view-transition{navigation:auto;types:check}", "") // https://drafts.csswg.org/css-transitions-2/#defining-before-change-style-the-starting-style-rule expectPrinted(t, ` From 4460d3fe2c04d42e8f2543efa65261d0bc0ebcf6 Mon Sep 17 00:00:00 2001 From: Evan Wallace Date: Fri, 31 Oct 2025 00:20:39 -0400 Subject: [PATCH 02/12] update release notes --- CHANGELOG.md | 19 +++++++++++++++---- internal/css_parser/css_parser_test.go | 9 ++++++++- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 491c9f6c614..7ae5715068e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Changelog -* Add support for the new `@view-transition` CSS at rule ([#4313](https://github.com/evanw/esbuild/pull/4313)) +* Add support for the new `@view-transition` CSS rule ([#4313](https://github.com/evanw/esbuild/pull/4313)) + + With this release, esbuild now has improved support for pretty-printing and minifying the new `@view-transition` rule (which esbuild was previously unaware of): ```css /* Original code */ @@ -8,11 +10,20 @@ navigation: auto; types: check; } - /* Output */ - @view-transition{navigation:auto;types:check} + + /* Old output */ + @view-transition { navigation: auto; types: check; } + + /* New output */ + @view-transition { + navigation: auto; + types: check; + } ``` - This was contributed by [@yisibl](https://github.com/yisibl). + The new view transition feature provides a mechanism for creating animated transitions between documents in a multi-page app. You can read more about view transition rules [here](https://developer.mozilla.org/en-US/docs/Web/CSS/@view-transition). + + This change was contributed by [@yisibl](https://github.com/yisibl). ## 0.25.11 diff --git a/internal/css_parser/css_parser_test.go b/internal/css_parser/css_parser_test.go index 5061e027f12..0203e713775 100644 --- a/internal/css_parser/css_parser_test.go +++ b/internal/css_parser/css_parser_test.go @@ -1516,8 +1516,15 @@ func TestAtRule(t *testing.T) { } } }`, "@supports (container-type: size){@container (width <= 150px){#inner{background-color:#87ceeb}}}", "") - expectPrintedMinify(t, `@view-transition { + + // https://drafts.csswg.org/css-view-transitions-2/#view-transition-rule + expectPrinted(t, "@view-transition { navigation: auto; types: check; }", `@view-transition { navigation: auto; + types: check; +} +`, "") + expectPrintedMinify(t, `@view-transition { + navigation: auto; types: check; }`, "@view-transition{navigation:auto;types:check}", "") From 26b29ed51ffe20730ffaf69921dbb53e27de464a Mon Sep 17 00:00:00 2001 From: Evan Wallace Date: Fri, 31 Oct 2025 17:12:38 -0400 Subject: [PATCH 03/12] fix #4315: `@media` deduplication bug edge case --- CHANGELOG.md | 6 ++++ internal/css_ast/css_ast.go | 17 ++++++++--- internal/css_parser/css_parser_test.go | 42 ++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ae5715068e..22bd73a5b80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## Unreleased + +* Fix a minification regression with CSS media queries ([#4315](https://github.com/evanw/esbuild/issues/4315)) + + The previous release introduced support for parsing media queries which unintentionally introduced a regression with the removal of duplicate media rules during minification. Specifically the grammar for `@media and { ... }` was missing an equality check for the `` part, so rules with different suffix clauses in this position would incorrectly compare equal and be deduplicated. This release fixes the regression. + * Add support for the new `@view-transition` CSS rule ([#4313](https://github.com/evanw/esbuild/pull/4313)) With this release, esbuild now has improved support for pretty-printing and minifying the new `@view-transition` rule (which esbuild was previously unaware of): diff --git a/internal/css_ast/css_ast.go b/internal/css_ast/css_ast.go index cd3a464cc65..551de98c7ed 100644 --- a/internal/css_ast/css_ast.go +++ b/internal/css_ast/css_ast.go @@ -848,19 +848,28 @@ type MQType struct { } func (q *MQType) Equal(query MQ, check *CrossFileEqualityCheck) bool { - p, ok := query.(*MQType) - return ok && q.Op == p.Op && q.Type == p.Type + if p, ok := query.(*MQType); ok && q.Op == p.Op && q.Type == p.Type { + return (q.AndOrNull.Data == nil && p.AndOrNull.Data == nil) || + (q.AndOrNull.Data != nil && p.AndOrNull.Data != nil && q.AndOrNull.Data.Equal(p.AndOrNull.Data, check)) + } + return false } func (q *MQType) EqualIgnoringWhitespace(query MQ) bool { - p, ok := query.(*MQType) - return ok && q.Op == p.Op && q.Type == p.Type + if p, ok := query.(*MQType); ok && q.Op == p.Op && q.Type == p.Type { + return (q.AndOrNull.Data == nil && p.AndOrNull.Data == nil) || + (q.AndOrNull.Data != nil && p.AndOrNull.Data != nil && q.AndOrNull.Data.EqualIgnoringWhitespace(p.AndOrNull.Data)) + } + return false } func (q *MQType) Hash() uint32 { hash := uint32(0) hash = helpers.HashCombine(hash, uint32(q.Op)) hash = helpers.HashCombineString(hash, q.Type) + if q.AndOrNull.Data != nil { + hash = helpers.HashCombine(hash, q.AndOrNull.Data.Hash()) + } return hash } diff --git a/internal/css_parser/css_parser_test.go b/internal/css_parser/css_parser_test.go index 0203e713775..e66c4f6b931 100644 --- a/internal/css_parser/css_parser_test.go +++ b/internal/css_parser/css_parser_test.go @@ -2642,6 +2642,48 @@ func TestMangleAtMedia(t *testing.T) { expectPrintedMangle(t, "@media not (1px <= width) { a { color: red } }", "@media (1px > width) {\n a {\n color: red;\n }\n}\n", "") expectPrintedMangle(t, "@media not (1px > width) { a { color: red } }", "@media (1px <= width) {\n a {\n color: red;\n }\n}\n", "") expectPrintedMangle(t, "@media not (1px >= width) { a { color: red } }", "@media (1px < width) {\n a {\n color: red;\n }\n}\n", "") + + // Merge + expectPrintedMangle(t, "b { @media (x) { a { color: red } } @media (x) { a { color: red } } }", + "b {\n @media (x) {\n a {\n color: red;\n }\n }\n}\n", "") + expectPrintedMangle(t, "b { @media (x: y) { a { color: red } } @media (x: y) { a { color: red } } }", + "b {\n @media (x: y) {\n a {\n color: red;\n }\n }\n}\n", "") + expectPrintedMangle(t, "b { @media (x < y > z) { a { color: red } } @media (x < y > z) { a { color: red } } }", + "b {\n @media (x < y > z) {\n a {\n color: red;\n }\n }\n}\n", "") + expectPrintedMangle(t, "b { @media (x) or (y) { a { color: red } } @media (x) or (y) { a { color: red } } }", + "b {\n @media (x) or (y) {\n a {\n color: red;\n }\n }\n}\n", "") + expectPrintedMangle(t, "b { @media (x) and (y) { a { color: red } } @media (x) and (y) { a { color: red } } }", + "b {\n @media (x) and (y) {\n a {\n color: red;\n }\n }\n}\n", "") + expectPrintedMangle(t, "b { @media not (x) { a { color: red } } @media not (x) { a { color: red } } }", + "b {\n @media not (x) {\n a {\n color: red;\n }\n }\n}\n", "") + expectPrintedMangle(t, "b { @media screen and (x) { a { color: red } } @media screen and (x) { a { color: red } } }", + "b {\n @media screen and (x) {\n a {\n color: red;\n }\n }\n}\n", "") + expectPrintedMangle(t, "b { @media screen and (x ? y) { a { color: red } } @media screen and (x ? y) { a { color: red } } }", + "b {\n @media screen and (x ? y) {\n a {\n color: red;\n }\n }\n}\n", "") + + // Don't merge + expectPrintedMangle(t, "b { @media (x) { a { color: red } } @media (y) { a { color: red } } }", + "b {\n @media (x) {\n a {\n color: red;\n }\n }\n @media (y) {\n a {\n color: red;\n }\n }\n}\n", "") + expectPrintedMangle(t, "b { @media (x: y) { a { color: red } } @media (x: z) { a { color: red } } }", + "b {\n @media (x: y) {\n a {\n color: red;\n }\n }\n @media (x: z) {\n a {\n color: red;\n }\n }\n}\n", "") + expectPrintedMangle(t, "b { @media (x < y > z) { a { color: red } } @media (x < y < z) { a { color: red } } }", + "b {\n @media (x < y > z) {\n a {\n color: red;\n }\n }\n @media (x < y < z) {\n a {\n color: red;\n }\n }\n}\n", "") + expectPrintedMangle(t, "b { @media (x < y > z) { a { color: red } } @media (x > y > z) { a { color: red } } }", + "b {\n @media (x < y > z) {\n a {\n color: red;\n }\n }\n @media (x > y > z) {\n a {\n color: red;\n }\n }\n}\n", "") + expectPrintedMangle(t, "b { @media (x) or (y) { a { color: red } } @media (x) and (y) { a { color: red } } }", + "b {\n @media (x) or (y) {\n a {\n color: red;\n }\n }\n @media (x) and (y) {\n a {\n color: red;\n }\n }\n}\n", "") + expectPrintedMangle(t, "b { @media (x) { a { color: red } } @media not (x) { a { color: red } } }", + "b {\n @media (x) {\n a {\n color: red;\n }\n }\n @media not (x) {\n a {\n color: red;\n }\n }\n}\n", "") + expectPrintedMangle(t, "b { @media (x) { a { color: red } } @media screen and (x) { a { color: red } } }", + "b {\n @media (x) {\n a {\n color: red;\n }\n }\n @media screen and (x) {\n a {\n color: red;\n }\n }\n}\n", "") + expectPrintedMangle(t, "b { @media screen and (x) { a { color: red } } @media print and (x) { a { color: red } } }", + "b {\n @media screen and (x) {\n a {\n color: red;\n }\n }\n @media print and (x) {\n a {\n color: red;\n }\n }\n}\n", "") + expectPrintedMangle(t, "b { @media screen and (x) { a { color: red } } @media not screen and (x) { a { color: red } } }", + "b {\n @media screen and (x) {\n a {\n color: red;\n }\n }\n @media not screen and (x) {\n a {\n color: red;\n }\n }\n}\n", "") + expectPrintedMangle(t, "b { @media screen and (x) { a { color: red } } @media screen and (y) { a { color: red } } }", + "b {\n @media screen and (x) {\n a {\n color: red;\n }\n }\n @media screen and (y) {\n a {\n color: red;\n }\n }\n}\n", "") + expectPrintedMangle(t, "b { @media screen and (x) { a { color: red } } @media screen and (x) and (x) { a { color: red } } }", + "b {\n @media screen and (x) {\n a {\n color: red;\n }\n }\n @media screen and (x) and (x) {\n a {\n color: red;\n }\n }\n}\n", "") } func TestLowerAtMediaRange(t *testing.T) { From 4a51f0b24d343d7ae5b7d5a3e5c3afce3f96a0f8 Mon Sep 17 00:00:00 2001 From: DepthFirst Disclosures Date: Sat, 1 Nov 2025 11:58:12 -0700 Subject: [PATCH 04/12] fix: escape dev server breadcrumb hrefs properly (#4316) --- pkg/api/serve_other.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/api/serve_other.go b/pkg/api/serve_other.go index e7d180f96cc..77269e3a549 100644 --- a/pkg/api/serve_other.go +++ b/pkg/api/serve_other.go @@ -668,7 +668,7 @@ func respondWithDirList(queryPath string, dirEntries map[string]bool, fileEntrie for i, part := range parts { if i+1 < len(parts) { html.WriteString("") } html.WriteString(escapeForHTML(part)) From d3c67f9e94267d06337d2e2e0d837844d2cac6bd Mon Sep 17 00:00:00 2001 From: Evan Wallace Date: Sat, 1 Nov 2025 15:20:28 -0400 Subject: [PATCH 05/12] fix #4310: add `Iterator` and other known globals --- CHANGELOG.md | 27 +++++++++++++ internal/bundler_tests/bundler_dce_test.go | 17 +++++++++ .../bundler_tests/snapshots/snapshots_dce.txt | 7 ++++ internal/config/globals.go | 38 ++++++++++++------- 4 files changed, 75 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 22bd73a5b80..93002048803 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,33 @@ The previous release introduced support for parsing media queries which unintentionally introduced a regression with the removal of duplicate media rules during minification. Specifically the grammar for `@media and { ... }` was missing an equality check for the `` part, so rules with different suffix clauses in this position would incorrectly compare equal and be deduplicated. This release fixes the regression. +* Update the list of known JavaScript globals ([#4310](https://github.com/evanw/esbuild/issues/4310)) + + This release updates esbuild's internal list of known JavaScript globals. These are globals that are known to not have side-effects when the property is accessed. For example, accessing the global `Array` property is considered to be side-effect free but accessing the global `scrollY` property can trigger a layout, which is a side-effect. This is used by esbuild's tree-shaking to safely remove unused code that is known to be side-effect free. This update adds the following global properties: + + From [ES2017](https://tc39.es/ecma262/2017/): + - `Atomics` + - `SharedArrayBuffer` + + From [ES2020](https://tc39.es/ecma262/2020/): + - `BigInt64Array` + - `BigUint64Array` + + From [ES2021](https://tc39.es/ecma262/2021/): + - `FinalizationRegistry` + - `WeakRef` + + From [ES2025](https://tc39.es/ecma262/2025/): + - `Float16Array` + - `Iterator` + + Note that this does not indicate that constructing any of these objects is side-effect free, just that accessing the identifier is side-effect free. For example, this now allows esbuild to tree-shake classes that extend from `Iterator`: + + ```js + // This can now be tree-shaken by esbuild: + class ExampleIterator extends Iterator {} + ``` + * Add support for the new `@view-transition` CSS rule ([#4313](https://github.com/evanw/esbuild/pull/4313)) With this release, esbuild now has improved support for pretty-printing and minifying the new `@view-transition` rule (which esbuild was previously unaware of): diff --git a/internal/bundler_tests/bundler_dce_test.go b/internal/bundler_tests/bundler_dce_test.go index 06428f705cf..d6e23fb6189 100644 --- a/internal/bundler_tests/bundler_dce_test.go +++ b/internal/bundler_tests/bundler_dce_test.go @@ -4930,3 +4930,20 @@ func TestDCEOfNegatedBigints(t *testing.T) { }, }) } + +// https://github.com/evanw/esbuild/issues/4310 +func TestDCEOfIteratorSuperclassIssue4310(t *testing.T) { + dce_suite.expectBundled(t, bundled{ + files: map[string]string{ + "/entry.js": ` + class Keep extends NotIterator {} + class Remove extends Iterator {} + `, + }, + entryPaths: []string{"/entry.js"}, + options: config.Options{ + Mode: config.ModeBundle, + AbsOutputDir: "/out", + }, + }) +} diff --git a/internal/bundler_tests/snapshots/snapshots_dce.txt b/internal/bundler_tests/snapshots/snapshots_dce.txt index 1c27ec3aa58..51eafdc9a55 100644 --- a/internal/bundler_tests/snapshots/snapshots_dce.txt +++ b/internal/bundler_tests/snapshots/snapshots_dce.txt @@ -652,6 +652,13 @@ use(isNotPure); } }; })(); +================================================================================ +TestDCEOfIteratorSuperclassIssue4310 +---------- /out/entry.js ---------- +// entry.js +var Keep = class extends NotIterator { +}; + ================================================================================ TestDCEOfNegatedBigints ---------- /out/entry.js ---------- diff --git a/internal/config/globals.go b/internal/config/globals.go index 1bbc9786f8c..7fcc0858dc3 100644 --- a/internal/config/globals.go +++ b/internal/config/globals.go @@ -27,18 +27,6 @@ var processedGlobals *ProcessedDefines // these functions has any side effects. It only says something about // referencing these function without calling them. var knownGlobals = [][]string{ - // These global identifiers should exist in all JavaScript environments. This - // deliberately omits "NaN", "Infinity", and "undefined" because these are - // treated as automatically-inlined constants instead of identifiers. - {"Array"}, - {"Boolean"}, - {"Function"}, - {"Math"}, - {"Number"}, - {"Object"}, - {"RegExp"}, - {"String"}, - // Object: Static methods // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object#Static_methods {"Object", "assign"}, @@ -166,36 +154,57 @@ var knownGlobals = [][]string{ {"JSON", "parse"}, {"JSON", "stringify"}, - // Other globals present in both the browser and node (except "eval" because - // it has special behavior) + // Other globals present in both the browser and node. This should include at + // least the following properties: + // https://tc39.es/ecma262/multipage/global-object.html#sec-constructor-properties-of-the-global-object + // + // Exceptions: + // - Don't include "eval" because it has special behavior + // - Don't include "NaN", "Infinity", and "undefined" because esbuild treats + // these as automatically-inlined constants instead of identifiers {"AbortController"}, {"AbortSignal"}, {"AggregateError"}, + {"Array"}, {"ArrayBuffer"}, + {"Atomics"}, {"BigInt"}, + {"BigInt64Array"}, + {"BigUint64Array"}, + {"Boolean"}, {"DataView"}, {"Date"}, {"Error"}, {"EvalError"}, {"Event"}, {"EventTarget"}, + {"FinalizationRegistry"}, + {"Float16Array"}, {"Float32Array"}, {"Float64Array"}, + {"Function"}, {"Int16Array"}, {"Int32Array"}, {"Int8Array"}, {"Intl"}, + {"Iterator"}, {"JSON"}, {"Map"}, + {"Math"}, {"MessageChannel"}, {"MessageEvent"}, {"MessagePort"}, + {"Number"}, + {"Object"}, {"Promise"}, {"Proxy"}, {"RangeError"}, {"ReferenceError"}, {"Reflect"}, + {"RegExp"}, {"Set"}, + {"SharedArrayBuffer"}, + {"String"}, {"Symbol"}, {"SyntaxError"}, {"TextDecoder"}, @@ -209,6 +218,7 @@ var knownGlobals = [][]string{ {"Uint8Array"}, {"Uint8ClampedArray"}, {"WeakMap"}, + {"WeakRef"}, {"WeakSet"}, {"WebAssembly"}, {"clearInterval"}, From 188944dd946dd54d50bbe844dc22969b604589d0 Mon Sep 17 00:00:00 2001 From: Evan Wallace Date: Sat, 1 Nov 2025 15:30:18 -0400 Subject: [PATCH 06/12] add some additional known static methods --- internal/config/globals.go | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/internal/config/globals.go b/internal/config/globals.go index 7fcc0858dc3..cceb1572d16 100644 --- a/internal/config/globals.go +++ b/internal/config/globals.go @@ -27,8 +27,23 @@ var processedGlobals *ProcessedDefines // these functions has any side effects. It only says something about // referencing these function without calling them. var knownGlobals = [][]string{ + // Array: Static methods + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array#static_methods + {"Array", "from"}, + {"Array", "fromAsync"}, + {"Array", "isArray"}, + {"Array", "of"}, + + // RegExp: Static methods + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#static_methods + {"RegExp", "escape"}, + + // Map: Static methods + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map#static_methods + {"Map", "groupBy"}, + // Object: Static methods - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object#Static_methods + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object#static_methods {"Object", "assign"}, {"Object", "create"}, {"Object", "defineProperties"}, @@ -52,7 +67,7 @@ var knownGlobals = [][]string{ {"Object", "values"}, // Object: Instance methods - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object#Instance_methods + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object#instance_methods {"Object", "prototype", "__defineGetter__"}, {"Object", "prototype", "__defineSetter__"}, {"Object", "prototype", "__lookupGetter__"}, @@ -85,7 +100,7 @@ var knownGlobals = [][]string{ {"Symbol", "unscopables"}, // Math: Static properties - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math#Static_properties + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math#static_properties {"Math", "E"}, {"Math", "LN10"}, {"Math", "LN2"}, @@ -96,7 +111,7 @@ var knownGlobals = [][]string{ {"Math", "SQRT2"}, // Math: Static methods - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math#Static_methods + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math#static_methods {"Math", "abs"}, {"Math", "acos"}, {"Math", "acosh"}, From 9039c468258fd9a19eeaf5e05fd6a3d582b46d3a Mon Sep 17 00:00:00 2001 From: Evan Wallace Date: Sat, 1 Nov 2025 15:46:28 -0400 Subject: [PATCH 07/12] simplify some call expression checks --- internal/js_parser/js_parser.go | 115 +++++++++++++++----------------- 1 file changed, 53 insertions(+), 62 deletions(-) diff --git a/internal/js_parser/js_parser.go b/internal/js_parser/js_parser.go index 4cc2e15f271..697d52f064d 100644 --- a/internal/js_parser/js_parser.go +++ b/internal/js_parser/js_parser.go @@ -14965,19 +14965,6 @@ func (p *parser) visitExprInOut(expr js_ast.Expr, in exprIn) (js_ast.Expr, exprO p.thenCatchChain.catchLoc = e.Args[1].Loc } - // Prepare to recognize "require.resolve()" and "Object.create" calls - couldBeRequireResolve := false - couldBeObjectCreate := false - if len(e.Args) == 1 { - if dot, ok := e.Target.Data.(*js_ast.EDot); ok && dot.OptionalChain == js_ast.OptionalChainNone { - if p.options.mode != config.ModePassThrough && dot.Name == "resolve" { - couldBeRequireResolve = true - } else if dot.Name == "create" { - couldBeObjectCreate = true - } - } - } - wasIdentifierBeforeVisit := false isParenthesizedOptionalChain := false switch e2 := e.Target.Data.(type) { @@ -15222,57 +15209,61 @@ func (p *parser) visitExprInOut(expr js_ast.Expr, in exprIn) (js_ast.Expr, exprO } case *js_ast.EDot: - // Recognize "require.resolve()" calls - if couldBeRequireResolve && t.Name == "resolve" { - if id, ok := t.Target.Data.(*js_ast.EIdentifier); ok && id.Ref == p.requireRef { - p.ignoreUsage(p.requireRef) - return p.maybeTransposeIfExprChain(e.Args[0], func(arg js_ast.Expr) js_ast.Expr { - if str, ok := e.Args[0].Data.(*js_ast.EString); ok { - // Ignore calls to require.resolve() if the control flow is provably - // dead here. We don't want to spend time scanning the required files - // if they will never be used. - if p.isControlFlowDead { - return js_ast.Expr{Loc: expr.Loc, Data: js_ast.ENullShared} - } + if len(e.Args) == 1 { + switch t.Name { + case "resolve": + // Recognize "require.resolve()" calls + if t.OptionalChain == js_ast.OptionalChainNone && p.options.mode != config.ModePassThrough { + if id, ok := t.Target.Data.(*js_ast.EIdentifier); ok && id.Ref == p.requireRef { + p.ignoreUsage(p.requireRef) + return p.maybeTransposeIfExprChain(e.Args[0], func(arg js_ast.Expr) js_ast.Expr { + if str, ok := e.Args[0].Data.(*js_ast.EString); ok { + // Ignore calls to require.resolve() if the control flow is provably + // dead here. We don't want to spend time scanning the required files + // if they will never be used. + if p.isControlFlowDead { + return js_ast.Expr{Loc: expr.Loc, Data: js_ast.ENullShared} + } - importRecordIndex := p.addImportRecord(ast.ImportRequireResolve, ast.EvaluationPhase, p.source.RangeOfString(e.Args[0].Loc), helpers.UTF16ToString(str.Value), nil, 0) - if p.fnOrArrowDataVisit.tryBodyCount != 0 { - record := &p.importRecords[importRecordIndex] - record.Flags |= ast.HandlesImportErrors - record.ErrorHandlerLoc = p.fnOrArrowDataVisit.tryCatchLoc - } - p.importRecordsForCurrentPart = append(p.importRecordsForCurrentPart, importRecordIndex) + importRecordIndex := p.addImportRecord(ast.ImportRequireResolve, ast.EvaluationPhase, p.source.RangeOfString(e.Args[0].Loc), helpers.UTF16ToString(str.Value), nil, 0) + if p.fnOrArrowDataVisit.tryBodyCount != 0 { + record := &p.importRecords[importRecordIndex] + record.Flags |= ast.HandlesImportErrors + record.ErrorHandlerLoc = p.fnOrArrowDataVisit.tryCatchLoc + } + p.importRecordsForCurrentPart = append(p.importRecordsForCurrentPart, importRecordIndex) - // Create a new expression to represent the operation - return js_ast.Expr{Loc: expr.Loc, Data: &js_ast.ERequireResolveString{ - ImportRecordIndex: importRecordIndex, - CloseParenLoc: e.CloseParenLoc, - }} - } + // Create a new expression to represent the operation + return js_ast.Expr{Loc: expr.Loc, Data: &js_ast.ERequireResolveString{ + ImportRecordIndex: importRecordIndex, + CloseParenLoc: e.CloseParenLoc, + }} + } - // Otherwise just return a clone of the "require.resolve()" call - return js_ast.Expr{Loc: expr.Loc, Data: &js_ast.ECall{ - Target: js_ast.Expr{Loc: e.Target.Loc, Data: &js_ast.EDot{ - Target: p.valueToSubstituteForRequire(t.Target.Loc), - Name: t.Name, - NameLoc: t.NameLoc, - }}, - Args: []js_ast.Expr{arg}, - Kind: e.Kind, - CloseParenLoc: e.CloseParenLoc, - }} - }), exprOut{} - } - } + // Otherwise just return a clone of the "require.resolve()" call + return js_ast.Expr{Loc: expr.Loc, Data: &js_ast.ECall{ + Target: js_ast.Expr{Loc: e.Target.Loc, Data: &js_ast.EDot{ + Target: p.valueToSubstituteForRequire(t.Target.Loc), + Name: t.Name, + NameLoc: t.NameLoc, + }}, + Args: []js_ast.Expr{arg}, + Kind: e.Kind, + CloseParenLoc: e.CloseParenLoc, + }} + }), exprOut{} + } + } - // Recognize "Object.create()" calls - if couldBeObjectCreate && t.Name == "create" { - if id, ok := t.Target.Data.(*js_ast.EIdentifier); ok { - if symbol := &p.symbols[id.Ref.InnerIndex]; symbol.Kind == ast.SymbolUnbound && symbol.OriginalName == "Object" { - switch e.Args[0].Data.(type) { - case *js_ast.ENull, *js_ast.EObject: - // Mark "Object.create(null)" and "Object.create({})" as pure - e.CanBeUnwrappedIfUnused = true + case "create": + // Recognize "Object.create()" calls + if id, ok := t.Target.Data.(*js_ast.EIdentifier); ok { + if symbol := &p.symbols[id.Ref.InnerIndex]; symbol.Kind == ast.SymbolUnbound && symbol.OriginalName == "Object" { + switch e.Args[0].Data.(type) { + case *js_ast.ENull, *js_ast.EObject: + // Mark "Object.create(null)" and "Object.create({})" as pure + e.CanBeUnwrappedIfUnused = true + } } } } @@ -15281,7 +15272,7 @@ func (p *parser) visitExprInOut(expr js_ast.Expr, in exprIn) (js_ast.Expr, exprO if p.options.minifySyntax { switch t.Name { case "charCodeAt": - // Recognize "charCodeAt()" calls + // Recognize "'string'.charCodeAt()" calls if str, ok := t.Target.Data.(*js_ast.EString); ok && len(e.Args) <= 1 { index := 0 hasIndex := false @@ -15301,7 +15292,7 @@ func (p *parser) visitExprInOut(expr js_ast.Expr, in exprIn) (js_ast.Expr, exprO } case "fromCharCode": - // Recognize "fromCharCode()" calls + // Recognize "String.fromCharCode()" calls if id, ok := t.Target.Data.(*js_ast.EIdentifier); ok { if symbol := &p.symbols[id.Ref.InnerIndex]; symbol.Kind == ast.SymbolUnbound && symbol.OriginalName == "String" { charCodes := make([]uint16, 0, len(e.Args)) From 07aa646bb2fd9c5eb1de804edf9eae5bd1617637 Mon Sep 17 00:00:00 2001 From: Evan Wallace Date: Sat, 1 Nov 2025 16:10:11 -0400 Subject: [PATCH 08/12] automatically mark "RegExp.escape()" calls as pure --- internal/js_parser/js_parser.go | 11 +++++++++++ internal/js_parser/js_parser_test.go | 12 ++++++++++++ 2 files changed, 23 insertions(+) diff --git a/internal/js_parser/js_parser.go b/internal/js_parser/js_parser.go index 697d52f064d..9ed1d8b1b46 100644 --- a/internal/js_parser/js_parser.go +++ b/internal/js_parser/js_parser.go @@ -15266,6 +15266,17 @@ func (p *parser) visitExprInOut(expr js_ast.Expr, in exprIn) (js_ast.Expr, exprO } } } + + case "escape": + // Recognize "RegExp.escape()" calls + if id, ok := t.Target.Data.(*js_ast.EIdentifier); ok { + if symbol := &p.symbols[id.Ref.InnerIndex]; symbol.Kind == ast.SymbolUnbound && symbol.OriginalName == "RegExp" { + if js_ast.KnownPrimitiveType(e.Args[0].Data) == js_ast.PrimitiveString { + // Mark "RegExp.escape" with a string literal as pure + e.CanBeUnwrappedIfUnused = true + } + } + } } } diff --git a/internal/js_parser/js_parser_test.go b/internal/js_parser/js_parser_test.go index c5cbd66377b..592033e8f8f 100644 --- a/internal/js_parser/js_parser_test.go +++ b/internal/js_parser/js_parser_test.go @@ -6751,6 +6751,18 @@ func TestAutoPureForDate(t *testing.T) { expectPrinted(t, "new Date(foo ? x : y)", "new Date(foo ? x : y);\n") } +func TestAutoPureForRegExpEscape(t *testing.T) { + expectPrinted(t, "RegExp.escape('x')", "/* @__PURE__ */ RegExp.escape(\"x\");\n") + expectPrinted(t, "RegExp.escape(`${x}`)", "/* @__PURE__ */ RegExp.escape(`${x}`);\n") + expectPrinted(t, "RegExp.escape(x ? 'y' : 'z')", "/* @__PURE__ */ RegExp.escape(x ? \"y\" : \"z\");\n") + + expectPrinted(t, "RegExp.escape()", "RegExp.escape();\n") + expectPrinted(t, "RegExp.escape(x`y`)", "RegExp.escape(x`y`);\n") + expectPrinted(t, "RegExp.escape('x', 'y')", "RegExp.escape(\"x\", \"y\");\n") + expectPrinted(t, "RegExp.escape(x ? 'y' : z)", "RegExp.escape(x ? \"y\" : z);\n") + expectPrinted(t, "RegExp.escape(x ? y : 'z')", "RegExp.escape(x ? y : \"z\");\n") +} + // See: https://github.com/tc39/proposal-explicit-resource-management func TestUsing(t *testing.T) { expectPrinted(t, "using x = y", "using x = y;\n") From f361debd61ffa0ae2d810fbe0e4c9d39183ed4c6 Mon Sep 17 00:00:00 2001 From: Evan Wallace Date: Sat, 1 Nov 2025 16:40:33 -0400 Subject: [PATCH 09/12] add some additional known static methods --- internal/config/globals.go | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/internal/config/globals.go b/internal/config/globals.go index cceb1572d16..6a1b7534c26 100644 --- a/internal/config/globals.go +++ b/internal/config/globals.go @@ -164,11 +164,40 @@ var knownGlobals = [][]string{ {"Reflect", "set"}, {"Reflect", "setPrototypeOf"}, - // JSON: Static Methods + // JSON: Static methods // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON#static_methods {"JSON", "parse"}, {"JSON", "stringify"}, + // TypedArray: Static methods + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray#static_methods + {"BigInt64Array", "from"}, + {"BigInt64Array", "of"}, + {"BigUint64Array", "from"}, + {"BigUint64Array", "of"}, + {"Float16Array", "from"}, + {"Float16Array", "of"}, + {"Float32Array", "from"}, + {"Float32Array", "of"}, + {"Float64Array", "from"}, + {"Float64Array", "of"}, + {"Int16Array", "from"}, + {"Int16Array", "of"}, + {"Int32Array", "from"}, + {"Int32Array", "of"}, + {"Int8Array", "from"}, + {"Int8Array", "of"}, + {"Uint16Array", "from"}, + {"Uint16Array", "of"}, + {"Uint32Array", "from"}, + {"Uint32Array", "of"}, + {"Uint8Array", "from"}, + {"Uint8Array", "fromBase64"}, + {"Uint8Array", "fromHex"}, + {"Uint8Array", "of"}, + {"Uint8ClampedArray", "from"}, + {"Uint8ClampedArray", "of"}, + // Other globals present in both the browser and node. This should include at // least the following properties: // https://tc39.es/ecma262/multipage/global-object.html#sec-constructor-properties-of-the-global-object From 6b2ee78d7f273d7ed4c4bb08b516939b373bcd67 Mon Sep 17 00:00:00 2001 From: Evan Wallace Date: Sat, 1 Nov 2025 17:45:18 -0400 Subject: [PATCH 10/12] minify: remove css rules containing empty `:is()` --- internal/css_parser/css_parser.go | 39 ++++++++++++++++++++++---- internal/css_parser/css_parser_test.go | 21 ++++++++++++++ internal/linker/linker.go | 6 ++-- 3 files changed, 57 insertions(+), 9 deletions(-) diff --git a/internal/css_parser/css_parser.go b/internal/css_parser/css_parser.go index 3f6ca6dc19b..c994fbac31f 100644 --- a/internal/css_parser/css_parser.go +++ b/internal/css_parser/css_parser.go @@ -705,8 +705,8 @@ next: // Mangle non-top-level rules using a back-to-front pass. Top-level rules // will be mangled by the linker instead for cross-file rule mangling. if !isTopLevel { - remover := MakeDuplicateRuleMangler(ast.SymbolMap{}) - mangledRules = remover.RemoveDuplicateRulesInPlace(p.source.Index, mangledRules, p.importRecords) + remover := MakeDeadRuleMangler(ast.SymbolMap{}) + mangledRules = remover.RemoveDeadRulesInPlace(p.source.Index, mangledRules, p.importRecords) } return mangledRules @@ -726,20 +726,20 @@ type callEntry struct { sourceIndex uint32 } -type DuplicateRuleRemover struct { +type DeadRuleRemover struct { entries map[uint32]hashEntry calls []callEntry check css_ast.CrossFileEqualityCheck } -func MakeDuplicateRuleMangler(symbols ast.SymbolMap) DuplicateRuleRemover { - return DuplicateRuleRemover{ +func MakeDeadRuleMangler(symbols ast.SymbolMap) DeadRuleRemover { + return DeadRuleRemover{ entries: make(map[uint32]hashEntry), check: css_ast.CrossFileEqualityCheck{Symbols: symbols}, } } -func (remover *DuplicateRuleRemover) RemoveDuplicateRulesInPlace(sourceIndex uint32, rules []css_ast.Rule, importRecords []ast.ImportRecord) []css_ast.Rule { +func (remover *DeadRuleRemover) RemoveDeadRulesInPlace(sourceIndex uint32, rules []css_ast.Rule, importRecords []ast.ImportRecord) []css_ast.Rule { // The caller may call this function multiple times, each with a different // set of import records. Remember each set of import records for equality // checks later. @@ -758,6 +758,11 @@ skipRule: for i := n - 1; i >= 0; i-- { rule := rules[i] + // Remove rules with selectors that don't apply to anything (e.g. ":is()") + if r, ok := rule.Data.(*css_ast.RSelector); ok && allSelectorsAreDead(r.Selectors) { + continue skipRule + } + // For duplicate rules, omit all but the last copy if hash, ok := rule.Data.Hash(); ok { entry := remover.entries[hash] @@ -795,6 +800,28 @@ skipRule: return rules[start:] } +func containsDeadSelectors(selectors []css_ast.CompoundSelector) bool { + for _, sel := range selectors { + for _, ss := range sel.SubclassSelectors { + if pseudo, ok := ss.Data.(*css_ast.SSPseudoClassWithSelectorList); ok && len(pseudo.Selectors) == 0 && + (pseudo.Kind == css_ast.PseudoClassIs || pseudo.Kind == css_ast.PseudoClassWhere) { + // ":is()" and ":where()" never match anything when empty + return true + } + } + } + return false +} + +func allSelectorsAreDead(selectors []css_ast.ComplexSelector) bool { + for _, sel := range selectors { + if !containsDeadSelectors(sel.Selectors) { + return false + } + } + return true +} + // Reference: https://developer.mozilla.org/en-US/docs/Web/HTML/Element var nonDeprecatedElementsSupportedByIE7 = map[string]bool{ "a": true, diff --git a/internal/css_parser/css_parser_test.go b/internal/css_parser/css_parser_test.go index e66c4f6b931..4bf129a06dc 100644 --- a/internal/css_parser/css_parser_test.go +++ b/internal/css_parser/css_parser_test.go @@ -2454,6 +2454,27 @@ func TestMangleAlpha(t *testing.T) { expectPrintedLowerMangle(t, "a { color: #000000FF }", "a {\n color: #000;\n}\n", "") } +func TestMangleDeadSelectors(t *testing.T) { + expectPrinted(t, "a { b { color: red } }", "a {\n b {\n color: red;\n }\n}\n", "") + expectPrinted(t, "a { :is() { color: red } }", "a {\n :is() {\n color: red;\n }\n}\n", "") + expectPrinted(t, "a { :where() { color: red } }", "a {\n :where() {\n color: red;\n }\n}\n", "") + + // Trimming away ":is()" can be relevant for automatically-generated style + // rules that are the result of a CSS nesting transform. For more info see + // https://github.com/evanw/esbuild/issues/4265 + expectPrintedMangle(t, "a { color: green; :is() { color: red } }", "a {\n color: green;\n}\n", "") + expectPrintedMangle(t, "a { color: green; :where() { color: red } }", "a {\n color: green;\n}\n", "") + expectPrintedMangle(t, "a { color: green; div + :is() { color: red } }", "a {\n color: green;\n}\n", "") + expectPrintedMangle(t, "a { color: green; div + :where() { color: red } }", "a {\n color: green;\n}\n", "") + + // Note: Style rules use an unforgiving selector list, so we can't trivially + // trim away known dead selectors from the list to keep the remaining + // selectors ("b" in the case below). Other parts of the known dead selector + // may be invalid, which would then render the whole style rule invalid. + expectPrintedMangle(t, "a { color: green; b, :foo :is() { color: red } }", "a {\n color: green;\n b,\n :foo :is() {\n color: red;\n }\n}\n", "") + expectPrintedMangle(t, "a { color: green; b, :foo :where() { color: red } }", "a {\n color: green;\n b,\n :foo :where() {\n color: red;\n }\n}\n", "") +} + func TestMangleDuplicateSelectors(t *testing.T) { expectPrinted(t, "a, a { color: red }", "a,\na {\n color: red;\n}\n", "") expectPrintedMangle(t, "a, a { color: red }", "a {\n color: red;\n}\n", "") diff --git a/internal/linker/linker.go b/internal/linker/linker.go index 588e7c3b0be..931cc672fdc 100644 --- a/internal/linker/linker.go +++ b/internal/linker/linker.go @@ -6110,9 +6110,9 @@ func (c *linkerContext) generateChunkCSS(chunkIndex int, chunkWaitGroup *sync.Wa // in parallel, and must be done from the last rule to the first rule. timer.Begin("Prepare CSS ASTs") asts := make([]css_ast.AST, len(chunkRepr.importsInChunkInOrder)) - var remover css_parser.DuplicateRuleRemover + var remover css_parser.DeadRuleRemover if c.options.MinifySyntax { - remover = css_parser.MakeDuplicateRuleMangler(c.graph.Symbols) + remover = css_parser.MakeDeadRuleMangler(c.graph.Symbols) } for i := len(chunkRepr.importsInChunkInOrder) - 1; i >= 0; i-- { entry := chunkRepr.importsInChunkInOrder[i] @@ -6208,7 +6208,7 @@ func (c *linkerContext) generateChunkCSS(chunkIndex int, chunkWaitGroup *sync.Wa // Remove top-level duplicate rules across files if c.options.MinifySyntax { - rules = remover.RemoveDuplicateRulesInPlace(entry.sourceIndex, rules, ast.ImportRecords) + rules = remover.RemoveDeadRulesInPlace(entry.sourceIndex, rules, ast.ImportRecords) } ast.Rules = rules From 5f03afdd007f6626d4300afc7cbb5bf7c9554393 Mon Sep 17 00:00:00 2001 From: Evan Wallace Date: Sat, 1 Nov 2025 18:27:08 -0400 Subject: [PATCH 11/12] update release notes --- CHANGELOG.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 93002048803..e6d05898abd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,6 +58,28 @@ This change was contributed by [@yisibl](https://github.com/yisibl). +* Trim CSS rules that will never match + + The CSS minifier will now remove rules whose selectors contain `:is()` and `:where()` as those selectors will never match. These selectors can currently be automatically generated by esbuild when you give esbuild nonsensical input such as the following: + + ```css + /* Original code */ + div:before { + color: green; + &.foo { + color: red; + } + } + + /* Old output (with --supported:nesting=false --minify) */ + div:before{color:green}:is().foo{color:red} + + /* New output (with --supported:nesting=false --minify) */ + div:before{color:green} + ``` + + This input is nonsensical because CSS nesting is (unfortunately) not supported inside of pseudo-elements such as `:before`. Currently esbuild generates a rule containing `:is()` in this case when you tell esbuild to transform nested CSS into non-nested CSS. I think it's reasonable to do that as it sort of helps explain what's going on (or at least indicates that something is wrong in the output). It shouldn't be present in minified code, however, so this release now strips it out. + ## 0.25.11 * Add support for `with { type: 'bytes' }` imports ([#4292](https://github.com/evanw/esbuild/issues/4292)) From 208f539945b145e7c9d6d844290f81c3fe5af320 Mon Sep 17 00:00:00 2001 From: Evan Wallace Date: Sat, 1 Nov 2025 19:34:16 -0400 Subject: [PATCH 12/12] publish 0.25.12 to npm --- CHANGELOG.md | 2 +- cmd/esbuild/version.go | 2 +- npm/@esbuild/aix-ppc64/package.json | 2 +- npm/@esbuild/android-arm/package.json | 2 +- npm/@esbuild/android-arm64/package.json | 2 +- npm/@esbuild/android-x64/package.json | 2 +- npm/@esbuild/darwin-arm64/package.json | 2 +- npm/@esbuild/darwin-x64/package.json | 2 +- npm/@esbuild/freebsd-arm64/package.json | 2 +- npm/@esbuild/freebsd-x64/package.json | 2 +- npm/@esbuild/linux-arm/package.json | 2 +- npm/@esbuild/linux-arm64/package.json | 2 +- npm/@esbuild/linux-ia32/package.json | 2 +- npm/@esbuild/linux-loong64/package.json | 2 +- npm/@esbuild/linux-mips64el/package.json | 2 +- npm/@esbuild/linux-ppc64/package.json | 2 +- npm/@esbuild/linux-riscv64/package.json | 2 +- npm/@esbuild/linux-s390x/package.json | 2 +- npm/@esbuild/linux-x64/package.json | 2 +- npm/@esbuild/netbsd-arm64/package.json | 2 +- npm/@esbuild/netbsd-x64/package.json | 2 +- npm/@esbuild/openbsd-arm64/package.json | 2 +- npm/@esbuild/openbsd-x64/package.json | 2 +- npm/@esbuild/openharmony-arm64/package.json | 2 +- npm/@esbuild/sunos-x64/package.json | 2 +- npm/@esbuild/wasi-preview1/package.json | 2 +- npm/@esbuild/win32-arm64/package.json | 2 +- npm/@esbuild/win32-ia32/package.json | 2 +- npm/@esbuild/win32-x64/package.json | 2 +- npm/esbuild-wasm/package.json | 2 +- npm/esbuild/package.json | 54 ++++++++++----------- version.txt | 2 +- 32 files changed, 58 insertions(+), 58 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e6d05898abd..6d2d648956f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## Unreleased +## 0.25.12 * Fix a minification regression with CSS media queries ([#4315](https://github.com/evanw/esbuild/issues/4315)) diff --git a/cmd/esbuild/version.go b/cmd/esbuild/version.go index 15d3930ac07..75a155b1a0d 100644 --- a/cmd/esbuild/version.go +++ b/cmd/esbuild/version.go @@ -1,3 +1,3 @@ package main -const esbuildVersion = "0.25.11" +const esbuildVersion = "0.25.12" diff --git a/npm/@esbuild/aix-ppc64/package.json b/npm/@esbuild/aix-ppc64/package.json index b7b8f80e12f..29ccc7b8fbf 100644 --- a/npm/@esbuild/aix-ppc64/package.json +++ b/npm/@esbuild/aix-ppc64/package.json @@ -1,6 +1,6 @@ { "name": "@esbuild/aix-ppc64", - "version": "0.25.11", + "version": "0.25.12", "description": "The IBM AIX PowerPC 64-bit binary for esbuild, a JavaScript bundler.", "repository": { "type": "git", diff --git a/npm/@esbuild/android-arm/package.json b/npm/@esbuild/android-arm/package.json index f2e772e0de2..3de3d39ac8e 100644 --- a/npm/@esbuild/android-arm/package.json +++ b/npm/@esbuild/android-arm/package.json @@ -1,6 +1,6 @@ { "name": "@esbuild/android-arm", - "version": "0.25.11", + "version": "0.25.12", "description": "A WebAssembly shim for esbuild on Android ARM.", "repository": { "type": "git", diff --git a/npm/@esbuild/android-arm64/package.json b/npm/@esbuild/android-arm64/package.json index e721f7df50f..61d75ef5cda 100644 --- a/npm/@esbuild/android-arm64/package.json +++ b/npm/@esbuild/android-arm64/package.json @@ -1,6 +1,6 @@ { "name": "@esbuild/android-arm64", - "version": "0.25.11", + "version": "0.25.12", "description": "The Android ARM 64-bit binary for esbuild, a JavaScript bundler.", "repository": { "type": "git", diff --git a/npm/@esbuild/android-x64/package.json b/npm/@esbuild/android-x64/package.json index bd978e061f0..7ad2b6fee9b 100644 --- a/npm/@esbuild/android-x64/package.json +++ b/npm/@esbuild/android-x64/package.json @@ -1,6 +1,6 @@ { "name": "@esbuild/android-x64", - "version": "0.25.11", + "version": "0.25.12", "description": "A WebAssembly shim for esbuild on Android x64.", "repository": { "type": "git", diff --git a/npm/@esbuild/darwin-arm64/package.json b/npm/@esbuild/darwin-arm64/package.json index cfac7659d94..3f0242c4786 100644 --- a/npm/@esbuild/darwin-arm64/package.json +++ b/npm/@esbuild/darwin-arm64/package.json @@ -1,6 +1,6 @@ { "name": "@esbuild/darwin-arm64", - "version": "0.25.11", + "version": "0.25.12", "description": "The macOS ARM 64-bit binary for esbuild, a JavaScript bundler.", "repository": { "type": "git", diff --git a/npm/@esbuild/darwin-x64/package.json b/npm/@esbuild/darwin-x64/package.json index 289d579bd05..d1e986cce8f 100644 --- a/npm/@esbuild/darwin-x64/package.json +++ b/npm/@esbuild/darwin-x64/package.json @@ -1,6 +1,6 @@ { "name": "@esbuild/darwin-x64", - "version": "0.25.11", + "version": "0.25.12", "description": "The macOS 64-bit binary for esbuild, a JavaScript bundler.", "repository": { "type": "git", diff --git a/npm/@esbuild/freebsd-arm64/package.json b/npm/@esbuild/freebsd-arm64/package.json index d6eeb495882..5c5315715b9 100644 --- a/npm/@esbuild/freebsd-arm64/package.json +++ b/npm/@esbuild/freebsd-arm64/package.json @@ -1,6 +1,6 @@ { "name": "@esbuild/freebsd-arm64", - "version": "0.25.11", + "version": "0.25.12", "description": "The FreeBSD ARM 64-bit binary for esbuild, a JavaScript bundler.", "repository": { "type": "git", diff --git a/npm/@esbuild/freebsd-x64/package.json b/npm/@esbuild/freebsd-x64/package.json index 3c18301dc2c..9d1c463b80f 100644 --- a/npm/@esbuild/freebsd-x64/package.json +++ b/npm/@esbuild/freebsd-x64/package.json @@ -1,6 +1,6 @@ { "name": "@esbuild/freebsd-x64", - "version": "0.25.11", + "version": "0.25.12", "description": "The FreeBSD 64-bit binary for esbuild, a JavaScript bundler.", "repository": { "type": "git", diff --git a/npm/@esbuild/linux-arm/package.json b/npm/@esbuild/linux-arm/package.json index d6714e80d1c..f10d7d42e01 100644 --- a/npm/@esbuild/linux-arm/package.json +++ b/npm/@esbuild/linux-arm/package.json @@ -1,6 +1,6 @@ { "name": "@esbuild/linux-arm", - "version": "0.25.11", + "version": "0.25.12", "description": "The Linux ARM binary for esbuild, a JavaScript bundler.", "repository": { "type": "git", diff --git a/npm/@esbuild/linux-arm64/package.json b/npm/@esbuild/linux-arm64/package.json index 6df57ec62ce..a89dbdd2179 100644 --- a/npm/@esbuild/linux-arm64/package.json +++ b/npm/@esbuild/linux-arm64/package.json @@ -1,6 +1,6 @@ { "name": "@esbuild/linux-arm64", - "version": "0.25.11", + "version": "0.25.12", "description": "The Linux ARM 64-bit binary for esbuild, a JavaScript bundler.", "repository": { "type": "git", diff --git a/npm/@esbuild/linux-ia32/package.json b/npm/@esbuild/linux-ia32/package.json index e656dda329d..8943db76cdf 100644 --- a/npm/@esbuild/linux-ia32/package.json +++ b/npm/@esbuild/linux-ia32/package.json @@ -1,6 +1,6 @@ { "name": "@esbuild/linux-ia32", - "version": "0.25.11", + "version": "0.25.12", "description": "The Linux 32-bit binary for esbuild, a JavaScript bundler.", "repository": { "type": "git", diff --git a/npm/@esbuild/linux-loong64/package.json b/npm/@esbuild/linux-loong64/package.json index ef7b2d3323c..28052fb2b42 100644 --- a/npm/@esbuild/linux-loong64/package.json +++ b/npm/@esbuild/linux-loong64/package.json @@ -1,6 +1,6 @@ { "name": "@esbuild/linux-loong64", - "version": "0.25.11", + "version": "0.25.12", "description": "The Linux LoongArch 64-bit binary for esbuild, a JavaScript bundler.", "repository": { "type": "git", diff --git a/npm/@esbuild/linux-mips64el/package.json b/npm/@esbuild/linux-mips64el/package.json index d838bdbc310..549062dab29 100644 --- a/npm/@esbuild/linux-mips64el/package.json +++ b/npm/@esbuild/linux-mips64el/package.json @@ -1,6 +1,6 @@ { "name": "@esbuild/linux-mips64el", - "version": "0.25.11", + "version": "0.25.12", "description": "The Linux MIPS 64-bit Little Endian binary for esbuild, a JavaScript bundler.", "repository": { "type": "git", diff --git a/npm/@esbuild/linux-ppc64/package.json b/npm/@esbuild/linux-ppc64/package.json index be56713f1cc..02ce51d0847 100644 --- a/npm/@esbuild/linux-ppc64/package.json +++ b/npm/@esbuild/linux-ppc64/package.json @@ -1,6 +1,6 @@ { "name": "@esbuild/linux-ppc64", - "version": "0.25.11", + "version": "0.25.12", "description": "The Linux PowerPC 64-bit Little Endian binary for esbuild, a JavaScript bundler.", "repository": { "type": "git", diff --git a/npm/@esbuild/linux-riscv64/package.json b/npm/@esbuild/linux-riscv64/package.json index 65992d85bf3..7a3233dfa3d 100644 --- a/npm/@esbuild/linux-riscv64/package.json +++ b/npm/@esbuild/linux-riscv64/package.json @@ -1,6 +1,6 @@ { "name": "@esbuild/linux-riscv64", - "version": "0.25.11", + "version": "0.25.12", "description": "The Linux RISC-V 64-bit binary for esbuild, a JavaScript bundler.", "repository": { "type": "git", diff --git a/npm/@esbuild/linux-s390x/package.json b/npm/@esbuild/linux-s390x/package.json index a302df4473c..e5888714be4 100644 --- a/npm/@esbuild/linux-s390x/package.json +++ b/npm/@esbuild/linux-s390x/package.json @@ -1,6 +1,6 @@ { "name": "@esbuild/linux-s390x", - "version": "0.25.11", + "version": "0.25.12", "description": "The Linux IBM Z 64-bit Big Endian binary for esbuild, a JavaScript bundler.", "repository": { "type": "git", diff --git a/npm/@esbuild/linux-x64/package.json b/npm/@esbuild/linux-x64/package.json index 1a62796f4f0..cf36fa75dac 100644 --- a/npm/@esbuild/linux-x64/package.json +++ b/npm/@esbuild/linux-x64/package.json @@ -1,6 +1,6 @@ { "name": "@esbuild/linux-x64", - "version": "0.25.11", + "version": "0.25.12", "description": "The Linux 64-bit binary for esbuild, a JavaScript bundler.", "repository": { "type": "git", diff --git a/npm/@esbuild/netbsd-arm64/package.json b/npm/@esbuild/netbsd-arm64/package.json index 1a1f77c6f89..fabbb682807 100644 --- a/npm/@esbuild/netbsd-arm64/package.json +++ b/npm/@esbuild/netbsd-arm64/package.json @@ -1,6 +1,6 @@ { "name": "@esbuild/netbsd-arm64", - "version": "0.25.11", + "version": "0.25.12", "description": "The NetBSD ARM 64-bit binary for esbuild, a JavaScript bundler.", "repository": { "type": "git", diff --git a/npm/@esbuild/netbsd-x64/package.json b/npm/@esbuild/netbsd-x64/package.json index 77ac6717fec..4ec88cb0908 100644 --- a/npm/@esbuild/netbsd-x64/package.json +++ b/npm/@esbuild/netbsd-x64/package.json @@ -1,6 +1,6 @@ { "name": "@esbuild/netbsd-x64", - "version": "0.25.11", + "version": "0.25.12", "description": "The NetBSD AMD64 binary for esbuild, a JavaScript bundler.", "repository": { "type": "git", diff --git a/npm/@esbuild/openbsd-arm64/package.json b/npm/@esbuild/openbsd-arm64/package.json index 23bc7f3dff3..6c08869313b 100644 --- a/npm/@esbuild/openbsd-arm64/package.json +++ b/npm/@esbuild/openbsd-arm64/package.json @@ -1,6 +1,6 @@ { "name": "@esbuild/openbsd-arm64", - "version": "0.25.11", + "version": "0.25.12", "description": "The OpenBSD ARM 64-bit binary for esbuild, a JavaScript bundler.", "repository": { "type": "git", diff --git a/npm/@esbuild/openbsd-x64/package.json b/npm/@esbuild/openbsd-x64/package.json index d782cf5af3d..4c972954306 100644 --- a/npm/@esbuild/openbsd-x64/package.json +++ b/npm/@esbuild/openbsd-x64/package.json @@ -1,6 +1,6 @@ { "name": "@esbuild/openbsd-x64", - "version": "0.25.11", + "version": "0.25.12", "description": "The OpenBSD 64-bit binary for esbuild, a JavaScript bundler.", "repository": { "type": "git", diff --git a/npm/@esbuild/openharmony-arm64/package.json b/npm/@esbuild/openharmony-arm64/package.json index 638a8f0156c..17641119d75 100644 --- a/npm/@esbuild/openharmony-arm64/package.json +++ b/npm/@esbuild/openharmony-arm64/package.json @@ -1,6 +1,6 @@ { "name": "@esbuild/openharmony-arm64", - "version": "0.25.11", + "version": "0.25.12", "description": "A WebAssembly shim for esbuild on OpenHarmony ARM64.", "repository": { "type": "git", diff --git a/npm/@esbuild/sunos-x64/package.json b/npm/@esbuild/sunos-x64/package.json index aed5f70f25e..fe68f511901 100644 --- a/npm/@esbuild/sunos-x64/package.json +++ b/npm/@esbuild/sunos-x64/package.json @@ -1,6 +1,6 @@ { "name": "@esbuild/sunos-x64", - "version": "0.25.11", + "version": "0.25.12", "description": "The illumos 64-bit binary for esbuild, a JavaScript bundler.", "repository": { "type": "git", diff --git a/npm/@esbuild/wasi-preview1/package.json b/npm/@esbuild/wasi-preview1/package.json index 91fdd9e1a5a..427b0921b30 100644 --- a/npm/@esbuild/wasi-preview1/package.json +++ b/npm/@esbuild/wasi-preview1/package.json @@ -1,6 +1,6 @@ { "name": "@esbuild/wasi-preview1", - "version": "0.25.11", + "version": "0.25.12", "description": "The WASI (WebAssembly System Interface) preview 1 binary for esbuild, a JavaScript bundler.", "repository": { "type": "git", diff --git a/npm/@esbuild/win32-arm64/package.json b/npm/@esbuild/win32-arm64/package.json index 1872f6a728f..8727de75b7b 100644 --- a/npm/@esbuild/win32-arm64/package.json +++ b/npm/@esbuild/win32-arm64/package.json @@ -1,6 +1,6 @@ { "name": "@esbuild/win32-arm64", - "version": "0.25.11", + "version": "0.25.12", "description": "The Windows ARM 64-bit binary for esbuild, a JavaScript bundler.", "repository": { "type": "git", diff --git a/npm/@esbuild/win32-ia32/package.json b/npm/@esbuild/win32-ia32/package.json index 104e264fab4..8d5e3b94936 100644 --- a/npm/@esbuild/win32-ia32/package.json +++ b/npm/@esbuild/win32-ia32/package.json @@ -1,6 +1,6 @@ { "name": "@esbuild/win32-ia32", - "version": "0.25.11", + "version": "0.25.12", "description": "The Windows 32-bit binary for esbuild, a JavaScript bundler.", "repository": { "type": "git", diff --git a/npm/@esbuild/win32-x64/package.json b/npm/@esbuild/win32-x64/package.json index 65b161e4da6..5b60c1df6bf 100644 --- a/npm/@esbuild/win32-x64/package.json +++ b/npm/@esbuild/win32-x64/package.json @@ -1,6 +1,6 @@ { "name": "@esbuild/win32-x64", - "version": "0.25.11", + "version": "0.25.12", "description": "The Windows 64-bit binary for esbuild, a JavaScript bundler.", "repository": { "type": "git", diff --git a/npm/esbuild-wasm/package.json b/npm/esbuild-wasm/package.json index ff7eb3e3434..346eebe470f 100644 --- a/npm/esbuild-wasm/package.json +++ b/npm/esbuild-wasm/package.json @@ -1,6 +1,6 @@ { "name": "esbuild-wasm", - "version": "0.25.11", + "version": "0.25.12", "description": "The cross-platform WebAssembly binary for esbuild, a JavaScript bundler.", "repository": { "type": "git", diff --git a/npm/esbuild/package.json b/npm/esbuild/package.json index db3a4d50ef2..afe58fd6612 100644 --- a/npm/esbuild/package.json +++ b/npm/esbuild/package.json @@ -1,6 +1,6 @@ { "name": "esbuild", - "version": "0.25.11", + "version": "0.25.12", "description": "An extremely fast JavaScript and CSS bundler and minifier.", "repository": { "type": "git", @@ -18,32 +18,32 @@ "esbuild": "bin/esbuild" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.11", - "@esbuild/android-arm": "0.25.11", - "@esbuild/android-arm64": "0.25.11", - "@esbuild/android-x64": "0.25.11", - "@esbuild/darwin-arm64": "0.25.11", - "@esbuild/darwin-x64": "0.25.11", - "@esbuild/freebsd-arm64": "0.25.11", - "@esbuild/freebsd-x64": "0.25.11", - "@esbuild/linux-arm": "0.25.11", - "@esbuild/linux-arm64": "0.25.11", - "@esbuild/linux-ia32": "0.25.11", - "@esbuild/linux-loong64": "0.25.11", - "@esbuild/linux-mips64el": "0.25.11", - "@esbuild/linux-ppc64": "0.25.11", - "@esbuild/linux-riscv64": "0.25.11", - "@esbuild/linux-s390x": "0.25.11", - "@esbuild/linux-x64": "0.25.11", - "@esbuild/netbsd-arm64": "0.25.11", - "@esbuild/netbsd-x64": "0.25.11", - "@esbuild/openbsd-arm64": "0.25.11", - "@esbuild/openbsd-x64": "0.25.11", - "@esbuild/openharmony-arm64": "0.25.11", - "@esbuild/sunos-x64": "0.25.11", - "@esbuild/win32-arm64": "0.25.11", - "@esbuild/win32-ia32": "0.25.11", - "@esbuild/win32-x64": "0.25.11" + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" }, "license": "MIT" } diff --git a/version.txt b/version.txt index 94f3628e82e..a5c3b469ad1 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -0.25.11 +0.25.12