-
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 insidefor
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 toreturn;
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 asreturn await undefined;
which schedules a task in the event loop and runs code in a different order than justreturn;
, which doesn't hide an implicitawait
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 functiona.b
witha
as the value forthis
but the second calls the functiona.b
with the default value forthis
(the global object in non-strict mode orundefined
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 orundefined
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`)
-