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

Skip javascriptcore's first parse step for ES Modules #15758

Merged
merged 73 commits into from
Jan 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
a0586da
add a test demonstrating the re-export problem
pfgithub Dec 7, 2024
c57cf76
{todo: true}
pfgithub Dec 7, 2024
37fffb4
add another export test
pfgithub Dec 11, 2024
2e5f949
Merge branch 'main' into pfg/fix-typescript-reexport
pfgithub Dec 11, 2024
3904259
oops missing quote
pfgithub Dec 11, 2024
4ee546a
wip
pfgithub Dec 11, 2024
2d59092
Merge branch 'main' into pfg/fix-typescript-reexport
pfgithub Dec 12, 2024
0d3d11a
examples using our own manually defined module records
pfgithub Dec 12, 2024
a72d203
starting on zig side
pfgithub Dec 13, 2024
c6e1ca1
wip: starting to fill out ModuleInfo
pfgithub Dec 13, 2024
5817c30
first module parse
pfgithub Dec 13, 2024
213bcfb
make sure to pass uses_import_meta flag
pfgithub Dec 13, 2024
344c6a7
import notes
pfgithub Dec 13, 2024
5774201
Merge branch 'main' into pfg/only-parse-twice
pfgithub Dec 13, 2024
e6fab95
more progress on filling the ModuleInfo
pfgithub Dec 14, 2024
7fe6556
support 'export * from '
pfgithub Dec 14, 2024
d1dd1b9
support `export {a, b, c} from "./d"` and `export {a, b}` and indirec…
pfgithub Dec 14, 2024
a655ad2
RELEASE_AND_RETURN & fix indirect checking
pfgithub Dec 14, 2024
5f88727
put vars in varDeclarations rather than lexicalDeclarations
pfgithub Dec 14, 2024
c57fead
set webkit commit hash
pfgithub Dec 14, 2024
0268a4f
fix
pfgithub Dec 14, 2024
605467d
error if results are differebt
pfgithub Dec 16, 2024
1644142
diff print for error
pfgithub Dec 16, 2024
f4418e3
fix 'class' missing lexicalVariable & jest import missing varDeclarat…
pfgithub Dec 16, 2024
e9cb96c
fix missing is_top_level check for s_function and s_class
pfgithub Dec 16, 2024
3fec10a
sort exportEntries and mask only importmetafeature for comparison
pfgithub Dec 16, 2024
55a36bb
fix missing exports for shorthand property names
pfgithub Dec 16, 2024
d8aea25
fix missing export for `export default (expression);`
pfgithub Dec 16, 2024
ea04b81
move the top level check inside toe p.moduleInfo
pfgithub Dec 16, 2024
ff0f561
no more printing except for a diff fail
pfgithub Dec 16, 2024
eeab914
something
pfgithub Dec 16, 2024
542a069
Merge branch 'main' into pfg/only-parse-twice
pfgithub Dec 17, 2024
cb8214c
Merge branch 'main' into pfg/only-parse-twice
pfgithub Dec 17, 2024
a6ac4a6
temporary fix until runtimetranspilercache while it still serializes …
pfgithub Dec 17, 2024
b391510
runtimetranspilercache notes
pfgithub Dec 17, 2024
a992242
allow 'var' inside 'try' to add to varDeclarations
pfgithub Dec 17, 2024
b0995f7
remove launch.json entry
pfgithub Dec 17, 2024
4694267
fix attributes comparison
pfgithub Dec 17, 2024
7e2c6b8
add faster compile errors env var
pfgithub Dec 17, 2024
b1905bf
use bun default_allocator
pfgithub Dec 17, 2024
93dcd32
binary transpiled module format
pfgithub Dec 18, 2024
05ce66c
Merge branch 'main' into pfg/only-parse-twice
pfgithub Dec 18, 2024
ab7584b
maybe in runtimetranspilercache?
pfgithub Dec 18, 2024
ce0b379
fix runtimetranspilercache
pfgithub Dec 18, 2024
a21a1cc
fix everything being broken
pfgithub Dec 18, 2024
2729b4b
?
pfgithub Dec 18, 2024
338931b
Merge branch 'main' into pfg/only-parse-twice
pfgithub Dec 18, 2024
555ee1d
add unused field
pfgithub Dec 18, 2024
78581aa
fix order
pfgithub Dec 18, 2024
1aecc55
note in contributing.md
pfgithub Dec 18, 2024
9b6a962
no individually allocating strings
pfgithub Dec 19, 2024
9cace81
switch to storing in the source provider
pfgithub Dec 19, 2024
042c6b5
PROFILE_MODE switch
pfgithub Dec 19, 2024
92b23d2
forgive bun:main for not having module_info in profile mode
pfgithub Dec 19, 2024
b449b00
no forgiveness
pfgithub Dec 19, 2024
2ea00c3
skip duping every ModuleInfo
pfgithub Dec 19, 2024
43e4e48
transpilercache moduleinfo support & require .module_info on all Reso…
pfgithub Dec 20, 2024
2834abe
infer module type in create & switch some to Module
pfgithub Dec 20, 2024
fb9a671
type-export.test.ts was completely skipped
pfgithub Dec 20, 2024
57260a9
add an import not found test
pfgithub Dec 20, 2024
0652407
set PROFILE_MODE
pfgithub Dec 20, 2024
fc24835
Merge branch 'main' into pfg/only-parse-twice
pfgithub Jan 2, 2025
78298e6
merge
pfgithub Jan 2, 2025
692ddc1
impl deinit for ModuleInfoDeserialized
pfgithub Jan 2, 2025
f0f8e9c
try calling deinit, find ci failures
pfgithub Jan 2, 2025
f3d0e2e
.
pfgithub Jan 2, 2025
729d2e6
pass resolve.test.ts by allowing null bytes in ModuleInfo strings & f…
pfgithub Jan 3, 2025
e7f6fa5
enable comparison in debug builds & windows
pfgithub Jan 3, 2025
a7e9549
Update BunAnalyzeTranspiledModule.cpp
pfgithub Jan 6, 2025
3e1016a
failing test case
pfgithub Jan 8, 2025
1cbd469
syntax error rather than crashing for multiple exports with the same …
pfgithub Jan 8, 2025
1766229
Merge branch 'main' into pfg/only-parse-twice
pfgithub Jan 8, 2025
3daed8d
Merge branch 'main' into pfg/only-parse-twice
pfgithub Jan 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ $ git clone https://github.com/oven-sh/WebKit vendor/WebKit

# Make a debug build of JSC. This will output build artifacts in ./vendor/WebKit/WebKitBuild/Debug
# Optionally, you can use `make jsc` for a release build
$ make jsc-debug
$ make jsc-debug && rm vendor/WebKit/WebKitBuild/Debug/JavaScriptCore/DerivedSources/inspector/InspectorProtocolObjects.h

# Build bun with the local JSC build
$ bun run build:local
Expand Down
5 changes: 5 additions & 0 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,11 @@ pub fn addInstallObjectFile(
name: []const u8,
out_mode: ObjectFormat,
) *Step {
if (@import("builtin").os.tag != .windows and std.posix.getenvZ("COMPILE_ERRORS_ONLY") != null) {
const failstep = b.addSystemCommand(&.{"COMPILE_ERRORS_ONLY set but there were no compile errors"});
failstep.step.dependOn(&compile.step);
return &failstep.step;
}
// bin always needed to be computed or else the compilation will do nothing. zig build system bug?
const bin = compile.getEmittedBin();
return &b.addInstallFile(switch (out_mode) {
Expand Down
2 changes: 2 additions & 0 deletions cmake/tools/SetupWebKit.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ if(WEBKIT_LOCAL)
${WEBKIT_PATH}
${WEBKIT_PATH}/JavaScriptCore/Headers/JavaScriptCore
${WEBKIT_PATH}/JavaScriptCore/PrivateHeaders
${WEBKIT_PATH}/JavaScriptCore/DerivedSources/inspector
${WEBKIT_PATH}/JavaScriptCore/PrivateHeaders/JavaScriptCore
${WEBKIT_PATH}/bmalloc/Headers
${WEBKIT_PATH}/WTF/Headers
)
Expand Down
477 changes: 477 additions & 0 deletions src/analyze_transpiled_module.zig

Large diffs are not rendered by default.

85 changes: 64 additions & 21 deletions src/bun.js/RuntimeTranspilerCache.zig
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
/// Version 11: Fix \uFFFF printing regression
/// Version 12: "use strict"; makes it CommonJS if we otherwise don't know which one to pick.
/// Version 13: Hoist `import.meta.require` definition, see #15738
const expected_version = 13;
/// Version 14: Include module info with an ES Module, see #15758
const expected_version = 14;

const bun = @import("root").bun;
const std = @import("std");
Expand All @@ -33,6 +34,7 @@ pub const RuntimeTranspilerCache = struct {

sourcemap_allocator: std.mem.Allocator,
output_code_allocator: std.mem.Allocator,
esm_record_allocator: std.mem.Allocator,

const seed = 42;
pub const Metadata = struct {
Expand All @@ -53,6 +55,10 @@ pub const RuntimeTranspilerCache = struct {
sourcemap_byte_length: u64 = 0,
sourcemap_hash: u64 = 0,

esm_record_byte_offset: u64 = 0,
esm_record_byte_length: u64 = 0,
esm_record_hash: u64 = 0,

pub const size = brk: {
var count: usize = 0;
const meta: Metadata = .{};
Expand All @@ -79,6 +85,10 @@ pub const RuntimeTranspilerCache = struct {
try writer.writeInt(u64, this.sourcemap_byte_offset, .little);
try writer.writeInt(u64, this.sourcemap_byte_length, .little);
try writer.writeInt(u64, this.sourcemap_hash, .little);

try writer.writeInt(u64, this.esm_record_byte_offset, .little);
try writer.writeInt(u64, this.esm_record_byte_length, .little);
try writer.writeInt(u64, this.esm_record_hash, .little);
}

pub fn decode(this: *Metadata, reader: anytype) !void {
Expand All @@ -103,6 +113,10 @@ pub const RuntimeTranspilerCache = struct {
this.sourcemap_byte_length = try reader.readInt(u64, .little);
this.sourcemap_hash = try reader.readInt(u64, .little);

this.esm_record_byte_offset = try reader.readInt(u64, .little);
this.esm_record_byte_length = try reader.readInt(u64, .little);
this.esm_record_hash = try reader.readInt(u64, .little);

switch (this.module_type) {
.esm, .cjs => {},
// Invalid module type
Expand All @@ -121,7 +135,7 @@ pub const RuntimeTranspilerCache = struct {
metadata: Metadata,
output_code: OutputCode = .{ .utf8 = "" },
sourcemap: []const u8 = "",

esm_record: []const u8 = "",
pub const OutputCode = union(enum) {
utf8: []const u8,
string: bun.String,
Expand All @@ -143,11 +157,14 @@ pub const RuntimeTranspilerCache = struct {
}
};

pub fn deinit(this: *Entry, sourcemap_allocator: std.mem.Allocator, output_code_allocator: std.mem.Allocator) void {
pub fn deinit(this: *Entry, sourcemap_allocator: std.mem.Allocator, output_code_allocator: std.mem.Allocator, esm_record_allocator: std.mem.Allocator) void {
this.output_code.deinit(output_code_allocator);
if (this.sourcemap.len > 0) {
sourcemap_allocator.free(this.sourcemap);
}
if (this.esm_record.len > 0) {
esm_record_allocator.free(this.esm_record);
}
}

pub fn save(
Expand All @@ -157,6 +174,7 @@ pub const RuntimeTranspilerCache = struct {
input_hash: u64,
features_hash: u64,
sourcemap: []const u8,
esm_record: []const u8,
output_code: OutputCode,
exports_kind: bun.JSAst.ExportsKind,
) !void {
Expand Down Expand Up @@ -202,6 +220,8 @@ pub const RuntimeTranspilerCache = struct {
.output_byte_offset = Metadata.size,
.output_byte_length = output_bytes.len,
.sourcemap_byte_offset = Metadata.size + output_bytes.len,
.esm_record_byte_offset = Metadata.size + output_bytes.len + sourcemap.len,
.esm_record_byte_length = esm_record.len,
};

metadata.output_hash = hash(output_bytes);
Expand All @@ -220,20 +240,26 @@ pub const RuntimeTranspilerCache = struct {
break :brk metadata_buf[0..metadata_stream.pos];
};

const vecs: []const bun.PlatformIOVecConst = if (output_bytes.len > 0)
&.{
bun.platformIOVecConstCreate(metadata_bytes),
bun.platformIOVecConstCreate(output_bytes),
bun.platformIOVecConstCreate(sourcemap),
}
else
&.{
bun.platformIOVecConstCreate(metadata_bytes),
bun.platformIOVecConstCreate(sourcemap),
};
var vecs_buf: [4]bun.PlatformIOVecConst = undefined;
var vecs_i: usize = 0;
vecs_buf[vecs_i] = bun.platformIOVecConstCreate(metadata_bytes);
vecs_i += 1;
if (output_bytes.len > 0) {
vecs_buf[vecs_i] = bun.platformIOVecConstCreate(output_bytes);
vecs_i += 1;
}
if (sourcemap.len > 0) {
vecs_buf[vecs_i] = bun.platformIOVecConstCreate(sourcemap);
vecs_i += 1;
}
if (esm_record.len > 0) {
vecs_buf[vecs_i] = bun.platformIOVecConstCreate(esm_record);
vecs_i += 1;
}
const vecs: []const bun.PlatformIOVecConst = vecs_buf[0..vecs_i];

var position: isize = 0;
const end_position = Metadata.size + output_bytes.len + sourcemap.len;
const end_position = Metadata.size + output_bytes.len + sourcemap.len + esm_record.len;

if (bun.Environment.allow_assert) {
var total: usize = 0;
Expand All @@ -243,7 +269,7 @@ pub const RuntimeTranspilerCache = struct {
}
bun.assert(end_position == total);
}
bun.assert(end_position == @as(i64, @intCast(sourcemap.len + output_bytes.len + Metadata.size)));
bun.assert(end_position == @as(i64, @intCast(sourcemap.len + output_bytes.len + Metadata.size + esm_record.len)));

bun.C.preallocate_file(tmpfile.fd.cast(), 0, @intCast(end_position)) catch {};
while (position < end_position) {
Expand All @@ -264,6 +290,7 @@ pub const RuntimeTranspilerCache = struct {
file: std.fs.File,
sourcemap_allocator: std.mem.Allocator,
output_code_allocator: std.mem.Allocator,
esm_record_allocator: std.mem.Allocator,
) !void {
const stat_size = try file.getEndPos();
if (stat_size < Metadata.size + this.metadata.output_byte_length + this.metadata.sourcemap_byte_length) {
Expand Down Expand Up @@ -339,6 +366,17 @@ pub const RuntimeTranspilerCache = struct {

this.sourcemap = sourcemap;
}

if (this.metadata.esm_record_byte_length > 0) {
const esm_record = try esm_record_allocator.alloc(u8, this.metadata.esm_record_byte_length);
errdefer esm_record_allocator.free(esm_record);
const read_bytes = try file.preadAll(esm_record, this.metadata.esm_record_byte_offset);
if (read_bytes != this.metadata.esm_record_byte_length) {
return error.MissingData;
}

this.esm_record = esm_record;
}
}
};

Expand Down Expand Up @@ -456,6 +494,7 @@ pub const RuntimeTranspilerCache = struct {
input_stat_size: u64,
sourcemap_allocator: std.mem.Allocator,
output_code_allocator: std.mem.Allocator,
esm_record_allocator: std.mem.Allocator,
) !Entry {
var tracer = bun.tracy.traceNamed(@src(), "RuntimeTranspilerCache.fromFile");
defer tracer.end();
Expand All @@ -470,6 +509,7 @@ pub const RuntimeTranspilerCache = struct {
input_stat_size,
sourcemap_allocator,
output_code_allocator,
esm_record_allocator,
);
}

Expand All @@ -480,6 +520,7 @@ pub const RuntimeTranspilerCache = struct {
input_stat_size: u64,
sourcemap_allocator: std.mem.Allocator,
output_code_allocator: std.mem.Allocator,
esm_record_allocator: std.mem.Allocator,
) !Entry {
var metadata_bytes_buf: [Metadata.size * 2]u8 = undefined;
const cache_fd = try bun.sys.open(cache_file_path.sliceAssumeZ(), bun.O.RDONLY, 0).unwrap();
Expand Down Expand Up @@ -511,7 +552,7 @@ pub const RuntimeTranspilerCache = struct {
return error.MismatchedFeatureHash;
}

try entry.load(file, sourcemap_allocator, output_code_allocator);
try entry.load(file, sourcemap_allocator, output_code_allocator, esm_record_allocator);

return entry;
}
Expand All @@ -528,6 +569,7 @@ pub const RuntimeTranspilerCache = struct {
input_hash: u64,
features_hash: u64,
sourcemap: []const u8,
esm_record: []const u8,
source_code: bun.String,
exports_kind: bun.JSAst.ExportsKind,
) !void {
Expand Down Expand Up @@ -567,6 +609,7 @@ pub const RuntimeTranspilerCache = struct {
input_hash,
features_hash,
sourcemap,
esm_record,
output_code,
exports_kind,
);
Expand Down Expand Up @@ -600,7 +643,7 @@ pub const RuntimeTranspilerCache = struct {
parser_options.hashForRuntimeTranspiler(&features_hasher, used_jsx);
this.features_hash = features_hasher.final();

this.entry = fromFile(input_hash, this.features_hash.?, source.contents.len, this.sourcemap_allocator, this.output_code_allocator) catch |err| {
this.entry = fromFile(input_hash, this.features_hash.?, source.contents.len, this.sourcemap_allocator, this.output_code_allocator, this.esm_record_allocator) catch |err| {
debug("get(\"{s}\") = {s}", .{ source.path.text, @errorName(err) });
return false;
};
Expand All @@ -616,7 +659,7 @@ pub const RuntimeTranspilerCache = struct {
if (comptime bun.Environment.isDebug) {
if (!bun_debug_restore_from_cache) {
if (this.entry) |*entry| {
entry.deinit(this.sourcemap_allocator, this.output_code_allocator);
entry.deinit(this.sourcemap_allocator, this.output_code_allocator, this.esm_record_allocator);
this.entry = null;
}
}
Expand All @@ -625,7 +668,7 @@ pub const RuntimeTranspilerCache = struct {
return this.entry != null;
}

pub fn put(this: *RuntimeTranspilerCache, output_code_bytes: []const u8, sourcemap: []const u8) void {
pub fn put(this: *RuntimeTranspilerCache, output_code_bytes: []const u8, sourcemap: []const u8, esm_record: []const u8) void {
if (comptime !bun.FeatureFlags.runtime_transpiler_cache)
@compileError("RuntimeTranspilerCache is disabled");

Expand All @@ -636,7 +679,7 @@ pub const RuntimeTranspilerCache = struct {
const output_code = bun.String.createLatin1(output_code_bytes);
this.output_code = output_code;

toFile(this.input_byte_length.?, this.input_hash.?, this.features_hash.?, sourcemap, output_code, this.exports_kind) catch |err| {
toFile(this.input_byte_length.?, this.input_hash.?, this.features_hash.?, sourcemap, esm_record, output_code, this.exports_kind) catch |err| {
debug("put() = {s}", .{@errorName(err)});
return;
};
Expand Down
Loading
Loading