Fix escaping of non-BMP characters in property names (#977)
Property names in object literals do not have to be quoted if the property is a valid JavaScript identifier. This is defined as starting with a character in the ID_Start Unicode category and ending with zero or more characters in the ID_Continue Unicode category. However, esbuild had a bug where non-BMP characters (i.e. characters encoded using two UTF-16 code units instead of one) were always checked against ID_Continue instead of ID_Start because they included a code unit that wasn't at the start. This could result in invalid JavaScript being generated when using --charset=utf8 because ID_Continue is a superset of ID_Start and contains some characters that are not valid at the start of an identifier. This bug has been fixed.
Be maximally liberal in the interpretation of the browser field (#740)
The browser field in package.json is an informal convention followed by browser-specific bundlers that allows package authors to substitute certain node-specific import paths with alternative browser-specific import paths. It doesn't have a rigorous specification and the canonical description of the feature doesn't include any tests. As a result, each bundler implements this feature differently. I have tried to create a survey of how different bundlers interpret the browser field and the results are very inconsistent.
This release attempts to change esbuild to support the union of the behavior of all other bundlers. That way if people have the browser field working with some other bundler and they switch to esbuild, the browser field shouldn't ever suddenly stop working. This seemed like the most principled approach to take in this situation.
The drawback of this approach is that it means the browser field may start working when switching to esbuild when it was previously not working. This could cause bugs, but I consider this to be a problem with the package (i.e. not using a more well-supported form of the browser field), not a problem with esbuild itself.
v0.11.8
Fix hash calculation for code splitting and dynamic imports (#1076)
The hash included in the file name of each output file is intended to change if and only if anything relevant to the content of that output file changes. It includes:
The contents of the file with the paths of other output files omitted
The output path of the file the final hash omitted
Some information about the input files involved in that output file
The contents of the associated source map, if there is one
All of the information above for all transitive dependencies found by following import statements
However, this didn't include dynamic import() expressions due to an oversight. With this release, dynamic import() expressions are now also counted as transitive dependencies. This fixes an issue where the content of an output file could change without its hash also changing. As a side effect of this change, dynamic imports inside output files of other output files are now listed in the metadata file if the metafile setting is enabled.
Refactor the internal module graph representation
This release changes a large amount of code relating to esbuild's internal module graph. The changes are mostly organizational and help consolidate most of the logic around maintaining various module graph invariants into a separate file where it's easier to audit. The Go language doesn't have great abstraction capabilities (e.g. no zero-cost iterators) so the enforcement of this new abstraction is unfortunately done by convention instead of by the compiler, and there is currently still some code that bypasses the abstraction. But it's better than it was before.
Another relevant change was moving a number of special cases that happened during the tree shaking traversal into the graph itself instead. Previously there were quite a few implicit dependency rules that were checked in specific places, which was hard to follow. Encoding these special case constraints into the graph itself makes the problem easier to reason about and should hopefully make the code more regular and robust.
Finally, this set of changes brings back full support for the sideEffects annotation in package.json. It was previously disabled when code splitting was active as a temporary measure due to the discovery of some bugs in that scenario. But I believe these bugs have been resolved now that tree shaking and code splitting are done in separate passes (see the previous release for more information).
v0.11.7
Fix incorrect chunk reference with code splitting, css, and dynamic imports (#1125)
This release fixes a bug where when you use code splitting, CSS imports in JS, and dynamic imports all combined, the dynamic import incorrectly references the sibling CSS chunk for the dynamic import instead of the primary JS chunk. In this scenario the entry point file corresponds to two different output chunks (one for CSS and one for JS) and the wrong chunk was being picked. This bug has been fixed.
Split apart tree shaking and code splitting (#1123)
The original code splitting algorithm allowed for files to be split apart and for different parts of the same file to end up in different chunks based on which entry points needed which parts. This was done at the same time as tree shaking by essentially performing tree shaking multiple times, once per entry point, and tracking which entry points each file part is live in. Each file part that is live in at least one entry point was then assigned to a code splitting chunk with all of the other code that is live in the same set of entry points. This ensures that entry points only import code that they will use (i.e. no code will be downloaded by an entry point that is guaranteed to not be used).
This file-splitting feature has been removed because it doesn't work well with the recently-added top-level await JavaScript syntax, which has complex evaluation order rules that operate at file boundaries. File parts now have a single boolean flag for whether they are live or not instead of a set of flags that track which entry points that part is reachable from (reachability is still tracked at the file level).
However, this change appears to have introduced some subtly incorrect behavior with code splitting because there is now an implicit dependency in the import graph between adjacent parts within the same file even if the two parts are unrelated and don't reference each other. This is due to the fact each entry point that references one part pulls in the file (but not the whole file, only the parts that are live in at least one entry point). So liveness must be fully computed first before code splitting is computed.
This release splits apart tree shaking and code splitting into two separate passes, which fixes certain cases where two generated code splitting chunks ended up each importing symbols from the other and causing a cycle. There should hopefully no longer be cycles in generated code splitting chunks.
Make this work in static class fields in TypeScript files
Fix escaping of non-BMP characters in property names (#977)
Property names in object literals do not have to be quoted if the property is a valid JavaScript identifier. This is defined as starting with a character in the ID_Start Unicode category and ending with zero or more characters in the ID_Continue Unicode category. However, esbuild had a bug where non-BMP characters (i.e. characters encoded using two UTF-16 code units instead of one) were always checked against ID_Continue instead of ID_Start because they included a code unit that wasn't at the start. This could result in invalid JavaScript being generated when using --charset=utf8 because ID_Continue is a superset of ID_Start and contains some characters that are not valid at the start of an identifier. This bug has been fixed.
Be maximally liberal in the interpretation of the browser field (#740)
The browser field in package.json is an informal convention followed by browser-specific bundlers that allows package authors to substitute certain node-specific import paths with alternative browser-specific import paths. It doesn't have a rigorous specification and the canonical description of the feature doesn't include any tests. As a result, each bundler implements this feature differently. I have tried to create a survey of how different bundlers interpret the browser field and the results are very inconsistent.
This release attempts to change esbuild to support the union of the behavior of all other bundlers. That way if people have the browser field working with some other bundler and they switch to esbuild, the browser field shouldn't ever suddenly stop working. This seemed like the most principled approach to take in this situation.
The drawback of this approach is that it means the browser field may start working when switching to esbuild when it was previously not working. This could cause bugs, but I consider this to be a problem with the package (i.e. not using a more well-supported form of the browser field), not a problem with esbuild itself.
0.11.8
Fix hash calculation for code splitting and dynamic imports (#1076)
The hash included in the file name of each output file is intended to change if and only if anything relevant to the content of that output file changes. It includes:
The contents of the file with the paths of other output files omitted
The output path of the file the final hash omitted
Some information about the input files involved in that output file
The contents of the associated source map, if there is one
All of the information above for all transitive dependencies found by following import statements
However, this didn't include dynamic import() expressions due to an oversight. With this release, dynamic import() expressions are now also counted as transitive dependencies. This fixes an issue where the content of an output file could change without its hash also changing. As a side effect of this change, dynamic imports inside output files of other output files are now listed in the metadata file if the metafile setting is enabled.
Refactor the internal module graph representation
This release changes a large amount of code relating to esbuild's internal module graph. The changes are mostly organizational and help consolidate most of the logic around maintaining various module graph invariants into a separate file where it's easier to audit. The Go language doesn't have great abstraction capabilities (e.g. no zero-cost iterators) so the enforcement of this new abstraction is unfortunately done by convention instead of by the compiler, and there is currently still some code that bypasses the abstraction. But it's better than it was before.
Another relevant change was moving a number of special cases that happened during the tree shaking traversal into the graph itself instead. Previously there were quite a few implicit dependency rules that were checked in specific places, which was hard to follow. Encoding these special case constraints into the graph itself makes the problem easier to reason about and should hopefully make the code more regular and robust.
Finally, this set of changes brings back full support for the sideEffects annotation in package.json. It was previously disabled when code splitting was active as a temporary measure due to the discovery of some bugs in that scenario. But I believe these bugs have been resolved now that tree shaking and code splitting are done in separate passes (see the previous release for more information).
0.11.7
Fix incorrect chunk reference with code splitting, css, and dynamic imports (#1125)
This release fixes a bug where when you use code splitting, CSS imports in JS, and dynamic imports all combined, the dynamic import incorrectly references the sibling CSS chunk for the dynamic import instead of the primary JS chunk. In this scenario the entry point file corresponds to two different output chunks (one for CSS and one for JS) and the wrong chunk was being picked. This bug has been fixed.
Split apart tree shaking and code splitting (#1123)
The original code splitting algorithm allowed for files to be split apart and for different parts of the same file to end up in different chunks based on which entry points needed which parts. This was done at the same time as tree shaking by essentially performing tree shaking multiple times, once per entry point, and tracking which entry points each file part is live in. Each file part that is live in at least one entry point was then assigned to a code splitting chunk with all of the other code that is live in the same set of entry points. This ensures that entry points only import code that they will use (i.e. no code will be downloaded by an entry point that is guaranteed to not be used).
This file-splitting feature has been removed because it doesn't work well with the recently-added top-level await JavaScript syntax, which has complex evaluation order rules that operate at file boundaries. File parts now have a single boolean flag for whether they are live or not instead of a set of flags that track which entry points that part is reachable from (reachability is still tracked at the file level).
However, this change appears to have introduced some subtly incorrect behavior with code splitting because there is now an implicit dependency in the import graph between adjacent parts within the same file even if the two parts are unrelated and don't reference each other. This is due to the fact each entry point that references one part pulls in the file (but not the whole file, only the parts that are live in at least one entry point). So liveness must be fully computed first before code splitting is computed.
Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.
Dependabot will merge this PR once CI passes on it, as requested by @alexlafroscia.
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Bumps esbuild from 0.8.9 to 0.11.9.
Release notes
Sourced from esbuild's releases.
... (truncated)
Changelog
Sourced from esbuild's changelog.
... (truncated)
Commits
d616dac
publish 0.11.9 to npma198304
Be maximally liberal in the interpretation of thebrowser
field (#1140)eac9513
fix non-bmp characters in identifier validation (#1139)093b23a
fix go lints94eee0c
publish 0.11.8 to npm0512729
use symbol generation helper in another place3d04212
add "bench-readmin-esbuild" to prepublishb35a7a8
release notes for refactor0ccf2ee
remove another case of manual bookkeepinga121af2
remove unnecessary invariant codeDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting
@dependabot rebase
.Dependabot will merge this PR once CI passes on it, as requested by @alexlafroscia.
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)