diff options
author | 2023-04-25 07:27:18 -0700 | |
---|---|---|
committer | 2023-04-25 07:27:18 -0700 | |
commit | 126885e1fe509b69be947d79aacb3ed6efdf666a (patch) | |
tree | bef407938525d69132824ffd3b0b54796035009d | |
parent | 5353d4101493632cb25d0cdddfef94f62bc5902d (diff) | |
download | bun-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>
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, |