aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2021-05-13 00:46:22 -0700
committerGravatar Jarred Sumner <jarred@jarredsumner.com> 2021-05-13 00:46:22 -0700
commitbed0227a8f2d8b674a98803659922d08ac665bfe (patch)
tree42e6cd96757a0f9c01d103de1f42bdc7a9e958b8
parent9fd6f635cd5092ce82359b504f1e053d7f0387d6 (diff)
downloadbun-bed0227a8f2d8b674a98803659922d08ac665bfe.tar.gz
bun-bed0227a8f2d8b674a98803659922d08ac665bfe.tar.zst
bun-bed0227a8f2d8b674a98803659922d08ac665bfe.zip
hm
Former-commit-id: 28fce4aac174c7cf7a492ca4c5442d57a4f395a3
-rw-r--r--src/bundler.zig35
-rw-r--r--src/cache.zig27
-rw-r--r--src/fs.zig3
-rw-r--r--src/js_lexer.zig21
-rw-r--r--src/json_parser.zig47
-rw-r--r--src/options.zig6
-rw-r--r--src/resolver/resolver.zig36
-rw-r--r--src/sync.zig2
-rw-r--r--src/thread_safe_hash_map.zig12
9 files changed, 143 insertions, 46 deletions
diff --git a/src/bundler.zig b/src/bundler.zig
index 04a3725f9..8df23e265 100644
--- a/src/bundler.zig
+++ b/src/bundler.zig
@@ -22,7 +22,7 @@ const ThreadSafeHashMap = @import("./thread_safe_hash_map.zig");
// pub const
// const BundleMap =
-
+const ResolveResults = ThreadSafeHashMap.ThreadSafeStringHashMap(Resolver.Resolver.Result);
pub const Bundler = struct {
options: options.BundleOptions,
log: *logger.Log,
@@ -30,7 +30,9 @@ pub const Bundler = struct {
result: options.TransformResult = undefined,
resolver: Resolver.Resolver,
fs: *Fs.FileSystem,
- thread_pool: *ThreadPool,
+ // thread_pool: *ThreadPool,
+
+ resolve_results: *ResolveResults,
// to_bundle:
@@ -43,20 +45,24 @@ pub const Bundler = struct {
) !Bundler {
var fs = try Fs.FileSystem.init1(allocator, opts.absolute_working_dir, opts.watch orelse false);
const bundle_options = try options.BundleOptions.fromApi(allocator, fs, log, opts);
- var pool = try allocator.create(ThreadPool);
- try pool.init(ThreadPool.InitConfig{
- .allocator = allocator,
- });
+ // var pool = try allocator.create(ThreadPool);
+ // try pool.init(ThreadPool.InitConfig{
+ // .allocator = allocator,
+ // });
return Bundler{
.options = bundle_options,
.fs = fs,
.allocator = allocator,
.resolver = Resolver.Resolver.init1(allocator, log, fs, bundle_options),
.log = log,
- .thread_pool = pool,
+ // .thread_pool = pool,
+ .result = options.TransformResult{},
+ .resolve_results = try ResolveResults.init(allocator),
};
}
+ pub fn scan(bundler: *Bundler) !void {}
+
pub fn bundle(
allocator: *std.mem.Allocator,
log: *logger.Log,
@@ -65,14 +71,27 @@ pub const Bundler = struct {
var bundler = try Bundler.init(allocator, log, opts);
var entry_points = try allocator.alloc(Resolver.Resolver.Result, bundler.options.entry_points.len);
+
var entry_point_i: usize = 0;
for (bundler.options.entry_points) |entry| {
- entry_points[entry_point_i] = bundler.resolver.resolve(bundler.fs.top_level_dir, entry, .entry_point) catch {
+ const result = bundler.resolver.resolve(bundler.fs.top_level_dir, entry, .entry_point) catch {
continue;
} orelse continue;
+ const key = result.path_pair.primary.text;
+ if (bundler.resolve_results.contains(key)) {
+ continue;
+ }
+ try bundler.resolve_results.put(key, result);
+ entry_points[entry_point_i] = result;
+ Output.print("Resolved {s} => {s}", .{ entry, result.path_pair.primary.text });
entry_point_i += 1;
}
+ switch (bundler.options.resolve_mode) {
+ .lazy, .dev, .bundle => {},
+ else => Global.panic("Unsupported resolve mode: {s}", .{@tagName(bundler.options.resolve_mode)}),
+ }
+
return bundler.result;
}
};
diff --git a/src/cache.zig b/src/cache.zig
index 77f38359b..52beb46bb 100644
--- a/src/cache.zig
+++ b/src/cache.zig
@@ -83,13 +83,22 @@ pub const Cache = struct {
}
};
- const size = if (mod_key != null) mod_key.?.size else null;
- const file = rfs.readFile(path, size) catch |err| {
- if (isDebug) {
- Output.printError("{s}: readFile error -- {s}", .{ path, @errorName(err) });
- }
- return err;
- };
+ var file: fs.File = undefined;
+ if (mod_key) |modk| {
+ file = rfs.readFile(path, modk.size) catch |err| {
+ if (isDebug) {
+ Output.printError("{s}: readFile error -- {s}", .{ path, @errorName(err) });
+ }
+ return err;
+ };
+ } else {
+ file = rfs.readFile(path, null) catch |err| {
+ if (isDebug) {
+ Output.printError("{s}: readFile error -- {s}", .{ path, @errorName(err) });
+ }
+ return err;
+ };
+ }
const entry = Entry{
.contents = file.contents,
@@ -195,11 +204,11 @@ pub const Cache = struct {
return entry.expr;
}
pub fn parseJSON(cache: *@This(), log: *logger.Log, source: logger.Source, allocator: *std.mem.Allocator) anyerror!?js_ast.Expr {
- return @call(std.builtin.CallOptions{ .modifier = .always_tail }, parse, .{ cache, log, source, allocator, false, json_parser.ParseJSON });
+ return try parse(cache, log, source, allocator, false, json_parser.ParseJSON);
}
pub fn parseTSConfig(cache: *@This(), log: *logger.Log, source: logger.Source, allocator: *std.mem.Allocator) anyerror!?js_ast.Expr {
- return @call(std.builtin.CallOptions{ .modifier = .always_tail }, parse, .{ cache, log, source, allocator, true, json_parser.ParseTSConfig });
+ return try parse(cache, log, source, allocator, true, json_parser.ParseTSConfig);
}
};
};
diff --git a/src/fs.zig b/src/fs.zig
index e5ab8e832..2577d4552 100644
--- a/src/fs.zig
+++ b/src/fs.zig
@@ -443,10 +443,11 @@ pub const FileSystem = struct {
defer file.close();
// Skip the extra file.stat() call when possible
- const size = _size orelse (file.getEndPos() catch |err| {
+ var size = _size orelse (file.getEndPos() catch |err| {
fs.readFileError(path, err);
return err;
});
+
const file_contents: []u8 = file.readToEndAllocOptions(fs.allocator, size, size, @alignOf(u8), null) catch |err| {
fs.readFileError(path, err);
return err;
diff --git a/src/js_lexer.zig b/src/js_lexer.zig
index e90886ead..512a5e5cd 100644
--- a/src/js_lexer.zig
+++ b/src/js_lexer.zig
@@ -1216,12 +1216,29 @@ pub const Lexer = struct {
// TODO: use wtf-8 encoding.
pub fn utf16ToStringWithValidation(lexer: *LexerType, js: JavascriptString) !string {
- return std.unicode.utf16leToUtf8Alloc(lexer.allocator, js);
+ // return std.unicode.utf16leToUtf8Alloc(lexer.allocator, js);
+ return utf16ToString(lexer, js);
}
// TODO: use wtf-8 encoding.
pub fn utf16ToString(lexer: *LexerType, js: JavascriptString) string {
- return std.unicode.utf16leToUtf8Alloc(lexer.allocator, js) catch unreachable;
+ var temp = std.mem.zeroes([4]u8);
+ var list = std.ArrayList(u8).initCapacity(lexer.allocator, js.len) catch unreachable;
+ var i: usize = 0;
+ while (i < js.len) : (i += 1) {
+ var r1 = @intCast(i32, js[i]);
+ if (r1 >= 0xD800 and r1 <= 0xDBFF and i + 1 < js.len) {
+ const r2 = @intCast(i32, js[i] + 1);
+ if (r2 >= 0xDC00 and r2 <= 0xDFFF) {
+ r1 = (r1 - 0xD800) << 10 | (r2 - 0xDC00) + 0x10000;
+ i += 1;
+ }
+ }
+ const width = strings.encodeWTF8Rune(&temp, r1);
+ list.appendSlice(temp[0..width]) catch unreachable;
+ }
+ return list.toOwnedSlice();
+ // return std.unicode.utf16leToUtf8Alloc(lexer.allocator, js) catch unreachable;
}
pub fn nextInsideJSXElement(lexer: *LexerType) !void {
diff --git a/src/json_parser.zig b/src/json_parser.zig
index 4fb1f89f7..120bcb4d7 100644
--- a/src/json_parser.zig
+++ b/src/json_parser.zig
@@ -93,11 +93,20 @@ fn JSONLikeParser(opts: js_lexer.JSONOptions) type {
return p.e(E.Null{}, loc);
},
.t_string_literal => {
- const value = p.lexer.string_literal;
+ var str: E.String = undefined;
+ if (p.lexer.string_literal_is_ascii) {
+ str = E.String{
+ .utf8 = p.lexer.string_literal_slice,
+ };
+ } else {
+ const value = p.lexer.stringLiteralUTF16();
+ str = E.String{
+ .value = value,
+ };
+ }
+
try p.lexer.next();
- return p.e(E.String{
- .value = value,
- }, loc);
+ return p.e(str, loc);
},
.t_numeric_literal => {
const value = p.lexer.number;
@@ -143,7 +152,7 @@ fn JSONLikeParser(opts: js_lexer.JSONOptions) type {
try p.lexer.next();
var is_single_line = !p.lexer.has_newline_before;
var properties = std.ArrayList(G.Property).init(p.allocator);
- var duplicates = std.StringHashMap(u1).init(p.allocator);
+ var duplicates = std.BufSet.init(p.allocator);
while (p.lexer.token != .t_close_brace) {
if (properties.items.len > 0) {
@@ -158,18 +167,30 @@ fn JSONLikeParser(opts: js_lexer.JSONOptions) type {
}
}
- var key_string = p.lexer.string_literal;
+ var str: E.String = undefined;
+ if (p.lexer.string_literal_is_ascii) {
+ str = E.String{
+ .utf8 = p.lexer.string_literal_slice,
+ };
+ } else {
+ const value = p.lexer.stringLiteralUTF16();
+ str = E.String{
+ .value = value,
+ };
+ }
+ const is_duplicate = duplicates.exists(p.lexer.string_literal_slice);
+ if (!is_duplicate) {
+ duplicates.put(p.lexer.string_literal_slice) catch unreachable;
+ }
var key_range = p.lexer.range();
- var key = p.e(E.String{ .value = key_string }, key_range.loc);
- try p.lexer.expect(.t_string_literal);
- var key_text = p.lexer.utf16ToString(key_string);
// Warn about duplicate keys
-
- const entry = duplicates.getOrPut(key_text) catch unreachable;
- if (entry.found_existing) {
- p.log.addRangeWarningFmt(p.source, key_range, p.allocator, "Duplicate key \"{s}\" in object literal", .{key_text}) catch unreachable;
+ if (is_duplicate) {
+ p.log.addRangeWarningFmt(p.source, key_range, p.allocator, "Duplicate key \"{s}\" in object literal", .{p.lexer.string_literal_slice}) catch unreachable;
}
+ var key = p.e(str, key_range.loc);
+ try p.lexer.expect(.t_string_literal);
+
try p.lexer.expect(.t_colon);
var value = try p.parseExpr();
properties.append(G.Property{ .key = key, .value = value }) catch unreachable;
diff --git a/src/options.zig b/src/options.zig
index 9d5f91699..7daa14804 100644
--- a/src/options.zig
+++ b/src/options.zig
@@ -421,9 +421,9 @@ pub const OutputFile = struct {
};
pub const TransformResult = struct {
- errors: []logger.Msg,
- warnings: []logger.Msg,
- output_files: []OutputFile,
+ errors: []logger.Msg = &([_]logger.Msg{}),
+ warnings: []logger.Msg = &([_]logger.Msg{}),
+ output_files: []OutputFile = &([_]OutputFile{}),
pub fn init(
output_files: []OutputFile,
log: *logger.Log,
diff --git a/src/resolver/resolver.zig b/src/resolver/resolver.zig
index 8ac9f083d..6d2425654 100644
--- a/src/resolver/resolver.zig
+++ b/src/resolver/resolver.zig
@@ -39,10 +39,10 @@ pub const DirInfo = struct {
};
pub const TemporaryBuffer = struct {
- pub var ExtensionPathBuf = std.mem.zeroes([512]u8);
- pub var TSConfigMatchStarBuf = std.mem.zeroes([512]u8);
- pub var TSConfigMatchPathBuf = std.mem.zeroes([512]u8);
- pub var TSConfigMatchFullBuf = std.mem.zeroes([512]u8);
+ pub threadlocal var ExtensionPathBuf = std.mem.zeroes([512]u8);
+ pub threadlocal var TSConfigMatchStarBuf = std.mem.zeroes([512]u8);
+ pub threadlocal var TSConfigMatchPathBuf = std.mem.zeroes([512]u8);
+ pub threadlocal var TSConfigMatchFullBuf = std.mem.zeroes([512]u8);
};
pub const Resolver = struct {
@@ -194,6 +194,9 @@ pub const Resolver = struct {
is_external: bool = false,
+ // This is true when the package was loaded from within the node_modules directory.
+ is_from_node_modules: bool = false,
+
diff_case: ?Fs.FileSystem.Entry.Lookup.DifferentCase = null,
// If present, any ES6 imports to this file can be considered to have no side
@@ -239,7 +242,18 @@ pub const Resolver = struct {
};
pub fn isExternalPattern(r: *Resolver, import_path: string) bool {
- Global.notimpl();
+ for (r.opts.external.patterns) |pattern| {
+ if (import_path.len >= pattern.prefix.len + pattern.suffix.len and (strings.startsWith(
+ import_path,
+ pattern.prefix,
+ ) and strings.endsWith(
+ import_path,
+ pattern.suffix,
+ ))) {
+ return true;
+ }
+ }
+ return false;
}
pub fn flushDebugLogs(r: *Resolver, flush_mode: DebugLogs.FlushMode) !void {
@@ -487,7 +501,11 @@ pub const Resolver = struct {
if (pair.secondary != null) {
pair.secondary.?.is_disabled = true;
}
- return Result{ .path_pair = pair, .diff_case = node_module.diff_case };
+ return Result{
+ .path_pair = pair,
+ .diff_case = node_module.diff_case,
+ .is_from_node_modules = true,
+ };
}
} else {
var primary = Path.init(import_path);
@@ -544,6 +562,11 @@ pub const Resolver = struct {
}
pub fn loadNodeModules(r: *Resolver, import_path: string, kind: ast.ImportKind, _dir_info: *DirInfo) ?MatchResult {
+ var res = _loadNodeModules(r, import_path, kind, _dir_info) orelse return null;
+ res.is_node_module = true;
+ return res;
+ }
+ pub fn _loadNodeModules(r: *Resolver, import_path: string, kind: ast.ImportKind, _dir_info: *DirInfo) ?MatchResult {
var dir_info = _dir_info;
if (r.debug_logs) |*debug| {
debug.addNoteFmt("Searching for {s} in \"node_modules\" directories starting from \"{s}\"", .{ import_path, dir_info.abs_path }) catch {};
@@ -706,6 +729,7 @@ pub const Resolver = struct {
pub const MatchResult = struct {
path_pair: PathPair,
+ is_node_module: bool = false,
diff_case: ?Fs.FileSystem.Entry.Lookup.DifferentCase = null,
};
diff --git a/src/sync.zig b/src/sync.zig
index 80e20cfa1..c43c227db 100644
--- a/src/sync.zig
+++ b/src/sync.zig
@@ -608,7 +608,7 @@ pub const RwLock = if (std.builtin.os.tag != .windows and std.builtin.link_libc)
},
.netbsd => extern struct {
ptr_magic: c_uint = 0x99990009,
- ptr_interlock: switch (std.builtin.arch) {
+ ptr_interlock: switch (std.Target.current.cpu.arch) {
.aarch64, .sparc, .x86_64, .i386 => u8,
.arm, .powerpc => c_int,
else => unreachable,
diff --git a/src/thread_safe_hash_map.zig b/src/thread_safe_hash_map.zig
index 321cb757f..40aeff7d6 100644
--- a/src/thread_safe_hash_map.zig
+++ b/src/thread_safe_hash_map.zig
@@ -9,9 +9,9 @@ pub fn ThreadSafeStringHashMap(comptime Value: type) type {
lock: sync.RwLock,
pub const HashMap = @This();
- pub fn init(allocator: *std.mem.Allocator) !*HashMapType {
- var self = try allocator.create(HashMapType);
- self.* = HashMapType{ .backing = HashMapType.init(allocator), .lock = sync.RwLock.init() };
+ pub fn init(allocator: *std.mem.Allocator) !*HashMap {
+ var self = try allocator.create(HashMap);
+ self.* = HashMap{ .backing = HashMapType.init(allocator), .lock = sync.RwLock.init() };
return self;
}
@@ -22,6 +22,12 @@ pub fn ThreadSafeStringHashMap(comptime Value: type) type {
return self.backing.get(key);
}
+ pub fn contains(self: *HashMap, str: string) bool {
+ self.lock.lockShared();
+ defer self.lock.unlockShared();
+ return self.backing.contains(str);
+ }
+
pub fn deinit(self: *HashMap, allocator: *std.mem.Allocator) void {
self.backing.deinit();
}