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

fix(Bun.build): handle non-object plugins #14050

Merged
merged 3 commits into from
Sep 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 2 additions & 1 deletion src/bun.js/api/BunObject.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1178,7 +1178,8 @@ fn doResolveWithArgs(
errorable.result.value,
query_string,
}) catch {
JSC.JSError(allocator, "Failed to allocate memory", .{}, ctx, exception);
dylan-conway marked this conversation as resolved.
Show resolved Hide resolved
// TODO: binding for createOutOfMemoryError
exception.* = JSC.createError(ctx, "Out of memory", .{}).asObjectRef();
return null;
};

Expand Down
100 changes: 62 additions & 38 deletions src/bun.js/api/JSBundler.zig
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@ const Fs = @import("../../fs.zig");
const Base = @import("../base.zig");
const getAllocator = Base.getAllocator;
const JSObject = JSC.JSObject;
const JSError = Base.JSError;
const JSValue = bun.JSC.JSValue;
const JSGlobalObject = JSC.JSGlobalObject;
const strings = bun.strings;
const JSError = bun.JSError;
const OOM = bun.OOM;

const To = Base.To;
const Request = WebCore.Request;
Expand Down Expand Up @@ -72,7 +73,9 @@ pub const JSBundler = struct {

pub const List = bun.StringArrayHashMapUnmanaged(Config);

pub fn fromJS(globalThis: *JSC.JSGlobalObject, config: JSC.JSValue, plugins: *?*Plugin, allocator: std.mem.Allocator) !Config {
const FromJSError = OOM || JSError;

pub fn fromJS(globalThis: *JSC.JSGlobalObject, config: JSC.JSValue, plugins: *?*Plugin, allocator: std.mem.Allocator) FromJSError!Config {
var this = Config{
.entry_points = bun.StringSet.init(allocator),
.external = bun.StringSet.init(allocator),
Expand All @@ -93,6 +96,10 @@ pub const JSBundler = struct {
if (try config.getArray(globalThis, "plugins")) |array| {
var iter = array.arrayIterator(globalThis);
while (iter.next()) |plugin| {
if (!plugin.isObject()) {
globalThis.throwInvalidArguments("Expected plugin to be an object", .{});
return error.JSError;
}
if (try plugin.getObject(globalThis, "SECRET_SERVER_COMPONENTS_INTERNALS")) |internals| {
if (internals.get(globalThis, "router")) |router_value| {
if (router_value.as(JSC.API.FileSystemRouter) != null) {
Expand All @@ -113,29 +120,29 @@ pub const JSBundler = struct {
while (array_iter.next()) |client_name| {
var slice = client_name.toSliceOrNull(globalThis) orelse {
globalThis.throwInvalidArguments("Expected directive.client to be an array of strings", .{});
return error.JSException;
return error.JSError;
};
defer slice.deinit();
try this.server_components.client.append(allocator, OwnedString.initCopy(allocator, slice.slice()) catch unreachable);
try this.server_components.client.append(allocator, try OwnedString.initCopy(allocator, slice.slice()));
}
} else {
globalThis.throwInvalidArguments("Expected directive.client to be an array of strings", .{});
return error.JSException;
return error.JSError;
}

if (try directive_object.getArray(globalThis, "server")) |server_names_array| {
var array_iter = server_names_array.arrayIterator(globalThis);
while (array_iter.next()) |server_name| {
var slice = server_name.toSliceOrNull(globalThis) orelse {
globalThis.throwInvalidArguments("Expected directive.server to be an array of strings", .{});
return error.JSException;
return error.JSError;
};
defer slice.deinit();
try this.server_components.server.append(allocator, OwnedString.initCopy(allocator, slice.slice()) catch unreachable);
try this.server_components.server.append(allocator, try OwnedString.initCopy(allocator, slice.slice()));
}
} else {
globalThis.throwInvalidArguments("Expected directive.server to be an array of strings", .{});
return error.JSException;
return error.JSError;
}

continue;
Expand Down Expand Up @@ -204,7 +211,7 @@ pub const JSBundler = struct {
var has_out_dir = false;
if (try config.getOptional(globalThis, "outdir", ZigString.Slice)) |slice| {
defer slice.deinit();
this.outdir.appendSliceExact(slice.slice()) catch unreachable;
try this.outdir.appendSliceExact(slice.slice());
has_out_dir = true;
}

Expand Down Expand Up @@ -234,7 +241,7 @@ pub const JSBundler = struct {
.esm => {},
else => {
globalThis.throwInvalidArguments("Formats besides 'esm' are not implemented", .{});
return error.JSException;
return error.JSError;
},
}
}
Expand Down Expand Up @@ -265,7 +272,7 @@ pub const JSBundler = struct {
}
} else {
globalThis.throwInvalidArguments("Expected minify to be a boolean or an object", .{});
return error.JSException;
return error.JSError;
}
}

Expand All @@ -274,14 +281,14 @@ pub const JSBundler = struct {
while (iter.next()) |entry_point| {
var slice = entry_point.toSliceOrNull(globalThis) orelse {
globalThis.throwInvalidArguments("Expected entrypoints to be an array of strings", .{});
return error.JSException;
return error.JSError;
};
defer slice.deinit();
try this.entry_points.insert(slice.slice());
}
} else {
globalThis.throwInvalidArguments("Expected entrypoints to be an array of strings", .{});
return error.JSException;
return error.JSError;
}

if (config.getTruthy(globalThis, "emitDCEAnnotations")) |flag| {
Expand All @@ -300,7 +307,7 @@ pub const JSBundler = struct {
if (conditions_value.isString()) {
var slice = conditions_value.toSliceOrNull(globalThis) orelse {
globalThis.throwInvalidArguments("Expected conditions to be an array of strings", .{});
return error.JSException;
return error.JSError;
};
defer slice.deinit();
try this.conditions.insert(slice.slice());
Expand All @@ -309,14 +316,14 @@ pub const JSBundler = struct {
while (iter.next()) |entry_point| {
var slice = entry_point.toSliceOrNull(globalThis) orelse {
globalThis.throwInvalidArguments("Expected conditions to be an array of strings", .{});
return error.JSException;
return error.JSError;
};
defer slice.deinit();
try this.conditions.insert(slice.slice());
}
} else {
globalThis.throwInvalidArguments("Expected conditions to be an array of strings", .{});
return error.JSException;
return error.JSError;
}
}

Expand All @@ -339,20 +346,24 @@ pub const JSBundler = struct {

var dir = std.fs.cwd().openDir(path.slice(), .{}) catch |err| {
globalThis.throwPretty("{s}: failed to open root directory: {s}", .{ @errorName(err), path.slice() });
return error.JSException;
return error.JSError;
};
defer dir.close();

var rootdir_buf: bun.PathBuffer = undefined;
this.rootdir.appendSliceExact(try bun.getFdPath(bun.toFD(dir.fd), &rootdir_buf)) catch unreachable;
const rootdir = bun.getFdPath(bun.toFD(dir.fd), &rootdir_buf) catch |err| {
globalThis.throwPretty("{s}: failed to get full root directory path: {s}", .{ @errorName(err), path.slice() });
return error.JSError;
};
try this.rootdir.appendSliceExact(rootdir);
}

if (try config.getArray(globalThis, "external")) |externals| {
var iter = externals.arrayIterator(globalThis);
while (iter.next()) |entry_point| {
var slice = entry_point.toSliceOrNull(globalThis) orelse {
globalThis.throwInvalidArguments("Expected external to be an array of strings", .{});
return error.JSException;
return error.JSError;
};
defer slice.deinit();
try this.external.insert(slice.slice());
Expand All @@ -368,56 +379,56 @@ pub const JSBundler = struct {

if (try config.getOptional(globalThis, "publicPath", ZigString.Slice)) |slice| {
defer slice.deinit();
this.public_path.appendSliceExact(slice.slice()) catch unreachable;
try this.public_path.appendSliceExact(slice.slice());
}

if (config.getTruthy(globalThis, "naming")) |naming| {
if (naming.isString()) {
if (try config.getOptional(globalThis, "naming", ZigString.Slice)) |slice| {
defer slice.deinit();
if (!strings.hasPrefixComptime(slice.slice(), "./")) {
this.names.owned_entry_point.appendSliceExact("./") catch unreachable;
try this.names.owned_entry_point.appendSliceExact("./");
}
this.names.owned_entry_point.appendSliceExact(slice.slice()) catch unreachable;
try this.names.owned_entry_point.appendSliceExact(slice.slice());
this.names.entry_point.data = this.names.owned_entry_point.list.items;
}
} else if (naming.isObject()) {
if (try naming.getOptional(globalThis, "entry", ZigString.Slice)) |slice| {
defer slice.deinit();
if (!strings.hasPrefixComptime(slice.slice(), "./")) {
this.names.owned_entry_point.appendSliceExact("./") catch unreachable;
try this.names.owned_entry_point.appendSliceExact("./");
}
this.names.owned_entry_point.appendSliceExact(slice.slice()) catch unreachable;
try this.names.owned_entry_point.appendSliceExact(slice.slice());
this.names.entry_point.data = this.names.owned_entry_point.list.items;
}

if (try naming.getOptional(globalThis, "chunk", ZigString.Slice)) |slice| {
defer slice.deinit();
if (!strings.hasPrefixComptime(slice.slice(), "./")) {
this.names.owned_chunk.appendSliceExact("./") catch unreachable;
try this.names.owned_chunk.appendSliceExact("./");
}
this.names.owned_chunk.appendSliceExact(slice.slice()) catch unreachable;
try this.names.owned_chunk.appendSliceExact(slice.slice());
this.names.chunk.data = this.names.owned_chunk.list.items;
}

if (try naming.getOptional(globalThis, "asset", ZigString.Slice)) |slice| {
defer slice.deinit();
if (!strings.hasPrefixComptime(slice.slice(), "./")) {
this.names.owned_asset.appendSliceExact("./") catch unreachable;
try this.names.owned_asset.appendSliceExact("./");
}
this.names.owned_asset.appendSliceExact(slice.slice()) catch unreachable;
try this.names.owned_asset.appendSliceExact(slice.slice());
this.names.asset.data = this.names.owned_asset.list.items;
}
} else {
globalThis.throwInvalidArguments("Expected naming to be a string or an object", .{});
return error.JSException;
return error.JSError;
}
}

if (try config.getObject(globalThis, "define")) |define| {
if (!define.isObject()) {
globalThis.throwInvalidArguments("define must be an object", .{});
return error.JSException;
return error.JSError;
}

var define_iter = JSC.JSPropertyIterator(.{
Expand All @@ -432,7 +443,7 @@ pub const JSBundler = struct {

if (!value_type.isStringLike()) {
globalThis.throwInvalidArguments("define \"{s}\" must be a JSON string", .{prop});
return error.JSException;
return error.JSError;
}

var val = JSC.ZigString.init("");
Expand All @@ -441,7 +452,7 @@ pub const JSBundler = struct {
val = JSC.ZigString.fromUTF8("\"\"");
}

const key = prop.toOwnedSlice(bun.default_allocator) catch bun.outOfMemory();
const key = try prop.toOwnedSlice(bun.default_allocator);

// value is always cloned
const value = val.toSlice(bun.default_allocator);
Expand All @@ -467,7 +478,7 @@ pub const JSBundler = struct {
while (loader_iter.next()) |prop| {
if (!prop.hasPrefixComptime(".") or prop.length() < 2) {
globalThis.throwInvalidArguments("loader property names must be file extensions, such as '.txt'", .{});
return error.JSException;
return error.JSError;
}

loader_values[loader_iter.i] = try loader_iter.value.toEnumFromMap(
Expand All @@ -476,7 +487,7 @@ pub const JSBundler = struct {
Api.Loader,
options.Loader.api_names,
);
loader_names[loader_iter.i] = prop.toOwnedSlice(bun.default_allocator) catch bun.outOfMemory();
loader_names[loader_iter.i] = try prop.toOwnedSlice(bun.default_allocator);
}

this.loaders = Api.LoaderMap{
Expand Down Expand Up @@ -565,8 +576,16 @@ pub const JSBundler = struct {
}

var plugins: ?*Plugin = null;
const config = Config.fromJS(globalThis, arguments[0], &plugins, globalThis.allocator()) catch {
return .undefined;
const config = Config.fromJS(globalThis, arguments[0], &plugins, globalThis.allocator()) catch |err| {
switch (err) {
error.JSError => {
return .zero;
},
error.OutOfMemory => {
globalThis.throwOutOfMemory();
return .zero;
},
}
};

return bun.BundleV2.generateFromJavaScript(
Expand All @@ -575,8 +594,13 @@ pub const JSBundler = struct {
globalThis,
globalThis.bunVM().eventLoop(),
bun.default_allocator,
) catch {
return .undefined;
) catch |err| {
switch (err) {
error.OutOfMemory => {
globalThis.throwOutOfMemory();
return .zero;
},
}
};
}

Expand Down
5 changes: 2 additions & 3 deletions src/bun.js/api/server.zig
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ const HTTP = bun.http;
const FetchEvent = WebCore.FetchEvent;
const js = bun.JSC.C;
const JSC = bun.JSC;
const JSError = @import("../base.zig").JSError;
const MarkedArrayBuffer = @import("../base.zig").MarkedArrayBuffer;
const getAllocator = @import("../base.zig").getAllocator;
const JSValue = bun.JSC.JSValue;
Expand Down Expand Up @@ -5901,14 +5900,14 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp

if (topic.len == 0) {
httplog("publish() topic invalid", .{});
JSC.JSError(this.vm.allocator, "publish requires a topic string", .{}, globalThis, exception);
exception.* = JSC.createError(globalThis, "publish requires a topic string", .{}).asObjectRef();
return .zero;
}

var topic_slice = topic.toSlice(bun.default_allocator);
defer topic_slice.deinit();
if (topic_slice.len == 0) {
JSC.JSError(this.vm.allocator, "publish requires a non-empty topic", .{}, globalThis, exception);
exception.* = JSC.createError(globalThis, "publish requires a non-empty topic", .{}).asObjectRef();
return .zero;
}

Expand Down
12 changes: 0 additions & 12 deletions src/bun.js/base.zig
Original file line number Diff line number Diff line change
Expand Up @@ -149,18 +149,6 @@ const ZigString = JSC.ZigString;

pub const PathString = bun.PathString;

pub fn JSError(
_: std.mem.Allocator,
comptime fmt: string,
args: anytype,
ctx: js.JSContextRef,
exception: ExceptionValueRef,
) void {
@setCold(true);

exception.* = createError(ctx, fmt, args).asObjectRef();
}

pub fn createError(
globalThis: *JSC.JSGlobalObject,
comptime fmt: string,
Expand Down
Loading
Loading