release notes
An extremely fast bundler for the web
release notes
Published 5/25/2021
PatchSafe upgraderelease notes
Published 5/25/2021
PatchSafe upgradeFix various code generation and minification issues (#1305)
This release fixes the following issues, which were all identified by running esbuild against the latest UglifyJS test suite:
The in operator is now surrounded parentheses inside arrow function expression bodies inside for loop initializers:
// Original code
for ((x => y in z); 0; ) ;
// Old output
for ((x) => y in z; 0; ) ;
// New output
for ((x) => (y in z); 0; ) ;
Without this, the in operator would cause the for loop to be considered a for-in loop instead.
The statement return undefined; is no longer minified to return; inside async generator functions:
// Original code
return undefined;
// Old output
return;
// New output
return void 0;
Using return undefined; inside an async generator function has the same effect as return await undefined; which schedules a task in the event loop and runs code in a different order than just return;, which doesn't hide an implicit await expression.
Property access expressions are no longer inlined in template tag position:
// Original code
(null, a.b)``, (null, a[b])``;
// Old output
a.b``, a[b]``;
// New output
(0, a.b)``, (0, a[b])``;
The expression a.b`c` is different than the expression (0, a.b)`c`. The first calls the function a.b with a as the value for this but the second calls the function a.b with the default value for this (the global object in non-strict mode or undefined in strict mode).
Verbatim __proto__ properties inside object spread are no longer inlined when minifying:
// Original code
x = { ...{ __proto__: { y: true } } }.y;
// Old output
x = { __proto__: { y: !0 } }.y;
// New output
x = { ...{ __proto__: { y: !0 } } }.y;
A verbatim (i.e. non-computed non-method) property called __proto__ inside an object literal actually sets the prototype of the surrounding object literal. It does not add an "own property" called __proto__ to that object literal, so inlining it into the parent object literal would be incorrect. The presence of a __proto__ property now stops esbuild from applying the object spread inlining optimization when minifying.
The value of this has now been fixed for lowered private class members that are used as template tags:
// Original code
x = (new (class {
a = this.#c``;
b = 1;
#c() { return this }
})).a.b;
// Old output
var _c, c_fn, _a;
x = new (_a = class {
constructor() {
__privateAdd(this, _c);
__publicField(this, "a", __privateMethod(this, _c, c_fn)``);
__publicField(this, "b", 1);
}
}, _c = new WeakSet(), c_fn = function() {
return this;
}, _a)().a.b;
// New output
var _c, c_fn, _a;
x = new (_a = class {
constructor() {
__privateAdd(this, _c);
__publicField(this, "a", __privateMethod(this, _c, c_fn).bind(this)``);
__publicField(this, "b", 1);
}
}, _c = new WeakSet(), c_fn = function() {
return this;
}, _a)().a.b;
The value of this here should be an instance of the class because the template tag is a property access expression. However, it was previously the default value (the global object in non-strict mode or undefined in strict mode) instead due to the private member transformation, which is incorrect.
Invalid escape sequences are now allowed in tagged template literals
This implements the template literal revision feature: https://github.com/tc39/proposal-template-literal-revision. It allows you to process tagged template literals using custom semantics that don't follow JavaScript escape sequence rules without causing a syntax error:
console.log((x => x.raw)`invalid \unicode escape sequence`)
Fix various code generation and minification issues (#1305)
This release fixes the following issues, which were all identified by running esbuild against the latest UglifyJS test suite:
The in operator is now surrounded parentheses inside arrow function expression bodies inside for loop initializers:
// Original code
for ((x => y in z); 0; ) ;
// Old output
for ((x) => y in z; 0; ) ;
// New output
for ((x) => (y in z); 0; ) ;
Without this, the in operator would cause the for loop to be considered a for-in loop instead.
The statement return undefined; is no longer minified to return; inside async generator functions:
// Original code
return undefined;
// Old output
return;
// New output
return void 0;
Using return undefined; inside an async generator function has the same effect as return await undefined; which schedules a task in the event loop and runs code in a different order than just return;, which doesn't hide an implicit await expression.
Property access expressions are no longer inlined in template tag position:
// Original code
(null, a.b)``, (null, a[b])``;
// Old output
a.b``, a[b]``;
// New output
(0, a.b)``, (0, a[b])``;
The expression a.b`c` is different than the expression (0, a.b)`c`. The first calls the function a.b with a as the value for this but the second calls the function a.b with the default value for this (the global object in non-strict mode or undefined in strict mode).
Verbatim __proto__ properties inside object spread are no longer inlined when minifying:
// Original code
x = { ...{ __proto__: { y: true } } }.y;
// Old output
x = { __proto__: { y: !0 } }.y;
// New output
x = { ...{ __proto__: { y: !0 } } }.y;
A verbatim (i.e. non-computed non-method) property called __proto__ inside an object literal actually sets the prototype of the surrounding object literal. It does not add an "own property" called __proto__ to that object literal, so inlining it into the parent object literal would be incorrect. The presence of a __proto__ property now stops esbuild from applying the object spread inlining optimization when minifying.
The value of this has now been fixed for lowered private class members that are used as template tags:
// Original code
x = (new (class {
a = this.#c``;
b = 1;
#c() { return this }
})).a.b;
// Old output
var _c, c_fn, _a;
x = new (_a = class {
constructor() {
__privateAdd(this, _c);
__publicField(this, "a", __privateMethod(this, _c, c_fn)``);
__publicField(this, "b", 1);
}
}, _c = new WeakSet(), c_fn = function() {
return this;
}, _a)().a.b;
// New output
var _c, c_fn, _a;
x = new (_a = class {
constructor() {
__privateAdd(this, _c);
__publicField(this, "a", __privateMethod(this, _c, c_fn).bind(this)``);
__publicField(this, "b", 1);
}
}, _c = new WeakSet(), c_fn = function() {
return this;
}, _a)().a.b;
The value of this here should be an instance of the class because the template tag is a property access expression. However, it was previously the default value (the global object in non-strict mode or undefined in strict mode) instead due to the private member transformation, which is incorrect.
Invalid escape sequences are now allowed in tagged template literals
This implements the template literal revision feature: https://github.com/tc39/proposal-template-literal-revision. It allows you to process tagged template literals using custom semantics that don't follow JavaScript escape sequence rules without causing a syntax error:
console.log((x => x.raw)`invalid \unicode escape sequence`)