aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2023-04-25 07:27:18 -0700
committerGravatar GitHub <noreply@github.com> 2023-04-25 07:27:18 -0700
commit126885e1fe509b69be947d79aacb3ed6efdf666a (patch)
treebef407938525d69132824ffd3b0b54796035009d
parent5353d4101493632cb25d0cdddfef94f62bc5902d (diff)
downloadbun-126885e1fe509b69be947d79aacb3ed6efdf666a.tar.gz
bun-126885e1fe509b69be947d79aacb3ed6efdf666a.tar.zst
bun-126885e1fe509b69be947d79aacb3ed6efdf666a.zip
Implement `onResolve` plugins in `Bun.build()`, support multiple onLoad and onResolve plugins (#2739)
* its 2023 * WIP `onResolve` plugins * more progress * it compiles * Lots of small fixes * Seems to work excluding entry points * Update BundlerPluginBuiltins.cpp --------- Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
-rw-r--r--src/bun.js/api/JSBundler.zig334
-rw-r--r--src/bun.js/bindings/JSBundlerPlugin.cpp692
-rw-r--r--src/bun.js/bindings/JSBundlerPlugin.h66
-rw-r--r--src/bun.js/bindings/ModuleLoader.cpp139
-rw-r--r--src/bun.js/bindings/ModuleLoader.h29
-rw-r--r--src/bun.js/bindings/ZigGlobalObject.cpp4
-rw-r--r--src/bun.js/bindings/ZigGlobalObject.h6
-rw-r--r--src/bun.js/bindings/sqlite/JSSQLStatement.h2
-rw-r--r--src/bun.js/bindings/webcore/DOMClientIsoSubspaces.h1
-rw-r--r--src/bun.js/bindings/webcore/DOMIsoSubspaces.h1
-rw-r--r--src/bun.js/builtins/WebCoreJSBuiltinInternals.cpp2
-rw-r--r--src/bun.js/builtins/WebCoreJSBuiltins.cpp3
-rw-r--r--src/bun.js/builtins/cpp/BundlerPluginBuiltins.cpp466
-rw-r--r--src/bun.js/builtins/cpp/BundlerPluginBuiltins.h146
-rw-r--r--src/bun.js/builtins/cpp/ByteLengthQueuingStrategyBuiltins.cpp2
-rw-r--r--src/bun.js/builtins/cpp/ByteLengthQueuingStrategyBuiltins.h2
-rw-r--r--src/bun.js/builtins/cpp/ConsoleObjectBuiltins.cpp2
-rw-r--r--src/bun.js/builtins/cpp/ConsoleObjectBuiltins.h2
-rw-r--r--src/bun.js/builtins/cpp/CountQueuingStrategyBuiltins.cpp2
-rw-r--r--src/bun.js/builtins/cpp/CountQueuingStrategyBuiltins.h2
-rw-r--r--src/bun.js/builtins/cpp/ImportMetaObjectBuiltins.cpp2
-rw-r--r--src/bun.js/builtins/cpp/ImportMetaObjectBuiltins.h2
-rw-r--r--src/bun.js/builtins/cpp/JSBufferConstructorBuiltins.cpp2
-rw-r--r--src/bun.js/builtins/cpp/JSBufferConstructorBuiltins.h2
-rw-r--r--src/bun.js/builtins/cpp/JSBufferPrototypeBuiltins.cpp2
-rw-r--r--src/bun.js/builtins/cpp/JSBufferPrototypeBuiltins.h2
-rw-r--r--src/bun.js/builtins/cpp/ProcessObjectInternalsBuiltins.cpp2
-rw-r--r--src/bun.js/builtins/cpp/ProcessObjectInternalsBuiltins.h2
-rw-r--r--src/bun.js/builtins/cpp/ReadableByteStreamControllerBuiltins.cpp2
-rw-r--r--src/bun.js/builtins/cpp/ReadableByteStreamControllerBuiltins.h2
-rw-r--r--src/bun.js/builtins/cpp/ReadableByteStreamInternalsBuiltins.cpp2
-rw-r--r--src/bun.js/builtins/cpp/ReadableByteStreamInternalsBuiltins.h2
-rw-r--r--src/bun.js/builtins/cpp/ReadableStreamBYOBReaderBuiltins.cpp2
-rw-r--r--src/bun.js/builtins/cpp/ReadableStreamBYOBReaderBuiltins.h2
-rw-r--r--src/bun.js/builtins/cpp/ReadableStreamBYOBRequestBuiltins.cpp2
-rw-r--r--src/bun.js/builtins/cpp/ReadableStreamBYOBRequestBuiltins.h2
-rw-r--r--src/bun.js/builtins/cpp/ReadableStreamBuiltins.cpp2
-rw-r--r--src/bun.js/builtins/cpp/ReadableStreamBuiltins.h2
-rw-r--r--src/bun.js/builtins/cpp/ReadableStreamDefaultControllerBuiltins.cpp2
-rw-r--r--src/bun.js/builtins/cpp/ReadableStreamDefaultControllerBuiltins.h2
-rw-r--r--src/bun.js/builtins/cpp/ReadableStreamDefaultReaderBuiltins.cpp2
-rw-r--r--src/bun.js/builtins/cpp/ReadableStreamDefaultReaderBuiltins.h2
-rw-r--r--src/bun.js/builtins/cpp/ReadableStreamInternalsBuiltins.cpp2
-rw-r--r--src/bun.js/builtins/cpp/ReadableStreamInternalsBuiltins.h2
-rw-r--r--src/bun.js/builtins/cpp/StreamInternalsBuiltins.cpp2
-rw-r--r--src/bun.js/builtins/cpp/StreamInternalsBuiltins.h2
-rw-r--r--src/bun.js/builtins/cpp/TransformStreamBuiltins.cpp2
-rw-r--r--src/bun.js/builtins/cpp/TransformStreamBuiltins.h2
-rw-r--r--src/bun.js/builtins/cpp/TransformStreamDefaultControllerBuiltins.cpp2
-rw-r--r--src/bun.js/builtins/cpp/TransformStreamDefaultControllerBuiltins.h2
-rw-r--r--src/bun.js/builtins/cpp/TransformStreamInternalsBuiltins.cpp2
-rw-r--r--src/bun.js/builtins/cpp/TransformStreamInternalsBuiltins.h2
-rw-r--r--src/bun.js/builtins/cpp/WebCoreJSBuiltinInternals.h2
-rw-r--r--src/bun.js/builtins/cpp/WebCoreJSBuiltins.h6
-rw-r--r--src/bun.js/builtins/cpp/WritableStreamDefaultControllerBuiltins.cpp2
-rw-r--r--src/bun.js/builtins/cpp/WritableStreamDefaultControllerBuiltins.h2
-rw-r--r--src/bun.js/builtins/cpp/WritableStreamDefaultWriterBuiltins.cpp2
-rw-r--r--src/bun.js/builtins/cpp/WritableStreamDefaultWriterBuiltins.h2
-rw-r--r--src/bun.js/builtins/cpp/WritableStreamInternalsBuiltins.cpp2
-rw-r--r--src/bun.js/builtins/cpp/WritableStreamInternalsBuiltins.h2
-rw-r--r--src/bun.js/builtins/js/BundlerPlugin.js418
-rw-r--r--src/bun.js/builtins/js/ConsoleObject.js2
-rw-r--r--src/bun.js/builtins/js/ImportMetaObject.js2
-rw-r--r--src/bun.js/builtins/js/JSBufferConstructor.js2
-rw-r--r--src/bun.js/builtins/js/JSBufferPrototype.js2
-rw-r--r--src/bun.js/builtins/js/ProcessObjectInternals.js2
-rw-r--r--src/bundler/bundle_v2.zig484
-rw-r--r--src/fs.zig12
-rw-r--r--src/import_record.zig1
-rw-r--r--src/logger.zig19
70 files changed, 2068 insertions, 863 deletions
diff --git a/src/bun.js/api/JSBundler.zig b/src/bun.js/api/JSBundler.zig
index c53d21f12..ae21e7acc 100644
--- a/src/bun.js/api/JSBundler.zig
+++ b/src/bun.js/api/JSBundler.zig
@@ -230,18 +230,22 @@ pub const JSBundler = struct {
// };
// defer decl.deinit();
- // if (try plugin.getOptional(globalThis, "name", ZigString.Slice)) |slice| {
- // defer slice.deinit();
- // decl.name.appendSliceExact(slice.slice()) catch unreachable;
- // }
-
- if (try plugin.getFunction(globalThis, "setup")) |_| {
- // decl.setup.set(globalThis, setup);
+ if (plugin.getOptional(globalThis, "name", ZigString.Slice) catch null) |slice| {
+ defer slice.deinit();
+ if (slice.len == 0) {
+ globalThis.throwInvalidArguments("Expected plugin to have a non-empty name", .{});
+ return error.JSError;
+ }
} else {
- globalThis.throwInvalidArguments("Expected plugin to have a setup() function", .{});
+ globalThis.throwInvalidArguments("Expected plugin to have a name", .{});
return error.JSError;
}
+ const function = (plugin.getFunction(globalThis, "setup") catch null) orelse {
+ globalThis.throwInvalidArguments("Expected plugin to have a setup() function", .{});
+ return error.JSError;
+ };
+
var bun_plugins: *Plugin = plugins.* orelse brk: {
plugins.* = Plugin.create(
globalThis,
@@ -254,11 +258,17 @@ pub const JSBundler = struct {
break :brk plugins.*.?;
};
- const plugin_result = bun_plugins.addPlugin(globalThis, plugin);
+ var plugin_result = bun_plugins.addPlugin(function);
+
+ if (!plugin_result.isEmptyOrUndefinedOrNull()) {
+ if (plugin_result.asAnyPromise()) |promise| {
+ globalThis.bunVM().waitForPromise(promise);
+ plugin_result = promise.result(globalThis.vm());
+ }
+ }
if (plugin_result.toError()) |err| {
globalThis.throwValue(err);
- bun_plugins.deinit();
return error.JSError;
}
}
@@ -356,20 +366,65 @@ pub const JSBundler = struct {
}
pub const Resolve = struct {
- import_record: *bun.ImportRecord,
- source_file: string = "",
- default_namespace: string = "",
+ import_record: MiniImportRecord,
/// Null means the Resolve is aborted
completion: ?*bun.BundleV2.JSBundleCompletionTask = null,
- value: Value,
+ value: Value = .{ .pending = {} },
+
+ js_task: JSC.AnyTask = undefined,
+ task: JSC.AnyEventLoop.Task = undefined,
+
+ pub const MiniImportRecord = struct {
+ kind: bun.ImportKind,
+ source_file: string = "",
+ namespace: string = "",
+ specifier: string = "",
+ importer_source_index: ?u32 = null,
+ import_record_index: u32 = 0,
+ range: logger.Range = logger.Range.None,
+ original_platform: options.Platform,
+ };
+
+ pub fn create(
+ from: union(enum) {
+ MiniImportRecord: MiniImportRecord,
+ ImportRecord: struct {
+ importer_source_index: u32,
+ import_record_index: u32,
+ source_file: []const u8 = "",
+ original_platform: options.Platform,
+ record: *const bun.ImportRecord,
+ },
+ },
+ completion: *bun.BundleV2.JSBundleCompletionTask,
+ ) Resolve {
+ return Resolve{
+ .import_record = switch (from) {
+ .MiniImportRecord => from.MiniImportRecord,
+ .ImportRecord => |file| MiniImportRecord{
+ .kind = file.record.kind,
+ .source_file = file.source_file,
+ .namespace = file.record.path.namespace,
+ .specifier = file.record.path.text,
+ .importer_source_index = file.importer_source_index,
+ .import_record_index = file.import_record_index,
+ .range = file.record.range,
+ .original_platform = file.original_platform,
+ },
+ },
+ .completion = completion,
+ .value = .{ .pending = {} },
+ };
+ }
pub const Value = union(enum) {
err: logger.Msg,
success: struct {
path: []const u8 = "",
namespace: []const u8 = "",
+ external: bool = false,
pub fn deinit(this: *@This()) void {
bun.default_allocator.destroy(this.path);
@@ -377,68 +432,24 @@ pub const JSBundler = struct {
}
},
no_match: void,
- pending: JSC.JSPromise.Strong,
+ pending: void,
consumed: void,
- fn badPluginError() Value {
- return .{
- .err = logger.Msg{
- .data = .{
- .text = bun.default_allocator.dupe(u8, "onResolve plugin returned an invalid value") catch unreachable,
- },
- },
- };
- }
-
pub fn consume(this: *Value) Value {
const result = this.*;
this.* = .{ .consumed = {} };
return result;
}
- pub fn fromJS(globalObject: *JSC.JSGlobalObject, source_file: []const u8, default_namespace: string, value: JSC.JSValue) Value {
- if (value.isEmptyOrUndefinedOrNull()) {
- return .{ .no_match = {} };
- }
-
- if (value.toError(globalObject)) |err| {
- return .{ .err = logger.Msg.fromJS(bun.default_allocator, globalObject, source_file, err) catch unreachable };
- }
-
- // I think we already do this check?
- if (!value.isObject()) return badPluginError();
-
- var namespace = ZigString.Slice.fromUTF8NeverFree(default_namespace);
-
- if (value.getOptional(globalObject, "namespace", ZigString.Slice) catch return badPluginError()) |namespace_slice| {
- namespace = namespace_slice;
- }
-
- const path = value.getOptional(globalObject, "path", ZigString.Slice) catch {
- namespace.deinit();
- return badPluginError();
- };
-
- return .{
- .success = .{
- .path = path.cloneWithAllocator(bun.default_allocator).slice(),
- .namespace = namespace.slice(),
- },
- };
- }
-
pub fn deinit(this: *Resolve.Value) void {
switch (this.*) {
- .pending => |*pending| {
- pending.deinit();
- },
.success => |*success| {
success.deinit();
},
.err => |*err| {
err.deinit(bun.default_allocator);
},
- .consumed => {},
+ .no_match, .pending, .consumed => {},
}
this.* = .{ .consumed = {} };
}
@@ -452,22 +463,73 @@ pub const JSBundler = struct {
const AnyTask = JSC.AnyTask.New(@This(), runOnJSThread);
- pub fn runOnJSThread(this: *Load) void {
+ pub fn dispatch(this: *Resolve) void {
var completion = this.completion orelse {
this.deinit();
return;
};
+ completion.ref();
- const result = completion.plugins.?.matchOnResolve(
+ this.js_task = AnyTask.init(this);
+ var concurrent_task = bun.default_allocator.create(JSC.ConcurrentTask) catch {
+ completion.deref();
+ this.deinit();
+ return;
+ };
+ concurrent_task.* = JSC.ConcurrentTask{
+ .auto_delete = true,
+ .task = this.js_task.task(),
+ };
+ completion.jsc_event_loop.enqueueTaskConcurrent(concurrent_task);
+ }
+
+ pub fn runOnJSThread(this: *Resolve) void {
+ var completion = this.completion orelse {
+ this.deinit();
+ return;
+ };
+
+ completion.plugins.?.matchOnResolve(
completion.globalThis,
- this.path,
- this.namespace,
+ this.import_record.specifier,
+ this.import_record.namespace,
+ this.import_record.source_file,
this,
+ this.import_record.kind,
);
+ }
+
+ export fn JSBundlerPlugin__onResolveAsync(
+ this: *Resolve,
+ _: *anyopaque,
+ path_value: JSValue,
+ namespace_value: JSValue,
+ external_value: JSValue,
+ ) void {
+ var completion = this.completion orelse {
+ this.deinit();
+ return;
+ };
+ if (path_value.isEmptyOrUndefinedOrNull() or namespace_value.isEmptyOrUndefinedOrNull()) {
+ this.value = .{ .no_match = {} };
+ } else {
+ const path = path_value.toSliceClone(completion.globalThis) orelse @panic("Unexpected: path is not a string");
+ const namespace = namespace_value.toSliceClone(completion.globalThis) orelse @panic("Unexpected: namespace is not a string");
+ this.value = .{
+ .success = .{
+ .path = path.slice(),
+ .namespace = namespace.slice(),
+ .external = external_value.to(bool),
+ },
+ };
+ }
- this.value = Value.fromJS(completion.globalThis, this.source_file, this.default_namespace, result);
completion.bundler.onResolveAsync(this);
}
+
+ comptime {
+ _ = JSBundlerPlugin__onResolveAsync;
+ }
};
pub const Load = struct {
@@ -484,6 +546,9 @@ pub const JSBundler = struct {
task: JSC.AnyEventLoop.Task = undefined,
parse_task: *bun.ParseTask = undefined,
+ /// Faster path: skip the extra threadpool dispatch when the file is not found
+ was_file: bool = false,
+
pub fn create(
completion: *bun.BundleV2.JSBundleCompletionTask,
source_index: Index,
@@ -494,7 +559,7 @@ pub const JSBundler = struct {
.source_index = source_index,
.default_loader = default_loader,
.completion = completion,
- .value = .{ .pending = .{} },
+ .value = .{ .pending = {} },
.path = path.text,
.namespace = path.namespace,
};
@@ -506,21 +571,19 @@ pub const JSBundler = struct {
source_code: []const u8 = "",
loader: options.Loader = options.Loader.file,
},
- pending: JSC.JSPromise.Strong,
+ pending: void,
+ no_match: void,
consumed: void,
pub fn deinit(this: *Value) void {
switch (this.*) {
- .pending => |*pending| {
- pending.strong.deinit();
- },
.success => |success| {
bun.default_allocator.destroy(success.source_code);
},
.err => |*err| {
err.deinit(bun.default_allocator);
},
- .consumed => {},
+ .no_match, .pending, .consumed => {},
}
this.* = .{ .consumed = {} };
}
@@ -546,19 +609,13 @@ pub const JSBundler = struct {
return;
};
- const err = completion.plugins.?.matchOnLoad(
+ completion.plugins.?.matchOnLoad(
completion.globalThis,
this.path,
this.namespace,
this,
+ this.default_loader,
);
-
- if (this.value == .pending) {
- if (!err.isEmptyOrUndefinedOrNull()) {
- var code = ZigString.Empty;
- JSBundlerPlugin__OnLoadAsync(this, err, &code, .js);
- }
- }
}
pub fn dispatch(this: *Load) void {
@@ -581,51 +638,56 @@ pub const JSBundler = struct {
completion.jsc_event_loop.enqueueTaskConcurrent(concurrent_task);
}
- export fn JSBundlerPlugin__getDefaultLoader(this: *Load) options.Loader {
- return this.default_loader;
- }
-
- export fn JSBundlerPlugin__OnLoadAsync(
+ export fn JSBundlerPlugin__onLoadAsync(
this: *Load,
- error_value: JSC.JSValue,
- source_code: *ZigString,
- loader: options.Loader,
+ _: *anyopaque,
+ source_code_value: JSValue,
+ loader_as_int: JSValue,
) void {
- if (this.completion) |completion| {
- if (error_value.toError()) |err| {
- if (this.value == .pending) this.value.pending.strong.deinit();
- this.value = .{
- .err = logger.Msg.fromJS(bun.default_allocator, completion.globalThis, this.path, err) catch unreachable,
- };
- } else if (!error_value.isEmptyOrUndefinedOrNull() and error_value.isCell() and error_value.jsType() == .JSPromise) {
- this.value.pending.strong.set(completion.globalThis, error_value);
+ var completion = this.completion orelse {
+ this.deinit();
+ return;
+ };
+ if (source_code_value.isEmptyOrUndefinedOrNull() or loader_as_int.isEmptyOrUndefinedOrNull()) {
+ this.value = .{ .no_match = {} };
+
+ if (this.was_file) {
+ // Faster path: skip the extra threadpool dispatch
+ completion.bundler.graph.pool.pool.schedule(bun.ThreadPool.Batch.from(&this.parse_task.task));
+ this.deinit();
return;
- } else {
- if (this.value == .pending) this.value.pending.strong.deinit();
- this.value = .{
- .success = .{
- .source_code = source_code.toSliceClone(bun.default_allocator).slice(),
- .loader = loader,
- },
- };
}
-
- completion.bundler.onLoadAsync(this);
} else {
- this.deinit();
+ var buffer_or_string: JSC.Node.SliceOrBuffer = JSC.Node.SliceOrBuffer.fromJS(completion.globalThis, bun.default_allocator, source_code_value) orelse
+ @panic("expected buffer or string");
+
+ const source_code = switch (buffer_or_string) {
+ .buffer => |arraybuffer| bun.default_allocator.dupe(u8, arraybuffer.slice()) catch @panic("Out of memory in onLoad callback"),
+ .string => |slice| (slice.cloneIfNeeded(bun.default_allocator) catch @panic("Out of memory in onLoad callback")).slice(),
+ };
+
+ this.value = .{
+ .success = .{
+ .loader = @intToEnum(options.Loader, @intCast(u8, loader_as_int.to(i32))),
+ .source_code = source_code,
+ },
+ };
}
+
+ completion.bundler.onLoadAsync(this);
}
comptime {
- _ = JSBundlerPlugin__getDefaultLoader;
- _ = JSBundlerPlugin__OnLoadAsync;
+ _ = JSBundlerPlugin__onLoadAsync;
}
};
pub const Plugin = opaque {
extern fn JSBundlerPlugin__create(*JSC.JSGlobalObject, JSC.JSGlobalObject.BunPluginTarget) *Plugin;
pub fn create(globalObject: *JSC.JSGlobalObject, target: JSC.JSGlobalObject.BunPluginTarget) *Plugin {
- return JSBundlerPlugin__create(globalObject, target);
+ var plugin = JSBundlerPlugin__create(globalObject, target);
+ JSC.JSValue.fromCell(plugin).protect();
+ return plugin;
}
extern fn JSBundlerPlugin__tombestone(*Plugin) void;
@@ -643,7 +705,8 @@ pub const JSBundler = struct {
namespaceString: *const ZigString,
path: *const ZigString,
context: *anyopaque,
- ) JSValue;
+ u8,
+ ) void;
extern fn JSBundlerPlugin__matchOnResolve(
*JSC.JSGlobalObject,
@@ -652,7 +715,8 @@ pub const JSBundler = struct {
path: *const ZigString,
importer: *const ZigString,
context: *anyopaque,
- ) JSValue;
+ u8,
+ ) void;
pub fn hasAnyMatches(
this: *Plugin,
@@ -673,13 +737,14 @@ pub const JSBundler = struct {
path: []const u8,
namespace: []const u8,
context: *anyopaque,
- ) JSC.JSValue {
- const namespace_string = if (strings.eqlComptime(namespace, "file"))
- ZigString.Empty
+ default_loader: options.Loader,
+ ) void {
+ const namespace_string = if (namespace.len == 0)
+ ZigString.init("file")
else
ZigString.fromUTF8(namespace);
const path_string = ZigString.fromUTF8(path);
- return JSBundlerPlugin__matchOnLoad(globalThis, this, &namespace_string, &path_string, context);
+ JSBundlerPlugin__matchOnLoad(globalThis, this, &namespace_string, &path_string, context, @enumToInt(default_loader));
}
pub fn matchOnResolve(
@@ -689,26 +754,27 @@ pub const JSBundler = struct {
namespace: []const u8,
importer: []const u8,
context: *anyopaque,
- ) JSC.JSValue {
+ import_record_kind: bun.ImportKind,
+ ) void {
const namespace_string = if (strings.eqlComptime(namespace, "file"))
ZigString.Empty
else
ZigString.fromUTF8(namespace);
const path_string = ZigString.fromUTF8(path);
const importer_string = ZigString.fromUTF8(importer);
- return JSBundlerPlugin__matchOnResolve(globalThis, this, &namespace_string, &path_string, &importer_string, context);
+ JSBundlerPlugin__matchOnResolve(globalThis, this, &namespace_string, &path_string, &importer_string, context, @enumToInt(import_record_kind));
}
pub fn addPlugin(
this: *Plugin,
- globalObject: *JSC.JSGlobalObject,
object: JSC.JSValue,
) JSValue {
- return setupJSBundlerPlugin(this, globalObject, object);
+ return JSBundlerPlugin__runSetupFunction(this, object);
}
pub fn deinit(this: *Plugin) void {
JSBundlerPlugin__tombestone(this);
+ JSC.JSValue.fromCell(this).unprotect();
}
pub fn setConfig(this: *Plugin, config: *anyopaque) void {
@@ -717,10 +783,36 @@ pub const JSBundler = struct {
extern fn JSBundlerPlugin__setConfig(*Plugin, *anyopaque) void;
- extern fn setupJSBundlerPlugin(
+ extern fn JSBundlerPlugin__runSetupFunction(
*Plugin,
- *JSC.JSGlobalObject,
JSC.JSValue,
) JSValue;
+
+ pub export fn JSBundlerPlugin__addError(
+ ctx: *anyopaque,
+ _: *Plugin,
+ exception: JSValue,
+ which: JSValue,
+ ) void {
+ switch (which.to(i32)) {
+ 1 => {
+ var this: *JSBundler.Resolve = bun.cast(*Resolve, ctx);
+ var completion = this.completion orelse return;
+ this.value = .{
+ .err = logger.Msg.fromJS(bun.default_allocator, completion.globalThis, this.import_record.source_file, exception) catch @panic("Out of memory in addError callback"),
+ };
+ completion.bundler.onResolveAsync(this);
+ },
+ 0 => {
+ var this: *Load = bun.cast(*Load, ctx);
+ var completion = this.completion orelse return;
+ this.value = .{
+ .err = logger.Msg.fromJS(bun.default_allocator, completion.globalThis, this.path, exception) catch @panic("Out of memory in addError callback"),
+ };
+ completion.bundler.onLoadAsync(this);
+ },
+ else => @panic("invalid error type"),
+ }
+ }
};
};
diff --git a/src/bun.js/bindings/JSBundlerPlugin.cpp b/src/bun.js/bindings/JSBundlerPlugin.cpp
index 2aaa40270..1ac8b0c30 100644
--- a/src/bun.js/bindings/JSBundlerPlugin.cpp
+++ b/src/bun.js/bindings/JSBundlerPlugin.cpp
@@ -19,508 +19,384 @@
#include "BunClientData.h"
#include "ModuleLoader.h"
#include "JavaScriptCore/RegularExpression.h"
+#include <JavaScriptCore/LazyProperty.h>
+#include <JavaScriptCore/LazyPropertyInlines.h>
+#include <JavaScriptCore/VMTrapsInlines.h>
namespace Bun {
-#define WRAP_BUNDLER_PLUGIN(argName) JSValue(bitwise_cast<double>(reinterpret_cast<uintptr_t>(argName)))
-#define UNWRAP_BUNDLER_PLUGIN(callFrame) reinterpret_cast<JSBundlerPlugin*>(bitwise_cast<uintptr_t>(callFrame->thisValue().asDouble()))
+#define WRAP_BUNDLER_PLUGIN(argName) jsNumber(bitwise_cast<double>(reinterpret_cast<uintptr_t>(argName)))
+#define UNWRAP_BUNDLER_PLUGIN(callFrame) reinterpret_cast<void*>(bitwise_cast<uintptr_t>(callFrame->argument(0).asDouble()))
-WTF_MAKE_ISO_ALLOCATED_IMPL(JSBundlerPlugin);
+extern "C" void JSBundlerPlugin__addError(void*, void*, JSC::EncodedJSValue, JSC::EncodedJSValue);
+extern "C" void JSBundlerPlugin__onLoadAsync(void*, void*, JSC::EncodedJSValue, JSC::EncodedJSValue);
+extern "C" void JSBundlerPlugin__onResolveAsync(void*, void*, JSC::EncodedJSValue, JSC::EncodedJSValue, JSC::EncodedJSValue);
-static bool isValidNamespaceString(String& namespaceString)
+JSC_DECLARE_HOST_FUNCTION(jsBundlerPluginFunction_addFilter);
+JSC_DECLARE_HOST_FUNCTION(jsBundlerPluginFunction_addError);
+JSC_DECLARE_HOST_FUNCTION(jsBundlerPluginFunction_onLoadAsync);
+JSC_DECLARE_HOST_FUNCTION(jsBundlerPluginFunction_onResolveAsync);
+
+void BundlerPlugin::NamespaceList::append(JSC::VM& vm, JSC::RegExp* filter, String& namespaceString)
{
- static JSC::Yarr::RegularExpression* namespaceRegex = nullptr;
- if (!namespaceRegex) {
- namespaceRegex = new JSC::Yarr::RegularExpression("^([/@a-zA-Z0-9_\\-]+)$"_s);
+ auto* nsGroup = group(namespaceString);
+
+ if (nsGroup == nullptr) {
+ namespaces.append(namespaceString);
+ groups.append(Vector<Yarr::RegularExpression> {});
+ nsGroup = &groups.last();
}
- return namespaceRegex->match(namespaceString) > -1;
+
+ Yarr::RegularExpression regex(
+ StringView(filter->pattern()),
+ filter->flags().contains(Yarr::Flags::IgnoreCase) ? Yarr::TextCaseSensitivity::TextCaseInsensitive : Yarr::TextCaseSensitivity::TextCaseInsensitive,
+ filter->multiline() ? Yarr::MultilineMode::MultilineEnabled : Yarr::MultilineMode::MultilineDisabled,
+ filter->eitherUnicode() ? Yarr::UnicodeMode::UnicodeAwareMode : Yarr::UnicodeMode::UnicodeUnawareMode);
+
+ nsGroup->append(WTFMove(regex));
}
-static EncodedJSValue jsFunctionAppendOnLoadPluginBody(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callframe, JSBundlerPlugin& plugin)
+bool BundlerPlugin::anyMatchesCrossThread(const ZigString* namespaceStr, const ZigString* path, bool isOnLoad)
{
- JSC::VM& vm = globalObject->vm();
- auto scope = DECLARE_THROW_SCOPE(vm);
- Ref protect(plugin);
-
- if (callframe->argumentCount() < 2) {
- throwException(globalObject, scope, createError(globalObject, "onLoad() requires at least 2 arguments"_s));
- return JSValue::encode(jsUndefined());
- }
+ auto namespaceString = namespaceStr ? Zig::toString(*namespaceStr) : String();
+ auto pathString = Zig::toString(*path);
- auto* filterObject = callframe->uncheckedArgument(0).toObject(globalObject);
- RETURN_IF_EXCEPTION(scope, encodedJSValue());
- auto clientData = WebCore::clientData(vm);
- auto& builtinNames = clientData->builtinNames();
- JSC::RegExpObject* filter = nullptr;
- if (JSValue filterValue = filterObject->getIfPropertyExists(globalObject, builtinNames.filterPublicName())) {
- if (filterValue.isCell() && filterValue.asCell()->inherits<JSC::RegExpObject>())
- filter = jsCast<JSC::RegExpObject*>(filterValue);
- }
+ if (isOnLoad) {
+ auto* group = this->onLoad.group(namespaceString);
+ if (group == nullptr) {
+ return false;
+ }
- if (!filter) {
- throwException(globalObject, scope, createError(globalObject, "onLoad() expects first argument to be an object with a filter RegExp"_s));
- return JSValue::encode(jsUndefined());
- }
+ auto& filters = *group;
- String namespaceString = String();
- if (JSValue namespaceValue = filterObject->getIfPropertyExists(globalObject, Identifier::fromString(vm, "namespace"_s))) {
- if (namespaceValue.isString()) {
- namespaceString = namespaceValue.toWTFString(globalObject);
- RETURN_IF_EXCEPTION(scope, encodedJSValue());
- if (!isValidNamespaceString(namespaceString)) {
- throwException(globalObject, scope, createError(globalObject, "namespace can only contain letters, numbers, dashes, or underscores"_s));
- return JSValue::encode(jsUndefined());
+ for (auto& filter : filters) {
+ if (filter.match(pathString) > -1) {
+ return true;
}
}
- RETURN_IF_EXCEPTION(scope, encodedJSValue());
- }
- auto func = callframe->uncheckedArgument(1);
- RETURN_IF_EXCEPTION(scope, encodedJSValue());
+ } else {
+ auto* group = this->onResolve.group(namespaceString);
+ if (group == nullptr) {
+ return false;
+ }
- if (!func.isCell() || !func.isCallable()) {
- throwException(globalObject, scope, createError(globalObject, "onLoad() expects second argument to be a function"_s));
- return JSValue::encode(jsUndefined());
- }
+ auto& filters = *group;
- plugin.onLoad.append(vm, filter->regExp(), jsCast<JSFunction*>(func), namespaceString);
+ for (auto& filter : filters) {
+ if (filter.match(pathString) > -1) {
+ return true;
+ }
+ }
+ }
- return JSValue::encode(jsUndefined());
+ return false;
}
-static EncodedJSValue jsFunctionAppendOnResolvePluginBody(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callframe, JSBundlerPlugin& plugin)
-{
- Ref protect(plugin);
- JSC::VM& vm = globalObject->vm();
- auto scope = DECLARE_THROW_SCOPE(vm);
-
- if (callframe->argumentCount() < 2) {
- throwException(globalObject, scope, createError(globalObject, "onResolve() requires at least 2 arguments"_s));
- return JSValue::encode(jsUndefined());
+static const HashTableValue JSBundlerPluginHashTable[] = {
+ { "addFilter"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBundlerPluginFunction_addFilter, 3 } },
+ { "addError"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBundlerPluginFunction_addError, 3 } },
+ { "onLoadAsync"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBundlerPluginFunction_onLoadAsync, 3 } },
+ { "onResolveAsync"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBundlerPluginFunction_onResolveAsync, 4 } },
+};
+
+class JSBundlerPlugin final : public JSC::JSNonFinalObject {
+public:
+ using Base = JSC::JSNonFinalObject;
+ static JSBundlerPlugin* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* config, BunPluginTarget target)
+ {
+ JSBundlerPlugin* ptr = new (NotNull, JSC::allocateCell<JSBundlerPlugin>(vm)) JSBundlerPlugin(vm, globalObject, structure, config, target);
+ ptr->finishCreation(vm);
+ return ptr;
}
- auto* filterObject = callframe->uncheckedArgument(0).toObject(globalObject);
- RETURN_IF_EXCEPTION(scope, encodedJSValue());
- auto clientData = WebCore::clientData(vm);
- auto& builtinNames = clientData->builtinNames();
- JSC::RegExpObject* filter = nullptr;
- if (JSValue filterValue = filterObject->getIfPropertyExists(globalObject, builtinNames.filterPublicName())) {
- if (filterValue.isCell() && filterValue.asCell()->inherits<JSC::RegExpObject>())
- filter = jsCast<JSC::RegExpObject*>(filterValue);
+ DECLARE_INFO;
+ template<typename, SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
+ {
+ if constexpr (mode == JSC::SubspaceAccess::Concurrently)
+ return nullptr;
+ return WebCore::subspaceForImpl<JSBundlerPlugin, WebCore::UseCustomHeapCellType::No>(
+ vm,
+ [](auto& spaces) { return spaces.m_clientSubspaceForBundlerPlugin.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForBundlerPlugin = std::forward<decltype(space)>(space); },
+ [](auto& spaces) { return spaces.m_subspaceForBundlerPlugin.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_subspaceForBundlerPlugin = std::forward<decltype(space)>(space); });
}
-
- if (!filter) {
- throwException(globalObject, scope, createError(globalObject, "onResolve() expects first argument to be an object with a filter RegExp"_s));
- return JSValue::encode(jsUndefined());
+ static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
+ {
+ return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
}
- String namespaceString = String();
- if (JSValue namespaceValue = filterObject->getIfPropertyExists(globalObject, Identifier::fromString(vm, "namespace"_s))) {
- if (namespaceValue.isString()) {
- namespaceString = namespaceValue.toWTFString(globalObject);
- RETURN_IF_EXCEPTION(scope, encodedJSValue());
- if (!isValidNamespaceString(namespaceString)) {
- throwException(globalObject, scope, createError(globalObject, "namespace can only contain letters, numbers, dashes, or underscores"_s));
- return JSValue::encode(jsUndefined());
- }
- }
-
- RETURN_IF_EXCEPTION(scope, encodedJSValue());
- }
+ DECLARE_VISIT_CHILDREN;
- auto func = callframe->uncheckedArgument(1);
- RETURN_IF_EXCEPTION(scope, encodedJSValue());
+ Bun::BundlerPlugin plugin;
+ JSC::LazyProperty<JSBundlerPlugin, JSC::JSFunction> onLoadFunction;
+ JSC::LazyProperty<JSBundlerPlugin, JSC::JSFunction> onResolveFunction;
+ JSC::LazyProperty<JSBundlerPlugin, JSC::JSFunction> setupFunction;
- if (!func.isCell() || !func.isCallable()) {
- throwException(globalObject, scope, createError(globalObject, "onResolve() expects second argument to be a function"_s));
- return JSValue::encode(jsUndefined());
+private:
+ JSBundlerPlugin(JSC::VM& vm, JSC::JSGlobalObject*, JSC::Structure* structure, void* config, BunPluginTarget target)
+ : JSC::JSNonFinalObject(vm, structure)
+ , plugin(BundlerPlugin(config, target))
+ {
}
- plugin.onResolve.append(vm, filter->regExp(), jsCast<JSFunction*>(func), namespaceString);
+ void finishCreation(JSC::VM&);
+};
- return JSValue::encode(jsUndefined());
-}
-
-JSC_DEFINE_HOST_FUNCTION(jsFunctionAppendOnLoadJSBundlerPlugin, (JSGlobalObject * globalObject, CallFrame* callframe))
+template<typename Visitor>
+void JSBundlerPlugin::visitChildrenImpl(JSCell* cell, Visitor& visitor)
{
- auto& plugin = *UNWRAP_BUNDLER_PLUGIN(callframe);
- return jsFunctionAppendOnLoadPluginBody(globalObject, callframe, plugin);
+ JSBundlerPlugin* thisObject = jsCast<JSBundlerPlugin*>(cell);
+ ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+ Base::visitChildren(thisObject, visitor);
+ thisObject->onLoadFunction.visit(visitor);
+ thisObject->onResolveFunction.visit(visitor);
+ thisObject->setupFunction.visit(visitor);
}
+DEFINE_VISIT_CHILDREN(JSBundlerPlugin);
-JSC_DEFINE_HOST_FUNCTION(jsFunctionAppendOnResolveJSBundlerPlugin, (JSGlobalObject * globalObject, CallFrame* callframe))
-{
- auto& plugin = *UNWRAP_BUNDLER_PLUGIN(callframe);
- return jsFunctionAppendOnResolvePluginBody(globalObject, callframe, plugin);
-}
+const JSC::ClassInfo JSBundlerPlugin::s_info = { "BundlerPlugin"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSBundlerPlugin) };
-extern "C" EncodedJSValue setupJSBundlerPlugin(JSBundlerPlugin* bundlerPlugin, JSC::JSGlobalObject* globalObject, JSValue objValue)
+JSC_DEFINE_HOST_FUNCTION(jsBundlerPluginFunction_addFilter, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame))
{
- JSC::VM& vm = globalObject->vm();
- auto clientData = WebCore::clientData(vm);
- auto throwScope = DECLARE_THROW_SCOPE(vm);
-
- if (!objValue || !objValue.isObject()) {
- JSC::throwTypeError(globalObject, throwScope, "plugin needs to be an object"_s);
- return JSValue::encode(throwScope.exception());
+ JSBundlerPlugin* thisObject = jsCast<JSBundlerPlugin*>(callFrame->thisValue());
+ if (thisObject->plugin.tombstoned) {
+ return JSC::JSValue::encode(JSC::jsUndefined());
}
- JSC::JSObject* obj = objValue.toObject(globalObject);
-
- JSC::JSValue setupFunctionValue = obj->getIfPropertyExists(globalObject, Identifier::fromString(vm, "setup"_s));
- if (!setupFunctionValue || setupFunctionValue.isUndefinedOrNull() || !setupFunctionValue.isCell() || !setupFunctionValue.isCallable()) {
- JSC::throwTypeError(globalObject, throwScope, "plugin needs a setup() function"_s);
- return JSValue::encode(throwScope.exception());
+ JSC::RegExpObject* regExp = jsCast<JSC::RegExpObject*>(callFrame->argument(0));
+ WTF::String namespaceStr = callFrame->argument(1).toWTFString(globalObject);
+ if (namespaceStr == "file"_s) {
+ namespaceStr = String();
}
- JSFunction* setupFunction = jsCast<JSFunction*>(setupFunctionValue);
- JSObject* builderObject = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype(), 3);
-
- JSC::JSFunction* onLoadFunction = JSC::JSFunction::create(vm, globalObject, 1, "onLoad"_s, jsFunctionAppendOnLoadJSBundlerPlugin, ImplementationVisibility::Public);
- JSC::JSFunction* onResolveFunction = JSC::JSFunction::create(vm, globalObject, 1, "onResolve"_s, jsFunctionAppendOnResolveJSBundlerPlugin, ImplementationVisibility::Public);
- JSC::JSBoundFunction* boundOnLoadFunction = JSC::JSBoundFunction::create(
- vm,
- globalObject,
- onLoadFunction,
- WRAP_BUNDLER_PLUGIN(bundlerPlugin),
- JSC::ArgList(),
- 1,
- jsString(vm, String("onLoad"_s)));
-
- JSC::JSBoundFunction* boundOnResolveFunction = JSC::JSBoundFunction::create(
- vm,
- globalObject,
- onResolveFunction,
- WRAP_BUNDLER_PLUGIN(bundlerPlugin),
- JSC::ArgList(),
- 1,
- jsString(vm, String("onResolve"_s)));
-
- bundlerPlugin->ref();
- vm.heap.addFinalizer(boundOnLoadFunction, [bundlerPlugin](JSC::JSCell* cell) {
- bundlerPlugin->deref();
- });
-
- bundlerPlugin->ref();
- vm.heap.addFinalizer(boundOnResolveFunction, [bundlerPlugin](JSC::JSCell* cell) {
- bundlerPlugin->deref();
- });
-
- builderObject->putDirect(
- vm,
- JSC::Identifier::fromString(vm, "onLoad"_s),
- boundOnLoadFunction,
- JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0);
- builderObject->putDirect(
- vm,
- JSC::Identifier::fromString(vm, "onResolve"_s),
- boundOnResolveFunction,
- JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0);
-
- JSC::MarkedArgumentBuffer args;
- args.append(builderObject);
-
- JSFunction* function = jsCast<JSFunction*>(setupFunctionValue);
- JSC::CallData callData = JSC::getCallData(function);
- JSValue result = call(globalObject, function, callData, JSC::jsUndefined(), args);
-
- RETURN_IF_EXCEPTION(throwScope, JSValue::encode(throwScope.exception()));
+ bool isOnLoad = callFrame->argument(2).toNumber(globalObject) == 1;
+ auto& vm = globalObject->vm();
- if (auto* promise = JSC::jsDynamicCast<JSC::JSPromise*>(result)) {
- RELEASE_AND_RETURN(throwScope, JSValue::encode(promise));
+ if (isOnLoad) {
+ thisObject->plugin.onLoad.append(vm, regExp->regExp(), namespaceStr);
+ } else {
+ thisObject->plugin.onResolve.append(vm, regExp->regExp(), namespaceStr);
}
- RELEASE_AND_RETURN(throwScope, JSValue::encode(jsUndefined()));
+ return JSC::JSValue::encode(JSC::jsUndefined());
}
-void JSBundlerPlugin::Group::append(JSC::VM& vm, JSC::RegExp* filter, JSC::JSFunction* func)
+JSC_DEFINE_HOST_FUNCTION(jsBundlerPluginFunction_addError, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame))
{
- Yarr::RegularExpression regex(
- StringView(filter->pattern()),
- filter->flags().contains(Yarr::Flags::IgnoreCase) ? Yarr::TextCaseSensitivity::TextCaseInsensitive : Yarr::TextCaseSensitivity::TextCaseInsensitive,
- filter->multiline() ? Yarr::MultilineMode::MultilineEnabled : Yarr::MultilineMode::MultilineDisabled,
- filter->eitherUnicode() ? Yarr::UnicodeMode::UnicodeAwareMode : Yarr::UnicodeMode::UnicodeUnawareMode);
- filters.append(WTFMove(regex));
- callbacks.append(JSC::Strong<JSC::JSFunction> { vm, func });
-}
+ JSBundlerPlugin* thisObject = jsCast<JSBundlerPlugin*>(callFrame->thisValue());
+ if (!thisObject->plugin.tombstoned) {
+ JSBundlerPlugin__addError(
+ UNWRAP_BUNDLER_PLUGIN(callFrame),
+ thisObject->plugin.config,
+ JSValue::encode(callFrame->argument(1)),
+ JSValue::encode(callFrame->argument(2)));
+ }
-void JSBundlerPlugin::Base::append(JSC::VM& vm, JSC::RegExp* filter, JSC::JSFunction* func, String& namespaceString)
+ return JSC::JSValue::encode(JSC::jsUndefined());
+}
+JSC_DEFINE_HOST_FUNCTION(jsBundlerPluginFunction_onLoadAsync, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame))
{
- if (namespaceString.isEmpty() || namespaceString == "file"_s) {
- this->fileNamespace.append(vm, filter, func);
- } else if (auto found = this->group(namespaceString)) {
- found->append(vm, filter, func);
- } else {
- Group newGroup;
- newGroup.append(vm, filter, func);
- this->groups.append(WTFMove(newGroup));
- this->namespaces.append(namespaceString);
+ JSBundlerPlugin* thisObject = jsCast<JSBundlerPlugin*>(callFrame->thisValue());
+ if (!thisObject->plugin.tombstoned) {
+ JSBundlerPlugin__onLoadAsync(
+ UNWRAP_BUNDLER_PLUGIN(callFrame),
+ thisObject->plugin.config,
+ JSValue::encode(callFrame->argument(1)),
+ JSValue::encode(callFrame->argument(2)));
}
-}
-JSFunction* JSBundlerPlugin::Group::find(String& path)
+ return JSC::JSValue::encode(JSC::jsUndefined());
+}
+JSC_DEFINE_HOST_FUNCTION(jsBundlerPluginFunction_onResolveAsync, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame))
{
- size_t count = filters.size();
- for (size_t i = 0; i < count; i++) {
- int matchLength = 0;
- if (filters[i].match(path, 0, &matchLength)) {
- return callbacks[i].get();
- }
+ JSBundlerPlugin* thisObject = jsCast<JSBundlerPlugin*>(callFrame->thisValue());
+ if (!thisObject->plugin.tombstoned) {
+ JSBundlerPlugin__onResolveAsync(
+ UNWRAP_BUNDLER_PLUGIN(callFrame),
+ thisObject->plugin.config,
+ JSValue::encode(callFrame->argument(1)),
+ JSValue::encode(callFrame->argument(2)),
+ JSValue::encode(callFrame->argument(3)));
}
- return nullptr;
+ return JSC::JSValue::encode(JSC::jsUndefined());
}
-EncodedJSValue JSBundlerPlugin::OnResolve::run(const ZigString* namespaceString, const ZigString* path, const ZigString* importer, void* context)
+void JSBundlerPlugin::finishCreation(JSC::VM& vm)
{
- Group* groupPtr = this->group(namespaceString ? Zig::toString(*namespaceString) : String());
- if (groupPtr == nullptr) {
- return JSValue::encode(jsUndefined());
- }
- Group& group = *groupPtr;
-
- auto pathString = Zig::toString(*path);
+ Base::finishCreation(vm);
+ ASSERT(inherits(vm, info()));
+ this->onLoadFunction.initLater(
+ [](const JSC::LazyProperty<JSBundlerPlugin, JSC::JSFunction>::Initializer& init) {
+ auto& vm = init.vm;
+ auto* globalObject = init.owner->globalObject();
+
+ init.set(
+ JSC::JSFunction::create(vm, WebCore::bundlerPluginRunOnLoadPluginsCodeGenerator(vm), globalObject));
+ });
+
+ this->onResolveFunction.initLater(
+ [](const JSC::LazyProperty<JSBundlerPlugin, JSC::JSFunction>::Initializer& init) {
+ auto& vm = init.vm;
+ auto* globalObject = init.owner->globalObject();
+
+ init.set(
+ JSC::JSFunction::create(vm, WebCore::bundlerPluginRunOnResolvePluginsCodeGenerator(vm), globalObject));
+ });
+
+ this->setupFunction.initLater(
+ [](const JSC::LazyProperty<JSBundlerPlugin, JSC::JSFunction>::Initializer& init) {
+ auto& vm = init.vm;
+ auto* globalObject = init.owner->globalObject();
+
+ init.set(
+ JSC::JSFunction::create(vm, WebCore::bundlerPluginRunSetupFunctionCodeGenerator(vm), globalObject));
+ });
+
+ auto* clientData = WebCore::clientData(vm);
+
+ this->putDirect(vm, Identifier::fromString(vm, String("onLoad"_s)), jsUndefined(), 0);
+ this->putDirect(vm, Identifier::fromString(vm, String("onResolve"_s)), jsUndefined(), 0);
+ reifyStaticProperties(vm, JSBundlerPlugin::info(), JSBundlerPluginHashTable, *this);
+}
- JSC::JSFunction* function = group.find(pathString);
- if (!function) {
- return JSValue::encode(JSC::jsUndefined());
- }
+extern "C" bool JSBundlerPlugin__anyMatches(Bun::JSBundlerPlugin* pluginObject, const ZigString* namespaceString, const ZigString* path, bool isOnLoad)
+{
+ return pluginObject->plugin.anyMatchesCrossThread(namespaceString, path, isOnLoad);
+}
- JSC::MarkedArgumentBuffer arguments;
- JSC::JSGlobalObject* globalObject = function->globalObject();
- auto& vm = globalObject->vm();
+extern "C" void JSBundlerPlugin__matchOnLoad(JSC::JSGlobalObject* globalObject, Bun::JSBundlerPlugin* plugin, const ZigString* namespaceString, const ZigString* path, void* context, uint8_t defaultLoaderId)
+{
+ WTF::String namespaceStringStr = namespaceString ? Zig::toStringCopy(*namespaceString) : WTF::String();
+ WTF::String pathStr = path ? Zig::toStringCopy(*path) : WTF::String();
- JSC::JSObject* paramsObject = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype(), 2);
- auto clientData = WebCore::clientData(vm);
- auto& builtinNames = clientData->builtinNames();
- paramsObject->putDirect(
- vm, clientData->builtinNames().pathPublicName(),
- Zig::toJSStringValue(*path, globalObject));
- paramsObject->putDirect(
- vm, clientData->builtinNames().importerPublicName(),
- Zig::toJSStringValue(*importer, globalObject));
- arguments.append(paramsObject);
-
- auto throwScope = DECLARE_THROW_SCOPE(vm);
- auto scope = DECLARE_CATCH_SCOPE(vm);
- scope.assertNoExceptionExceptTermination();
+ JSFunction* function = plugin->onLoadFunction.get(plugin);
+ if (UNLIKELY(!function))
+ return;
JSC::CallData callData = JSC::getCallData(function);
- auto result = call(globalObject, function, callData, JSC::jsUndefined(), arguments);
- if (UNLIKELY(scope.exception())) {
- return JSValue::encode(scope.exception());
- }
+ if (UNLIKELY(callData.type == JSC::CallData::Type::None))
+ return;
- if (auto* promise = JSC::jsDynamicCast<JSPromise*>(result)) {
- switch (promise->status(vm)) {
- case JSPromise::Status::Pending: {
- return JSValue::encode(promise);
- }
- case JSPromise::Status::Rejected: {
- promise->internalField(JSC::JSPromise::Field::Flags).set(vm, promise, jsNumber(static_cast<unsigned>(JSC::JSPromise::Status::Fulfilled)));
- result = promise->result(vm);
- return JSValue::encode(result);
- }
- case JSPromise::Status::Fulfilled: {
- result = promise->result(vm);
- break;
- }
+ auto scope = DECLARE_CATCH_SCOPE(plugin->vm());
+ JSC::MarkedArgumentBuffer arguments;
+ arguments.append(WRAP_BUNDLER_PLUGIN(context));
+ arguments.append(JSC::jsString(plugin->vm(), pathStr));
+ arguments.append(JSC::jsString(plugin->vm(), namespaceStringStr));
+ arguments.append(JSC::jsNumber(defaultLoaderId));
+
+ auto result = call(globalObject, function, callData, plugin, arguments);
+
+ if (scope.exception()) {
+ auto exception = scope.exception();
+ scope.clearException();
+ if (!plugin->plugin.tombstoned) {
+ JSBundlerPlugin__addError(
+ context,
+ plugin->plugin.config,
+ JSC::JSValue::encode(exception),
+ JSValue::encode(jsNumber(0)));
}
}
-
- if (!result.isObject()) {
- JSC::throwTypeError(globalObject, throwScope, "onLoad() expects an object returned"_s);
- return JSValue::encode({});
- }
-
- RELEASE_AND_RETURN(throwScope, JSValue::encode(result));
}
-EncodedJSValue JSBundlerPlugin::OnLoad::run(const ZigString* namespaceString, const ZigString* path, void* context)
+extern "C" void JSBundlerPlugin__matchOnResolve(JSC::JSGlobalObject* globalObject, Bun::JSBundlerPlugin* plugin, const ZigString* namespaceString, const ZigString* path, const ZigString* importer, void* context, uint8_t kindId)
{
- Group* groupPtr = this->group(namespaceString ? Zig::toString(*namespaceString) : String());
- if (groupPtr == nullptr) {
- return JSValue::encode(jsUndefined());
+ WTF::String namespaceStringStr = namespaceString ? Zig::toStringCopy(*namespaceString) : WTF::String("file"_s);
+ if (namespaceStringStr.length() == 0) {
+ namespaceStringStr = WTF::String("file"_s);
}
- Group& group = *groupPtr;
-
- auto pathString = Zig::toString(*path);
-
- JSC::JSFunction* function = group.find(pathString);
- if (!function) {
- return JSValue::encode(JSC::jsUndefined());
- }
-
- JSC::MarkedArgumentBuffer arguments;
- JSC::JSGlobalObject* globalObject = function->globalObject();
+ WTF::String pathStr = path ? Zig::toStringCopy(*path) : WTF::String();
+ WTF::String importerStr = importer ? Zig::toStringCopy(*importer) : WTF::String();
auto& vm = globalObject->vm();
- auto& callbacks = group.callbacks;
-
- auto& filters = group.filters;
-
- for (size_t i = 0; i < filters.size(); i++) {
- if (!filters[i].match(pathString)) {
- continue;
- }
- JSC::JSFunction* function = callbacks[i].get();
- if (UNLIKELY(!function)) {
- continue;
- }
-
- JSC::MarkedArgumentBuffer arguments;
- JSC::VM& vm = globalObject->vm();
-
- JSC::JSObject* paramsObject = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype(), 1);
- auto clientData = WebCore::clientData(vm);
- auto& builtinNames = clientData->builtinNames();
- paramsObject->putDirect(
- vm, clientData->builtinNames().pathPublicName(),
- Zig::toJSStringValue(*path, globalObject));
- arguments.append(paramsObject);
-
- auto throwScope = DECLARE_THROW_SCOPE(vm);
- auto scope = DECLARE_CATCH_SCOPE(vm);
- scope.assertNoExceptionExceptTermination();
-
- JSC::CallData callData = JSC::getCallData(function);
+ JSFunction* function = plugin->onResolveFunction.get(plugin);
+ if (UNLIKELY(!function))
+ return;
- auto result = call(globalObject, function, callData, JSC::jsUndefined(), arguments);
-
- if (UNLIKELY(!scope.exception() && result && !result.isUndefinedOrNull() && !result.isCell())) {
- throwTypeError(globalObject, throwScope, "onLoad() expects an object returned"_s);
- }
-
- if (UNLIKELY(scope.exception())) {
- JSC::Exception* exception = scope.exception();
- scope.clearException();
- return JSValue::encode(exception);
- }
+ JSC::CallData callData = JSC::getCallData(function);
- result = Bun::handleVirtualModuleResultForJSBundlerPlugin(
- reinterpret_cast<Zig::GlobalObject*>(globalObject),
- result,
- path,
- nullptr,
- context);
-
- if (UNLIKELY(scope.exception())) {
- JSC::Exception* exception = scope.exception();
- scope.clearException();
- return JSValue::encode(exception);
- }
+ if (UNLIKELY(callData.type == JSC::CallData::Type::None))
+ return;
- if (!result || result.isUndefined()) {
- RELEASE_AND_RETURN(throwScope, JSValue::encode(jsUndefined()));
- }
+ auto scope = DECLARE_CATCH_SCOPE(vm);
+ JSC::MarkedArgumentBuffer arguments;
+ arguments.append(JSC::jsString(vm, pathStr));
+ arguments.append(JSC::jsString(vm, namespaceStringStr));
+ arguments.append(JSC::jsString(vm, importerStr));
+ arguments.append(WRAP_BUNDLER_PLUGIN(context));
+ arguments.append(JSC::jsNumber(kindId));
- if (auto* promise = JSC::jsDynamicCast<JSPromise*>(result)) {
- switch (promise->status(vm)) {
- case JSPromise::Status::Pending: {
- RELEASE_AND_RETURN(throwScope, JSValue::encode(result));
- }
- case JSPromise::Status::Rejected: {
- promise->internalField(JSC::JSPromise::Field::Flags).set(vm, promise, jsNumber(static_cast<unsigned>(JSC::JSPromise::Status::Fulfilled)));
- result = promise->result(vm);
- RELEASE_AND_RETURN(throwScope, JSValue::encode(result));
- }
- case JSPromise::Status::Fulfilled: {
- result = promise->result(vm);
- break;
- }
- }
- }
+ auto result = call(globalObject, function, callData, plugin, arguments);
- if (!result.isObject()) {
- JSC::throwTypeError(globalObject, throwScope, "onResolve() expects an object returned"_s);
- JSC::Exception* exception = scope.exception();
- scope.clearException();
- return JSValue::encode(exception);
+ if (UNLIKELY(scope.exception())) {
+ auto exception = JSValue(scope.exception());
+ scope.clearException();
+ if (!plugin->plugin.tombstoned) {
+ JSBundlerPlugin__addError(
+ context,
+ plugin->plugin.config,
+ JSC::JSValue::encode(exception),
+ JSValue::encode(jsNumber(1)));
}
-
- RELEASE_AND_RETURN(throwScope, JSValue::encode(result));
+ return;
}
-
- return JSValue::encode(JSC::jsUndefined());
}
-bool JSBundlerPlugin::anyMatchesCrossThread(const ZigString* namespaceStr, const ZigString* path, bool isOnLoad)
+extern "C" Bun::JSBundlerPlugin* JSBundlerPlugin__create(Zig::GlobalObject* globalObject, BunPluginTarget target)
{
- auto namespaceString = namespaceStr ? Zig::toString(*namespaceStr) : String();
- auto pathString = Zig::toString(*path);
-
- if (isOnLoad) {
- auto* group = this->onLoad.group(namespaceString);
- if (group == nullptr) {
- return false;
- }
+ return JSBundlerPlugin::create(
+ globalObject->vm(),
+ globalObject,
+ // TODO: cache this structure on the global object
+ JSBundlerPlugin::createStructure(
+ globalObject->vm(),
+ globalObject,
+ globalObject->objectPrototype()),
+ nullptr,
+ target);
+}
- auto& filters = group->filters;
+extern "C" EncodedJSValue JSBundlerPlugin__runSetupFunction(
+ Bun::JSBundlerPlugin* plugin,
+ EncodedJSValue encodedSetupFunction)
+{
+ auto& vm = plugin->vm();
+ auto scope = DECLARE_CATCH_SCOPE(vm);
- for (auto& filter : filters) {
- if (filter.match(pathString) > -1) {
- return true;
- }
- }
+ auto* setupFunction = jsCast<JSFunction*>(plugin->setupFunction.get(plugin));
+ if (UNLIKELY(!setupFunction))
+ return JSValue::encode(jsUndefined());
- } else {
- auto* group = this->onResolve.group(namespaceString);
- if (group == nullptr) {
- return false;
- }
+ JSC::CallData callData = JSC::getCallData(setupFunction);
+ if (UNLIKELY(callData.type == JSC::CallData::Type::None))
+ return JSValue::encode(jsUndefined());
- auto& filters = group->filters;
+ MarkedArgumentBuffer arguments;
+ arguments.append(JSValue::decode(encodedSetupFunction));
+ auto* lexicalGlobalObject = jsCast<JSFunction*>(JSValue::decode(encodedSetupFunction))->globalObject();
- for (auto& filter : filters) {
- if (filter.match(pathString) > -1) {
- return true;
- }
- }
+ auto result = JSC::call(lexicalGlobalObject, setupFunction, callData, plugin, arguments);
+ if (UNLIKELY(scope.exception())) {
+ auto exception = scope.exception();
+ scope.clearException();
+ return JSValue::encode(exception);
}
- return false;
-}
-
-} // namespace Bun
-
-extern "C" bool JSBundlerPlugin__anyMatches(Bun::JSBundlerPlugin* plugin, const ZigString* namespaceString, const ZigString* path, bool isOnLoad)
-{
- return plugin->anyMatchesCrossThread(namespaceString, path, isOnLoad);
-}
-
-extern "C" JSC::EncodedJSValue JSBundlerPlugin__matchOnLoad(JSC::JSGlobalObject* globalObject, Bun::JSBundlerPlugin* plugin, const ZigString* namespaceString, const ZigString* path, void* context)
-{
- Ref protect(*plugin);
- return plugin->onLoad.run(
- namespaceString,
- path,
- context);
-}
-
-extern "C" JSC::EncodedJSValue JSBundlerPlugin__matchOnResolve(JSC::JSGlobalObject* globalObject, Bun::JSBundlerPlugin* plugin, const ZigString* namespaceString, const ZigString* path, const ZigString* importer, void* context)
-{
- Ref protect(*plugin);
- return plugin->onResolve.run(
- namespaceString,
- path,
- importer,
- context);
-}
-
-extern "C" Bun::JSBundlerPlugin* JSBundlerPlugin__create(Zig::GlobalObject* globalObject, BunPluginTarget target)
-{
- RefPtr<Bun::JSBundlerPlugin> plugin = adoptRef(*new Bun::JSBundlerPlugin(target, nullptr));
- plugin->ref();
- return plugin.leakRef();
+ return JSValue::encode(result);
}
extern "C" void JSBundlerPlugin__setConfig(Bun::JSBundlerPlugin* plugin, void* config)
{
- plugin->config = config;
+ plugin->plugin.config = config;
}
extern "C" void JSBundlerPlugin__tombestone(Bun::JSBundlerPlugin* plugin)
{
- plugin->tombstone();
- plugin->deref();
+ plugin->plugin.tombstone();
}
+
+} // namespace Bun
diff --git a/src/bun.js/bindings/JSBundlerPlugin.h b/src/bun.js/bindings/JSBundlerPlugin.h
index fde124ccf..6434aab1b 100644
--- a/src/bun.js/bindings/JSBundlerPlugin.h
+++ b/src/bun.js/bindings/JSBundlerPlugin.h
@@ -7,46 +7,29 @@
#include "JavaScriptCore/RegularExpression.h"
#include "helpers.h"
#include <JavaScriptCore/Yarr.h>
+#include <JavaScriptCore/Strong.h>
namespace Bun {
using namespace JSC;
-class JSBundlerPlugin final : public WTF::RefCounted<JSBundlerPlugin> {
+class BundlerPlugin final {
public:
- WTF_MAKE_ISO_ALLOCATED(JSBundlerPlugin);
- static JSBundlerPlugin* create(JSC::JSGlobalObject* globalObject, BunPluginTarget target, void* config = nullptr);
-
- // This is a list of pairs of regexps and functions to match against
- class Group {
-
- public:
- Vector<Yarr::RegularExpression> filters = {};
- Vector<JSC::Strong<JSC::JSFunction>> callbacks = {};
-
- void append(JSC::VM& vm, JSC::RegExp* filter, JSC::JSFunction* func);
- JSFunction* find(String& path);
- void clear()
- {
- filters.clear();
- callbacks.clear();
- }
- };
-
- class Base {
+ class NamespaceList final {
public:
- Group fileNamespace = {};
+ Vector<Yarr::RegularExpression> fileNamespace = {};
Vector<String> namespaces = {};
- Vector<Group> groups = {};
+ Vector<Vector<Yarr::RegularExpression>> groups = {};
BunPluginTarget target { BunPluginTargetBun };
- Group* group(const String& namespaceStr)
+ Vector<Yarr::RegularExpression>* group(const String& namespaceStr)
{
if (namespaceStr.isEmpty()) {
return &fileNamespace;
}
- for (size_t i = 0; i < namespaces.size(); i++) {
+ size_t length = namespaces.size();
+ for (size_t i = 0; i < length; i++) {
if (namespaces[i] == namespaceStr) {
return &groups[i];
}
@@ -55,49 +38,24 @@ public:
return nullptr;
}
- void append(JSC::VM& vm, JSC::RegExp* filter, JSC::JSFunction* func, String& namespaceString);
- };
-
- class OnLoad final : public Base {
-
- public:
- OnLoad()
- : Base()
- {
- }
-
- EncodedJSValue run(const ZigString* namespaceString, const ZigString* path, void* context);
- };
-
- class OnResolve final : public Base {
-
- public:
- OnResolve()
- : Base()
- {
- }
-
- EncodedJSValue run(const ZigString* namespaceString, const ZigString* path, const ZigString* importer, void* context);
+ void append(JSC::VM& vm, JSC::RegExp* filter, String& namespaceString);
};
public:
bool anyMatchesCrossThread(const ZigString* namespaceStr, const ZigString* path, bool isOnLoad);
void tombstone() { tombstoned = true; }
- JSBundlerPlugin(BunPluginTarget target, void* config)
+ BundlerPlugin(void* config, BunPluginTarget target)
{
this->target = target;
this->config = config;
}
- OnLoad onLoad = {};
- OnResolve onResolve = {};
+ NamespaceList onLoad = {};
+ NamespaceList onResolve = {};
BunPluginTarget target { BunPluginTargetBrowser };
void* config { nullptr };
bool tombstoned { false };
-
- using RefCounted::deref;
- using RefCounted::ref;
};
} // namespace Zig \ No newline at end of file
diff --git a/src/bun.js/bindings/ModuleLoader.cpp b/src/bun.js/bindings/ModuleLoader.cpp
index 00b975d88..40e41b083 100644
--- a/src/bun.js/bindings/ModuleLoader.cpp
+++ b/src/bun.js/bindings/ModuleLoader.cpp
@@ -40,56 +40,7 @@ namespace Bun {
using namespace Zig;
using namespace WebCore;
-extern "C" BunLoaderType Bun__getDefaultLoader(JSC::JSGlobalObject*, const ZigString* specifier);
-extern "C" BunLoaderType JSBundlerPlugin__getDefaultLoader(void* context);
-extern "C" void JSBundlerPlugin__OnLoadAsync(void* ctx, EncodedJSValue errorValue, ZigString* sourceCode, BunLoaderType loader);
-OnLoadResult handleOnLoadResult(Zig::GlobalObject* globalObject, JSC::JSValue objectValue, const ZigString* specifier, void* context);
-
-JSValue handleVirtualModuleResultForJSBundlerPlugin(
- Zig::GlobalObject* globalObject,
- JSValue virtualModuleResult,
- const ZigString* specifier,
- const ZigString* referrer,
- void* bundlerPluginContext)
-{
- auto onLoadResult = handleOnLoadResult(globalObject, virtualModuleResult, specifier, bundlerPluginContext);
- JSC::VM& vm = globalObject->vm();
-
- switch (onLoadResult.type) {
- case OnLoadResultTypeCode: {
- JSBundlerPlugin__OnLoadAsync(bundlerPluginContext, JSValue::encode({}), &onLoadResult.value.sourceText.string, onLoadResult.value.sourceText.loader);
- return jsUndefined();
- }
- case OnLoadResultTypeError: {
- JSBundlerPlugin__OnLoadAsync(bundlerPluginContext, JSValue::encode(onLoadResult.value.error), nullptr, BunLoaderTypeNone);
- return jsUndefined();
- }
-
- case OnLoadResultTypePromise: {
- JSFunction* performPromiseThenFunction = globalObject->performPromiseThenFunction();
- auto callData = JSC::getCallData(performPromiseThenFunction);
- ASSERT(callData.type != CallData::Type::None);
- auto specifierString = Zig::toString(*specifier);
- auto referrerString = referrer ? Zig::toString(*referrer) : String();
- PendingVirtualModuleResult* pendingModule = PendingVirtualModuleResult::create(globalObject, specifierString, referrerString, bundlerPluginContext);
- pendingModule->internalField(2).set(vm, pendingModule, virtualModuleResult);
- JSC::JSPromise* promise = pendingModule->promise();
-
- MarkedArgumentBuffer arguments;
- arguments.append(promise);
- arguments.append(globalObject->thenable(jsFunctionOnLoadObjectResultResolveForJSBundlerPlugin));
- arguments.append(globalObject->thenable(jsFunctionOnLoadObjectResultRejectForJSBundlerPlugin));
- arguments.append(jsUndefined());
- arguments.append(pendingModule);
- ASSERT(!arguments.hasOverflowed());
- JSC::call(globalObject, performPromiseThenFunction, callData, jsUndefined(), arguments);
- return promise;
- }
- default: {
- __builtin_unreachable();
- }
- }
-}
+extern "C" BunLoaderType Bun__getDefaultLoader(JSC::JSGlobalObject*, ZigString* specifier);
static JSC::JSInternalPromise* rejectedInternalPromise(JSC::JSGlobalObject* globalObject, JSC::JSValue value)
{
@@ -137,16 +88,11 @@ JSC::JSInternalPromise* PendingVirtualModuleResult::internalPromise()
return jsCast<JSC::JSInternalPromise*>(internalField(2).get());
}
-JSC::JSPromise* PendingVirtualModuleResult::promise()
-{
- return jsCast<JSC::JSPromise*>(internalField(2).get());
-}
-
const ClassInfo PendingVirtualModuleResult::s_info = { "PendingVirtualModule"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(PendingVirtualModuleResult) };
-PendingVirtualModuleResult* PendingVirtualModuleResult::create(VM& vm, Structure* structure, void* bundlerPluginContext)
+PendingVirtualModuleResult* PendingVirtualModuleResult::create(VM& vm, Structure* structure)
{
- PendingVirtualModuleResult* mod = new (NotNull, allocateCell<PendingVirtualModuleResult>(vm)) PendingVirtualModuleResult(vm, structure, bundlerPluginContext);
+ PendingVirtualModuleResult* mod = new (NotNull, allocateCell<PendingVirtualModuleResult>(vm)) PendingVirtualModuleResult(vm, structure);
return mod;
}
Structure* PendingVirtualModuleResult::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
@@ -154,9 +100,8 @@ Structure* PendingVirtualModuleResult::createStructure(VM& vm, JSGlobalObject* g
return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info());
}
-PendingVirtualModuleResult::PendingVirtualModuleResult(VM& vm, Structure* structure, void* bundlerPluginContext)
+PendingVirtualModuleResult::PendingVirtualModuleResult(VM& vm, Structure* structure)
: Base(vm, structure)
- , m_bundlerPluginContext(bundlerPluginContext)
{
}
@@ -165,9 +110,7 @@ void PendingVirtualModuleResult::finishCreation(VM& vm, const WTF::String& speci
Base::finishCreation(vm);
Base::internalField(0).set(vm, this, JSC::jsString(vm, specifier));
Base::internalField(1).set(vm, this, JSC::jsString(vm, referrer));
- if (!this->m_bundlerPluginContext) {
- Base::internalField(2).set(vm, this, JSC::JSInternalPromise::create(vm, globalObject()->internalPromiseStructure()));
- }
+ Base::internalField(2).set(vm, this, JSC::JSInternalPromise::create(vm, globalObject()->internalPromiseStructure()));
}
template<typename Visitor>
@@ -180,22 +123,21 @@ void PendingVirtualModuleResult::visitChildrenImpl(JSCell* cell, Visitor& visito
DEFINE_VISIT_CHILDREN(PendingVirtualModuleResult);
-PendingVirtualModuleResult* PendingVirtualModuleResult::create(JSC::JSGlobalObject* globalObject, const WTF::String& specifier, const WTF::String& referrer, void* bundlerPluginContext)
+PendingVirtualModuleResult* PendingVirtualModuleResult::create(JSC::JSGlobalObject* globalObject, const WTF::String& specifier, const WTF::String& referrer)
{
- auto* virtualModule = create(globalObject->vm(), reinterpret_cast<Zig::GlobalObject*>(globalObject)->pendingVirtualModuleResultStructure(), bundlerPluginContext);
+ auto* virtualModule = create(globalObject->vm(), reinterpret_cast<Zig::GlobalObject*>(globalObject)->pendingVirtualModuleResultStructure());
virtualModule->finishCreation(globalObject->vm(), specifier, referrer);
return virtualModule;
}
-OnLoadResult handleOnLoadResultNotPromise(Zig::GlobalObject* globalObject, JSC::JSValue objectValue, const ZigString* specifier, void* bunPluginContext)
+OnLoadResult handleOnLoadResultNotPromise(Zig::GlobalObject* globalObject, JSC::JSValue objectValue, ZigString* specifier)
{
OnLoadResult result = {};
result.type = OnLoadResultTypeError;
- result.bundlerPluginContext = bunPluginContext;
JSC::VM& vm = globalObject->vm();
result.value.error = JSC::jsUndefined();
auto scope = DECLARE_THROW_SCOPE(vm);
- BunLoaderType loader = bunPluginContext ? JSBundlerPlugin__getDefaultLoader(bunPluginContext) : Bun__getDefaultLoader(globalObject, specifier);
+ BunLoaderType loader = Bun__getDefaultLoader(globalObject, specifier);
if (JSC::Exception* exception = JSC::jsDynamicCast<JSC::Exception*>(objectValue)) {
result.value.error = exception->value();
@@ -269,17 +211,16 @@ OnLoadResult handleOnLoadResultNotPromise(Zig::GlobalObject* globalObject, JSC::
return result;
}
-OnLoadResult handleOnLoadResult(Zig::GlobalObject* globalObject, JSC::JSValue objectValue, const ZigString* specifier, void* context)
+static OnLoadResult handleOnLoadResult(Zig::GlobalObject* globalObject, JSC::JSValue objectValue, ZigString* specifier)
{
if (JSC::JSPromise* promise = JSC::jsDynamicCast<JSC::JSPromise*>(objectValue)) {
OnLoadResult result = {};
result.type = OnLoadResultTypePromise;
result.value.promise = objectValue;
- result.bundlerPluginContext = context;
return result;
}
- return handleOnLoadResultNotPromise(globalObject, objectValue, specifier, context);
+ return handleOnLoadResultNotPromise(globalObject, objectValue, specifier);
}
template<bool allowPromise>
@@ -287,10 +228,10 @@ static JSValue handleVirtualModuleResult(
Zig::GlobalObject* globalObject,
JSValue virtualModuleResult,
ErrorableResolvedSource* res,
- const ZigString* specifier,
- const ZigString* referrer)
+ ZigString* specifier,
+ ZigString* referrer)
{
- auto onLoadResult = handleOnLoadResult(globalObject, virtualModuleResult, specifier, nullptr);
+ auto onLoadResult = handleOnLoadResult(globalObject, virtualModuleResult, specifier);
JSC::VM& vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
@@ -412,8 +353,8 @@ template<bool allowPromise>
static JSValue fetchSourceCode(
Zig::GlobalObject* globalObject,
ErrorableResolvedSource* res,
- const ZigString* specifier,
- const ZigString* referrer)
+ ZigString* specifier,
+ ZigString* referrer)
{
void* bunVM = globalObject->bunVM();
auto& vm = globalObject->vm();
@@ -545,46 +486,6 @@ static JSValue fetchSourceCode(
return rejectOrResolve(JSC::JSSourceCode::create(vm, JSC::SourceCode(WTFMove(provider))));
}
-extern "C" JSC::EncodedJSValue jsFunctionOnLoadObjectResultResolveForJSBundlerPlugin(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame)
-{
- JSC::VM& vm = globalObject->vm();
- ErrorableResolvedSource res = {};
- res.success = false;
- JSC::JSValue objectResult = callFrame->argument(0);
- PendingVirtualModuleResult* pendingModule = JSC::jsCast<PendingVirtualModuleResult*>(callFrame->argument(1));
- JSC::JSValue specifierString = pendingModule->internalField(0).get();
- JSC::JSValue referrerString = pendingModule->internalField(1).get();
- pendingModule->internalField(0).set(vm, pendingModule, JSC::jsUndefined());
- pendingModule->internalField(1).set(vm, pendingModule, JSC::jsUndefined());
- void* bunPluginContext = pendingModule->m_bundlerPluginContext;
- JSC::JSPromise* promise = pendingModule->promise();
-
- ZigString specifier = Zig::toZigString(specifierString, globalObject);
- ZigString referrer = Zig::toZigString(referrerString, globalObject);
- return JSC::JSValue::encode(
- handleVirtualModuleResultForJSBundlerPlugin(reinterpret_cast<Zig::GlobalObject*>(globalObject), objectResult, &specifier, &referrer, bunPluginContext));
-}
-
-extern "C" JSC::EncodedJSValue jsFunctionOnLoadObjectResultRejectForJSBundlerPlugin(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame)
-{
- JSC::VM& vm = globalObject->vm();
- ErrorableResolvedSource res = {};
- JSC::JSValue reason = callFrame->argument(0);
- PendingVirtualModuleResult* pendingModule = JSC::jsCast<PendingVirtualModuleResult*>(callFrame->argument(1));
- JSC::JSValue specifierString = pendingModule->internalField(0).get();
- JSC::JSValue referrerString = pendingModule->internalField(1).get();
- pendingModule->internalField(0).set(vm, pendingModule, JSC::jsUndefined());
- pendingModule->internalField(1).set(vm, pendingModule, JSC::jsUndefined());
-
- ZigString specifier = Zig::toZigString(specifierString, globalObject);
- ZigString referrer = Zig::toZigString(referrerString, globalObject);
- pendingModule->internalField(2).set(vm, pendingModule, JSC::jsUndefined());
-
- JSBundlerPlugin__OnLoadAsync(pendingModule->m_bundlerPluginContext, JSValue::encode(reason), nullptr, BunLoaderTypeNone);
-
- return JSValue::encode(reason);
-}
-
extern "C" JSC::EncodedJSValue jsFunctionOnLoadObjectResultResolve(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame)
{
JSC::VM& vm = globalObject->vm();
@@ -643,8 +544,8 @@ extern "C" JSC::EncodedJSValue jsFunctionOnLoadObjectResultReject(JSC::JSGlobalO
JSValue fetchSourceCodeSync(
Zig::GlobalObject* globalObject,
ErrorableResolvedSource* res,
- const ZigString* specifier,
- const ZigString* referrer)
+ ZigString* specifier,
+ ZigString* referrer)
{
return fetchSourceCode<false>(globalObject, res, specifier, referrer);
}
@@ -652,8 +553,8 @@ JSValue fetchSourceCodeSync(
JSValue fetchSourceCodeAsync(
Zig::GlobalObject* globalObject,
ErrorableResolvedSource* res,
- const ZigString* specifier,
- const ZigString* referrer)
+ ZigString* specifier,
+ ZigString* referrer)
{
return fetchSourceCode<true>(globalObject, res, specifier, referrer);
}
diff --git a/src/bun.js/bindings/ModuleLoader.h b/src/bun.js/bindings/ModuleLoader.h
index f24a8fdb1..9090abcdc 100644
--- a/src/bun.js/bindings/ModuleLoader.h
+++ b/src/bun.js/bindings/ModuleLoader.h
@@ -37,7 +37,6 @@ union OnLoadResultValue {
struct OnLoadResult {
OnLoadResultValue value;
OnLoadResultType type;
- void* bundlerPluginContext { nullptr };
};
class PendingVirtualModuleResult : public JSC::JSInternalFieldObjectImpl<3> {
@@ -56,13 +55,12 @@ public:
[](auto& spaces, auto&& space) { spaces.m_subspaceForPendingVirtualModuleResult = std::forward<decltype(space)>(space); });
}
- JS_EXPORT_PRIVATE static PendingVirtualModuleResult* create(VM&, Structure*, void* bundlerPluginContext = nullptr);
- static PendingVirtualModuleResult* create(JSC::JSGlobalObject* globalObject, const WTF::String& specifier, const WTF::String& referrer, void* bundlerPluginContext = nullptr);
+ JS_EXPORT_PRIVATE static PendingVirtualModuleResult* create(VM&, Structure*);
+ static PendingVirtualModuleResult* create(JSC::JSGlobalObject* globalObject, const WTF::String& specifier, const WTF::String& referrer);
static PendingVirtualModuleResult* createWithInitialValues(VM&, Structure*);
static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
JSC::JSInternalPromise* internalPromise();
- JSC::JSPromise* promise();
static std::array<JSValue, numberOfInternalFields> initialValues()
{
@@ -76,32 +74,21 @@ public:
DECLARE_EXPORT_INFO;
DECLARE_VISIT_CHILDREN;
- void* m_bundlerPluginContext { nullptr };
-
- PendingVirtualModuleResult(JSC::VM&, JSC::Structure*, void* bundlerPluginContext = nullptr);
+ PendingVirtualModuleResult(JSC::VM&, JSC::Structure*);
void finishCreation(JSC::VM&, const WTF::String& specifier, const WTF::String& referrer);
};
-OnLoadResult handleOnLoadResult(Zig::GlobalObject* globalObject, JSC::JSValue objectValue, ZigString* specifier, void* bunPluginContext = nullptr);
-OnLoadResult handleOnLoadResultNotPromise(Zig::GlobalObject* globalObject, JSC::JSValue objectValue, void* bunPluginContext = nullptr);
-
-JSValue handleVirtualModuleResultForJSBundlerPlugin(
- Zig::GlobalObject* globalObject,
- JSValue virtualModuleResult,
- const ZigString* specifier,
- const ZigString* referrer,
- void* bundlerPluginContext);
-
+OnLoadResult handleOnLoadResultNotPromise(Zig::GlobalObject* globalObject, JSC::JSValue objectValue);
JSValue fetchSourceCodeSync(
Zig::GlobalObject* globalObject,
ErrorableResolvedSource* res,
- const ZigString* specifier,
- const ZigString* referrer);
+ ZigString* specifier,
+ ZigString* referrer);
JSValue fetchSourceCodeAsync(
Zig::GlobalObject* globalObject,
ErrorableResolvedSource* res,
- const ZigString* specifier,
- const ZigString* referrer);
+ ZigString* specifier,
+ ZigString* referrer);
} // namespace Bun \ No newline at end of file
diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp
index a00d49343..b969acf4c 100644
--- a/src/bun.js/bindings/ZigGlobalObject.cpp
+++ b/src/bun.js/bindings/ZigGlobalObject.cpp
@@ -3944,10 +3944,6 @@ GlobalObject::PromiseFunctions GlobalObject::promiseHandlerID(EncodedJSValue (*h
return GlobalObject::PromiseFunctions::Bun__TestScope__onReject;
} else if (handler == Bun__TestScope__onResolve) {
return GlobalObject::PromiseFunctions::Bun__TestScope__onResolve;
- } else if (handler == jsFunctionOnLoadObjectResultRejectForJSBundlerPlugin) {
- return GlobalObject::PromiseFunctions::jsFunctionOnLoadObjectResultResolveForJSBundlerPlugin;
- } else if (handler == jsFunctionOnLoadObjectResultResolveForJSBundlerPlugin) {
- return GlobalObject::PromiseFunctions::jsFunctionOnLoadObjectResultRejectForJSBundlerPlugin;
} else if (handler == CallbackJob__onResolve) {
return GlobalObject::PromiseFunctions::CallbackJob__onResolve;
} else if (handler == CallbackJob__onReject) {
diff --git a/src/bun.js/bindings/ZigGlobalObject.h b/src/bun.js/bindings/ZigGlobalObject.h
index e16230b32..0bdfd1d82 100644
--- a/src/bun.js/bindings/ZigGlobalObject.h
+++ b/src/bun.js/bindings/ZigGlobalObject.h
@@ -48,8 +48,6 @@ extern "C" void Bun__reportUnhandledError(JSC__JSGlobalObject*, JSC::EncodedJSVa
// defined in ModuleLoader.cpp
extern "C" JSC::EncodedJSValue jsFunctionOnLoadObjectResultResolve(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame);
extern "C" JSC::EncodedJSValue jsFunctionOnLoadObjectResultReject(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame);
-extern "C" JSC::EncodedJSValue jsFunctionOnLoadObjectResultResolveForJSBundlerPlugin(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame);
-extern "C" JSC::EncodedJSValue jsFunctionOnLoadObjectResultRejectForJSBundlerPlugin(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame);
// #include "EventTarget.h"
// namespace WebCore {
@@ -294,8 +292,6 @@ public:
jsFunctionOnLoadObjectResultResolve,
jsFunctionOnLoadObjectResultReject,
- jsFunctionOnLoadObjectResultResolveForJSBundlerPlugin,
- jsFunctionOnLoadObjectResultRejectForJSBundlerPlugin,
Bun__TestScope__onReject,
Bun__TestScope__onResolve,
@@ -303,7 +299,7 @@ public:
CallbackJob__onResolve,
CallbackJob__onReject,
};
- static constexpr size_t promiseFunctionsSize = 24;
+ static constexpr size_t promiseFunctionsSize = 22;
static PromiseFunctions promiseHandlerID(EncodedJSValue (*handler)(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1));
diff --git a/src/bun.js/bindings/sqlite/JSSQLStatement.h b/src/bun.js/bindings/sqlite/JSSQLStatement.h
index b941ef040..e63b99fbb 100644
--- a/src/bun.js/bindings/sqlite/JSSQLStatement.h
+++ b/src/bun.js/bindings/sqlite/JSSQLStatement.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 Codeblog Corp
+ * Copyright (C) 2023 Codeblog Corp
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/bindings/webcore/DOMClientIsoSubspaces.h b/src/bun.js/bindings/webcore/DOMClientIsoSubspaces.h
index 53b5b6994..1f7419c88 100644
--- a/src/bun.js/bindings/webcore/DOMClientIsoSubspaces.h
+++ b/src/bun.js/bindings/webcore/DOMClientIsoSubspaces.h
@@ -31,6 +31,7 @@ public:
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForCallSite;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForNapiExternal;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForRequireResolveFunction;
+ std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForBundlerPlugin;
#include "ZigGeneratedClasses+DOMClientIsoSubspaces.h"
/* --- bun --- */
diff --git a/src/bun.js/bindings/webcore/DOMIsoSubspaces.h b/src/bun.js/bindings/webcore/DOMIsoSubspaces.h
index 089d12043..d55810fcb 100644
--- a/src/bun.js/bindings/webcore/DOMIsoSubspaces.h
+++ b/src/bun.js/bindings/webcore/DOMIsoSubspaces.h
@@ -31,6 +31,7 @@ public:
std::unique_ptr<IsoSubspace> m_subspaceForCallSite;
std::unique_ptr<IsoSubspace> m_subspaceForNapiExternal;
std::unique_ptr<IsoSubspace> m_subspaceForRequireResolveFunction;
+ std::unique_ptr<IsoSubspace> m_subspaceForBundlerPlugin;
#include "ZigGeneratedClasses+DOMIsoSubspaces.h"
/*-- BUN --*/
diff --git a/src/bun.js/builtins/WebCoreJSBuiltinInternals.cpp b/src/bun.js/builtins/WebCoreJSBuiltinInternals.cpp
index 6cc8f64fe..6d7b0cb04 100644
--- a/src/bun.js/builtins/WebCoreJSBuiltinInternals.cpp
+++ b/src/bun.js/builtins/WebCoreJSBuiltinInternals.cpp
@@ -9,7 +9,7 @@ namespace Zig { class GlobalObject; }
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/WebCoreJSBuiltins.cpp b/src/bun.js/builtins/WebCoreJSBuiltins.cpp
index f5b25a463..492a7b8d1 100644
--- a/src/bun.js/builtins/WebCoreJSBuiltins.cpp
+++ b/src/bun.js/builtins/WebCoreJSBuiltins.cpp
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -33,6 +33,7 @@
// DO NOT EDIT THIS FILE. It is automatically generated from JavaScript files for
// builtins by the script: Source/JavaScriptCore/Scripts/generate-js-builtins.py
+#include "BundlerPluginBuiltins.cpp"
#include "ByteLengthQueuingStrategyBuiltins.cpp"
#include "ConsoleObjectBuiltins.cpp"
#include "CountQueuingStrategyBuiltins.cpp"
diff --git a/src/bun.js/builtins/cpp/BundlerPluginBuiltins.cpp b/src/bun.js/builtins/cpp/BundlerPluginBuiltins.cpp
new file mode 100644
index 000000000..53c357257
--- /dev/null
+++ b/src/bun.js/builtins/cpp/BundlerPluginBuiltins.cpp
@@ -0,0 +1,466 @@
+/*
+ * Copyright (c) 2015 Igalia
+ * Copyright (c) 2015 Igalia S.L.
+ * Copyright (c) 2015 Igalia.
+ * Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
+ * Copyright (c) 2015, 2016, 2017 Canon Inc.
+ * Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+// DO NOT EDIT THIS FILE. It is automatically generated from JavaScript files for
+// builtins by the script: Source/JavaScriptCore/Scripts/generate-js-builtins.py
+
+#include "config.h"
+#include "BundlerPluginBuiltins.h"
+
+#include "WebCoreJSClientData.h"
+#include <JavaScriptCore/IdentifierInlines.h>
+#include <JavaScriptCore/ImplementationVisibility.h>
+#include <JavaScriptCore/Intrinsic.h>
+#include <JavaScriptCore/JSObjectInlines.h>
+#include <JavaScriptCore/VM.h>
+
+namespace WebCore {
+
+const JSC::ConstructAbility s_bundlerPluginRunOnResolvePluginsCodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
+const JSC::ConstructorKind s_bundlerPluginRunOnResolvePluginsCodeConstructorKind = JSC::ConstructorKind::None;
+const JSC::ImplementationVisibility s_bundlerPluginRunOnResolvePluginsCodeImplementationVisibility = JSC::ImplementationVisibility::Public;
+const int s_bundlerPluginRunOnResolvePluginsCodeLength = 3284;
+static const JSC::Intrinsic s_bundlerPluginRunOnResolvePluginsCodeIntrinsic = JSC::NoIntrinsic;
+const char* const s_bundlerPluginRunOnResolvePluginsCode =
+ "(function (\n" \
+ " specifier,\n" \
+ " inputNamespace,\n" \
+ " importer,\n" \
+ " internalID,\n" \
+ " kindId\n" \
+ ") {\n" \
+ " \"use strict\";\n" \
+ "\n" \
+ " //\n" \
+ " const kind = [\n" \
+ " \"entry-point\",\n" \
+ " \"import-statement\",\n" \
+ " \"require-call\",\n" \
+ " \"dynamic-import\",\n" \
+ " \"require-resolve\",\n" \
+ " \"import-rule\",\n" \
+ " \"url-token\",\n" \
+ " \"internal\",\n" \
+ " ][kindId];\n" \
+ "\n" \
+ " var promiseResult = (async (inputPath, inputNamespace, importer, kind) => {\n" \
+ " var results = this.onResolve.@get(inputNamespace);\n" \
+ " if (!resuls) {\n" \
+ " this.onResolveAsync(internalID, null, null, null);\n" \
+ " return null;\n" \
+ " }\n" \
+ "\n" \
+ " for (let [filter, callback] of results) {\n" \
+ " if (filtertest(inputPath)) {\n" \
+ " var result = callback({\n" \
+ " path: inputPath,\n" \
+ " importer,\n" \
+ " namespace: inputNamespace,\n" \
+ " kind,\n" \
+ " });\n" \
+ " while (\n" \
+ " result &&\n" \
+ " @isPromise(result) &&\n" \
+ " (@getPromiseInternalField(result, @promiseFieldFlags) &\n" \
+ " @promiseStateMask) ===\n" \
+ " @promiseStateFulfilled\n" \
+ " ) {\n" \
+ " result = @getPromiseInternalField(\n" \
+ " result,\n" \
+ " @promiseFieldReactionsOrResult\n" \
+ " );\n" \
+ " }\n" \
+ "\n" \
+ " if (result && @isPromise(result)) {\n" \
+ " result = await result;\n" \
+ " }\n" \
+ "\n" \
+ " if (!result || !@isObject(result)) {\n" \
+ " continue;\n" \
+ " }\n" \
+ "\n" \
+ " var {\n" \
+ " path,\n" \
+ " namespace: userNamespace = inputNamespace,\n" \
+ " external,\n" \
+ " } = result;\n" \
+ " if (\n" \
+ " !(typeof path === \"string\") ||\n" \
+ " !(typeof userNamespace === \"string\")\n" \
+ " ) {\n" \
+ " @throwTypeError(\n" \
+ " \"onResolve plugins must return an object with a string 'path' and string 'loader' field\"\n" \
+ " );\n" \
+ " }\n" \
+ "\n" \
+ " if (!path) {\n" \
+ " continue;\n" \
+ " }\n" \
+ "\n" \
+ " if (!userNamespace) {\n" \
+ " userNamespace = inputNamespace;\n" \
+ " }\n" \
+ "\n" \
+ " if (typeof external !== \"boolean\" && !@isUndefinedOrNull(external)) {\n" \
+ " @throwTypeError(\n" \
+ " 'onResolve plugins \"external\" field must be boolean or unspecified'\n" \
+ " );\n" \
+ " }\n" \
+ "\n" \
+ " if (!external) {\n" \
+ " if (userNamespace === \"file\") {\n" \
+ " //\n" \
+ " if (path[0] !== \"/\" || path.includes(\"..\")) {\n" \
+ " @throwTypeError(\n" \
+ " 'onResolve plugin \"path\" must be absolute when the namespace is \"file\"'\n" \
+ " );\n" \
+ " }\n" \
+ " }\n" \
+ "\n" \
+ " if (userNamespace === \"dataurl\") {\n" \
+ " if (!path.startsWith(\"data:\")) {\n" \
+ " @throwTypeError(\n" \
+ " 'onResolve plugin \"path\" must start with \"data:\" when the namespace is\"dataurl\"'\n" \
+ " );\n" \
+ " }\n" \
+ " }\n" \
+ " }\n" \
+ "\n" \
+ " this.onReslveAsync(internalID, path, userNamespace, external);\n" \
+ " return null;\n" \
+ " }\n" \
+ " }\n" \
+ "\n" \
+ " this.onResolveAsync(internalID, null, null, null);\n" \
+ " return null;\n" \
+ " })(specifier, inputNamespace, importer, kind);\n" \
+ "\n" \
+ " while (\n" \
+ " promiseResult &&\n" \
+ " @isPromise(promiseResult) &&\n" \
+ " (@getPromiseInternalField(promiseResult, @promiseFieldFlags) &\n" \
+ " @promiseStateMask) ===\n" \
+ " @promiseStateFulfilled\n" \
+ " ) {\n" \
+ " promiseResult = @getPromiseInternalField(\n" \
+ " promiseResult,\n" \
+ " @promiseFieldReactionsOrResult\n" \
+ " );\n" \
+ " }\n" \
+ "\n" \
+ " if (promiseResult && @isPromise(promiseResult)) {\n" \
+ " promiseResult.then(\n" \
+ " () => {},\n" \
+ " (e) => {\n" \
+ " this.addError(internalID, e, 0);\n" \
+ " }\n" \
+ " );\n" \
+ " }\n" \
+ "})\n" \
+;
+
+const JSC::ConstructAbility s_bundlerPluginRunSetupFunctionCodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
+const JSC::ConstructorKind s_bundlerPluginRunSetupFunctionCodeConstructorKind = JSC::ConstructorKind::None;
+const JSC::ImplementationVisibility s_bundlerPluginRunSetupFunctionCodeImplementationVisibility = JSC::ImplementationVisibility::Public;
+const int s_bundlerPluginRunSetupFunctionCodeLength = 3262;
+static const JSC::Intrinsic s_bundlerPluginRunSetupFunctionCodeIntrinsic = JSC::NoIntrinsic;
+const char* const s_bundlerPluginRunSetupFunctionCode =
+ "(function (setup) {\n" \
+ " \"use strict\";\n" \
+ " var onLoadPlugins = new Map(),\n" \
+ " onResolvePlugins = new Map();\n" \
+ "\n" \
+ " function validate(filterObject, callback, map) {\n" \
+ " if (!filterObject || !@isObject(filterObject)) {\n" \
+ " @throwTypeError('Expected an object with \"filter\" RegExp');\n" \
+ " }\n" \
+ "\n" \
+ " if (!callback || !@isCallable(callback)) {\n" \
+ " @throwTypeError(\"callback must be a function\");\n" \
+ " }\n" \
+ "\n" \
+ " var { filter, namespace = \"file\" } = filterObject;\n" \
+ "\n" \
+ " if (!filter) {\n" \
+ " @throwTypeError('Expected an object with \"filter\" RegExp');\n" \
+ " }\n" \
+ "\n" \
+ " if (!@isRegExpObject(filter)) {\n" \
+ " @throwTypeError(\"filter must be a RegExp\");\n" \
+ " }\n" \
+ "\n" \
+ " if (namespace && !(typeof namespace === \"string\")) {\n" \
+ " @throwTypeError(\"namespace must be a string\");\n" \
+ " }\n" \
+ "\n" \
+ " if (namespace?.length ?? 0) {\n" \
+ " namespace = \"file\";\n" \
+ " }\n" \
+ "\n" \
+ " if (!/^([/@a-zA-Z0-9_\\\\-]+)$/.test(namespace)) {\n" \
+ " @throwTypeError(\"namespace can only contain @a-zA-Z0-9_\\\\-\");\n" \
+ " }\n" \
+ "\n" \
+ " var callbacks = map.@get(namespace);\n" \
+ "\n" \
+ " if (!callbacks) {\n" \
+ " map.@set(namespace, [[filter, callback]]);\n" \
+ " } else {\n" \
+ " @arrayPush(callbacks, [filter, callback]);\n" \
+ " }\n" \
+ " }\n" \
+ "\n" \
+ " function onLoad(filterObject, callback) {\n" \
+ " validate(filterObject, callback, onLoadPlugins);\n" \
+ " }\n" \
+ "\n" \
+ " function onResolve(filterObject, callback) {\n" \
+ " validate(filterObject, callback, onResolvePlugins);\n" \
+ " }\n" \
+ "\n" \
+ " const processSetupResult = () => {\n" \
+ " var anyOnLoad = false,\n" \
+ " anyOnResolve = false;\n" \
+ "\n" \
+ " for (var [namespace, callbacks] of onLoadPlugins.entries()) {\n" \
+ " for (var [filter] of callbacks) {\n" \
+ " this.addFilter(filter, namespace, 1);\n" \
+ " anyOnLoad = true;\n" \
+ " }\n" \
+ " }\n" \
+ "\n" \
+ " for (var [namespace, callbacks] of onResolvePlugins.entries()) {\n" \
+ " for (var [filter] of callbacks) {\n" \
+ " this.addFilter(filter, namespace, 0);\n" \
+ " anyOnResolve = true;\n" \
+ " }\n" \
+ " }\n" \
+ "\n" \
+ " if (anyOnResolve) {\n" \
+ " var onResolveObject = this.onResolve;\n" \
+ " if (!onResolveObject) {\n" \
+ " this.onResolve = onResolvePlugins;\n" \
+ " } else {\n" \
+ " for (var [namespace, callbacks] of onResolvePlugins.entries()) {\n" \
+ " var existing = onResolveObject.@get(namespace);\n" \
+ "\n" \
+ " if (!existing) {\n" \
+ " onResolveObject.@set(namespace, callbacks);\n" \
+ " } else {\n" \
+ " onResolveObject.@set(existing.concat(callbacks));\n" \
+ " }\n" \
+ " }\n" \
+ " }\n" \
+ " }\n" \
+ "\n" \
+ " if (anyOnLoad) {\n" \
+ " var onLoadObject = this.onLoad;\n" \
+ " if (!onLoadObject) {\n" \
+ " this.onLoad = onLoadPlugins;\n" \
+ " } else {\n" \
+ " for (var [namespace, callbacks] of onLoadPlugins.entries()) {\n" \
+ " var existing = onLoadObject.@get(namespace);\n" \
+ "\n" \
+ " if (!existing) {\n" \
+ " onLoadObject.@set(namespace, callbacks);\n" \
+ " } else {\n" \
+ " onLoadObject.@set(existing.concat(callbacks));\n" \
+ " }\n" \
+ " }\n" \
+ " }\n" \
+ " }\n" \
+ "\n" \
+ " return anyOnLoad || anyOnResolve;\n" \
+ " };\n" \
+ "\n" \
+ " var setupResult = setup({\n" \
+ " onLoad,\n" \
+ " onResolve,\n" \
+ " });\n" \
+ "\n" \
+ " if (setupResult && @isPromise(setupResult)) {\n" \
+ " if (\n" \
+ " @getPromiseInternalField(setupResult, @promiseFieldFlags) &\n" \
+ " @promiseStateFulfilled\n" \
+ " ) {\n" \
+ " setupResult = @getPromiseInternalField(\n" \
+ " setupResult,\n" \
+ " @promiseFieldReactionsOrResult\n" \
+ " );\n" \
+ " } else {\n" \
+ " return setupResult.@then(processSetupResult);\n" \
+ " }\n" \
+ " }\n" \
+ "\n" \
+ " return processSetupResult();\n" \
+ "})\n" \
+;
+
+const JSC::ConstructAbility s_bundlerPluginRunOnLoadPluginsCodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
+const JSC::ConstructorKind s_bundlerPluginRunOnLoadPluginsCodeConstructorKind = JSC::ConstructorKind::None;
+const JSC::ImplementationVisibility s_bundlerPluginRunOnLoadPluginsCodeImplementationVisibility = JSC::ImplementationVisibility::Public;
+const int s_bundlerPluginRunOnLoadPluginsCodeLength = 2726;
+static const JSC::Intrinsic s_bundlerPluginRunOnLoadPluginsCodeIntrinsic = JSC::NoIntrinsic;
+const char* const s_bundlerPluginRunOnLoadPluginsCode =
+ "(function (internalID, path, namespace, defaultLoaderId) {\n" \
+ " \"use strict\";\n" \
+ "\n" \
+ " const LOADERS_MAP = {\n" \
+ " jsx: 0,\n" \
+ " js: 1,\n" \
+ " ts: 2,\n" \
+ " tsx: 3,\n" \
+ " css: 4,\n" \
+ " file: 5,\n" \
+ " json: 6,\n" \
+ " toml: 7,\n" \
+ " wasm: 8,\n" \
+ " napi: 9,\n" \
+ " base64: 10,\n" \
+ " dataurl: 11,\n" \
+ " text: 12,\n" \
+ " };\n" \
+ " const loaderName = [\n" \
+ " \"jsx\",\n" \
+ " \"js\",\n" \
+ " \"ts\",\n" \
+ " \"tsx\",\n" \
+ " \"css\",\n" \
+ " \"file\",\n" \
+ " \"json\",\n" \
+ " \"toml\",\n" \
+ " \"wasm\",\n" \
+ " \"napi\",\n" \
+ " \"base64\",\n" \
+ " \"dataurl\",\n" \
+ " \"text\",\n" \
+ " ][defaultLoaderId];\n" \
+ "\n" \
+ " var promiseResult = (async (internalID, path, namespace, defaultLoader) => {\n" \
+ " var results = this.onLoad.@get(namespace);\n" \
+ " if (!results) {\n" \
+ " this.onLoadAsync(internalID, null, null, null);\n" \
+ " return null;\n" \
+ " }\n" \
+ "\n" \
+ " for (let [filter, callback] of results) {\n" \
+ " if (filter.test(path)) {\n" \
+ " var result = callback({\n" \
+ " path,\n" \
+ " namespace,\n" \
+ " loader: defaultLoader,\n" \
+ " });\n" \
+ "\n" \
+ " while (\n" \
+ " result &&\n" \
+ " @isPromise(result) &&\n" \
+ " (@getPromiseInternalField(result, @promiseFieldFlags) &\n" \
+ " @promiseStateMask) ===\n" \
+ " @promiseStateFulfilled\n" \
+ " ) {\n" \
+ " result = @getPromiseInternalField(\n" \
+ " result,\n" \
+ " @promiseFieldReactionsOrResult\n" \
+ " );\n" \
+ " }\n" \
+ "\n" \
+ " if (result && @isPromise(result)) {\n" \
+ " result = await result;\n" \
+ " }\n" \
+ "\n" \
+ " if (!result || !@isObject(result)) {\n" \
+ " continue;\n" \
+ " }\n" \
+ "\n" \
+ " var { contents, loader = defaultLoader } = result;\n" \
+ " if (!(typeof contents === \"string\") && !@isTypedArrayView(contents)) {\n" \
+ " @throwTypeError(\n" \
+ " 'onLoad plugins must return an object with \"contents\" as a string or Uint8Array'\n" \
+ " );\n" \
+ " }\n" \
+ "\n" \
+ " if (!(typeof loader === \"string\")) {\n" \
+ " @throwTypeError(\n" \
+ " 'onLoad plugins must return an object with \"loader\" as a string'\n" \
+ " );\n" \
+ " }\n" \
+ "\n" \
+ " const chosenLoader = LOADERS_MAP[loader];\n" \
+ " if (chosenLoader === @undefined) {\n" \
+ " @throwTypeError('Loader \"' + loader + '\" is not supported.');\n" \
+ " }\n" \
+ "\n" \
+ " this.onLoadAsync(internalID, contents, chosenLoader);\n" \
+ " return null;\n" \
+ " }\n" \
+ " }\n" \
+ "\n" \
+ " this.onLoadAsync(internalID, null, null);\n" \
+ " return null;\n" \
+ " })(internalID, path, namespace, loaderName);\n" \
+ "\n" \
+ " while (\n" \
+ " promiseResult &&\n" \
+ " @isPromise(promiseResult) &&\n" \
+ " (@getPromiseInternalField(promiseResult, @promiseFieldFlags) &\n" \
+ " @promiseStateMask) ===\n" \
+ " @promiseStateFulfilled\n" \
+ " ) {\n" \
+ " promiseResult = @getPromiseInternalField(\n" \
+ " promiseResult,\n" \
+ " @promiseFieldReactionsOrResult\n" \
+ " );\n" \
+ " }\n" \
+ "\n" \
+ " if (promiseResult && @isPromise(promiseResult)) {\n" \
+ " promiseResult.then(\n" \
+ " () => {},\n" \
+ " (e) => {\n" \
+ " this.addError(internalID, e, 0);\n" \
+ " }\n" \
+ " );\n" \
+ " }\n" \
+ "})\n" \
+;
+
+
+#define DEFINE_BUILTIN_GENERATOR(codeName, functionName, overriddenName, argumentCount) \
+JSC::FunctionExecutable* codeName##Generator(JSC::VM& vm) \
+{\
+ JSVMClientData* clientData = static_cast<JSVMClientData*>(vm.clientData); \
+ return clientData->builtinFunctions().bundlerPluginBuiltins().codeName##Executable()->link(vm, nullptr, clientData->builtinFunctions().bundlerPluginBuiltins().codeName##Source(), std::nullopt, s_##codeName##Intrinsic); \
+}
+WEBCORE_FOREACH_BUNDLERPLUGIN_BUILTIN_CODE(DEFINE_BUILTIN_GENERATOR)
+#undef DEFINE_BUILTIN_GENERATOR
+
+
+} // namespace WebCore
diff --git a/src/bun.js/builtins/cpp/BundlerPluginBuiltins.h b/src/bun.js/builtins/cpp/BundlerPluginBuiltins.h
new file mode 100644
index 000000000..91b3233f2
--- /dev/null
+++ b/src/bun.js/builtins/cpp/BundlerPluginBuiltins.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2015 Igalia
+ * Copyright (c) 2015 Igalia S.L.
+ * Copyright (c) 2015 Igalia.
+ * Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
+ * Copyright (c) 2015, 2016, 2017 Canon Inc.
+ * Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+// DO NOT EDIT THIS FILE. It is automatically generated from JavaScript files for
+// builtins by the script: Source/JavaScriptCore/Scripts/generate-js-builtins.py
+
+#pragma once
+
+#include <JavaScriptCore/BuiltinUtils.h>
+#include <JavaScriptCore/Identifier.h>
+#include <JavaScriptCore/JSFunction.h>
+#include <JavaScriptCore/UnlinkedFunctionExecutable.h>
+
+namespace JSC {
+class FunctionExecutable;
+}
+
+namespace WebCore {
+
+/* BundlerPlugin */
+extern const char* const s_bundlerPluginRunOnResolvePluginsCode;
+extern const int s_bundlerPluginRunOnResolvePluginsCodeLength;
+extern const JSC::ConstructAbility s_bundlerPluginRunOnResolvePluginsCodeConstructAbility;
+extern const JSC::ConstructorKind s_bundlerPluginRunOnResolvePluginsCodeConstructorKind;
+extern const JSC::ImplementationVisibility s_bundlerPluginRunOnResolvePluginsCodeImplementationVisibility;
+extern const char* const s_bundlerPluginRunSetupFunctionCode;
+extern const int s_bundlerPluginRunSetupFunctionCodeLength;
+extern const JSC::ConstructAbility s_bundlerPluginRunSetupFunctionCodeConstructAbility;
+extern const JSC::ConstructorKind s_bundlerPluginRunSetupFunctionCodeConstructorKind;
+extern const JSC::ImplementationVisibility s_bundlerPluginRunSetupFunctionCodeImplementationVisibility;
+extern const char* const s_bundlerPluginRunOnLoadPluginsCode;
+extern const int s_bundlerPluginRunOnLoadPluginsCodeLength;
+extern const JSC::ConstructAbility s_bundlerPluginRunOnLoadPluginsCodeConstructAbility;
+extern const JSC::ConstructorKind s_bundlerPluginRunOnLoadPluginsCodeConstructorKind;
+extern const JSC::ImplementationVisibility s_bundlerPluginRunOnLoadPluginsCodeImplementationVisibility;
+
+#define WEBCORE_FOREACH_BUNDLERPLUGIN_BUILTIN_DATA(macro) \
+ macro(runOnResolvePlugins, bundlerPluginRunOnResolvePlugins, 5) \
+ macro(runSetupFunction, bundlerPluginRunSetupFunction, 1) \
+ macro(runOnLoadPlugins, bundlerPluginRunOnLoadPlugins, 4) \
+
+#define WEBCORE_BUILTIN_BUNDLERPLUGIN_RUNONRESOLVEPLUGINS 1
+#define WEBCORE_BUILTIN_BUNDLERPLUGIN_RUNSETUPFUNCTION 1
+#define WEBCORE_BUILTIN_BUNDLERPLUGIN_RUNONLOADPLUGINS 1
+
+#define WEBCORE_FOREACH_BUNDLERPLUGIN_BUILTIN_CODE(macro) \
+ macro(bundlerPluginRunOnResolvePluginsCode, runOnResolvePlugins, ASCIILiteral(), s_bundlerPluginRunOnResolvePluginsCodeLength) \
+ macro(bundlerPluginRunSetupFunctionCode, runSetupFunction, ASCIILiteral(), s_bundlerPluginRunSetupFunctionCodeLength) \
+ macro(bundlerPluginRunOnLoadPluginsCode, runOnLoadPlugins, ASCIILiteral(), s_bundlerPluginRunOnLoadPluginsCodeLength) \
+
+#define WEBCORE_FOREACH_BUNDLERPLUGIN_BUILTIN_FUNCTION_NAME(macro) \
+ macro(runOnLoadPlugins) \
+ macro(runOnResolvePlugins) \
+ macro(runSetupFunction) \
+
+#define DECLARE_BUILTIN_GENERATOR(codeName, functionName, overriddenName, argumentCount) \
+ JSC::FunctionExecutable* codeName##Generator(JSC::VM&);
+
+WEBCORE_FOREACH_BUNDLERPLUGIN_BUILTIN_CODE(DECLARE_BUILTIN_GENERATOR)
+#undef DECLARE_BUILTIN_GENERATOR
+
+class BundlerPluginBuiltinsWrapper : private JSC::WeakHandleOwner {
+public:
+ explicit BundlerPluginBuiltinsWrapper(JSC::VM& vm)
+ : m_vm(vm)
+ WEBCORE_FOREACH_BUNDLERPLUGIN_BUILTIN_FUNCTION_NAME(INITIALIZE_BUILTIN_NAMES)
+#define INITIALIZE_BUILTIN_SOURCE_MEMBERS(name, functionName, overriddenName, length) , m_##name##Source(JSC::makeSource(StringImpl::createWithoutCopying(s_##name, length), { }))
+ WEBCORE_FOREACH_BUNDLERPLUGIN_BUILTIN_CODE(INITIALIZE_BUILTIN_SOURCE_MEMBERS)
+#undef INITIALIZE_BUILTIN_SOURCE_MEMBERS
+ {
+ }
+
+#define EXPOSE_BUILTIN_EXECUTABLES(name, functionName, overriddenName, length) \
+ JSC::UnlinkedFunctionExecutable* name##Executable(); \
+ const JSC::SourceCode& name##Source() const { return m_##name##Source; }
+ WEBCORE_FOREACH_BUNDLERPLUGIN_BUILTIN_CODE(EXPOSE_BUILTIN_EXECUTABLES)
+#undef EXPOSE_BUILTIN_EXECUTABLES
+
+ WEBCORE_FOREACH_BUNDLERPLUGIN_BUILTIN_FUNCTION_NAME(DECLARE_BUILTIN_IDENTIFIER_ACCESSOR)
+
+ void exportNames();
+
+private:
+ JSC::VM& m_vm;
+
+ WEBCORE_FOREACH_BUNDLERPLUGIN_BUILTIN_FUNCTION_NAME(DECLARE_BUILTIN_NAMES)
+
+#define DECLARE_BUILTIN_SOURCE_MEMBERS(name, functionName, overriddenName, length) \
+ JSC::SourceCode m_##name##Source;\
+ JSC::Weak<JSC::UnlinkedFunctionExecutable> m_##name##Executable;
+ WEBCORE_FOREACH_BUNDLERPLUGIN_BUILTIN_CODE(DECLARE_BUILTIN_SOURCE_MEMBERS)
+#undef DECLARE_BUILTIN_SOURCE_MEMBERS
+
+};
+
+#define DEFINE_BUILTIN_EXECUTABLES(name, functionName, overriddenName, length) \
+inline JSC::UnlinkedFunctionExecutable* BundlerPluginBuiltinsWrapper::name##Executable() \
+{\
+ if (!m_##name##Executable) {\
+ JSC::Identifier executableName = functionName##PublicName();\
+ if (overriddenName)\
+ executableName = JSC::Identifier::fromString(m_vm, overriddenName);\
+ m_##name##Executable = JSC::Weak<JSC::UnlinkedFunctionExecutable>(JSC::createBuiltinExecutable(m_vm, m_##name##Source, executableName, s_##name##ImplementationVisibility, s_##name##ConstructorKind, s_##name##ConstructAbility), this, &m_##name##Executable);\
+ }\
+ return m_##name##Executable.get();\
+}
+WEBCORE_FOREACH_BUNDLERPLUGIN_BUILTIN_CODE(DEFINE_BUILTIN_EXECUTABLES)
+#undef DEFINE_BUILTIN_EXECUTABLES
+
+inline void BundlerPluginBuiltinsWrapper::exportNames()
+{
+#define EXPORT_FUNCTION_NAME(name) m_vm.propertyNames->appendExternalName(name##PublicName(), name##PrivateName());
+ WEBCORE_FOREACH_BUNDLERPLUGIN_BUILTIN_FUNCTION_NAME(EXPORT_FUNCTION_NAME)
+#undef EXPORT_FUNCTION_NAME
+}
+
+} // namespace WebCore
diff --git a/src/bun.js/builtins/cpp/ByteLengthQueuingStrategyBuiltins.cpp b/src/bun.js/builtins/cpp/ByteLengthQueuingStrategyBuiltins.cpp
index bea8d88c3..3f5c2e8d7 100644
--- a/src/bun.js/builtins/cpp/ByteLengthQueuingStrategyBuiltins.cpp
+++ b/src/bun.js/builtins/cpp/ByteLengthQueuingStrategyBuiltins.cpp
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/ByteLengthQueuingStrategyBuiltins.h b/src/bun.js/builtins/cpp/ByteLengthQueuingStrategyBuiltins.h
index fc56f2911..29c6f2830 100644
--- a/src/bun.js/builtins/cpp/ByteLengthQueuingStrategyBuiltins.h
+++ b/src/bun.js/builtins/cpp/ByteLengthQueuingStrategyBuiltins.h
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/ConsoleObjectBuiltins.cpp b/src/bun.js/builtins/cpp/ConsoleObjectBuiltins.cpp
index 3c00ec702..438c84b67 100644
--- a/src/bun.js/builtins/cpp/ConsoleObjectBuiltins.cpp
+++ b/src/bun.js/builtins/cpp/ConsoleObjectBuiltins.cpp
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/ConsoleObjectBuiltins.h b/src/bun.js/builtins/cpp/ConsoleObjectBuiltins.h
index 975394c5f..128468602 100644
--- a/src/bun.js/builtins/cpp/ConsoleObjectBuiltins.h
+++ b/src/bun.js/builtins/cpp/ConsoleObjectBuiltins.h
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/CountQueuingStrategyBuiltins.cpp b/src/bun.js/builtins/cpp/CountQueuingStrategyBuiltins.cpp
index 10ec153ba..7690a83de 100644
--- a/src/bun.js/builtins/cpp/CountQueuingStrategyBuiltins.cpp
+++ b/src/bun.js/builtins/cpp/CountQueuingStrategyBuiltins.cpp
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/CountQueuingStrategyBuiltins.h b/src/bun.js/builtins/cpp/CountQueuingStrategyBuiltins.h
index 06811f00a..b03125a76 100644
--- a/src/bun.js/builtins/cpp/CountQueuingStrategyBuiltins.h
+++ b/src/bun.js/builtins/cpp/CountQueuingStrategyBuiltins.h
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/ImportMetaObjectBuiltins.cpp b/src/bun.js/builtins/cpp/ImportMetaObjectBuiltins.cpp
index ca1efe026..83a2ba8c2 100644
--- a/src/bun.js/builtins/cpp/ImportMetaObjectBuiltins.cpp
+++ b/src/bun.js/builtins/cpp/ImportMetaObjectBuiltins.cpp
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/ImportMetaObjectBuiltins.h b/src/bun.js/builtins/cpp/ImportMetaObjectBuiltins.h
index 1a7c5d844..b5a4f6e6b 100644
--- a/src/bun.js/builtins/cpp/ImportMetaObjectBuiltins.h
+++ b/src/bun.js/builtins/cpp/ImportMetaObjectBuiltins.h
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/JSBufferConstructorBuiltins.cpp b/src/bun.js/builtins/cpp/JSBufferConstructorBuiltins.cpp
index 11b3325dc..6e663afce 100644
--- a/src/bun.js/builtins/cpp/JSBufferConstructorBuiltins.cpp
+++ b/src/bun.js/builtins/cpp/JSBufferConstructorBuiltins.cpp
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/JSBufferConstructorBuiltins.h b/src/bun.js/builtins/cpp/JSBufferConstructorBuiltins.h
index f9181b402..da990268b 100644
--- a/src/bun.js/builtins/cpp/JSBufferConstructorBuiltins.h
+++ b/src/bun.js/builtins/cpp/JSBufferConstructorBuiltins.h
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/JSBufferPrototypeBuiltins.cpp b/src/bun.js/builtins/cpp/JSBufferPrototypeBuiltins.cpp
index 0b13457e4..8bd695758 100644
--- a/src/bun.js/builtins/cpp/JSBufferPrototypeBuiltins.cpp
+++ b/src/bun.js/builtins/cpp/JSBufferPrototypeBuiltins.cpp
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/JSBufferPrototypeBuiltins.h b/src/bun.js/builtins/cpp/JSBufferPrototypeBuiltins.h
index 60c00bedf..38544b9b5 100644
--- a/src/bun.js/builtins/cpp/JSBufferPrototypeBuiltins.h
+++ b/src/bun.js/builtins/cpp/JSBufferPrototypeBuiltins.h
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/ProcessObjectInternalsBuiltins.cpp b/src/bun.js/builtins/cpp/ProcessObjectInternalsBuiltins.cpp
index 63882fd9a..ecd86f811 100644
--- a/src/bun.js/builtins/cpp/ProcessObjectInternalsBuiltins.cpp
+++ b/src/bun.js/builtins/cpp/ProcessObjectInternalsBuiltins.cpp
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/ProcessObjectInternalsBuiltins.h b/src/bun.js/builtins/cpp/ProcessObjectInternalsBuiltins.h
index a109d2de0..4fcdb4810 100644
--- a/src/bun.js/builtins/cpp/ProcessObjectInternalsBuiltins.h
+++ b/src/bun.js/builtins/cpp/ProcessObjectInternalsBuiltins.h
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/ReadableByteStreamControllerBuiltins.cpp b/src/bun.js/builtins/cpp/ReadableByteStreamControllerBuiltins.cpp
index b55d1782a..9f431a8d0 100644
--- a/src/bun.js/builtins/cpp/ReadableByteStreamControllerBuiltins.cpp
+++ b/src/bun.js/builtins/cpp/ReadableByteStreamControllerBuiltins.cpp
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/ReadableByteStreamControllerBuiltins.h b/src/bun.js/builtins/cpp/ReadableByteStreamControllerBuiltins.h
index 2e19b9d21..20083abbb 100644
--- a/src/bun.js/builtins/cpp/ReadableByteStreamControllerBuiltins.h
+++ b/src/bun.js/builtins/cpp/ReadableByteStreamControllerBuiltins.h
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/ReadableByteStreamInternalsBuiltins.cpp b/src/bun.js/builtins/cpp/ReadableByteStreamInternalsBuiltins.cpp
index 9b5d31790..5d7e20a5c 100644
--- a/src/bun.js/builtins/cpp/ReadableByteStreamInternalsBuiltins.cpp
+++ b/src/bun.js/builtins/cpp/ReadableByteStreamInternalsBuiltins.cpp
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/ReadableByteStreamInternalsBuiltins.h b/src/bun.js/builtins/cpp/ReadableByteStreamInternalsBuiltins.h
index 06ee280bf..aa140d53e 100644
--- a/src/bun.js/builtins/cpp/ReadableByteStreamInternalsBuiltins.h
+++ b/src/bun.js/builtins/cpp/ReadableByteStreamInternalsBuiltins.h
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/ReadableStreamBYOBReaderBuiltins.cpp b/src/bun.js/builtins/cpp/ReadableStreamBYOBReaderBuiltins.cpp
index 28893061f..04264fc40 100644
--- a/src/bun.js/builtins/cpp/ReadableStreamBYOBReaderBuiltins.cpp
+++ b/src/bun.js/builtins/cpp/ReadableStreamBYOBReaderBuiltins.cpp
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/ReadableStreamBYOBReaderBuiltins.h b/src/bun.js/builtins/cpp/ReadableStreamBYOBReaderBuiltins.h
index c1d1a4c7f..54f1985c7 100644
--- a/src/bun.js/builtins/cpp/ReadableStreamBYOBReaderBuiltins.h
+++ b/src/bun.js/builtins/cpp/ReadableStreamBYOBReaderBuiltins.h
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/ReadableStreamBYOBRequestBuiltins.cpp b/src/bun.js/builtins/cpp/ReadableStreamBYOBRequestBuiltins.cpp
index 30ff7eea1..7c67a3443 100644
--- a/src/bun.js/builtins/cpp/ReadableStreamBYOBRequestBuiltins.cpp
+++ b/src/bun.js/builtins/cpp/ReadableStreamBYOBRequestBuiltins.cpp
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/ReadableStreamBYOBRequestBuiltins.h b/src/bun.js/builtins/cpp/ReadableStreamBYOBRequestBuiltins.h
index a5549ad98..497a17bb0 100644
--- a/src/bun.js/builtins/cpp/ReadableStreamBYOBRequestBuiltins.h
+++ b/src/bun.js/builtins/cpp/ReadableStreamBYOBRequestBuiltins.h
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/ReadableStreamBuiltins.cpp b/src/bun.js/builtins/cpp/ReadableStreamBuiltins.cpp
index c8d329052..21c099c56 100644
--- a/src/bun.js/builtins/cpp/ReadableStreamBuiltins.cpp
+++ b/src/bun.js/builtins/cpp/ReadableStreamBuiltins.cpp
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/ReadableStreamBuiltins.h b/src/bun.js/builtins/cpp/ReadableStreamBuiltins.h
index b85038a43..47ebda954 100644
--- a/src/bun.js/builtins/cpp/ReadableStreamBuiltins.h
+++ b/src/bun.js/builtins/cpp/ReadableStreamBuiltins.h
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/ReadableStreamDefaultControllerBuiltins.cpp b/src/bun.js/builtins/cpp/ReadableStreamDefaultControllerBuiltins.cpp
index 27fcaba83..8719e4cc1 100644
--- a/src/bun.js/builtins/cpp/ReadableStreamDefaultControllerBuiltins.cpp
+++ b/src/bun.js/builtins/cpp/ReadableStreamDefaultControllerBuiltins.cpp
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/ReadableStreamDefaultControllerBuiltins.h b/src/bun.js/builtins/cpp/ReadableStreamDefaultControllerBuiltins.h
index 5ae59810a..3925f5fb9 100644
--- a/src/bun.js/builtins/cpp/ReadableStreamDefaultControllerBuiltins.h
+++ b/src/bun.js/builtins/cpp/ReadableStreamDefaultControllerBuiltins.h
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/ReadableStreamDefaultReaderBuiltins.cpp b/src/bun.js/builtins/cpp/ReadableStreamDefaultReaderBuiltins.cpp
index b8f617978..2e8388a4f 100644
--- a/src/bun.js/builtins/cpp/ReadableStreamDefaultReaderBuiltins.cpp
+++ b/src/bun.js/builtins/cpp/ReadableStreamDefaultReaderBuiltins.cpp
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/ReadableStreamDefaultReaderBuiltins.h b/src/bun.js/builtins/cpp/ReadableStreamDefaultReaderBuiltins.h
index b883be6b8..cd061220a 100644
--- a/src/bun.js/builtins/cpp/ReadableStreamDefaultReaderBuiltins.h
+++ b/src/bun.js/builtins/cpp/ReadableStreamDefaultReaderBuiltins.h
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/ReadableStreamInternalsBuiltins.cpp b/src/bun.js/builtins/cpp/ReadableStreamInternalsBuiltins.cpp
index 40f421b56..b7d388218 100644
--- a/src/bun.js/builtins/cpp/ReadableStreamInternalsBuiltins.cpp
+++ b/src/bun.js/builtins/cpp/ReadableStreamInternalsBuiltins.cpp
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/ReadableStreamInternalsBuiltins.h b/src/bun.js/builtins/cpp/ReadableStreamInternalsBuiltins.h
index a617260be..d34758e0b 100644
--- a/src/bun.js/builtins/cpp/ReadableStreamInternalsBuiltins.h
+++ b/src/bun.js/builtins/cpp/ReadableStreamInternalsBuiltins.h
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/StreamInternalsBuiltins.cpp b/src/bun.js/builtins/cpp/StreamInternalsBuiltins.cpp
index 7663e93ef..7f84dd40e 100644
--- a/src/bun.js/builtins/cpp/StreamInternalsBuiltins.cpp
+++ b/src/bun.js/builtins/cpp/StreamInternalsBuiltins.cpp
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/StreamInternalsBuiltins.h b/src/bun.js/builtins/cpp/StreamInternalsBuiltins.h
index 089992d77..b068e244c 100644
--- a/src/bun.js/builtins/cpp/StreamInternalsBuiltins.h
+++ b/src/bun.js/builtins/cpp/StreamInternalsBuiltins.h
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/TransformStreamBuiltins.cpp b/src/bun.js/builtins/cpp/TransformStreamBuiltins.cpp
index ee31dd1aa..7552cc5b0 100644
--- a/src/bun.js/builtins/cpp/TransformStreamBuiltins.cpp
+++ b/src/bun.js/builtins/cpp/TransformStreamBuiltins.cpp
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/TransformStreamBuiltins.h b/src/bun.js/builtins/cpp/TransformStreamBuiltins.h
index 8547fd350..68b36206a 100644
--- a/src/bun.js/builtins/cpp/TransformStreamBuiltins.h
+++ b/src/bun.js/builtins/cpp/TransformStreamBuiltins.h
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/TransformStreamDefaultControllerBuiltins.cpp b/src/bun.js/builtins/cpp/TransformStreamDefaultControllerBuiltins.cpp
index 3584e70ef..696d11c80 100644
--- a/src/bun.js/builtins/cpp/TransformStreamDefaultControllerBuiltins.cpp
+++ b/src/bun.js/builtins/cpp/TransformStreamDefaultControllerBuiltins.cpp
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/TransformStreamDefaultControllerBuiltins.h b/src/bun.js/builtins/cpp/TransformStreamDefaultControllerBuiltins.h
index a38e0111e..b0b75cda8 100644
--- a/src/bun.js/builtins/cpp/TransformStreamDefaultControllerBuiltins.h
+++ b/src/bun.js/builtins/cpp/TransformStreamDefaultControllerBuiltins.h
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/TransformStreamInternalsBuiltins.cpp b/src/bun.js/builtins/cpp/TransformStreamInternalsBuiltins.cpp
index 7a89bff99..329eb52ea 100644
--- a/src/bun.js/builtins/cpp/TransformStreamInternalsBuiltins.cpp
+++ b/src/bun.js/builtins/cpp/TransformStreamInternalsBuiltins.cpp
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/TransformStreamInternalsBuiltins.h b/src/bun.js/builtins/cpp/TransformStreamInternalsBuiltins.h
index 4850ac1fb..b362896c9 100644
--- a/src/bun.js/builtins/cpp/TransformStreamInternalsBuiltins.h
+++ b/src/bun.js/builtins/cpp/TransformStreamInternalsBuiltins.h
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/WebCoreJSBuiltinInternals.h b/src/bun.js/builtins/cpp/WebCoreJSBuiltinInternals.h
index fe709cb07..fde4bb97e 100644
--- a/src/bun.js/builtins/cpp/WebCoreJSBuiltinInternals.h
+++ b/src/bun.js/builtins/cpp/WebCoreJSBuiltinInternals.h
@@ -9,7 +9,7 @@ namespace Zig { class GlobalObject; }
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/WebCoreJSBuiltins.h b/src/bun.js/builtins/cpp/WebCoreJSBuiltins.h
index 598e0948e..63a375248 100644
--- a/src/bun.js/builtins/cpp/WebCoreJSBuiltins.h
+++ b/src/bun.js/builtins/cpp/WebCoreJSBuiltins.h
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -35,6 +35,7 @@
#pragma once
+#include "BundlerPluginBuiltins.h"
#include "ByteLengthQueuingStrategyBuiltins.h"
#include "ConsoleObjectBuiltins.h"
#include "CountQueuingStrategyBuiltins.h"
@@ -65,6 +66,7 @@ class JSBuiltinFunctions {
public:
explicit JSBuiltinFunctions(JSC::VM& vm)
: m_vm(vm)
+ , m_bundlerPluginBuiltins(m_vm)
, m_byteLengthQueuingStrategyBuiltins(m_vm)
, m_consoleObjectBuiltins(m_vm)
, m_countQueuingStrategyBuiltins(m_vm)
@@ -95,6 +97,7 @@ public:
m_writableStreamInternalsBuiltins.exportNames();
}
+ BundlerPluginBuiltinsWrapper& bundlerPluginBuiltins() { return m_bundlerPluginBuiltins; }
ByteLengthQueuingStrategyBuiltinsWrapper& byteLengthQueuingStrategyBuiltins() { return m_byteLengthQueuingStrategyBuiltins; }
ConsoleObjectBuiltinsWrapper& consoleObjectBuiltins() { return m_consoleObjectBuiltins; }
CountQueuingStrategyBuiltinsWrapper& countQueuingStrategyBuiltins() { return m_countQueuingStrategyBuiltins; }
@@ -120,6 +123,7 @@ public:
private:
JSC::VM& m_vm;
+ BundlerPluginBuiltinsWrapper m_bundlerPluginBuiltins;
ByteLengthQueuingStrategyBuiltinsWrapper m_byteLengthQueuingStrategyBuiltins;
ConsoleObjectBuiltinsWrapper m_consoleObjectBuiltins;
CountQueuingStrategyBuiltinsWrapper m_countQueuingStrategyBuiltins;
diff --git a/src/bun.js/builtins/cpp/WritableStreamDefaultControllerBuiltins.cpp b/src/bun.js/builtins/cpp/WritableStreamDefaultControllerBuiltins.cpp
index 90d672297..9da322b83 100644
--- a/src/bun.js/builtins/cpp/WritableStreamDefaultControllerBuiltins.cpp
+++ b/src/bun.js/builtins/cpp/WritableStreamDefaultControllerBuiltins.cpp
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/WritableStreamDefaultControllerBuiltins.h b/src/bun.js/builtins/cpp/WritableStreamDefaultControllerBuiltins.h
index 41e5a62ab..ca7d33d66 100644
--- a/src/bun.js/builtins/cpp/WritableStreamDefaultControllerBuiltins.h
+++ b/src/bun.js/builtins/cpp/WritableStreamDefaultControllerBuiltins.h
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/WritableStreamDefaultWriterBuiltins.cpp b/src/bun.js/builtins/cpp/WritableStreamDefaultWriterBuiltins.cpp
index 580e85d6f..fc00693ca 100644
--- a/src/bun.js/builtins/cpp/WritableStreamDefaultWriterBuiltins.cpp
+++ b/src/bun.js/builtins/cpp/WritableStreamDefaultWriterBuiltins.cpp
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/WritableStreamDefaultWriterBuiltins.h b/src/bun.js/builtins/cpp/WritableStreamDefaultWriterBuiltins.h
index 70d154bcd..fe0a6ef34 100644
--- a/src/bun.js/builtins/cpp/WritableStreamDefaultWriterBuiltins.h
+++ b/src/bun.js/builtins/cpp/WritableStreamDefaultWriterBuiltins.h
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/WritableStreamInternalsBuiltins.cpp b/src/bun.js/builtins/cpp/WritableStreamInternalsBuiltins.cpp
index 44c3e05a4..6b2111f4b 100644
--- a/src/bun.js/builtins/cpp/WritableStreamInternalsBuiltins.cpp
+++ b/src/bun.js/builtins/cpp/WritableStreamInternalsBuiltins.cpp
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/cpp/WritableStreamInternalsBuiltins.h b/src/bun.js/builtins/cpp/WritableStreamInternalsBuiltins.h
index f38a4ac60..bc114276b 100644
--- a/src/bun.js/builtins/cpp/WritableStreamInternalsBuiltins.h
+++ b/src/bun.js/builtins/cpp/WritableStreamInternalsBuiltins.h
@@ -5,7 +5,7 @@
* Copyright (c) 2015, 2016 Canon Inc. All rights reserved.
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
- * Copyright (c) 2022 Codeblog Corp. All rights reserved.
+ * Copyright (c) 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/js/BundlerPlugin.js b/src/bun.js/builtins/js/BundlerPlugin.js
new file mode 100644
index 000000000..70e6a97a5
--- /dev/null
+++ b/src/bun.js/builtins/js/BundlerPlugin.js
@@ -0,0 +1,418 @@
+/*
+ * Copyright (C) 2023 Codeblog Corp. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// This API expects 4 functions:
+// - onLoadAsync
+// - onResolveAsync
+// - addError
+// - addFilter
+//
+// It should be generic enough to reuse for Bun.plugin() eventually, too.
+
+function runOnResolvePlugins(
+ specifier,
+ inputNamespace,
+ importer,
+ internalID,
+ kindId
+) {
+ "use strict";
+
+ // Must be kept in sync with ImportRecord.label
+ const kind = [
+ "entry-point",
+ "import-statement",
+ "require-call",
+ "dynamic-import",
+ "require-resolve",
+ "import-rule",
+ "url-token",
+ "internal",
+ ][kindId];
+
+ var promiseResult = (async (inputPath, inputNamespace, importer, kind) => {
+ var results = this.onResolve.@get(inputNamespace);
+ if (!resuls) {
+ this.onResolveAsync(internalID, null, null, null);
+ return null;
+ }
+
+ for (let [filter, callback] of results) {
+ if (filtertest(inputPath)) {
+ var result = callback({
+ path: inputPath,
+ importer,
+ namespace: inputNamespace,
+ kind,
+ });
+ while (
+ result &&
+ @isPromise(result) &&
+ (@getPromiseInternalField(result, @promiseFieldFlags) &
+ @promiseStateMask) ===
+ @promiseStateFulfilled
+ ) {
+ result = @getPromiseInternalField(
+ result,
+ @promiseFieldReactionsOrResult
+ );
+ }
+
+ if (result && @isPromise(result)) {
+ result = await result;
+ }
+
+ if (!result || !@isObject(result)) {
+ continue;
+ }
+
+ var {
+ path,
+ namespace: userNamespace = inputNamespace,
+ external,
+ } = result;
+ if (
+ !(typeof path === "string") ||
+ !(typeof userNamespace === "string")
+ ) {
+ @throwTypeError(
+ "onResolve plugins must return an object with a string 'path' and string 'loader' field"
+ );
+ }
+
+ if (!path) {
+ continue;
+ }
+
+ if (!userNamespace) {
+ userNamespace = inputNamespace;
+ }
+
+ if (typeof external !== "boolean" && !@isUndefinedOrNull(external)) {
+ @throwTypeError(
+ 'onResolve plugins "external" field must be boolean or unspecified'
+ );
+ }
+
+ if (!external) {
+ if (userNamespace === "file") {
+ // TODO: Windows
+ if (path[0] !== "/" || path.includes("..")) {
+ @throwTypeError(
+ 'onResolve plugin "path" must be absolute when the namespace is "file"'
+ );
+ }
+ }
+
+ if (userNamespace === "dataurl") {
+ if (!path.startsWith("data:")) {
+ @throwTypeError(
+ 'onResolve plugin "path" must start with "data:" when the namespace is"dataurl"'
+ );
+ }
+ }
+ }
+
+ this.onReslveAsync(internalID, path, userNamespace, external);
+ return null;
+ }
+ }
+
+ this.onResolveAsync(internalID, null, null, null);
+ return null;
+ })(specifier, inputNamespace, importer, kind);
+
+ while (
+ promiseResult &&
+ @isPromise(promiseResult) &&
+ (@getPromiseInternalField(promiseResult, @promiseFieldFlags) &
+ @promiseStateMask) ===
+ @promiseStateFulfilled
+ ) {
+ promiseResult = @getPromiseInternalField(
+ promiseResult,
+ @promiseFieldReactionsOrResult
+ );
+ }
+
+ if (promiseResult && @isPromise(promiseResult)) {
+ promiseResult.then(
+ () => {},
+ (e) => {
+ this.addError(internalID, e, 0);
+ }
+ );
+ }
+}
+
+function runSetupFunction(setup) {
+ "use strict";
+ var onLoadPlugins = new Map(),
+ onResolvePlugins = new Map();
+
+ function validate(filterObject, callback, map) {
+ if (!filterObject || !@isObject(filterObject)) {
+ @throwTypeError('Expected an object with "filter" RegExp');
+ }
+
+ if (!callback || !@isCallable(callback)) {
+ @throwTypeError("callback must be a function");
+ }
+
+ var { filter, namespace = "file" } = filterObject;
+
+ if (!filter) {
+ @throwTypeError('Expected an object with "filter" RegExp');
+ }
+
+ if (!@isRegExpObject(filter)) {
+ @throwTypeError("filter must be a RegExp");
+ }
+
+ if (namespace && !(typeof namespace === "string")) {
+ @throwTypeError("namespace must be a string");
+ }
+
+ if (namespace?.length ?? 0) {
+ namespace = "file";
+ }
+
+ if (!/^([/@a-zA-Z0-9_\\-]+)$/.test(namespace)) {
+ @throwTypeError("namespace can only contain @a-zA-Z0-9_\\-");
+ }
+
+ var callbacks = map.@get(namespace);
+
+ if (!callbacks) {
+ map.@set(namespace, [[filter, callback]]);
+ } else {
+ @arrayPush(callbacks, [filter, callback]);
+ }
+ }
+
+ function onLoad(filterObject, callback) {
+ validate(filterObject, callback, onLoadPlugins);
+ }
+
+ function onResolve(filterObject, callback) {
+ validate(filterObject, callback, onResolvePlugins);
+ }
+
+ const processSetupResult = () => {
+ var anyOnLoad = false,
+ anyOnResolve = false;
+
+ for (var [namespace, callbacks] of onLoadPlugins.entries()) {
+ for (var [filter] of callbacks) {
+ this.addFilter(filter, namespace, 1);
+ anyOnLoad = true;
+ }
+ }
+
+ for (var [namespace, callbacks] of onResolvePlugins.entries()) {
+ for (var [filter] of callbacks) {
+ this.addFilter(filter, namespace, 0);
+ anyOnResolve = true;
+ }
+ }
+
+ if (anyOnResolve) {
+ var onResolveObject = this.onResolve;
+ if (!onResolveObject) {
+ this.onResolve = onResolvePlugins;
+ } else {
+ for (var [namespace, callbacks] of onResolvePlugins.entries()) {
+ var existing = onResolveObject.@get(namespace);
+
+ if (!existing) {
+ onResolveObject.@set(namespace, callbacks);
+ } else {
+ onResolveObject.@set(existing.concat(callbacks));
+ }
+ }
+ }
+ }
+
+ if (anyOnLoad) {
+ var onLoadObject = this.onLoad;
+ if (!onLoadObject) {
+ this.onLoad = onLoadPlugins;
+ } else {
+ for (var [namespace, callbacks] of onLoadPlugins.entries()) {
+ var existing = onLoadObject.@get(namespace);
+
+ if (!existing) {
+ onLoadObject.@set(namespace, callbacks);
+ } else {
+ onLoadObject.@set(existing.concat(callbacks));
+ }
+ }
+ }
+ }
+
+ return anyOnLoad || anyOnResolve;
+ };
+
+ var setupResult = setup({
+ onLoad,
+ onResolve,
+ });
+
+ if (setupResult && @isPromise(setupResult)) {
+ if (
+ @getPromiseInternalField(setupResult, @promiseFieldFlags) &
+ @promiseStateFulfilled
+ ) {
+ setupResult = @getPromiseInternalField(
+ setupResult,
+ @promiseFieldReactionsOrResult
+ );
+ } else {
+ return setupResult.@then(processSetupResult);
+ }
+ }
+
+ return processSetupResult();
+}
+
+function runOnLoadPlugins(internalID, path, namespace, defaultLoaderId) {
+ "use strict";
+
+ const LOADERS_MAP = {
+ jsx: 0,
+ js: 1,
+ ts: 2,
+ tsx: 3,
+ css: 4,
+ file: 5,
+ json: 6,
+ toml: 7,
+ wasm: 8,
+ napi: 9,
+ base64: 10,
+ dataurl: 11,
+ text: 12,
+ };
+ const loaderName = [
+ "jsx",
+ "js",
+ "ts",
+ "tsx",
+ "css",
+ "file",
+ "json",
+ "toml",
+ "wasm",
+ "napi",
+ "base64",
+ "dataurl",
+ "text",
+ ][defaultLoaderId];
+
+ var promiseResult = (async (internalID, path, namespace, defaultLoader) => {
+ var results = this.onLoad.@get(namespace);
+ if (!results) {
+ this.onLoadAsync(internalID, null, null, null);
+ return null;
+ }
+
+ for (let [filter, callback] of results) {
+ if (filter.test(path)) {
+ var result = callback({
+ path,
+ namespace,
+ loader: defaultLoader,
+ });
+
+ while (
+ result &&
+ @isPromise(result) &&
+ (@getPromiseInternalField(result, @promiseFieldFlags) &
+ @promiseStateMask) ===
+ @promiseStateFulfilled
+ ) {
+ result = @getPromiseInternalField(
+ result,
+ @promiseFieldReactionsOrResult
+ );
+ }
+
+ if (result && @isPromise(result)) {
+ result = await result;
+ }
+
+ if (!result || !@isObject(result)) {
+ continue;
+ }
+
+ var { contents, loader = defaultLoader } = result;
+ if (!(typeof contents === "string") && !@isTypedArrayView(contents)) {
+ @throwTypeError(
+ 'onLoad plugins must return an object with "contents" as a string or Uint8Array'
+ );
+ }
+
+ if (!(typeof loader === "string")) {
+ @throwTypeError(
+ 'onLoad plugins must return an object with "loader" as a string'
+ );
+ }
+
+ const chosenLoader = LOADERS_MAP[loader];
+ if (chosenLoader === @undefined) {
+ @throwTypeError('Loader "' + loader + '" is not supported.');
+ }
+
+ this.onLoadAsync(internalID, contents, chosenLoader);
+ return null;
+ }
+ }
+
+ this.onLoadAsync(internalID, null, null);
+ return null;
+ })(internalID, path, namespace, loaderName);
+
+ while (
+ promiseResult &&
+ @isPromise(promiseResult) &&
+ (@getPromiseInternalField(promiseResult, @promiseFieldFlags) &
+ @promiseStateMask) ===
+ @promiseStateFulfilled
+ ) {
+ promiseResult = @getPromiseInternalField(
+ promiseResult,
+ @promiseFieldReactionsOrResult
+ );
+ }
+
+ if (promiseResult && @isPromise(promiseResult)) {
+ promiseResult.then(
+ () => {},
+ (e) => {
+ this.addError(internalID, e, 0);
+ }
+ );
+ }
+}
diff --git a/src/bun.js/builtins/js/ConsoleObject.js b/src/bun.js/builtins/js/ConsoleObject.js
index 8601748c6..d51ed08ef 100644
--- a/src/bun.js/builtins/js/ConsoleObject.js
+++ b/src/bun.js/builtins/js/ConsoleObject.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Codeblog Corp. All rights reserved.
+ * Copyright 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/js/ImportMetaObject.js b/src/bun.js/builtins/js/ImportMetaObject.js
index b8d7900c0..e2a9a42d8 100644
--- a/src/bun.js/builtins/js/ImportMetaObject.js
+++ b/src/bun.js/builtins/js/ImportMetaObject.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Codeblog Corp. All rights reserved.
+ * Copyright 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/js/JSBufferConstructor.js b/src/bun.js/builtins/js/JSBufferConstructor.js
index eecd52568..f5389385e 100644
--- a/src/bun.js/builtins/js/JSBufferConstructor.js
+++ b/src/bun.js/builtins/js/JSBufferConstructor.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Codeblog Corp. All rights reserved.
+ * Copyright 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/js/JSBufferPrototype.js b/src/bun.js/builtins/js/JSBufferPrototype.js
index 32aebb3f2..ec22806e2 100644
--- a/src/bun.js/builtins/js/JSBufferPrototype.js
+++ b/src/bun.js/builtins/js/JSBufferPrototype.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Codeblog Corp. All rights reserved.
+ * Copyright 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bun.js/builtins/js/ProcessObjectInternals.js b/src/bun.js/builtins/js/ProcessObjectInternals.js
index d9ab6d88a..82df97f63 100644
--- a/src/bun.js/builtins/js/ProcessObjectInternals.js
+++ b/src/bun.js/builtins/js/ProcessObjectInternals.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Codeblog Corp. All rights reserved.
+ * Copyright 2023 Codeblog Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/bundler/bundle_v2.zig b/src/bundler/bundle_v2.zig
index 335edc033..8277007d0 100644
--- a/src/bundler/bundle_v2.zig
+++ b/src/bundler/bundle_v2.zig
@@ -350,8 +350,8 @@ pub const BundleV2 = struct {
}
fn isDone(ptr: *anyopaque) bool {
- var this = bun.cast(*BundleV2, ptr);
- return this.graph.parse_pending == 0;
+ var this = bun.cast(*const BundleV2, ptr);
+ return this.graph.parse_pending == 0 and this.graph.resolve_pending == 0;
}
pub fn waitForParse(this: *BundleV2) void {
@@ -360,6 +360,167 @@ pub const BundleV2 = struct {
debug("Parsed {d} files, producing {d} ASTs", .{ this.graph.input_files.len, this.graph.ast.len });
}
+ /// This runs on the Bundle Thread.
+ pub fn runResolver(
+ this: *BundleV2,
+ import_record: bun.JSC.API.JSBundler.Resolve.MiniImportRecord,
+ platform: options.Platform,
+ ) void {
+ var resolve_result = this.bundler.resolver.resolve(
+ Fs.PathName.init(import_record.source_file).dirWithTrailingSlash(),
+ import_record.specifier,
+ import_record.kind,
+ ) catch |err| {
+ var handles_import_errors = false;
+ var source: ?*const Logger.Source = null;
+
+ if (import_record.importer_source_index) |importer| {
+ var record: *ImportRecord = &this.graph.ast.items(.import_records)[importer].slice()[import_record.import_record_index];
+ source = &this.graph.input_files.items(.source)[importer];
+ handles_import_errors = record.handles_import_errors;
+
+ // Disable failing packages from being printed.
+ // This may cause broken code to write.
+ // However, doing this means we tell them all the resolve errors
+ // Rather than just the first one.
+ record.path.is_disabled = true;
+ }
+
+ switch (err) {
+ error.ModuleNotFound => {
+ const addError = Logger.Log.addResolveErrorWithTextDupe;
+
+ const path_to_use = import_record.specifier;
+
+ if (!handles_import_errors) {
+ if (isPackagePath(import_record.specifier)) {
+ if (platform.isWebLike() and options.ExternalModules.isNodeBuiltin(path_to_use)) {
+ addError(
+ this.bundler.log,
+ source,
+ import_record.range,
+ this.graph.allocator,
+ "Could not resolve Node.js builtin: \"{s}\".",
+ .{path_to_use},
+ import_record.kind,
+ ) catch unreachable;
+ } else {
+ addError(
+ this.bundler.log,
+ source,
+ import_record.range,
+ this.graph.allocator,
+ "Could not resolve: \"{s}\". Maybe you need to \"bun install\"?",
+ .{path_to_use},
+ import_record.kind,
+ ) catch unreachable;
+ }
+ } else {
+ addError(
+ this.bundler.log,
+ source,
+ import_record.range,
+ this.graph.allocator,
+ "Could not resolve: \"{s}\"",
+ .{
+ path_to_use,
+ },
+ import_record.kind,
+ ) catch unreachable;
+ }
+ }
+ },
+ // assume other errors are already in the log
+ else => {},
+ }
+ return;
+ };
+
+ var out_source_index: ?Index = null;
+
+ var path: *Fs.Path = resolve_result.path() orelse {
+ if (import_record.importer_source_index) |importer| {
+ var record: *ImportRecord = &this.graph.ast.items(.import_records)[importer].slice()[import_record.import_record_index];
+
+ // Disable failing packages from being printed.
+ // This may cause broken code to write.
+ // However, doing this means we tell them all the resolve errors
+ // Rather than just the first one.
+ record.path.is_disabled = true;
+ }
+
+ return;
+ };
+
+ if (resolve_result.is_external) {
+ return;
+ }
+
+ if (path.pretty.ptr == path.text.ptr) {
+ // TODO: outbase
+ const rel = bun.path.relative(this.bundler.fs.top_level_dir, path.text);
+ if (rel.len > 0 and rel[0] != '.') {
+ path.pretty = rel;
+ }
+ }
+
+ var secondary_path_to_copy: ?Fs.Path = null;
+ if (resolve_result.path_pair.secondary) |*secondary| {
+ if (!secondary.is_disabled and
+ secondary != path and
+ !strings.eqlLong(secondary.text, path.text, true))
+ {
+ secondary_path_to_copy = secondary.dupeAlloc(this.graph.allocator) catch @panic("Ran out of memory");
+ }
+ }
+
+ var entry = this.graph.path_to_source_index_map.getOrPut(this.graph.allocator, path.hashKey()) catch @panic("Ran out of memory");
+ if (!entry.found_existing) {
+ path.* = path.dupeAlloc(this.graph.allocator) catch @panic("Ran out of memory");
+
+ // We need to parse this
+ const source_index = Index.init(@intCast(u32, this.graph.ast.len));
+ entry.value_ptr.* = source_index.get();
+ out_source_index = source_index;
+ this.graph.ast.append(this.graph.allocator, js_ast.Ast.empty) catch unreachable;
+ const loader = path.loader(&this.bundler.options.loaders) orelse options.Loader.file;
+
+ this.graph.input_files.append(this.graph.allocator, .{
+ .source = .{
+ .path = path.*,
+ .key_path = path.*,
+ .contents = "",
+ .index = source_index,
+ },
+ .loader = loader,
+ .side_effects = _resolver.SideEffects.has_side_effects,
+ }) catch @panic("Ran out of memory");
+ var task = this.graph.allocator.create(ParseTask) catch @panic("Ran out of memory");
+ task.* = ParseTask.init(&resolve_result, source_index, this);
+ task.loader = loader;
+ task.jsx = this.bundler.options.jsx;
+ task.task.node.next = null;
+ task.tree_shaking = this.linker.options.tree_shaking;
+ task.known_platform = import_record.original_platform;
+
+ this.graph.parse_pending += 1;
+
+ // Handle onLoad plugins
+ if (!this.enqueueOnLoadPluginIfNeeded(task)) {
+ this.graph.pool.pool.schedule(ThreadPoolLib.Batch.from(&task.task));
+ }
+ } else {
+ out_source_index = Index.init(entry.value_ptr.*);
+ }
+
+ if (out_source_index) |source_index| {
+ if (import_record.importer_source_index) |importer| {
+ var record: *ImportRecord = &this.graph.ast.items(.import_records)[importer].slice()[import_record.import_record_index];
+ record.source_index = source_index;
+ }
+ }
+ }
+
pub fn enqueueItem(
this: *BundleV2,
hash: ?u64,
@@ -769,9 +930,29 @@ pub const BundleV2 = struct {
load: *bun.JSC.API.JSBundler.Load,
this: *BundleV2,
) void {
+ debug("onLoad: ({d}, {s})", .{ load.source_index.get(), @tagName(load.value) });
defer load.deinit();
switch (load.value.consume()) {
+ .no_match => {
+ // If it's a file namespace, we should run it through the parser like normal.
+ // The file could be on disk.
+ const source = &this.graph.input_files.items(.source)[load.source_index.get()];
+ if (strings.eqlComptime(source.path.namespace, "file")) {
+ this.graph.pool.pool.schedule(ThreadPoolLib.Batch.from(&load.parse_task.task));
+ return;
+ }
+
+ // When it's not a file, this is a build error and we should report it.
+ // we have no way of loading non-files.
+ this.bundler.log.addErrorFmt(source, Logger.Loc.Empty, bun.default_allocator, "Module not found {} in namespace {}", .{
+ bun.fmt.quote(source.path.pretty),
+ bun.fmt.quote(source.path.namespace),
+ }) catch {};
+
+ // An error ocurred, prevent spinning the event loop forever
+ this.graph.parse_pending -= 1;
+ },
.success => |code| {
this.graph.input_files.items(.loader)[load.source_index.get()] = code.loader;
this.graph.input_files.items(.source)[load.source_index.get()].contents = code.source_code;
@@ -796,11 +977,127 @@ pub const BundleV2 = struct {
}
pub fn onResolve(
- this: *BundleV2,
resolve: *bun.JSC.API.JSBundler.Resolve,
+ this: *BundleV2,
) void {
- _ = this;
defer resolve.deinit();
+ defer this.graph.resolve_pending -= 1;
+ debug("onResolve: ({s}:{s}, {s})", .{ resolve.import_record.namespace, resolve.import_record.specifier, @tagName(resolve.value) });
+
+ switch (resolve.value.consume()) {
+ .no_match => {
+ // If it's a file namespace, we should run it through the resolver like normal.
+ //
+ // The file could be on disk.
+ if (strings.eqlComptime(resolve.import_record.namespace, "file")) {
+ this.runResolver(resolve.import_record, resolve.import_record.original_platform);
+ return;
+ }
+
+ // When it's not a file, this is an error and we should report it.
+ //
+ // We have no way of loading non-files.
+ if (resolve.import_record.kind == .entry_point or resolve.import_record.importer_source_index == null) {
+ this.bundler.log.addErrorFmt(null, Logger.Loc.Empty, this.graph.allocator, "Module not found {} in namespace {}", .{
+ bun.fmt.quote(resolve.import_record.specifier),
+ bun.fmt.quote(resolve.import_record.namespace),
+ }) catch {};
+ } else {
+ const source = &this.graph.input_files.items(.source)[resolve.import_record.importer_source_index.?];
+ this.bundler.log.addRangeErrorFmt(
+ source,
+ resolve.import_record.range,
+ this.graph.allocator,
+ "Module not found {} in namespace {}",
+ .{
+ bun.fmt.quote(resolve.import_record.specifier),
+ bun.fmt.quote(resolve.import_record.namespace),
+ },
+ ) catch {};
+ }
+ },
+ .success => |result| {
+ var out_source_index: ?Index = null;
+ if (!result.external) {
+ this.free_list.appendSlice(&.{ result.namespace, result.path }) catch {};
+
+ var path = Fs.Path.init(result.path);
+ if (path.namespace.len == 0 or strings.eqlComptime(path.namespace, "file")) {
+ path.namespace = "file";
+ } else {
+ path.namespace = result.namespace;
+ }
+
+ var existing = this.graph.path_to_source_index_map.getOrPut(this.graph.allocator, path.hashKey()) catch unreachable;
+ if (!existing.found_existing) {
+ // We need to parse this
+ const source_index = Index.init(@intCast(u32, this.graph.ast.len));
+ existing.value_ptr.* = source_index.get();
+ out_source_index = source_index;
+ this.graph.ast.append(this.graph.allocator, js_ast.Ast.empty) catch unreachable;
+ const loader = path.loader(&this.bundler.options.loaders) orelse options.Loader.file;
+
+ this.graph.input_files.append(this.graph.allocator, .{
+ .source = .{
+ .path = path,
+ .key_path = path,
+ .contents = "",
+ .index = source_index,
+ },
+ .loader = loader,
+ .side_effects = _resolver.SideEffects.has_side_effects,
+ }) catch unreachable;
+ var task = this.graph.allocator.create(ParseTask) catch unreachable;
+ task.* = ParseTask{
+ .ctx = this,
+ .path = path,
+ // unknown at this point:
+ .contents_or_fd = .{
+ .fd = .{
+ .dir = 0,
+ .file = 0,
+ },
+ },
+ .side_effects = _resolver.SideEffects.has_side_effects,
+ .jsx = this.bundler.options.jsx,
+ .source_index = source_index,
+ .module_type = .unknown,
+ .loader = loader,
+ .tree_shaking = this.linker.options.tree_shaking,
+ .known_platform = resolve.import_record.original_platform,
+ };
+ task.task.node.next = null;
+
+ this.graph.parse_pending += 1;
+
+ // Handle onLoad plugins
+ if (!this.enqueueOnLoadPluginIfNeeded(task)) {
+ this.graph.pool.pool.schedule(ThreadPoolLib.Batch.from(&task.task));
+ }
+ } else {
+ out_source_index = Index.init(existing.value_ptr.*);
+ bun.default_allocator.free(result.namespace);
+ bun.default_allocator.free(result.path);
+ }
+ } else {
+ bun.default_allocator.free(result.namespace);
+ bun.default_allocator.free(result.path);
+ }
+
+ if (out_source_index) |source_index| {
+ if (resolve.import_record.importer_source_index) |importer| {
+ var import_record: *ImportRecord = &this.graph.ast.items(.import_records)[importer].slice()[resolve.import_record.import_record_index];
+ import_record.source_index = source_index;
+ }
+ }
+ },
+ .err => |err| {
+ this.bundler.log.msgs.append(err) catch unreachable;
+ this.bundler.log.errors += @as(usize, @boolToInt(err.kind == .err));
+ this.bundler.log.warnings += @as(usize, @boolToInt(err.kind == .warn));
+ },
+ .pending, .consumed => unreachable,
+ }
}
pub fn generateInNewThreadWrap(
@@ -981,10 +1278,52 @@ pub const BundleV2 = struct {
return try this.linker.generateChunksInParallel(chunks);
}
+ pub fn enqueueOnResolvePluginIfNeeded(
+ this: *BundleV2,
+ source_index: Index.Int,
+ import_record: *const ImportRecord,
+ source_file: []const u8,
+ import_record_index: u32,
+ original_platform: ?options.Platform,
+ ) bool {
+ if (this.plugins) |plugins| {
+ if (plugins.hasAnyMatches(&import_record.path, false)) {
+ // This is where onResolve plugins are enqueued
+ var resolve: *JSC.API.JSBundler.Resolve = bun.default_allocator.create(JSC.API.JSBundler.Resolve) catch unreachable;
+ debug("enqueue onResolve: {s}:{s}", .{
+ import_record.path.namespace,
+ import_record.path.text,
+ });
+ _ = @atomicRmw(usize, &this.graph.resolve_pending, .Add, 1, .Monotonic);
+
+ resolve.* = JSC.API.JSBundler.Resolve.create(
+ .{
+ .ImportRecord = .{
+ .record = import_record,
+ .source_file = source_file,
+ .import_record_index = import_record_index,
+ .importer_source_index = source_index,
+ .original_platform = original_platform orelse this.bundler.options.platform,
+ },
+ },
+ this.completion.?,
+ );
+ resolve.dispatch();
+ return true;
+ }
+ }
+
+ return false;
+ }
+
pub fn enqueueOnLoadPluginIfNeeded(this: *BundleV2, parse: *ParseTask) bool {
if (this.plugins) |plugins| {
if (plugins.hasAnyMatches(&parse.path, true)) {
// This is where onLoad plugins are enqueued
+ debug("enqueue onLoad: {s}:{s}", .{
+ parse.path.namespace,
+ parse.path.text,
+ });
var load = bun.default_allocator.create(JSC.API.JSBundler.Load) catch unreachable;
load.* = JSC.API.JSBundler.Load.create(
this.completion.?,
@@ -1079,7 +1418,7 @@ pub const BundleV2 = struct {
// If the same file is imported and required, and those point to different files
// Automatically rewrite it to the secondary one
if (value.secondary_path_for_commonjs_interop) |secondary_path| {
- const secondary_hash = bun.hash(secondary_path.text);
+ const secondary_hash = secondary_path.hashKey();
if (graph.path_to_source_index_map.get(secondary_hash)) |secondary| {
existing.found_existing = true;
existing.value_ptr.* = secondary;
@@ -1512,7 +1851,8 @@ pub const ParseTask = struct {
try resolve_queue.ensureUnusedCapacity(estimated_resolve_queue_count);
var last_error: ?anyerror = null;
- for (ast.import_records.slice()) |*import_record| {
+
+ for (ast.import_records.slice(), 0..) |*import_record, i| {
// Don't resolve the runtime
if (import_record.is_unused or import_record.is_internal) {
continue;
@@ -1562,71 +1902,11 @@ pub const ParseTask = struct {
}
}
- if (resolver.resolve(source_dir, import_record.path.text, import_record.kind)) |_resolved_import| {
- var resolve_result = _resolved_import;
- // if there were errors, lets go ahead and collect them all
- if (last_error != null) continue;
-
- var path: *Fs.Path = resolve_result.path() orelse {
- import_record.path.is_disabled = true;
- import_record.source_index = Index.invalid;
-
- continue;
- };
-
- if (resolve_result.is_external) {
- continue;
- }
-
- var resolve_entry = try resolve_queue.getOrPut(wyhash(0, path.text));
- if (resolve_entry.found_existing) {
- import_record.path = resolve_entry.value_ptr.*.path;
-
- continue;
- }
-
- if (path.pretty.ptr == path.text.ptr) {
- // TODO: outbase
- const rel = bun.path.relative(bundler.fs.top_level_dir, path.text);
- if (rel.len > 0 and rel[0] != '.') {
- path.pretty = rel;
- }
- }
-
- var secondary_path_to_copy: ?Fs.Path = null;
- if (resolve_result.path_pair.secondary) |*secondary| {
- if (!secondary.is_disabled and
- secondary != path and
- !strings.eqlLong(secondary.text, path.text, true))
- {
- secondary_path_to_copy = try secondary.dupeAlloc(allocator);
- }
- }
-
- path.* = try path.dupeAlloc(allocator);
- import_record.path = path.*;
- debug("created ParseTask: {s}", .{path.text});
-
- var resolve_task = bun.default_allocator.create(ParseTask) catch @panic("Ran out of memory");
- resolve_task.* = ParseTask.init(&resolve_result, null, this.ctx);
-
- resolve_task.secondary_path_for_commonjs_interop = secondary_path_to_copy;
-
- if (use_directive != .none) {
- resolve_task.known_platform = platform;
- } else if (task.known_platform) |known_platform| {
- resolve_task.known_platform = known_platform;
- }
-
- resolve_task.jsx.development = task.jsx.development;
-
- if (resolve_task.loader == null) {
- resolve_task.loader = path.loader(&bundler.options.loaders);
- resolve_task.tree_shaking = task.tree_shaking;
- }
+ if (this.ctx.enqueueOnResolvePluginIfNeeded(source.index.get(), import_record, source.path.text, @truncate(u32, i), platform)) {
+ continue;
+ }
- resolve_entry.value_ptr.* = resolve_task;
- } else |err| {
+ var resolve_result = resolver.resolve(source_dir, import_record.path.text, import_record.kind) catch |err| {
// Disable failing packages from being printed.
// This may cause broken code to write.
// However, doing this means we tell them all the resolve errors
@@ -1681,7 +1961,70 @@ pub const ParseTask = struct {
last_error = err;
},
}
+ continue;
+ };
+ // if there were errors, lets go ahead and collect them all
+ if (last_error != null) continue;
+
+ var path: *Fs.Path = resolve_result.path() orelse {
+ import_record.path.is_disabled = true;
+ import_record.source_index = Index.invalid;
+
+ continue;
+ };
+
+ if (resolve_result.is_external) {
+ continue;
+ }
+
+ var resolve_entry = try resolve_queue.getOrPut(wyhash(0, path.text));
+ if (resolve_entry.found_existing) {
+ import_record.path = resolve_entry.value_ptr.*.path;
+
+ continue;
+ }
+
+ if (path.pretty.ptr == path.text.ptr) {
+ // TODO: outbase
+ const rel = bun.path.relative(bundler.fs.top_level_dir, path.text);
+ if (rel.len > 0 and rel[0] != '.') {
+ path.pretty = rel;
+ }
}
+
+ var secondary_path_to_copy: ?Fs.Path = null;
+ if (resolve_result.path_pair.secondary) |*secondary| {
+ if (!secondary.is_disabled and
+ secondary != path and
+ !strings.eqlLong(secondary.text, path.text, true))
+ {
+ secondary_path_to_copy = try secondary.dupeAlloc(allocator);
+ }
+ }
+
+ path.* = try path.dupeAlloc(allocator);
+ import_record.path = path.*;
+ debug("created ParseTask: {s}", .{path.text});
+
+ var resolve_task = bun.default_allocator.create(ParseTask) catch @panic("Ran out of memory");
+ resolve_task.* = ParseTask.init(&resolve_result, null, this.ctx);
+
+ resolve_task.secondary_path_for_commonjs_interop = secondary_path_to_copy;
+
+ if (use_directive != .none) {
+ resolve_task.known_platform = platform;
+ } else if (task.known_platform) |known_platform| {
+ resolve_task.known_platform = known_platform;
+ }
+
+ resolve_task.jsx.development = task.jsx.development;
+
+ if (resolve_task.loader == null) {
+ resolve_task.loader = path.loader(&bundler.options.loaders);
+ resolve_task.tree_shaking = task.tree_shaking;
+ }
+
+ resolve_entry.value_ptr.* = resolve_task;
}
if (last_error) |err| {
@@ -1958,6 +2301,7 @@ pub const Graph = struct {
allocator: std.mem.Allocator = undefined,
parse_pending: usize = 0,
+ resolve_pending: usize = 0,
/// Stable source index mapping
source_index_map: std.AutoArrayHashMapUnmanaged(Index.Int, Ref.Int) = .{},
diff --git a/src/fs.zig b/src/fs.zig
index e7c0df19e..eddd37bca 100644
--- a/src/fs.zig
+++ b/src/fs.zig
@@ -1211,6 +1211,18 @@ pub const Path = struct {
is_disabled: bool = false,
is_symlink: bool = false,
+ pub fn hashKey(this: *const Path) u64 {
+ if (this.namespace.len == 0 or strings.eqlComptime(this.namespace, "file")) {
+ return bun.hash(this.text);
+ }
+
+ var hasher = std.hash.Wyhash.init(0);
+ hasher.update(this.namespace);
+ hasher.update("::::::::");
+ hasher.update(this.text);
+ return hasher.final();
+ }
+
pub fn packageName(this: *const Path) ?string {
var name_to_use = this.pretty;
if (strings.lastIndexOf(this.text, std.fs.path.sep_str ++ "node_modules" ++ std.fs.path.sep_str)) |node_modules| {
diff --git a/src/import_record.zig b/src/import_record.zig
index 6cc86a4ad..dd34fe5d9 100644
--- a/src/import_record.zig
+++ b/src/import_record.zig
@@ -44,6 +44,7 @@ pub const ImportKind = enum(u8) {
labels.set(ImportKind.require_resolve, "require-resolve");
labels.set(ImportKind.at, "import-rule");
labels.set(ImportKind.url, "url-token");
+ labels.set(ImportKind.internal, "internal");
break :brk labels;
};
diff --git a/src/logger.zig b/src/logger.zig
index bee10ff31..a9555c952 100644
--- a/src/logger.zig
+++ b/src/logger.zig
@@ -403,7 +403,12 @@ pub const Msg = struct {
pub fn fromJS(allocator: std.mem.Allocator, globalObject: *bun.JSC.JSGlobalObject, file: string, err: bun.JSC.JSValue) !Msg {
var zig_exception_holder: bun.JSC.ZigException.Holder = bun.JSC.ZigException.Holder.init();
- err.toZigException(globalObject, zig_exception_holder.zigException());
+ if (err.toError()) |value| {
+ value.toZigException(globalObject, zig_exception_holder.zigException());
+ } else {
+ zig_exception_holder.zig_exception.message = JSC.ZigString.fromUTF8(err.toSlice(globalObject, allocator).slice());
+ }
+
return Msg{
.data = .{
.text = zig_exception_holder.zigException().message.toSliceClone(allocator).slice(),
@@ -813,7 +818,7 @@ pub const Log = struct {
inline fn _addResolveErrorWithLevel(
log: *Log,
- source: *const Source,
+ source: ?*const Source,
r: Range,
allocator: std.mem.Allocator,
comptime fmt: string,
@@ -865,7 +870,7 @@ pub const Log = struct {
inline fn _addResolveError(
log: *Log,
- source: *const Source,
+ source: ?*const Source,
r: Range,
allocator: std.mem.Allocator,
comptime fmt: string,
@@ -879,7 +884,7 @@ pub const Log = struct {
inline fn _addResolveWarn(
log: *Log,
- source: *const Source,
+ source: ?*const Source,
r: Range,
allocator: std.mem.Allocator,
comptime fmt: string,
@@ -893,7 +898,7 @@ pub const Log = struct {
pub fn addResolveError(
log: *Log,
- source: *const Source,
+ source: ?*const Source,
r: Range,
allocator: std.mem.Allocator,
comptime fmt: string,
@@ -907,7 +912,7 @@ pub const Log = struct {
pub fn addResolveErrorWithTextDupe(
log: *Log,
- source: *const Source,
+ source: ?*const Source,
r: Range,
allocator: std.mem.Allocator,
comptime fmt: string,
@@ -920,7 +925,7 @@ pub const Log = struct {
pub fn addResolveErrorWithTextDupeMaybeWarn(
log: *Log,
- source: *const Source,
+ source: ?*const Source,
r: Range,
allocator: std.mem.Allocator,
comptime fmt: string,