diff options
author | 2021-05-12 13:00:25 -0700 | |
---|---|---|
committer | 2021-05-12 13:00:25 -0700 | |
commit | c09d7cf83905111ef7af9ee5bbd523f56664395c (patch) | |
tree | 84fed91f8f6522594b109c09140f69d9c39ff598 | |
parent | f8131f42bcd039964586cbf3bd019dc9a449c438 (diff) | |
download | bun-c09d7cf83905111ef7af9ee5bbd523f56664395c.tar.gz bun-c09d7cf83905111ef7af9ee5bbd523f56664395c.tar.zst bun-c09d7cf83905111ef7af9ee5bbd523f56664395c.zip |
That's all the errors??
Former-commit-id: f9a74df73d2831bfdd8e6f1c0e5c999ea300fc0d
-rw-r--r-- | src/cache.zig | 61 | ||||
-rw-r--r-- | src/fs.zig | 96 | ||||
-rw-r--r-- | src/js_ast.zig | 24 | ||||
-rw-r--r-- | src/js_lexer.zig | 16 | ||||
-rw-r--r-- | src/js_parser/js_parser.zig | 12 | ||||
-rw-r--r-- | src/json_parser.zig | 10 | ||||
-rw-r--r-- | src/logger.zig | 40 | ||||
-rw-r--r-- | src/options.zig | 8 | ||||
-rw-r--r-- | src/resolver/package_json.zig | 30 | ||||
-rw-r--r-- | src/resolver/resolve_path.zig | 2 | ||||
-rw-r--r-- | src/resolver/resolver.zig | 89 | ||||
-rw-r--r-- | src/resolver/tsconfig_json.zig | 86 |
12 files changed, 254 insertions, 220 deletions
diff --git a/src/cache.zig b/src/cache.zig index 505a4653c..77f38359b 100644 --- a/src/cache.zig +++ b/src/cache.zig @@ -8,6 +8,8 @@ const options = @import("./options.zig"); const Defines = @import("./defines.zig").Defines; const std = @import("std"); const fs = @import("./fs.zig"); +const sync = @import("sync.zig"); +const Mutex = sync.Mutex; pub const Cache = struct { pub const Set = struct { @@ -19,18 +21,18 @@ pub const Cache = struct { return Set{ .js = JavaScript{}, .fs = Fs{ - .mutex = std.Thread.Mutex{}, + .mutex = Mutex.init(), .entries = std.StringHashMap(Fs.Entry).init(allocator), }, .json = Json{ - .mutex = std.Thread.Mutex{}, + .mutex = Mutex.init(), .entries = std.StringHashMap(*Json.Entry).init(allocator), }, }; } }; pub const Fs = struct { - mutex: std.Thread.Mutex, + mutex: Mutex, entries: std.StringHashMap(Entry), pub const Entry = struct { @@ -54,12 +56,12 @@ pub const Cache = struct { c.entries.deinit(); } - pub fn readFile(c: *Fs, _fs: fs.FileSystem, path: string) !*Entry { - const rfs: _fs.RealFS = _fs.fs; + pub fn readFile(c: *Fs, _fs: *fs.FileSystem, path: string) !Entry { + var rfs = _fs.fs; { - const hold = c.mutex.acquire(); - defer hold.release(); + c.mutex.lock(); + defer c.mutex.unlock(); if (c.entries.get(path)) |entry| { return entry; } @@ -67,7 +69,7 @@ pub const Cache = struct { // If the file's modification key hasn't changed since it was cached, assume // the contents of the file are also the same and skip reading the file. - var mod_key: ?fs.FileSystem.Implementation.ModKey = rfs.modKey(path) catch |err| { + var mod_key: ?fs.FileSystem.Implementation.ModKey = rfs.modKey(path) catch |err| handler: { switch (err) { error.FileNotFound, error.AccessDenied => { return err; @@ -76,7 +78,7 @@ pub const Cache = struct { if (isDebug) { Output.printError("modkey error: {s}", .{@errorName(err)}); } - mod_key = null; + break :handler null; }, } }; @@ -94,15 +96,16 @@ pub const Cache = struct { .mod_key = mod_key, }; - const hold = c.mutex.acquire(); - defer hold.release(); - var res = c.entries.getOrPut(path, entry) catch unreachable; + c.mutex.lock(); + defer c.mutex.unlock(); + var res = c.entries.getOrPut(path) catch unreachable; + if (res.found_existing) { res.entry.value.deinit(c.entries.allocator); } res.entry.value = entry; - return &en.value; + return res.entry.value; } }; @@ -153,19 +156,19 @@ pub const Cache = struct { ok: bool = false, // msgs: []logger.Msg, }; - mutex: std.Thread.Mutex, + mutex: Mutex, entries: std.StringHashMap(*Entry), pub fn init(allocator: *std.mem.Allocator) Json { return Json{ - .mutex = std.Thread.Mutex{}, + .mutex = Mutex.init(), .entries = std.StringHashMap(Entry).init(allocator), }; } - fn parse(cache: *@This(), log: *logger.Log, source: logger.Source, allocator: *std.mem.Allocator, is_tsconfig: bool, func: anytype) anyerror!?Expr { + fn parse(cache: *@This(), log: *logger.Log, source: logger.Source, allocator: *std.mem.Allocator, is_tsconfig: bool, func: anytype) anyerror!?js_ast.Expr { { - const hold = cache.mutex.acquire(); - defer hold.release(); - if (cache.entries.get(source.key_path)) |entry| { + cache.mutex.lock(); + defer cache.mutex.unlock(); + if (cache.entries.get(source.key_path.text)) |entry| { return entry.expr; } } @@ -174,8 +177,8 @@ pub const Cache = struct { defer { temp_log.appendTo(log) catch {}; } - const expr = func(&source, &temp_log, allocator) catch { - null; + const expr = func(&source, &temp_log, allocator) catch handler: { + break :handler null; }; const entry = try allocator.create(Entry); entry.* = Entry{ @@ -185,18 +188,18 @@ pub const Cache = struct { .ok = expr != null, }; - const hold = cache.mutex.acquire(); - defer hold.release(); - std.debug.assert(source.key_path.len > 0); // missing key_path in source - try cache.entries.put(source.key_path, entry); + cache.mutex.lock(); + defer cache.mutex.unlock(); + std.debug.assert(source.key_path.text.len > 0); // missing key_path in source + try cache.entries.put(source.key_path.text, entry); return entry.expr; } - pub fn parseJSON(cache: *@This(), log: *logger.Log, source: logger.Source, allocator: *std.mem.Allocator) anyerror!?Expr { - return @call(std.builtin.CallOptions{ .modifier = .always_tail }, parse, .{ cache, log, opts, source, allocator, false, json_parser.ParseJSON }); + 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 }); } - pub fn parseTSConfig(cache: *@This(), log: *logger.Log, source: logger.Source, allocator: *std.mem.Allocator) anyerror!?Expr { - return @call(std.builtin.CallOptions{ .modifier = .always_tail }, parse, .{ cache, log, opts, source, allocator, true, json_parser.ParseTSConfig }); + 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 }); } }; }; diff --git a/src/fs.zig b/src/fs.zig index cdf8c520d..2337bdb19 100644 --- a/src/fs.zig +++ b/src/fs.zig @@ -123,22 +123,22 @@ pub const FileSystem = struct { file, }; - pub fn kind(entry: *Entry, fs: *Implementation) !Kind { + pub fn kind(entry: *Entry, fs: *Implementation) Kind { entry.mutex.lock(); defer entry.mutex.unlock(); if (entry.need_stat) { entry.need_stat = false; - entry.cache = try fs.kind(entry.dir, entry.base); + entry.cache = fs.kind(entry.dir, entry.base) catch unreachable; } return entry.cache.kind; } - pub fn symlink(entry: *Entry, fs: *Implementation) !string { + pub fn symlink(entry: *Entry, fs: *Implementation) string { entry.mutex.lock(); defer entry.mutex.unlock(); if (entry.need_stat) { entry.need_stat = false; - entry.cache = try fs.kind(entry.dir, entry.base); + entry.cache = fs.kind(entry.dir, entry.base) catch unreachable; } return entry.cache.symlink; } @@ -175,32 +175,32 @@ pub const FileSystem = struct { }; } + pub const ModKeyError = error{ + Unusable, + }; pub const ModKey = struct { inode: std.fs.File.INode = 0, size: u64 = 0, mtime: i128 = 0, mode: std.fs.File.Mode = 0, - pub const Error = error{ - Unusable, - }; pub fn generate(fs: *RealFS, path: string) anyerror!ModKey { var file = try std.fs.openFileAbsolute(path, std.fs.File.OpenFlags{ .read = true }); defer file.close(); const stat = try file.stat(); - const seconds = stat.mtime / std.time.ns_per_s; + const seconds = @divTrunc(stat.mtime, @as(@TypeOf(stat.mtime), std.time.ns_per_s)); // We can't detect changes if the file system zeros out the modification time if (seconds == 0 and std.time.ns_per_s == 0) { - return Error.Unusable; + return error.Unusable; } // Don't generate a modification key if the file is too new const now = std.time.nanoTimestamp(); - const now_seconds = now / std.time.ns_per_s; + const now_seconds = @divTrunc(now, std.time.ns_per_s); if (seconds > seconds or (seconds == now_seconds and stat.mtime > now)) { - return Error.Unusable; + return error.Unusable; } return ModKey{ @@ -214,35 +214,38 @@ pub const FileSystem = struct { pub const SafetyGap = 3; }; - fn modKeyError(fs: *RealFS, path: string, err: anyerror) !void { + fn modKeyError(fs: *RealFS, path: string, err: anyerror) void { if (fs.watcher) |*watcher| { - watch_data.watch_mutex.lock(); - defer watch_data.watch_mutex.unlock(); + fs.watcher_mutex.lock(); + defer fs.watcher_mutex.unlock(); var state = WatchData.State.file_missing; switch (err) { - ModKey.Error.Unusable => { + error.Unusable => { state = WatchData.State.file_unusable_mod_key; }, else => {}, } - var entry = try watcher.getOrPutValue(path, WatchData{ .state = state }); + var entry = watcher.getOrPutValue(path, WatchData{ .state = state }) catch unreachable; entry.value.state = state; } - return err; } - pub fn modKey(fs: *RealFS, path: string) !ModKey { + pub fn modKey(fs: *RealFS, path: string) anyerror!ModKey { fs.limiter.before(); defer fs.limiter.after(); - const key = ModKey.generate(fs, path) catch |err| return fs.modKeyError(path, err); + const key = ModKey.generate(fs, path) catch |err| { + fs.modKeyError(path, err); + return err; + }; + if (fs.watcher) |*watcher| { fs.watcher_mutex.lock(); defer fs.watcher_mutex.unlock(); - var entry = try watcher.getOrPutValue(path, WatchData{ .state = .file_has_mod_key, .mod_key = key }); + var entry = watcher.getOrPutValue(path, WatchData{ .state = .file_has_mod_key, .mod_key = key }) catch unreachable; entry.value.mod_key = key; } @@ -420,32 +423,39 @@ pub const FileSystem = struct { return result; } - fn readFileError(fs: *RealFS, path: string, err: anyerror) !void { + fn readFileError(fs: *RealFS, path: string, err: anyerror) void { if (fs.watcher) |*watcher| { fs.watcher_mutex.lock(); defer fs.watcher_mutex.unlock(); - var res = try watcher.getOrPutValue(path, WatchData{ .state = .file_missing }); + var res = watcher.getOrPutValue(path, WatchData{ .state = .file_missing }) catch unreachable; res.value.state = .file_missing; } - - return err; } pub fn readFile(fs: *RealFS, path: string, _size: ?usize) !File { fs.limiter.before(); defer fs.limiter.after(); - const file: std.fs.File = std.fs.openFileAbsolute(path, std.fs.File.OpenFlags{ .read = true, .write = false }) catch |err| return fs.readFileError(path, err); + const file: std.fs.File = std.fs.openFileAbsolute(path, std.fs.File.OpenFlags{ .read = true, .write = false }) catch |err| { + fs.readFileError(path, err); + return err; + }; defer file.close(); // Skip the extra file.stat() call when possible - const size = _size orelse (try file.getEndPos() catch |err| return fs.readFileError(path, err)); - const file_contents: []u8 = file.readToEndAllocOptions(fs.allocator, size, size, @alignOf(u8), null) catch |err| return fs.readFileError(path, err); + const 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; + }; if (fs.watcher) |*watcher| { - var hold = fs.watcher_mutex.acquire(); - defer hold.release(); - var res = try watcher.getOrPutValue(path, WatchData{}); + fs.watcher_mutex.lock(); + defer fs.watcher_mutex.unlock(); + var res = watcher.getOrPutValue(path, WatchData{}) catch unreachable; res.value.state = .file_need_mod_key; res.value.file_contents = file_contents; } @@ -464,16 +474,17 @@ pub const FileSystem = struct { const file = try std.fs.openFileAbsolute(entry_path, .{ .read = true, .write = false }); defer file.close(); - const stat = try file.stat(); + var stat = try file.stat(); + var _kind = stat.kind; var cache = Entry.Cache{ .kind = Entry.Kind.file, .symlink = "" }; - + var symlink: []u8 = &([_]u8{}); if (_kind == .SymLink) { // windows has a max filepath of 255 chars // we give it a little longer for other platforms - var out_buffer = [_]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - var out_slice = &(out_buffer); - var symlink = entry_path; + var out_buffer = std.mem.zeroes([512]u8); + var out_slice = &out_buffer; + symlink = entry_path; var links_walked: u8 = 0; while (links_walked < 255) : (links_walked += 1) { @@ -482,7 +493,7 @@ pub const FileSystem = struct { if (!std.fs.path.isAbsolute(link)) { combo[0] = dir; combo[1] = link; - if (link.ptr != out_slice.ptr) { + if (link.ptr != &out_buffer) { fs.allocator.free(link); } link = std.fs.path.join(fs.allocator, &combo) catch return cache; @@ -496,8 +507,8 @@ pub const FileSystem = struct { const stat2 = file2.stat() catch return cache; // Re-run "lstat" on the symlink target - mode = stat2.mode; - if (mode == .Symlink) { + _kind = stat2.kind; + if (_kind != .SymLink) { break; } dir = std.fs.path.dirname(link) orelse return cache; @@ -508,12 +519,11 @@ pub const FileSystem = struct { } } - if (mode == .Directory) { - _kind = Entry.Kind.dir; + if (_kind == .Directory) { + cache.kind = .dir; } else { - _kind = Entry.Kind.file; + cache.kind = .file; } - cache.kind = _kind; cache.symlink = symlink; return cache; @@ -627,7 +637,7 @@ pub const Path = struct { // for now, assume you won't try to normalize a path longer than 1024 chars pub fn normalize(str: string, allocator: *std.mem.Allocator) string { if (str.len == 0 or (str.len == 1 and str[0] == ' ')) return "."; - if (resolvePath(normalize_buf, str)) |out| { + if (resolvePath(&normalize_buf, str)) |out| { return allocator.dupe(u8, out) catch unreachable; } return str; diff --git a/src/js_ast.zig b/src/js_ast.zig index 6a93310a2..66954a5bb 100644 --- a/src/js_ast.zig +++ b/src/js_ast.zig @@ -938,7 +938,7 @@ pub const E = struct { } }, string => { - return strings.utf16EqlString(other.utf8, s.value); + return strings.utf16EqlString(s.value, other); }, JavascriptString => { return std.mem.eql(u16, other.value, s.value); @@ -1381,13 +1381,15 @@ pub const Expr = struct { pub const Query = struct { expr: Expr, loc: logger.Loc }; - pub fn getProperty(expr: *Expr, name: string) ?Query { - const obj: *E.Object = expr.data.e_object orelse return null; + pub fn getProperty(expr: *const Expr, name: string) ?Query { + if (std.meta.activeTag(expr.data) != .e_object) return null; + const obj: *E.Object = expr.data.e_object; for (obj.properties) |prop| { const value = prop.value orelse continue; const key = prop.key orelse continue; - const key_str: *E.String = key.data.e_string orelse continue; + if (std.meta.activeTag(key.data) != .e_string) continue; + const key_str: *E.String = key.data.e_string; if (key_str.eql(string, name)) { return Query{ .expr = value, .loc = key.loc }; } @@ -1396,16 +1398,20 @@ pub const Expr = struct { return null; } - pub fn getString(expr: *Expr, allocator: *std.mem.Allocator) !?string { - const key_str: *E.String = expr.data.e_string orelse return null; + pub fn getString(expr: *const Expr, allocator: *std.mem.Allocator) ?string { + if (std.meta.activeTag(expr.data) != .e_string) return null; - return if (key_str.isUTF8()) key_str.value else key_str.string(allocator); + const key_str: *E.String = expr.data.e_string; + + return if (key_str.isUTF8()) key_str.utf8 else key_str.string(allocator) catch null; } pub fn getBool( - expr: *Expr, + expr: *const Expr, ) ?bool { - const obj: *E.Boolean = expr.data.e_boolean orelse return null; + if (std.meta.activeTag(expr.data) != .e_boolean) return null; + + const obj = expr.data.e_boolean; return obj.value; } diff --git a/src/js_lexer.zig b/src/js_lexer.zig index 4c758c6a4..e90886ead 100644 --- a/src/js_lexer.zig +++ b/src/js_lexer.zig @@ -52,7 +52,7 @@ pub const Lexer = struct { log: *logger.Log, json_options: ?JSONOptions = null, for_global_name: bool = false, - source: *logger.Source, + source: *const logger.Source, current: usize = 0, start: usize = 0, end: usize = 0, @@ -1094,11 +1094,11 @@ pub const Lexer = struct { }; } - pub fn initGlobalName(log: *logger.Log, source: *logger.Source, allocator: *std.mem.Allocator) !LexerType { - var empty_string_literal: JavascriptString = emptyJavaScriptString; + pub fn initGlobalName(log: *logger.Log, source: *const logger.Source, allocator: *std.mem.Allocator) !LexerType { + var empty_string_literal: JavascriptString = &emptyJavaScriptString; var lex = LexerType{ .log = log, - .source = source.*, + .source = source, .string_literal_is_ascii = true, .string_literal = empty_string_literal, .string_literal_buffer = std.ArrayList(u16).init(allocator), @@ -1113,11 +1113,11 @@ pub const Lexer = struct { return lex; } - pub fn initTSConfig(log: *logger.Log, source: *logger.Source, allocator: *std.mem.Allocator) !LexerType { - var empty_string_literal: JavascriptString = emptyJavaScriptString; + pub fn initTSConfig(log: *logger.Log, source: *const logger.Source, allocator: *std.mem.Allocator) !LexerType { + var empty_string_literal: JavascriptString = &emptyJavaScriptString; var lex = LexerType{ .log = log, - .source = source.*, + .source = source, .string_literal = empty_string_literal, .string_literal_buffer = std.ArrayList(u16).init(allocator), .prev_error_loc = logger.Loc.Empty, @@ -1135,7 +1135,7 @@ pub const Lexer = struct { return lex; } - pub fn initJSON(log: *logger.Log, source: *logger.Source, allocator: *std.mem.Allocator) !LexerType { + pub fn initJSON(log: *logger.Log, source: *const logger.Source, allocator: *std.mem.Allocator) !LexerType { var empty_string_literal: JavascriptString = &emptyJavaScriptString; var lex = LexerType{ .log = log, diff --git a/src/js_parser/js_parser.zig b/src/js_parser/js_parser.zig index e15699a55..5cbf5cd3e 100644 --- a/src/js_parser/js_parser.zig +++ b/src/js_parser/js_parser.zig @@ -1323,8 +1323,8 @@ pub const Parser = struct { var i: usize = 0; var additional_stmt: ?Stmt = null; if (jsx_factory_symbol.use_count_estimate > 0) { - jsx_imports[i] = p.options.jsx.factory; - try symbols.put(p.options.jsx.factory, p.jsx_factory_ref); + jsx_imports[i] = p.options.jsx.factory[0]; + try symbols.put(p.options.jsx.factory[0], p.jsx_factory_ref); i += 1; } @@ -1347,9 +1347,9 @@ pub const Parser = struct { } if (jsx_fragment_symbol.use_count_estimate > 0) { - jsx_imports[i] = p.options.jsx.fragment; + jsx_imports[i] = p.options.jsx.fragment[0]; - try symbols.put(p.options.jsx.fragment, p.jsx_fragment_ref); + try symbols.put(p.options.jsx.fragment[0], p.jsx_fragment_ref); i += 1; } @@ -2208,9 +2208,9 @@ pub const P = struct { p.jsx_filename_ref = p.newSymbol(.other, Prefill.Runtime.JSXFilename) catch unreachable; } const jsx_importname = p.options.jsx.jsx; - p.jsx_fragment_ref = p.newSymbol(.other, p.options.jsx.fragment) catch unreachable; + p.jsx_fragment_ref = p.newSymbol(.other, p.options.jsx.fragment[p.options.jsx.fragment.len - 1]) catch unreachable; p.jsx_runtime_ref = p.newSymbol(.other, jsx_importname) catch unreachable; - p.jsx_factory_ref = p.newSymbol(.other, p.options.jsx.factory) catch unreachable; + p.jsx_factory_ref = p.newSymbol(.other, p.options.jsx.factory[p.options.jsx.factory.len - 1]) catch unreachable; } // ECMAScript modules are always interpreted as strict mode. This has to be diff --git a/src/json_parser.zig b/src/json_parser.zig index 80c7511a7..4fb1f89f7 100644 --- a/src/json_parser.zig +++ b/src/json_parser.zig @@ -41,11 +41,11 @@ const Lexer = js_lexer.Lexer; fn JSONLikeParser(opts: js_lexer.JSONOptions) type { return struct { lexer: Lexer, - source: *logger.Source, + source: *const logger.Source, log: *logger.Log, allocator: *std.mem.Allocator, - pub fn init(allocator: *std.mem.Allocator, source: *logger.Source, log: *logger.Log) !Parser { + pub fn init(allocator: *std.mem.Allocator, source: *const logger.Source, log: *logger.Log) !Parser { if (opts.allow_comments) { return Parser{ .lexer = try Lexer.initTSConfig(log, source, allocator), @@ -210,14 +210,14 @@ fn JSONLikeParser(opts: js_lexer.JSONOptions) type { const JSONParser = JSONLikeParser(js_lexer.JSONOptions{}); const TSConfigParser = JSONLikeParser(js_lexer.JSONOptions{ .allow_comments = true, .allow_trailing_commas = true }); -pub fn ParseJSON(source: *logger.Source, log: *logger.Log, allocator: *std.mem.Allocator) !Expr { +pub fn ParseJSON(source: *const logger.Source, log: *logger.Log, allocator: *std.mem.Allocator) !Expr { var parser = try JSONParser.init(allocator, source, log); return parser.parseExpr(); } -pub fn ParseTSConfig(log: logger.Loc, source: *logger.Source, allocator: *std.mem.Allocator) !Expr { - var parser = try TSConfigParser.init(allocator, log, source); +pub fn ParseTSConfig(source: *const logger.Source, log: *logger.Log, allocator: *std.mem.Allocator) !Expr { + var parser = try TSConfigParser.init(allocator, source, log); return parser.parseExpr(); } diff --git a/src/logger.zig b/src/logger.zig index ec93e52cc..a07adc203 100644 --- a/src/logger.zig +++ b/src/logger.zig @@ -214,7 +214,7 @@ pub const Log = struct { }; } - pub fn addVerbose(log: *Log, source: ?*Source, loc: Loc, text: string) !void { + pub fn addVerbose(log: *Log, source: ?*const Source, loc: Loc, text: string) !void { try log.addMsg(Msg{ .kind = .verbose, .data = rangeData(source, Range{ .loc = loc }, text), @@ -232,7 +232,7 @@ pub const Log = struct { self.msgs.deinit(); } - pub fn addVerboseWithNotes(log: *Log, source: ?*Source, loc: Loc, text: string, notes: []Data) !void { + pub fn addVerboseWithNotes(log: *Log, source: ?*const Source, loc: Loc, text: string, notes: []Data) !void { try log.addMsg(Msg{ .kind = .verbose, .data = rangeData(source, Range{ .loc = loc }, text), @@ -240,7 +240,7 @@ pub const Log = struct { }); } - pub fn addRangeError(log: *Log, source: ?*Source, r: Range, text: string) !void { + pub fn addRangeError(log: *Log, source: ?*const Source, r: Range, text: string) !void { log.errors += 1; try log.addMsg(Msg{ .kind = .err, @@ -248,7 +248,7 @@ pub const Log = struct { }); } - pub fn addRangeErrorFmt(log: *Log, source: ?*Source, r: Range, allocator: *std.mem.Allocator, comptime text: string, args: anytype) !void { + pub fn addRangeErrorFmt(log: *Log, source: ?*const Source, r: Range, allocator: *std.mem.Allocator, comptime text: string, args: anytype) !void { log.errors += 1; try log.addMsg(Msg{ .kind = .err, @@ -256,7 +256,7 @@ pub const Log = struct { }); } - pub fn addRangeErrorFmtWithNotes(log: *Log, source: ?*Source, r: Range, allocator: *std.mem.Allocator, notes: []Data, comptime text: string, args: anytype) !void { + pub fn addRangeErrorFmtWithNotes(log: *Log, source: ?*const Source, r: Range, allocator: *std.mem.Allocator, notes: []Data, comptime text: string, args: anytype) !void { log.errors += 1; try log.addMsg(Msg{ .kind = .err, @@ -265,7 +265,7 @@ pub const Log = struct { }); } - pub fn addErrorFmt(log: *Log, source: ?*Source, l: Loc, allocator: *std.mem.Allocator, comptime text: string, args: anytype) !void { + pub fn addErrorFmt(log: *Log, source: ?*const Source, l: Loc, allocator: *std.mem.Allocator, comptime text: string, args: anytype) !void { log.errors += 1; try log.addMsg(Msg{ .kind = .err, @@ -273,7 +273,7 @@ pub const Log = struct { }); } - pub fn addRangeWarning(log: *Log, source: ?*Source, r: Range, text: string) !void { + pub fn addRangeWarning(log: *Log, source: ?*const Source, r: Range, text: string) !void { log.warnings += 1; try log.addMsg(Msg{ .kind = .warn, @@ -281,7 +281,7 @@ pub const Log = struct { }); } - pub fn addWarningFmt(log: *Log, source: ?*Source, l: Loc, allocator: *std.mem.Allocator, comptime text: string, args: anytype) !void { + pub fn addWarningFmt(log: *Log, source: ?*const Source, l: Loc, allocator: *std.mem.Allocator, comptime text: string, args: anytype) !void { log.warnings += 1; try log.addMsg(Msg{ .kind = .err, @@ -289,7 +289,7 @@ pub const Log = struct { }); } - pub fn addRangeWarningFmt(log: *Log, source: ?*Source, r: Range, allocator: *std.mem.Allocator, comptime text: string, args: anytype) !void { + pub fn addRangeWarningFmt(log: *Log, source: ?*const Source, r: Range, allocator: *std.mem.Allocator, comptime text: string, args: anytype) !void { log.warnings += 1; try log.addMsg(Msg{ .kind = .warn, @@ -297,7 +297,7 @@ pub const Log = struct { }); } - pub fn addWarning(log: *Log, source: ?*Source, l: Loc, text: string) !void { + pub fn addWarning(log: *Log, source: ?*const Source, l: Loc, text: string) !void { log.warnings += 1; try log.addMsg(Msg{ .kind = .warn, @@ -305,14 +305,14 @@ pub const Log = struct { }); } - pub fn addRangeDebug(log: *Log, source: ?*Source, r: Range, text: string) !void { + pub fn addRangeDebug(log: *Log, source: ?*const Source, r: Range, text: string) !void { try log.addMsg(Msg{ .kind = .debug, .data = rangeData(source, r, text), }); } - pub fn addRangeDebugWithNotes(log: *Log, source: ?*Source, r: Range, text: string, notes: []Data) !void { + pub fn addRangeDebugWithNotes(log: *Log, source: ?*const Source, r: Range, text: string, notes: []Data) !void { // log.de += 1; try log.addMsg(Msg{ .kind = Kind.debug, @@ -321,7 +321,7 @@ pub const Log = struct { }); } - pub fn addRangeErrorWithNotes(log: *Log, source: ?*Source, r: Range, text: string, notes: []Data) !void { + pub fn addRangeErrorWithNotes(log: *Log, source: ?*const Source, r: Range, text: string, notes: []Data) !void { log.errors += 1; try log.addMsg(Msg{ .kind = Kind.err, @@ -330,7 +330,7 @@ pub const Log = struct { }); } - pub fn addRangeWarningWithNotes(log: *Log, source: ?*Source, r: Range, text: string, notes: []Data) !void { + pub fn addRangeWarningWithNotes(log: *Log, source: ?*const Source, r: Range, text: string, notes: []Data) !void { log.warnings += 1; try log.addMsg(Msg{ .kind = .warning, @@ -345,7 +345,7 @@ pub const Log = struct { } // TODO: - pub fn addError(self: *Log, _source: ?*Source, loc: Loc, text: string) !void { + pub fn addError(self: *Log, _source: ?*const Source, loc: Loc, text: string) !void { self.errors += 1; try self.addMsg(Msg{ .kind = .err, .data = rangeData(_source, Range{ .loc = loc }, text) }); } @@ -400,14 +400,14 @@ pub const Source = struct { pub fn initPathString(pathString: string, contents: string) Source { var path = fs.Path.init(pathString); - return Source{ .path = path, .identifier_name = path.name.base, .contents = contents }; + return Source{ .key_path = path, .path = path, .identifier_name = path.name.base, .contents = contents }; } - pub fn textForRange(self: *Source, r: Range) string { + pub fn textForRange(self: *const Source, r: Range) string { return self.contents[r.loc.i()..r.endI()]; } - pub fn rangeOfOperatorBefore(self: *Source, loc: Loc, op: string) Range { + pub fn rangeOfOperatorBefore(self: *const Source, loc: Loc, op: string) Range { const text = self.contents[0..loc.i()]; const index = strings.index(text, op); if (index >= 0) { @@ -419,7 +419,7 @@ pub const Source = struct { return Range{ .loc = loc }; } - pub fn rangeOfString(self: *Source, loc: Loc) Range { + pub fn rangeOfString(self: *const Source, loc: Loc) Range { const text = self.contents[loc.i()..]; if (text.len == 0) { @@ -446,7 +446,7 @@ pub const Source = struct { return Range{ .loc = loc, .len = 0 }; } - pub fn rangeOfOperatorAfter(self: *Source, loc: Loc, op: string) Range { + pub fn rangeOfOperatorAfter(self: *const Source, loc: Loc, op: string) Range { const text = self.contents[loc.i()..]; const index = strings.index(text, op); if (index >= 0) { diff --git a/src/options.zig b/src/options.zig index 29be30cca..b994dbe4b 100644 --- a/src/options.zig +++ b/src/options.zig @@ -180,8 +180,8 @@ pub const defaultLoaders = std.ComptimeStringMap(Loader, .{ pub const JSX = struct { pub const Pragma = struct { // these need to be arrays - factory: string = "React.createElement", - fragment: string = "React.Fragment", + factory: []string = &(Defaults.Factory), + fragment: []string = &(Defaults.Fragment), runtime: JSX.Runtime = JSX.Runtime.automatic, /// Facilitates automatic JSX importing @@ -192,6 +192,10 @@ pub const JSX = struct { development: bool = true, parse: bool = true, + pub const Defaults = struct { + pub var Factory = [_]string{ "React", "createElement" }; + pub var Fragment = [_]string{ "React", "Fragment" }; + }; pub fn fromApi(jsx: api.Api.Jsx) Pragma { var pragma = JSX.Pragma{}; diff --git a/src/resolver/package_json.zig b/src/resolver/package_json.zig index 3bab16ef2..68d6bacb1 100644 --- a/src/resolver/package_json.zig +++ b/src/resolver/package_json.zig @@ -44,28 +44,23 @@ pub const PackageJSON = struct { // browser_map: BrowserMap, - pub fn parse(r: *resolver.Resolver, input_path: string) ?*PackageJSON { - if (!has_set_default_main_fields) { - has_set_default_main_fields = true; - } - + pub fn parse(r: *resolver.Resolver, input_path: string) ?PackageJSON { const parts = [_]string{ input_path, "package.json" }; const package_json_path = std.fs.path.join(r.allocator, &parts) catch unreachable; errdefer r.allocator.free(package_json_path); - const entry: *r.caches.fs.Entry = try r.caches.fs.readFile(r.fs, input_path) catch |err| { - r.log.addErrorFmt(null, .empty, r.allocator, "Cannot read file \"{s}\": {s}", .{ r.prettyPath(fs.Path.init(input_path)), @errorName(err) }) catch unreachable; + const entry = r.caches.fs.readFile(r.fs, input_path) catch |err| { + r.log.addErrorFmt(null, logger.Loc.Empty, r.allocator, "Cannot read file \"{s}\": {s}", .{ r.prettyPath(fs.Path.init(input_path)), @errorName(err) }) catch unreachable; return null; }; - if (r.debug_logs) |debug| { + if (r.debug_logs) |*debug| { debug.addNoteFmt("The file \"{s}\" exists", .{package_json_path}) catch unreachable; } - const key_path = fs.Path.init(allocator.dupe(package_json_path) catch unreachable); + const key_path = fs.Path.init(r.allocator.dupe(u8, package_json_path) catch unreachable); - var json_source = logger.Source.initPathString(key_path); - json_source.contents = entry.contents; + var json_source = logger.Source.initPathString(key_path.text, entry.contents); json_source.path.pretty = r.prettyPath(json_source.path); const json: js_ast.Expr = (r.caches.json.parseJSON(r.log, json_source, r.allocator) catch |err| { @@ -77,8 +72,9 @@ pub const PackageJSON = struct { var package_json = PackageJSON{ .source = json_source, + .module_type = .unknown, .browser_map = BrowserMap.init(r.allocator), - .main_fields_map = MainFieldMap.init(r.allocator), + .main_fields = MainFieldMap.init(r.allocator), }; if (json.getProperty("type")) |type_json| { @@ -110,7 +106,7 @@ pub const PackageJSON = struct { if (json.getProperty(main)) |main_json| { const expr: js_ast.Expr = main_json.expr; - if ((main_json.getString(r.allocator) catch null)) |str| { + if ((expr.getString(r.allocator))) |str| { if (str.len > 0) { package_json.main_fields.put(main, str) catch unreachable; } @@ -132,13 +128,13 @@ pub const PackageJSON = struct { // }, // if (json.getProperty("browser")) |browser_prop| { - switch (browser_prop.data) { + switch (browser_prop.expr.data) { .e_object => |obj| { // The value is an object // Remap all files in the browser field for (obj.properties) |prop| { - var _key_str = (prop.key orelse continue).getString(r.allocator) catch unreachable; + var _key_str = (prop.key orelse continue).getString(r.allocator) orelse continue; const value: js_ast.Expr = prop.value orelse continue; // Normalize the path so we can compare against it without getting @@ -155,7 +151,7 @@ pub const PackageJSON = struct { switch (value.data) { .e_string => |str| { // If this is a string, it's a replacement package - package_json.browser_map.put(key, str) catch unreachable; + package_json.browser_map.put(key, str.string(r.allocator) catch unreachable) catch unreachable; }, .e_boolean => |boolean| { if (!boolean.value) { @@ -163,7 +159,7 @@ pub const PackageJSON = struct { } }, else => { - r.log.addWarning("Each \"browser\" mapping must be a string or boolean", value.loc) catch unreachable; + r.log.addWarning(&json_source, value.loc, "Each \"browser\" mapping must be a string or boolean") catch unreachable; }, } } diff --git a/src/resolver/resolve_path.zig b/src/resolver/resolve_path.zig index 78f00cf96..f639bff1b 100644 --- a/src/resolver/resolve_path.zig +++ b/src/resolver/resolve_path.zig @@ -25,7 +25,7 @@ pub fn resolvePath(buffer: []u8, src_path: []const u8) ?[]u8 { } } else { if (end + segment.len + 1 > buffer.len) - return error.BufferTooSmall; + return null; const start = end; buffer[end] = '/'; diff --git a/src/resolver/resolver.zig b/src/resolver/resolver.zig index 340648399..88bc13cd5 100644 --- a/src/resolver/resolver.zig +++ b/src/resolver/resolver.zig @@ -34,7 +34,7 @@ pub const DirInfo = struct { entries: fs.FileSystem.DirEntry, has_node_modules: bool = false, // Is there a "node_modules" subdirectory? package_json: ?*PackageJSON = null, // Is there a "package.json" file? - ts_config_json: ?*TSConfigJSON = null, // Is there a "tsconfig.json" file in this directory or a parent directory? + tsconfig_json: ?*TSConfigJSON = null, // Is there a "tsconfig.json" file in this directory or a parent directory? abs_real_path: string = "", // If non-empty, this is the real absolute path resolving any symlinks }; @@ -331,7 +331,7 @@ pub const Resolver = struct { // First, check path overrides from the nearest enclosing TypeScript "tsconfig.json" file if ((r.dirInfoCached(source_dir) catch null)) |_dir_info| { const dir_info: *DirInfo = _dir_info; - if (dir_info.ts_config_json) |tsconfig| { + if (dir_info.tsconfig_json) |tsconfig| { if (tsconfig.paths.count() > 0) { const res = r.matchTSConfigPaths(tsconfig, import_path, kind); return Result{ .path_pair = res.path_pair, .diff_case = res.diff_case }; @@ -384,27 +384,23 @@ pub const Resolver = struct { const entry = try r.caches.fs.readFile(r.fs, file); const key_path = Path.init(file); - const source = logger.Source{ - .key_path = key_path, - .pretty_path = r.prettyPath(key_path), - .contents = entry.contents, - }; - const file_dir = std.fs.path.dirname(file); + const source = logger.Source.initPathString(key_path.text, entry.contents); + const file_dir = std.fs.path.dirname(file) orelse return null; - var result = try TSConfigJSON.parse(r.allocator, r.log, r.opts, r.caches.json) orelse return null; + var result = (try TSConfigJSON.parse(r.allocator, r.log, source, &r.caches.json)) orelse return null; if (result.base_url) |base| { // this might leak if (!std.fs.path.isAbsolute(base)) { - var paths = [_]string{ file_dir, base }; - result.base_url = std.fs.path.join(r.allocator, paths) catch unreachable; + const paths = [_]string{ file_dir, base }; + result.base_url = std.fs.path.join(r.allocator, &paths) catch unreachable; } } if (result.paths.count() > 0 and (result.base_url_for_paths.len == 0 or !std.fs.path.isAbsolute(result.base_url_for_paths))) { // this might leak - var paths = [_]string{ file_dir, base }; - result.base_url_for_paths = std.fs.path.join(r.allocator, paths) catch unreachable; + const paths = [_]string{ file_dir, result.base_url.? }; + result.base_url_for_paths = std.fs.path.join(r.allocator, &paths) catch unreachable; } return result; @@ -416,7 +412,10 @@ pub const Resolver = struct { } pub fn parsePackageJSON(r: *Resolver, file: string) !?*PackageJSON { - return try PackageJSON.parse(r, file); + const pkg = PackageJSON.parse(r, file) orelse return null; + var _pkg = try r.allocator.create(PackageJSON); + _pkg.* = pkg; + return _pkg; } pub fn isPackagePath(path: string) bool { @@ -504,7 +503,7 @@ pub const Resolver = struct { if (!strings.eqlComptime(base, "node_modules")) { if (entries.get("node_modules")) |entry| { // the catch might be wrong! - info.has_node_modules = (entry.entry.kind(rfs) catch .file) == .dir; + info.has_node_modules = (entry.entry.kind(rfs)) == .dir; } } @@ -514,19 +513,21 @@ pub const Resolver = struct { // Make sure "absRealPath" is the real path of the directory (resolving any symlinks) if (!r.opts.preserve_symlinks) { - if (parent_info.entries.get(base)) |entry| { + if (parent_info.entries.get(base)) |lookup| { + const entry = lookup.entry; + var symlink = entry.symlink(rfs); if (symlink.len > 0) { - if (r.debug_logs) |logs| { - try logs.addNote(std.fmt.allocPrint(r.allocator, "Resolved symlink \"{s}\" to \"{s}\"", .{ path, symlink })); + if (r.debug_logs) |*logs| { + try logs.addNote(std.fmt.allocPrint(r.allocator, "Resolved symlink \"{s}\" to \"{s}\"", .{ path, symlink }) catch unreachable); } info.abs_real_path = symlink; } else if (parent_info.abs_real_path.len > 0) { // this might leak a little i'm not sure const parts = [_]string{ parent_info.abs_real_path, base }; - symlink = std.fs.path.join(r.allocator, &parts); - if (r.debug_logs) |logs| { - try logs.addNote(std.fmt.allocPrint(r.allocator, "Resolved symlink \"{s}\" to \"{s}\"", .{ path, symlink })); + symlink = std.fs.path.join(r.allocator, &parts) catch unreachable; + if (r.debug_logs) |*logs| { + try logs.addNote(std.fmt.allocPrint(r.allocator, "Resolved symlink \"{s}\" to \"{s}\"", .{ path, symlink }) catch unreachable); } info.abs_real_path = symlink; } @@ -535,19 +536,20 @@ pub const Resolver = struct { } // Record if this directory has a package.json file - if (entries.get("package.json")) |entry| { + if (entries.get("package.json")) |lookup| { + const entry = lookup.entry; if (entry.kind(rfs) == .file) { - info.package_json = r.parsePackageJSON(path); + info.package_json = r.parsePackageJSON(path) catch null; if (info.package_json) |pkg| { - if (pkg.browser_map != null) { + if (pkg.browser_map.count() > 0) { info.enclosing_browser_scope = info; } - if (r.debug_logs) |logs| { - try logs.addNote(std.fmt.allocPrint(r.allocator, "Resolved package.json in \"{s}\"", .{ + if (r.debug_logs) |*logs| { + logs.addNoteFmt("Resolved package.json in \"{s}\"", .{ path, - })); + }) catch unreachable; } } } @@ -557,14 +559,20 @@ pub const Resolver = struct { { var tsconfig_path: ?string = null; if (r.opts.tsconfig_override == null) { - var entry = entries.get("tsconfig.json"); - if (entry.kind(rfs) == .file) { - const parts = [_]string{ path, "tsconfig.json" }; - tsconfig_path = try std.fs.path.join(r.allocator, parts); - } else if (entries.get("jsconfig.json")) |jsconfig| { - if (jsconfig.kind(rfs) == .file) { - const parts = [_]string{ path, "jsconfig.json" }; - tsconfig_path = try std.fs.path.join(r.allocator, parts); + if (entries.get("tsconfig.json")) |lookup| { + const entry = lookup.entry; + if (entry.kind(rfs) == .file) { + const parts = [_]string{ path, "tsconfig.json" }; + tsconfig_path = try std.fs.path.join(r.allocator, &parts); + } + } + if (tsconfig_path == null) { + if (entries.get("jsconfig.json")) |lookup| { + const entry = lookup.entry; + if (entry.kind(rfs) == .file) { + const parts = [_]string{ path, "jsconfig.json" }; + tsconfig_path = try std.fs.path.join(r.allocator, &parts); + } } } } else if (parent == null) { @@ -574,20 +582,21 @@ pub const Resolver = struct { if (tsconfig_path) |tsconfigpath| { var visited = std.StringHashMap(bool).init(r.allocator); defer visited.deinit(); - info.ts_config_json = r.parseTSConfig(tsconfigpath, visited) catch |err| { + info.tsconfig_json = r.parseTSConfig(tsconfigpath, &visited) catch |err| brk: { const pretty = r.prettyPath(Path.init(tsconfigpath)); if (err == error.ENOENT) { - r.log.addErrorFmt(null, logger.Loc.Empty, r.allocator, "Cannot find tsconfig file \"{s}\"", .{pretty}); + r.log.addErrorFmt(null, logger.Loc.Empty, r.allocator, "Cannot find tsconfig file \"{s}\"", .{pretty}) catch unreachable; } else if (err != error.ParseErrorAlreadyLogged) { - r.log.addErrorFmt(null, logger.Loc.Empty, r.allocator, "Cannot read file \"{s}\": {s}", .{ pretty, @errorName(err) }); + r.log.addErrorFmt(null, logger.Loc.Empty, r.allocator, "Cannot read file \"{s}\": {s}", .{ pretty, @errorName(err) }) catch unreachable; } + break :brk null; }; } } - if (info.ts_config_json == null and parent != null) { - info.ts_config_json = parent.?.tsconfig_json; + if (info.tsconfig_json == null and parent != null) { + info.tsconfig_json = parent.?.tsconfig_json; } return info; diff --git a/src/resolver/tsconfig_json.zig b/src/resolver/tsconfig_json.zig index b4e027413..6c7992833 100644 --- a/src/resolver/tsconfig_json.zig +++ b/src/resolver/tsconfig_json.zig @@ -1,10 +1,10 @@ usingnamespace @import("../global.zig"); const std = @import("std"); const options = @import("../options.zig"); -const log = @import("../logger.zig"); -const cache = @import("../cache.zig"); const logger = @import("../logger.zig"); +const cache = @import("../cache.zig"); const js_ast = @import("../js_ast.zig"); +const js_lexer = @import("../js_lexer.zig"); const alloc = @import("../alloc.zig"); const PathsMap = std.StringHashMap([]string); @@ -53,7 +53,6 @@ pub const TSConfigJSON = struct { allocator: *std.mem.Allocator, log: *logger.Log, source: logger.Source, - opts: options.TransformOptions, json_cache: *cache.Cache.Json, ) anyerror!?*TSConfigJSON { // Unfortunately "tsconfig.json" isn't actually JSON. It's some other @@ -64,52 +63,52 @@ pub const TSConfigJSON = struct { // these particular files. This is likely not a completely accurate // emulation of what the TypeScript compiler does (e.g. string escape // behavior may also be different). - const json: js_ast.Expr = (json_cache.parseTSConfig(log, opts, source, allocator) catch null) orelse return null; + const json: js_ast.Expr = (json_cache.parseTSConfig(log, source, allocator) catch null) orelse return null; var result: TSConfigJSON = TSConfigJSON{ .abs_path = source.key_path.text, .paths = PathsMap.init(allocator) }; errdefer allocator.free(result.paths); - if (extends != null) { - if (json.getProperty("extends")) |extends_value| { - log.addWarning(&source, extends_value.loc, "\"extends\" is not implemented yet") catch unreachable; - // if ((extends_value.expr.getString(allocator) catch null)) |str| { - // if (extends(str, source.rangeOfString(extends_value.loc))) |base| { - // result.jsx = base.jsx; - // result.base_url_for_paths = base.base_url_for_paths; - // result.use_define_for_class_fields = base.use_define_for_class_fields; - // result.preserve_imports_not_used_as_values = base.preserve_imports_not_used_as_values; - // // https://github.com/microsoft/TypeScript/issues/14527#issuecomment-284948808 - // result.paths = base.paths; - // } - // } - } + if (json.getProperty("extends")) |extends_value| { + log.addWarning(&source, extends_value.loc, "\"extends\" is not implemented yet") catch unreachable; + // if ((extends_value.expr.getString(allocator) catch null)) |str| { + // if (extends(str, source.rangeOfString(extends_value.loc))) |base| { + // result.jsx = base.jsx; + // result.base_url_for_paths = base.base_url_for_paths; + // result.use_define_for_class_fields = base.use_define_for_class_fields; + // result.preserve_imports_not_used_as_values = base.preserve_imports_not_used_as_values; + // // https://github.com/microsoft/TypeScript/issues/14527#issuecomment-284948808 + // result.paths = base.paths; + // } + // } } // Parse "compilerOptions" if (json.getProperty("compilerOptions")) |compiler_opts| { + var has_base_url = false; // Parse "baseUrl" if (compiler_opts.expr.getProperty("baseUrl")) |base_url_prop| { // maybe we should add a warning when it exists but the value is an array or osmething invalid? - if ((base_url_prop.expr.getString(allocator) catch null)) |base_url| { + if ((base_url_prop.expr.getString(allocator))) |base_url| { result.base_url = base_url; + has_base_url = true; } } // Parse "jsxFactory" if (compiler_opts.expr.getProperty("jsxFactory")) |jsx_prop| { if (jsx_prop.expr.getString(allocator)) |str| { - result.jsx.factory = try parseMemberExpressionForJSX(log, source, jsx_prop.loc, str, allocator); + result.jsx.factory = try parseMemberExpressionForJSX(log, &source, jsx_prop.loc, str, allocator); } } // Parse "jsxFragmentFactory" if (compiler_opts.expr.getProperty("jsxFactory")) |jsx_prop| { if (jsx_prop.expr.getString(allocator)) |str| { - result.jsx.fragment = try parseMemberExpressionForJSX(log, source, jsx_prop.loc, str, allocator); + result.jsx.fragment = try parseMemberExpressionForJSX(log, &source, jsx_prop.loc, str, allocator); } } // Parse "jsxImportSource" - if (compiler_opts.expr.getProperty("jsxImportSource")) |jsx_factory_prop| { + if (compiler_opts.expr.getProperty("jsxImportSource")) |jsx_prop| { if (jsx_prop.expr.getString(allocator)) |str| { result.jsx.import_source = str; } @@ -123,16 +122,16 @@ pub const TSConfigJSON = struct { } // Parse "importsNotUsedAsValues" - if (compiler_opts.expr.getProperty("importsNotUsedAsValues")) |imports_not_used_as_values_prop| { + if (compiler_opts.expr.getProperty("importsNotUsedAsValues")) |jsx_prop| { // This should never allocate since it will be utf8 - if ((jsx_prop.expr.getString(allocator) catch null)) |str| { + if ((jsx_prop.expr.getString(allocator))) |str| { switch (ImportsNotUsedAsValue.List.get(str) orelse ImportsNotUsedAsValue.invalid) { .preserve, .err => { result.preserve_imports_not_used_as_values = true; }, .remove => {}, else => { - log.addRangeWarningFmt(source, source.rangeOfString(imports_not_used_as_values_prop.loc), allocator, "Invalid value \"{s}\" for \"importsNotUsedAsValues\"", .{str}) catch {}; + log.addRangeWarningFmt(&source, source.rangeOfString(jsx_prop.loc), allocator, "Invalid value \"{s}\" for \"importsNotUsedAsValues\"", .{str}) catch {}; }, } } @@ -146,9 +145,9 @@ pub const TSConfigJSON = struct { result.paths = PathsMap.init(allocator); for (paths.properties) |property| { const key_prop = property.key orelse continue; - const key = (key_prop.getString(allocator) catch null) orelse continue; + const key = (key_prop.getString(allocator)) orelse continue; - if (!TSConfigJSON.isValidTSConfigPathNoBaseURLPattern(key, log, source, key_prop.loc)) { + if (!TSConfigJSON.isValidTSConfigPathNoBaseURLPattern(key, log, &source, allocator, key_prop.loc)) { continue; } @@ -178,20 +177,27 @@ pub const TSConfigJSON = struct { switch (value_prop.data) { .e_array => |array| { if (array.items.len > 0) { - var paths = allocator.alloc(string, array.items.len) catch unreachable; - errdefer allocator.free(paths); + var values = allocator.alloc(string, array.items.len) catch unreachable; + errdefer allocator.free(values); var count: usize = 0; for (array.items) |expr| { - if ((expr.getString(allocator) catch null)) |str| { - if (TSConfigJSON.isValidTSConfigPathPattern(str, log, source, loc, allocator) and + if ((expr.getString(allocator))) |str| { + if (TSConfigJSON.isValidTSConfigPathPattern( + str, + log, + &source, + expr.loc, + allocator, + ) and (has_base_url or TSConfigJSON.isValidTSConfigPathNoBaseURLPattern( str, log, - source, - loc, + &source, + allocator, + expr.loc, ))) { - paths[count] = str; + values[count] = str; count += 1; } } @@ -199,15 +205,15 @@ pub const TSConfigJSON = struct { if (count > 0) { result.paths.put( key, - paths[0..count], + values[0..count], ) catch unreachable; } } }, else => { log.addRangeWarningFmt( - source, - log, + &source, + source.rangeOfString(key_prop.loc), allocator, "Substitutions for pattern \"{s}\" should be an array", .{key}, @@ -226,7 +232,7 @@ pub const TSConfigJSON = struct { return _result; } - pub fn isValidTSConfigPathPattern(text: string, log: *logger.Log, source: *logger.Source, loc: logger.Loc, allocator: *std.mem.Allocator) bool { + pub fn isValidTSConfigPathPattern(text: string, log: *logger.Log, source: *const logger.Source, loc: logger.Loc, allocator: *std.mem.Allocator) bool { var found_asterisk = false; for (text) |c, i| { if (c == '*') { @@ -242,7 +248,7 @@ pub const TSConfigJSON = struct { return true; } - pub fn parseMemberExpressionForJSX(log: *logger.Log, source: *logger.Source, loc: logger.Loc, text: string, allocator: *std.mem.Allocator) ![]string { + pub fn parseMemberExpressionForJSX(log: *logger.Log, source: *const logger.Source, loc: logger.Loc, text: string, allocator: *std.mem.Allocator) ![]string { if (text.len == 0) { return &([_]string{}); } @@ -267,7 +273,7 @@ pub const TSConfigJSON = struct { return c == '/' or c == '\\'; } - pub fn isValidTSConfigPathNoBaseURLPattern(text: string, log: logger.Log, source: *logger.Source, loc: logger.Loc) bool { + pub fn isValidTSConfigPathNoBaseURLPattern(text: string, log: *logger.Log, source: *const logger.Source, allocator: *std.mem.Allocator, loc: logger.Loc) bool { var c0: u8 = 0; var c1: u8 = 0; var c2: u8 = 0; |