mirror of
https://github.com/oven-sh/bun
synced 2026-02-09 10:28:47 +00:00
have name in crash handler
This commit is contained in:
@@ -122,14 +122,27 @@ pub const JSBundler = struct {
|
||||
return globalThis.throwInvalidArguments("Expected plugin to be an object", .{});
|
||||
}
|
||||
|
||||
if (try plugin.getOptional(globalThis, "name", ZigString.Slice)) |slice| {
|
||||
defer slice.deinit();
|
||||
if (slice.len == 0) {
|
||||
const name = name: {
|
||||
var raw_val = try plugin.get(globalThis, "name") orelse {
|
||||
return globalThis.throwInvalidArguments("Expected plugin to have a name", .{});
|
||||
};
|
||||
if (!raw_val.isString()) {
|
||||
return globalThis.throwInvalidArguments("Expected plugin to have a name", .{});
|
||||
}
|
||||
const bunstr: bun.String = try raw_val.toBunString2(globalThis);
|
||||
if (bunstr.length() == 0) {
|
||||
bunstr.deref();
|
||||
return globalThis.throwInvalidArguments("Expected plugin to have a non-empty name", .{});
|
||||
}
|
||||
} else {
|
||||
return globalThis.throwInvalidArguments("Expected plugin to have a name", .{});
|
||||
}
|
||||
if (bunstr.tag != .WTFStringImpl) {
|
||||
var new_bun_str = raw_val.toBunString(globalThis);
|
||||
new_bun_str.toWTF();
|
||||
break :name new_bun_str;
|
||||
}
|
||||
break :name bunstr;
|
||||
};
|
||||
defer name.deref();
|
||||
bun.debugAssert(name.tag == .WTFStringImpl);
|
||||
|
||||
const function = try plugin.getFunction(globalThis, "setup") orelse {
|
||||
return globalThis.throwInvalidArguments("Expected plugin to have a setup() function", .{});
|
||||
@@ -138,6 +151,7 @@ pub const JSBundler = struct {
|
||||
var bun_plugins: *Plugin = plugins.* orelse brk: {
|
||||
plugins.* = Plugin.create(
|
||||
globalThis,
|
||||
name.value.WTFStringImpl,
|
||||
switch (this.target) {
|
||||
.bun, .bun_macro => JSC.JSGlobalObject.BunPluginTarget.bun,
|
||||
.node => JSC.JSGlobalObject.BunPluginTarget.node,
|
||||
@@ -924,10 +938,10 @@ pub const JSBundler = struct {
|
||||
};
|
||||
|
||||
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 {
|
||||
extern fn JSBundlerPlugin__create(*JSC.JSGlobalObject, bun.WTF.StringImpl, JSC.JSGlobalObject.BunPluginTarget) *Plugin;
|
||||
pub fn create(globalObject: *JSC.JSGlobalObject, name: bun.WTF.StringImpl, target: JSC.JSGlobalObject.BunPluginTarget) *Plugin {
|
||||
JSC.markBinding(@src());
|
||||
const plugin = JSBundlerPlugin__create(globalObject, target);
|
||||
const plugin = JSBundlerPlugin__create(globalObject, name, target);
|
||||
JSC.JSValue.fromCell(plugin).protect();
|
||||
return plugin;
|
||||
}
|
||||
|
||||
@@ -113,20 +113,20 @@ static const HashTableValue JSBundlerPluginHashTable[] = {
|
||||
{ "generateDeferPromise"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBundlerPluginFunction_generateDeferPromise, 0 } },
|
||||
};
|
||||
|
||||
|
||||
class JSBundlerPlugin final : public JSC::JSNonFinalObject {
|
||||
public:
|
||||
using Base = JSC::JSNonFinalObject;
|
||||
static JSBundlerPlugin* create(JSC::VM& vm,
|
||||
JSC::JSGlobalObject* globalObject,
|
||||
JSC::Structure* structure,
|
||||
WTF::StringImpl* name,
|
||||
void* config,
|
||||
BunPluginTarget target,
|
||||
JSBundlerPluginAddErrorCallback addError = JSBundlerPlugin__addError,
|
||||
JSBundlerPluginOnLoadAsyncCallback onLoadAsync = JSBundlerPlugin__onLoadAsync,
|
||||
JSBundlerPluginOnResolveAsyncCallback onResolveAsync = JSBundlerPlugin__onResolveAsync)
|
||||
{
|
||||
JSBundlerPlugin* ptr = new (NotNull, JSC::allocateCell<JSBundlerPlugin>(vm)) JSBundlerPlugin(vm, globalObject, structure, config, target,
|
||||
JSBundlerPlugin* ptr = new (NotNull, JSC::allocateCell<JSBundlerPlugin>(vm)) JSBundlerPlugin(vm, globalObject, structure, name, config, target,
|
||||
addError,
|
||||
onLoadAsync,
|
||||
onResolveAsync);
|
||||
@@ -161,10 +161,10 @@ public:
|
||||
WTF::HashMap<WTF::String, void*> onBeforeParseHandles;
|
||||
|
||||
private:
|
||||
JSBundlerPlugin(JSC::VM& vm, JSC::JSGlobalObject*, JSC::Structure* structure, void* config, BunPluginTarget target,
|
||||
JSBundlerPlugin(JSC::VM& vm, JSC::JSGlobalObject*, JSC::Structure* structure, WTF::StringImpl* name, void* config, BunPluginTarget target,
|
||||
JSBundlerPluginAddErrorCallback addError, JSBundlerPluginOnLoadAsyncCallback onLoadAsync, JSBundlerPluginOnResolveAsyncCallback onResolveAsync)
|
||||
: JSC::JSNonFinalObject(vm, structure)
|
||||
, plugin(BundlerPlugin(config, target, addError, onLoadAsync, onResolveAsync))
|
||||
, plugin(BundlerPlugin(config, name, target, addError, onLoadAsync, onResolveAsync))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -250,21 +250,20 @@ void BundlerPlugin::NativePluginList::append(JSC::VM& vm, JSC::RegExp* filter, S
|
||||
|
||||
nsGroup->append(nativeFilterRegexp);
|
||||
}
|
||||
|
||||
|
||||
if (index == std::numeric_limits<unsigned>::max()) {
|
||||
this->fileCallbacks.append(NativePluginCallback{callback, external});
|
||||
this->fileCallbacks.append(NativePluginCallback { callback, external });
|
||||
} else {
|
||||
if (this->namespaceCallbacks.size() <= index) {
|
||||
this->namespaceCallbacks.grow(index + 1);
|
||||
}
|
||||
this->namespaceCallbacks[index].append(NativePluginCallback{callback, external});
|
||||
this->namespaceCallbacks[index].append(NativePluginCallback { callback, external });
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void CrashHandler__setInsideNativePlugin(bool value);
|
||||
extern "C" void CrashHandler__setInsideNativePlugin(bool value, const char* plugin_name);
|
||||
|
||||
|
||||
int BundlerPlugin::NativePluginList::call(JSC::VM& vm, int* shouldContinue, void* bunContextPtr, const BunString* namespaceStr, const BunString* pathString, void* onBeforeParseArgs, void* onBeforeParseResult)
|
||||
int BundlerPlugin::NativePluginList::call(JSC::VM& vm, BundlerPlugin* plugin, int* shouldContinue, void* bunContextPtr, const BunString* namespaceStr, const BunString* pathString, void* onBeforeParseArgs, void* onBeforeParseResult)
|
||||
{
|
||||
unsigned index = 0;
|
||||
const auto* group = this->group(namespaceStr->toWTFString(BunString::ZeroCopy), index);
|
||||
@@ -281,6 +280,11 @@ int BundlerPlugin::NativePluginList::call(JSC::VM& vm, int* shouldContinue, void
|
||||
int count = 0;
|
||||
constexpr bool usesPatternContextBuffer = false;
|
||||
const WTF::String& path = pathString->toWTFString(BunString::ZeroCopy);
|
||||
if (!plugin->name_c.has_value()) {
|
||||
auto plugin_name_c = plugin->name->utf8();
|
||||
plugin->name_c = std::make_optional(plugin_name_c);
|
||||
}
|
||||
CString& plugin_name = plugin->name_c.value();
|
||||
for (size_t i = 0, total = callbacks.size(); i < total && *shouldContinue; ++i) {
|
||||
Yarr::MatchingContextHolder regExpContext(vm, usesPatternContextBuffer, nullptr, Yarr::MatchFrom::CompilerThread);
|
||||
|
||||
@@ -289,13 +293,13 @@ int BundlerPlugin::NativePluginList::call(JSC::VM& vm, int* shouldContinue, void
|
||||
if (group->at(i).first.match(path) > -1) {
|
||||
Bun::NapiExternal* external = callbacks[i].external;
|
||||
if (external) {
|
||||
((OnBeforeParseArguments*) (onBeforeParseArgs))->external = external->value();
|
||||
((OnBeforeParseArguments*)(onBeforeParseArgs))->external = external->value();
|
||||
}
|
||||
|
||||
JSBundlerPluginNativeOnBeforeParseCallback callback = callbacks[i].callback;
|
||||
CrashHandler__setInsideNativePlugin(true);
|
||||
CrashHandler__setInsideNativePlugin(true, plugin_name.data());
|
||||
callback(onBeforeParseArgs, onBeforeParseResult);
|
||||
CrashHandler__setInsideNativePlugin(false);
|
||||
CrashHandler__setInsideNativePlugin(false, nullptr);
|
||||
|
||||
count++;
|
||||
}
|
||||
@@ -352,7 +356,7 @@ JSC_DEFINE_HOST_FUNCTION(jsBundlerPluginFunction_onBeforeParse, (JSC::JSGlobalOb
|
||||
Bun::NapiModuleMeta* meta = (Bun::NapiModuleMeta*)napi_external->value();
|
||||
void* dlopen_handle = meta->dlopenHandle;
|
||||
|
||||
#if OS(WINDOWS)
|
||||
#if OS(WINDOWS)
|
||||
BunString onbefore_parse_symbol_str = Bun::toString(on_before_parse_symbol);
|
||||
void* on_before_parse_symbol_ptr = GetProcAddress(&onbefore_parse_symbol_str);
|
||||
#else
|
||||
@@ -560,7 +564,7 @@ extern "C" void JSBundlerPlugin__matchOnResolve(JSC::JSGlobalObject* globalObjec
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" Bun::JSBundlerPlugin* JSBundlerPlugin__create(Zig::GlobalObject* globalObject, BunPluginTarget target)
|
||||
extern "C" Bun::JSBundlerPlugin* JSBundlerPlugin__create(Zig::GlobalObject* globalObject, WTF::StringImpl* name, BunPluginTarget target)
|
||||
{
|
||||
return JSBundlerPlugin::create(
|
||||
globalObject->vm(),
|
||||
@@ -570,6 +574,7 @@ extern "C" Bun::JSBundlerPlugin* JSBundlerPlugin__create(Zig::GlobalObject* glob
|
||||
globalObject->vm(),
|
||||
globalObject,
|
||||
globalObject->objectPrototype()),
|
||||
name,
|
||||
nullptr,
|
||||
target);
|
||||
}
|
||||
@@ -634,7 +639,7 @@ extern "C" int JSBundlerPlugin__callOnBeforeParsePlugins(
|
||||
void* onBeforeParseResult,
|
||||
int* shouldContinue)
|
||||
{
|
||||
return plugin->plugin.onBeforeParse.call(plugin->vm(), shouldContinue, bunContextPtr, namespaceStr, pathString, onBeforeParseArgs, onBeforeParseResult);
|
||||
return plugin->plugin.onBeforeParse.call(plugin->vm(), &plugin->plugin, shouldContinue, bunContextPtr, namespaceStr, pathString, onBeforeParseArgs, onBeforeParseResult);
|
||||
}
|
||||
|
||||
extern "C" int JSBundlerPlugin__hasOnBeforeParsePlugins(Bun::JSBundlerPlugin* plugin)
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
typedef void (*JSBundlerPluginAddErrorCallback)(void*, void*, JSC::EncodedJSValue, JSC::EncodedJSValue);
|
||||
typedef void (*JSBundlerPluginOnLoadAsyncCallback)(void*, void*, JSC::EncodedJSValue, JSC::EncodedJSValue);
|
||||
typedef void (*JSBundlerPluginOnResolveAsyncCallback)(void*, void*, JSC::EncodedJSValue, JSC::EncodedJSValue, JSC::EncodedJSValue);
|
||||
typedef void (*JSBundlerPluginNativeOnBeforeParseCallback)( void*, void*);
|
||||
typedef void (*JSBundlerPluginNativeOnBeforeParseCallback)(void*, void*);
|
||||
|
||||
namespace Bun {
|
||||
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
void append(JSC::VM& vm, JSC::RegExp* filter, String& namespaceString, unsigned& index);
|
||||
};
|
||||
|
||||
#include "../../../packages/bun-native-bundler-plugin-api/bundler_plugin.h"
|
||||
#include "../../../packages/bun-native-bundler-plugin-api/bundler_plugin.h"
|
||||
|
||||
/// In native plugins, the regular expression could be called concurrently on multiple threads.
|
||||
/// Therefore, we need a mutex to synchronize access.
|
||||
@@ -69,7 +69,7 @@ public:
|
||||
PerNamespaceCallbackList fileCallbacks = {};
|
||||
Vector<PerNamespaceCallbackList> namespaceCallbacks = {};
|
||||
|
||||
int call(JSC::VM& vm, int* shouldContinue, void* bunContextPtr, const BunString* namespaceStr, const BunString* pathString, void* onBeforeParseArgs, void* onBeforeParseResult);
|
||||
int call(JSC::VM& vm, BundlerPlugin* plugin, int* shouldContinue, void* bunContextPtr, const BunString* namespaceStr, const BunString* pathString, void* onBeforeParseArgs, void* onBeforeParseResult);
|
||||
void append(JSC::VM& vm, JSC::RegExp* filter, String& namespaceString, JSBundlerPluginNativeOnBeforeParseCallback callback, NapiExternal* external);
|
||||
|
||||
Vector<NativeFilterRegexp>* group(const String& namespaceStr, unsigned& index)
|
||||
@@ -95,15 +95,18 @@ public:
|
||||
bool anyMatchesCrossThread(JSC::VM&, const BunString* namespaceStr, const BunString* path, bool isOnLoad);
|
||||
void tombstone() { tombstoned = true; }
|
||||
|
||||
BundlerPlugin(void* config, BunPluginTarget target, JSBundlerPluginAddErrorCallback addError, JSBundlerPluginOnLoadAsyncCallback onLoadAsync, JSBundlerPluginOnResolveAsyncCallback onResolveAsync)
|
||||
BundlerPlugin(void* config, WTF::StringImpl* name, BunPluginTarget target, JSBundlerPluginAddErrorCallback addError, JSBundlerPluginOnLoadAsyncCallback onLoadAsync, JSBundlerPluginOnResolveAsyncCallback onResolveAsync)
|
||||
: addError(addError)
|
||||
, onLoadAsync(onLoadAsync)
|
||||
, onResolveAsync(onResolveAsync)
|
||||
{
|
||||
this->name = name;
|
||||
this->target = target;
|
||||
this->config = config;
|
||||
}
|
||||
|
||||
WTF::StringImpl* name;
|
||||
std::optional<CString> name_c = {};
|
||||
NamespaceList onLoad = {};
|
||||
NamespaceList onResolve = {};
|
||||
NativePluginList onBeforeParse = {};
|
||||
|
||||
@@ -51,9 +51,11 @@ var panic_mutex = std.Thread.Mutex{};
|
||||
threadlocal var panic_stage: usize = 0;
|
||||
|
||||
threadlocal var inside_native_plugin: bool = false;
|
||||
threadlocal var inside_native_plugin_str: ?[*:0]const u8 = null;
|
||||
|
||||
export fn CrashHandler__setInsideNativePlugin(value: bool) callconv(.C) void {
|
||||
export fn CrashHandler__setInsideNativePlugin(value: bool, name: ?[*:0]const u8) callconv(.C) void {
|
||||
inside_native_plugin = value;
|
||||
inside_native_plugin_str = name;
|
||||
}
|
||||
|
||||
/// This can be set by various parts of the codebase to indicate a broader
|
||||
@@ -233,14 +235,17 @@ pub fn crashHandler(
|
||||
writer.writeAll("=" ** 60 ++ "\n") catch std.posix.abort();
|
||||
printMetadata(writer) catch std.posix.abort();
|
||||
|
||||
writer.print(
|
||||
\\
|
||||
\\Bun has encountered a crash while running the a native plugin.
|
||||
\\
|
||||
\\This indicates either a bug in the native plugin or in Bun.
|
||||
\\
|
||||
\\
|
||||
, .{}) catch std.posix.abort();
|
||||
if (inside_native_plugin) {
|
||||
const native_plugin_name = inside_native_plugin_str orelse "<unknown>";
|
||||
writer.print(
|
||||
\\
|
||||
\\Bun has encountered a crash while running the "{s}" native plugin.
|
||||
\\
|
||||
\\This indicates either a bug in the native plugin or in Bun.
|
||||
\\
|
||||
\\
|
||||
, .{native_plugin_name}) catch std.posix.abort();
|
||||
}
|
||||
} else {
|
||||
if (Output.enable_ansi_colors) {
|
||||
writer.writeAll(Output.prettyFmt("<red>", true)) catch std.posix.abort();
|
||||
@@ -324,14 +329,15 @@ pub fn crashHandler(
|
||||
writer.writeAll(Output.prettyFmt(": ", true)) catch std.posix.abort();
|
||||
}
|
||||
if (inside_native_plugin) {
|
||||
const native_plugin_name = inside_native_plugin_str orelse "<unknown>";
|
||||
writer.print(
|
||||
\\Bun has encountered a crash while running a native plugin.
|
||||
\\Bun has encountered a crash while running the "{s}" native plugin.
|
||||
\\
|
||||
\\To send a redacted crash report to Bun's team,
|
||||
\\please file a GitHub issue using the link below:
|
||||
\\
|
||||
\\
|
||||
, .{}) catch std.posix.abort();
|
||||
, .{native_plugin_name}) catch std.posix.abort();
|
||||
} else if (reason == .out_of_memory) {
|
||||
writer.writeAll(
|
||||
\\Bun has ran out of memory.
|
||||
|
||||
Reference in New Issue
Block a user