aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2021-08-11 21:46:23 -0700
committerGravatar Jarred Sumner <jarred@jarredsumner.com> 2021-08-11 21:46:23 -0700
commit160f83cf9e73cbc4c342238c1ca45884a9316ef8 (patch)
tree3cc1e0988ac0941b53fab9b4d10887edf99f4139
parent3e0a78bc0d94989a46314b09109d2a8eedf1e032 (diff)
downloadbun-160f83cf9e73cbc4c342238c1ca45884a9316ef8.tar.gz
bun-160f83cf9e73cbc4c342238c1ca45884a9316ef8.tar.zst
bun-160f83cf9e73cbc4c342238c1ca45884a9316ef8.zip
When there are errors while generating the .jsb, fail the build.
Former-commit-id: 734f021602ac59aeaef9d7583a927ede94ab644a
-rw-r--r--src/bundler.zig112
-rw-r--r--src/cli.zig52
-rw-r--r--src/fs.zig22
-rw-r--r--src/js_parser/js_parser.zig11
4 files changed, 163 insertions, 34 deletions
diff --git a/src/bundler.zig b/src/bundler.zig
index e500360de..f7167d170 100644
--- a/src/bundler.zig
+++ b/src/bundler.zig
@@ -31,7 +31,7 @@ const PackageJSON = @import("./resolver/package_json.zig").PackageJSON;
const DebugLogs = _resolver.DebugLogs;
const NodeModuleBundle = @import("./node_module_bundle.zig").NodeModuleBundle;
const Router = @import("./router.zig");
-
+const isPackagePath = _resolver.isPackagePath;
const Css = @import("css_scanner.zig");
pub const ServeResult = struct {
@@ -510,7 +510,7 @@ pub fn NewBundler(cache_files: bool) type {
framework_config: ?Api.LoadedFramework,
route_config: ?Api.LoadedRouteConfig,
destination: [*:0]const u8,
- ) !Api.JavascriptBundleContainer {
+ ) !?Api.JavascriptBundleContainer {
var tmpdir: std.fs.Dir = try bundler.fs.fs.openTmpDir();
var tmpname_buf: [64]u8 = undefined;
bundler.resetStore();
@@ -620,6 +620,12 @@ pub fn NewBundler(cache_files: bool) type {
} else |err| {}
}
+ if (this.log.errors > 0) {
+ // We stop here because if there are errors we don't know if the bundle is valid
+ // This manifests as a crash when sorting through the module list because we may have added files to the bundle which were never actually finished being added.
+ return null;
+ }
+
// Ensure we never overflow
this.code_end_byte_offset = @truncate(
u32,
@@ -901,11 +907,64 @@ pub fn NewBundler(cache_files: bool) type {
file_path.text,
});
}
+
+ switch (err) {
+ error.ModuleNotFound => {
+ if (isPackagePath(import_record.path.text)) {
+ if (this.bundler.options.platform.isWebLike() and options.ExternalModules.isNodeBuiltin(import_record.path.text)) {
+ try this.log.addResolveError(
+ &source,
+ import_record.range,
+ this.allocator,
+ "Could not resolve Node.js builtin: \"{s}\".",
+ .{import_record.path.text},
+ import_record.kind,
+ );
+ } else {
+ try this.log.addResolveError(
+ &source,
+ import_record.range,
+ this.allocator,
+ "Could not resolve: \"{s}\". Maybe you need to \"npm install\" (or yarn/pnpm)?",
+ .{import_record.path.text},
+ import_record.kind,
+ );
+ }
+ } else {
+ try this.log.addResolveError(
+ &source,
+ import_record.range,
+ this.allocator,
+ "Could not resolve: \"{s}\"",
+ .{
+ import_record.path.text,
+ },
+ import_record.kind,
+ );
+ }
+ },
+ // assume other errors are already in the log
+ else => {},
+ }
}
}
const package = resolve.package_json orelse this.bundler.resolver.packageJSONForResolvedNodeModule(&resolve) orelse unreachable;
- var package_relative_path = file_path.packageRelativePathString(package.name);
+ var package_relative_path_ = file_path.packageRelativePathString(package.name);
+ var package_relative_path = package_relative_path_.path;
+
+ {
+ // avoid recursion
+ // this would only come up if you had a package like this
+ // node_modules/next/next/next/next/next/next/next/next/next/next/next/dist/compiled/foo/index.js
+ // ^ package.json in the dir
+ // 24 is arbitrary, but it sounds too high to be realistic
+ var i: u8 = 0;
+ while (package_relative_path_.is_parent_package and i < 24) : (i += 1) {
+ package_relative_path_ = file_path.packageRelativePathString(package_relative_path_.name);
+ package_relative_path = package_relative_path_.path;
+ }
+ }
// const load_from_symbol_ref = ast.runtime_imports.$$r.?;
// const reexport_ref = ast.runtime_imports.__reExport.?;
@@ -1023,6 +1082,12 @@ pub fn NewBundler(cache_files: bool) type {
const code_length = this.tmpfile_byte_offset - code_offset;
// std.debug.assert(code_length == written);
var package_get_or_put_entry = try this.package_list_map.getOrPut(package.hash);
+
+ if (comptime isDebug) {
+ Output.prettyln("{s}/{s} \n", .{ package.name, package_relative_path });
+ Output.flush();
+ }
+
if (!package_get_or_put_entry.found_existing) {
package_get_or_put_entry.value_ptr.* = @truncate(u32, this.package_list.items.len);
try this.package_list.append(
@@ -1132,7 +1197,46 @@ pub fn NewBundler(cache_files: bool) type {
hasher.update(import_record.path.text);
hasher.update(std.mem.asBytes(&package_json.hash));
get_or_put_result.value_ptr.* = @truncate(u32, hasher.final());
- } else |err| {}
+ } else |err| {
+ switch (err) {
+ error.ModuleNotFound => {
+ if (isPackagePath(import_record.path.text)) {
+ if (this.bundler.options.platform.isWebLike() and options.ExternalModules.isNodeBuiltin(import_record.path.text)) {
+ try this.log.addResolveError(
+ &source,
+ import_record.range,
+ this.allocator,
+ "Could not resolve Node.js builtin: \"{s}\".",
+ .{import_record.path.text},
+ import_record.kind,
+ );
+ } else {
+ try this.log.addResolveError(
+ &source,
+ import_record.range,
+ this.allocator,
+ "Could not resolve: \"{s}\". Maybe you need to \"npm install\" (or yarn/pnpm)?",
+ .{import_record.path.text},
+ import_record.kind,
+ );
+ }
+ } else {
+ try this.log.addResolveError(
+ &source,
+ import_record.range,
+ this.allocator,
+ "Could not resolve: \"{s}\"",
+ .{
+ import_record.path.text,
+ },
+ import_record.kind,
+ );
+ }
+ },
+ // assume other errors are already in the log
+ else => {},
+ }
+ }
}
},
// TODO:
diff --git a/src/cli.zig b/src/cli.zig
index d1b26e2ba..8d6644930 100644
--- a/src/cli.zig
+++ b/src/cli.zig
@@ -460,11 +460,15 @@ pub const Cli = struct {
route_conf_: ?Api.LoadedRouteConfig,
router: ?Router,
) void {
- try alloc.setup(std.heap.c_allocator);
- var stdout_ = std.io.getStdOut();
- var stderr_ = std.io.getStdErr();
- var output_source = Output.Source.init(stdout_, stderr_);
- Output.Source.set(&output_source);
+ if (FeatureFlags.parallel_jsb) {
+ try alloc.setup(std.heap.c_allocator);
+ var stdout_ = std.io.getStdOut();
+ var stderr_ = std.io.getStdErr();
+ var output_source = Output.Source.init(stdout_, stderr_);
+ Output.Source.set(&output_source);
+
+ Output.enable_ansi_colors = stderr_.isTty();
+ }
defer Output.flush();
defer {
@@ -472,7 +476,7 @@ pub const Cli = struct {
wait_group.done();
}
}
- Output.enable_ansi_colors = stderr_.isTty();
+
_generate(logs, std.heap.c_allocator, transform_args, _filepath, server_conf, route_conf_, router) catch return;
}
};
@@ -513,34 +517,38 @@ pub const Cli = struct {
{
// Always generate the client-only bundle
// we can revisit this decision if people ask
- var node_modules = try bundler.ServeBundler.GenerateNodeModuleBundle.generate(
+ var node_modules_ = try bundler.ServeBundler.GenerateNodeModuleBundle.generate(
&this_bundler,
allocator,
loaded_framework,
loaded_route_config,
filepath,
);
+
if (server_bundler_generator_thread) |thread| {
wait_group.wait();
}
- var elapsed = @divTrunc(std.time.nanoTimestamp() - start_time, @as(i128, std.time.ns_per_ms));
- var bundle = NodeModuleBundle.init(node_modules, allocator);
-
- if (log_.errors > 0) {
- try log_.print(Output.errorWriter());
- } else {
- bundle.printSummary();
- const indent = comptime " ";
- Output.prettyln(indent ++ "<d>{d:6}ms elapsed", .{@intCast(u32, elapsed)});
-
- if (server_bundler_generator_thread != null) {
- Output.prettyln(indent ++ "<r>Saved to ./{s}, ./{s}", .{ filepath, server_bundle_filepath });
+ if (node_modules_) |node_modules| {
+ if (log_.errors > 0) {
+ try log_.print(Output.errorWriter());
} else {
- Output.prettyln(indent ++ "<r>Saved to ./{s}", .{filepath});
- }
+ var elapsed = @divTrunc(std.time.nanoTimestamp() - start_time, @as(i128, std.time.ns_per_ms));
+ var bundle = NodeModuleBundle.init(node_modules, allocator);
+ bundle.printSummary();
+ const indent = comptime " ";
+ Output.prettyln(indent ++ "<d>{d:6}ms elapsed", .{@intCast(u32, elapsed)});
+
+ if (server_bundler_generator_thread != null) {
+ Output.prettyln(indent ++ "<r>Saved to ./{s}, ./{s}", .{ filepath, server_bundle_filepath });
+ } else {
+ Output.prettyln(indent ++ "<r>Saved to ./{s}", .{filepath});
+ }
- try log_.printForLogLevel(Output.errorWriter());
+ try log_.printForLogLevel(Output.errorWriter());
+ }
+ } else {
+ try log_.print(Output.errorWriter());
}
}
return;
diff --git a/src/fs.zig b/src/fs.zig
index 4e043aaf8..19fdef3db 100644
--- a/src/fs.zig
+++ b/src/fs.zig
@@ -984,17 +984,31 @@ pub const Path = struct {
name: PathName,
is_disabled: bool = false,
+ const PackageRelative = struct {
+ path: string,
+ name: string,
+ is_parent_package: bool = false,
+ };
// "/foo/bar/node_modules/react/index.js" => "index.js"
// "/foo/bar/node_modules/.pnpm/react@17.0.1/node_modules/react/index.js" => "index.js"
- pub fn packageRelativePathString(this: *const Path, name: string) string {
+ // "/css-stress-test/node_modules/next/dist/compiled/neo-async/async.js" => "dist/compiled/neo-async/async.js "
+ pub fn packageRelativePathString(this: *const Path, name: string) PackageRelative {
// TODO: we don't need to print this buffer, this is inefficient
var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;
- const search_path = std.fmt.bufPrint(&buffer, std.fs.path.sep_str ++ "node_modules" ++ std.fs.path.sep_str ++ "{s}" ++ std.fs.path.sep_str, .{name}) catch return this.text;
+ const search_path = std.fmt.bufPrint(&buffer, std.fs.path.sep_str ++ "node_modules" ++ std.fs.path.sep_str ++ "{s}" ++ std.fs.path.sep_str, .{name}) catch return .{ .name = name, .path = this.text };
if (strings.lastIndexOf(this.canonicalNodeModuleText(), search_path)) |i| {
- return this.canonicalNodeModuleText()[i + search_path.len ..];
+ return .{ .path = this.canonicalNodeModuleText()[i + search_path.len ..], .name = name };
}
- return this.canonicalNodeModuleText();
+ if (strings.lastIndexOf(this.text, search_path[0.."/node_modules/".len])) |i| {
+ const node_modules_relative = this.text[i + "/node_modules/".len ..];
+
+ if (strings.indexOfChar(node_modules_relative, std.fs.path.sep)) |j| {
+ return .{ .path = node_modules_relative[j + 1 ..], .name = node_modules_relative[0..j], .is_parent_package = true };
+ }
+ }
+
+ return .{ .path = this.text, .name = name };
}
pub fn nodeModulesRelativePathString(
diff --git a/src/js_parser/js_parser.zig b/src/js_parser/js_parser.zig
index 9801e7e32..8b9649aa2 100644
--- a/src/js_parser/js_parser.zig
+++ b/src/js_parser/js_parser.zig
@@ -10315,11 +10315,14 @@ pub fn NewParser(
e_.must_keep_due_to_with_stmt = result.is_inside_with_scope;
e_.ref = result.ref;
+ // TODO: fix the underyling cause here
+ // The problem seems to be that result.ref.inner_index is not always set.
+
// Handle assigning to a constant
- if (in.assign_target != .none and p.symbols.items[result.ref.inner_index].kind == .cconst) {
- const r = js_lexer.rangeOfIdentifier(p.source, expr.loc);
- p.log.addRangeErrorFmt(p.source, r, p.allocator, "Cannot assign to {s} because it is a constant", .{name}) catch unreachable;
- }
+ // if (in.assign_target != .none and p.symbols.items[result.ref.inner_index].kind == .cconst) {
+ // const r = js_lexer.rangeOfIdentifier(p.source, expr.loc);
+ // p.log.addRangeErrorFmt(p.source, r, p.allocator, "Cannot assign to {s} because it is a constant", .{name}) catch unreachable;
+ // }
var original_name: ?string = null;