Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(bundler): implement enum inlining / more constant folding #12144

Draft
wants to merge 14 commits into
base: main
Choose a base branch
from

Conversation

paperdave
Copy link
Collaborator

@paperdave paperdave commented Jun 25, 2024

Fixes #11764
Fixes #2945
Fixes #2889

Draft TODO:

  • e_inlined_enum
  • inline enum as well as in simplify functions
  • Enum use-before-define behavior
  • Implement required changes in TS namespaces
  • Fix sibling namespace scopes
  • Cross-file enums while bundling
  • Tests
  • Note: late-stage numeric folding (js printer) is not implemented, and will not be for now

Initially was a PR to fix an enum bug, but it turned out the bug was due to a lack of a feature: enum inlining. So I decided to do it, since it was a feature I personally have a big use for (For example, the bun.report project has a regex hack workaround to force enum inlining, because the codegen otherwise is an abomination)

Simple Sample

enum A {
  Hello = 1,
  World,
}

console.log(A.Hello);
console.log(A.World);
console.log(A.Hello + A.World);

After:

// index.ts
console.log(1 /* Hello */);
console.log(2 /* World */);
console.log(3);

Before:

// index.ts
var A;
(function(A2) {
  A2[A2["Hello"] = 1] = "Hello";
  A2[A2["World"] = 2] = "World";
})(A || (A = {}));
console.log(A.Hello);
console.log(A.World);
console.log(A.Hello + A.World);

If you reference the enum directly, you can get the two-way map. This even works with const enum, as it is TSC's job to prohibit such usage.

enum A {
  Hello = 1,
  World,
}

console.log(A);

The codegen of these enums have been improved. Projects with heavy enum usage should see smaller bundle sizes. Now:

var A;
((A2) => {
  A2[A2.Hello = 1] = "Hello";
  A2[A2.World = 2] = "World";
})(A ||= {});

Before:

// index.ts
var A;
(function(A2) {
  A2[A2["Hello"] = 1] = "Hello";
  A2[A2["World"] = 2] = "World";
})(A || (A = {}));
console.log(A);

It would be interesting as a future project to see if the size of these enums could be shrunk further, but esbuild doesn't do that, and I think personally it's fine to leave enum in the dust as const enum and inlining all values becomes the new norm.

Copy link
Contributor

github-actions bot commented Jun 25, 2024

@paperdave, your commit has failing tests :(

💪 15 failing tests Darwin AARCH64

  • test/bundler/bundler_edgecase.test.ts 1 failing
  • test/bundler/bundler_minify.test.ts 2 failing
  • test/bundler/bundler_npm.test.ts 1 failing
  • test/bundler/esbuild/dce.test.ts 1 failing
  • test/bundler/esbuild/default.test.ts 3 failing
  • test/bundler/esbuild/extra.test.ts 1 failing
  • test/bundler/esbuild/importstar_ts.test.ts 4 failing
  • test/bundler/esbuild/importstar.test.ts 9 failing
  • test/cli/run/transpiler-cache.test.ts 4 failing
  • test/integration/next-pages/test/next-build.test.ts 1 failing
  • test/js/bun/jsc/bun-jsc.test.ts 1 failing
  • test/js/third_party/msw.test.ts 1 failing
  • test/js/web/fetch/blob-cow.test.ts 1 failing
  • test/transpiler/transpiler-stack-overflow.test.ts 1 failing
  • test/transpiler/transpiler.test.js 9 failing

💻 15 failing tests Darwin x64 baseline

  • test/bundler/bundler_edgecase.test.ts 1 failing
  • test/bundler/bundler_minify.test.ts 2 failing
  • test/bundler/bundler_npm.test.ts 1 failing
  • test/bundler/esbuild/dce.test.ts 1 failing
  • test/bundler/esbuild/default.test.ts 3 failing
  • test/bundler/esbuild/extra.test.ts 1 failing
  • test/bundler/esbuild/importstar_ts.test.ts 4 failing
  • test/bundler/esbuild/importstar.test.ts 9 failing
  • test/cli/run/transpiler-cache.test.ts 4 failing
  • test/integration/next-pages/test/next-build.test.ts 1 failing
  • test/js/bun/jsc/bun-jsc.test.ts 1 failing
  • test/js/third_party/msw.test.ts 1 failing
  • test/js/web/fetch/blob-cow.test.ts 1 failing
  • test/transpiler/transpiler-stack-overflow.test.ts 1 failing
  • test/transpiler/transpiler.test.js 9 failing

💻 15 failing tests Darwin x64

  • test/bundler/bundler_edgecase.test.ts 1 failing
  • test/bundler/bundler_minify.test.ts 2 failing
  • test/bundler/bundler_npm.test.ts 1 failing
  • test/bundler/esbuild/dce.test.ts 1 failing
  • test/bundler/esbuild/default.test.ts 3 failing
  • test/bundler/esbuild/extra.test.ts 1 failing
  • test/bundler/esbuild/importstar_ts.test.ts 4 failing
  • test/bundler/esbuild/importstar.test.ts 9 failing
  • test/cli/run/transpiler-cache.test.ts 4 failing
  • test/integration/next-pages/test/next-build.test.ts 1 failing
  • test/js/bun/jsc/bun-jsc.test.ts 1 failing
  • test/js/third_party/msw.test.ts 1 failing
  • test/js/web/fetch/blob-cow.test.ts 1 failing
  • test/transpiler/transpiler-stack-overflow.test.ts 1 failing
  • test/transpiler/transpiler.test.js 9 failing

🐧💪 15 failing tests Linux AARCH64

  • test/bundler/bundler_edgecase.test.ts 1 failing
  • test/bundler/bundler_minify.test.ts 2 failing
  • test/bundler/bundler_npm.test.ts 1 failing
  • test/bundler/esbuild/dce.test.ts 1 failing
  • test/bundler/esbuild/default.test.ts 3 failing
  • test/bundler/esbuild/extra.test.ts 1 failing
  • test/bundler/esbuild/importstar_ts.test.ts 4 failing
  • test/bundler/esbuild/importstar.test.ts 9 failing
  • test/cli/run/transpiler-cache.test.ts 4 failing
  • test/integration/next-pages/test/next-build.test.ts 1 failing
  • test/js/bun/jsc/bun-jsc.test.ts 1 failing
  • test/js/third_party/msw.test.ts 1 failing
  • test/js/web/fetch/blob-cow.test.ts 1 failing
  • test/transpiler/transpiler-stack-overflow.test.ts SIGKILL
  • test/transpiler/transpiler.test.js 9 failing

🐧🖥 16 failing tests Linux x64 baseline

  • test/bundler/bundler_edgecase.test.ts 1 failing
  • test/bundler/bundler_minify.test.ts 2 failing
  • test/bundler/bundler_npm.test.ts 1 failing
  • test/bundler/esbuild/dce.test.ts 1 failing
  • test/bundler/esbuild/default.test.ts 3 failing
  • test/bundler/esbuild/extra.test.ts 1 failing
  • test/bundler/esbuild/importstar_ts.test.ts 4 failing
  • test/bundler/esbuild/importstar.test.ts 9 failing
  • test/cli/run/transpiler-cache.test.ts 4 failing
  • test/integration/next-pages/test/next-build.test.ts 1 failing
  • test/js/bun/dns/resolve-dns.test.ts 1 failing
  • test/js/bun/jsc/bun-jsc.test.ts 1 failing
  • test/js/third_party/msw.test.ts 1 failing
  • test/js/web/fetch/blob-cow.test.ts 1 failing
  • test/transpiler/transpiler-stack-overflow.test.ts SIGKILL
  • test/transpiler/transpiler.test.js 9 failing

🐧🖥 15 failing tests Linux x64

  • test/bundler/bundler_edgecase.test.ts 1 failing
  • test/bundler/bundler_minify.test.ts 2 failing
  • test/bundler/bundler_npm.test.ts 1 failing
  • test/bundler/esbuild/dce.test.ts 1 failing
  • test/bundler/esbuild/default.test.ts 3 failing
  • test/bundler/esbuild/extra.test.ts 1 failing
  • test/bundler/esbuild/importstar_ts.test.ts 4 failing
  • test/bundler/esbuild/importstar.test.ts 9 failing
  • test/cli/run/transpiler-cache.test.ts 4 failing
  • test/integration/next-pages/test/next-build.test.ts 1 failing
  • test/js/bun/jsc/bun-jsc.test.ts 1 failing
  • test/js/third_party/msw.test.ts 1 failing
  • test/js/web/fetch/blob-cow.test.ts 1 failing
  • test/transpiler/transpiler-stack-overflow.test.ts SIGKILL
  • test/transpiler/transpiler.test.js 9 failing

🪟💻 22 failing tests Windows x64 baseline

  • test/bundler/bundler_edgecase.test.ts 1 failing
  • test/bundler/bundler_minify.test.ts 2 failing
  • test/bundler/esbuild/dce.test.ts 1 failing
  • test/bundler/esbuild/default.test.ts 3 failing
  • test/bundler/esbuild/extra.test.ts 1 failing
  • test/bundler/esbuild/importstar_ts.test.ts 4 failing
  • test/bundler/esbuild/importstar.test.ts 9 failing
  • test/cli/install/registry/bun-install-registry.test.ts 1 failing
  • test/cli/install/registry/bun-install-windowsshim.test.ts code 1
  • test/cli/run/run-unicode.test.ts 1 failing
  • test/cli/run/transpiler-cache.test.ts 4 failing
  • test/integration/next-pages/test/next-build.test.ts 1 failing
  • test/js/bun/jsc/bun-jsc.test.ts 1 failing
  • test/js/node/child_process/child_process.test.ts 1 failing
  • test/js/third_party/grpc-js/test-channel-credentials.test.ts STATUS_SEVERITY_ERROR
  • test/js/third_party/grpc-js/test-client.test.ts STATUS_SEVERITY_ERROR
  • test/js/third_party/grpc-js/test-idle-timer.test.ts STATUS_SEVERITY_ERROR
  • test/js/third_party/grpc-js/test-retry.test.ts STATUS_SEVERITY_ERROR
  • test/js/third_party/msw.test.ts 1 failing
  • test/js/web/fetch/blob-cow.test.ts 1 failing
  • test/transpiler/transpiler-stack-overflow.test.ts 1 failing
  • test/transpiler/transpiler.test.js 9 failing

🪟💻 22 failing tests Windows x64

  • test/bundler/bundler_edgecase.test.ts 1 failing
  • test/bundler/bundler_minify.test.ts 2 failing
  • test/bundler/esbuild/dce.test.ts 1 failing
  • test/bundler/esbuild/default.test.ts 3 failing
  • test/bundler/esbuild/extra.test.ts 1 failing
  • test/bundler/esbuild/importstar_ts.test.ts 4 failing
  • test/bundler/esbuild/importstar.test.ts 9 failing
  • test/cli/install/registry/bun-install-registry.test.ts 2 failing
  • test/cli/install/registry/bun-install-windowsshim.test.ts code 1
  • test/cli/run/run-unicode.test.ts 1 failing
  • test/cli/run/transpiler-cache.test.ts 4 failing
  • test/integration/next-pages/test/next-build.test.ts 1 failing
  • test/js/bun/jsc/bun-jsc.test.ts 1 failing
  • test/js/node/child_process/child_process.test.ts 1 failing
  • test/js/third_party/grpc-js/test-channel-credentials.test.ts STATUS_SEVERITY_ERROR
  • test/js/third_party/grpc-js/test-client.test.ts STATUS_SEVERITY_ERROR
  • test/js/third_party/grpc-js/test-idle-timer.test.ts STATUS_SEVERITY_ERROR
  • test/js/third_party/grpc-js/test-retry.test.ts STATUS_SEVERITY_ERROR
  • test/js/third_party/msw.test.ts 1 failing
  • test/js/web/fetch/blob-cow.test.ts 1 failing
  • test/transpiler/transpiler-stack-overflow.test.ts 1 failing
  • test/transpiler/transpiler.test.js 9 failing

View logs

@paperdave paperdave changed the title feat(bundler): implement enum inlining / ts namespace fixes feat(bundler): implement enum inlining / more constant folding Jun 27, 2024
@robobun

This comment was marked as outdated.

/// by calling out to the APIs in WebKit which are responsible for this operation.
///
/// This can return `null` in wasm builds to avoid linking JSC
pub fn toString(this: Number, allocator: std.mem.Allocator) ?string {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: this is renamed from toStringSafely to toString, not because it is now less safe, but because the original intent of "we are taking a safer approach" does not apply.

@@ -123,7 +123,7 @@ pub fn getOSGlibCVersion(os: OperatingSystem) ?Version {
}

pub fn build(b: *Build) !void {
std.debug.print("zig build v{s}\n", .{builtin.zig_version_string});
std.log.info("zig compiler v{s}", .{builtin.zig_version_string});
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

apologies for doing a ton of other random things in this pr. i fixed the banned.json linter which resulted in needing to apply a ton of small transformations. i did this because i was sick of std.debug.print showing at all in my cmd+shift+f menu. this also resulted in the deletion of some old files, which some did not even past astgen.

additionally, i have been using a client side spell-checker, so it just becomes annoying to see a ton of yellow underlines. maybe i will upstream a ci check to keep spelling somewhat intact (i have been very impressed with the typos cli and lsp, it is very low false positive).

@compileError("This function can only be called in comptime.");
}
var x = 0; // if you hit an error on this line, you are not in a comptime context
_ = &x;
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comptime @inComptime is a compiler error in 0.14 and in 0.13 does not do what we want.

@@ -46,8 +46,6 @@ pub const allow_json_single_quotes = true;

pub const react_specific_warnings = true;

pub const log_allocations = false;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this behavior is now provided via BUN_DEBUG_mimalloc=1

@paperdave paperdave marked this pull request as ready for review June 29, 2024 04:25
const use = part.symbol_uses.getPtr(ref).?;

// Rare path: this import is a TypeScript enum
if (c.graph.meta.items(.imports_to_bind)[id].get(ref)) |import_data| {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please hoist this .items[id] call above the for loop

/// generated proxy symbols that represent the property access "x3.y". This
/// map is unique per namespace block because "x3" is the argument symbol that
/// is specific to that particular namespace block.
property_accesses: std.StringArrayHashMapUnmanaged(Ref) = .{},
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
property_accesses: std.StringArrayHashMapUnmanaged(Ref) = .{},
property_accesses: bun.StringArrayHashMapUnmanaged(Ref) = .{},

@paperdave paperdave marked this pull request as draft June 29, 2024 05:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants