mirror of
https://github.com/oven-sh/bun
synced 2026-02-14 04:49:06 +00:00
bun --inspect (#4158)
* Let the debugger to pause/resume the event loop
* Add initial support for Debug Adapter Protocol
* Add progress
* Update Worker.cpp
* Fix require("console") #3820 (#4073)
* Fix #3820
* Add Module (#4074)
* Set exports to {} in user-constructed CommonJSModuleRecords (#4076)
* feat(bun/test): Implement "toSatisfy" & "toIncludeRepeated" (fwup) (#3651)
* Fix merge issues
* oop
* make codegen
* Fix build issues
---------
Co-authored-by: dave caruso <me@paperdave.net>
* worker tests (#4058)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
* feat(bun:test) add support for test.each() and describe.each() (#4047)
* rename callback to func
* update testscope to handle function arguments
* works
* big cleanup
* works in debug, not release
* fix memory issue & update tests
* catch & str test
* write types for each() & switch tests to ts
* rm & typo
* move some code around & support describe
* review changes
* Fix one of the astro segfaults, also fix bun init version (#4079)
* 4->16
* add assertions
* fix version stuff
* Remove unintentional logs from #4043
* Run prettier
* Update main-worker-file.js
* Update SIMDUTF (#4078)
* Fix constructing buffer from a UTF16 string with the Latin1 encoding. (#4086)
Close: #3914
* Add support for `bun --revision` (#4027)
Co-authored-by: Yash Sharma <yashsharma@Yashs-MacBook-Air.local>
* Updates
* Update __global.zig
* remove non-node node-fallbacks (#4082)
* remove non-node node-fallbacks.
* organize the imports
* Fix test
* Sync bun-polyfills branch (#4081)
* bun-polyfills: initial impl. & baseline refactor
* move @types/ws dep from root to /test/
* bun-types: remove ReadableStream.forEach method
(this does not exist, probably added by mistake)
* bun-polyfills: remove extraneous stream utils
* bun-polyfills: add types syncing file
* bun-polyfills: re-arrange global polyfills
* bun-polyfills: fix FileBlob streams types again
* bun-polyfills: sync all of @types/node
* bun-polyfills: typeguard all current polyfills
* bun-polyfills: fix import paths
* bun-polyfills: switch to wasm impl. of farmhash
* bun-polyfills: support default import of bun obj
* bun-polyfills: transpiler placeholder file
* bun-polyfills: loaderless import.meta polyfill
* bun-polyfills: refactor import.meta polyfill
* bun-polyfills: repl entrypoint & todo list index
* bun-types: Add null to return type of Bun.which
* bun-types: match Bun.sha with Bun.hash.SHA512_256
* bun-polyfills: new "repl" package.json script
* bun-polyfills: full refactor of toplevel hashes
* bun-polyfills: these are fixed
* bun-types: NODE_ENV is optional
* bun-polyfills: fix Bun.env types
* bun-types+polyfills: fix HeapSnapshot.version type
* bun-polyfills: fix some web streams type conflicts
* bun-polyfills: update internal FileBlob.slice
* bun-polyfills: fix subproc stdin conversions
* bun-polyfills: better internal fileblob types
* bun-polyfills: try to sync global performance type
* bun-polyfills: working zig wasm polyfills setup
* bun-polyfills: update scripts
* bun-polyfills: fix wasm file location resolution
* bun-polyfills: goodbye farmhash (replaced by zig)
* bun-polyfills: move all Bun.hash polyfills to zig
* bun-polyfills: reimpl. seeding of seeded hashes
* bun-polyfills: impl. undocumented murmur32v2
* bun-polyfills: switch zighash from jsdoc to .d.ts
* bun-types: partial fix of Hash types
* bun-polyfills: documented Hash.murmur32v2
* bun-polyfills: misc updates
* bun-polyfills: enable sourcemaps
* bun-polyfills: handle empty inputs to hash funcs
* bun-types: narrow down hash func types
* bun-polyfills: remove unnecessary bigint casts
* bun-polyfills: impl. Bun.isMainThread
* bun-polyfills: impl. Bun.sleep and fix sleepSync
* bun-polyfills: impl. indexOfLine
* bun-polyfills: impl. Bun.peek.status
* bun-types: fix hashing test
---------
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
* Add remix guide
* Fix title
* add util.formatWithOptions (#4090)
* Add formatWithOptions
* tests and tweaks
* adjust
---------
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
* bun test: format description of test.each (#4092)
* bun test: format description
* add tests for tests
* only
---------
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
* Fixes #4062 (#4106)
* Fixes #4062
* Update encoding.zig
* Use faster C++ impl
* Update wtf-bindings.cpp
* undo
* Fixup
---------
Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
* zig fmt
* Update remix guide
* fs.zig: create temp files with 0o700, not 0o007 (#4107)
* Handle thundering herd of setInterval (#4109)
Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
* Fix memory leak in base64url (#4111)
Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
* run files without extensions (#4113)
* run script without extension
* process stdio write fix
* don't check for trailing slash, var stream
* More lazily initialize these static strings
* Remove assertion
* wip
* Add --inspect flag
* Deprecate loading `node_modules.bun`
* realpath
* regenerate schema
* More
* more
* Update cli.zig
* Debugger JS loads
* have fun
* Most of the code
* Its starting to work.
* more progress
* win some, lose some
* Update dap.ts
* Async Context Tracking
* untested websocket
* Emit Console messages
* Error handling
* errors
* Make profiling work better
* [clap] CLI arguments with optional values ignore positional params
In `bun --inspect foo.js`, `foo.js` should not be the value of `--inspect`. It is a positional parameter. `--inspect=foo`
* Support multiple simultaneous clients, automatically unpause on disconnect
* regenerate
* Update Makefile
* Update WebKit
* Update cli.zig
* Update InternalModuleRegistry+createInternalModuleById.h
* BaseURL
* Update WebKit
* Add web-inspector-bun
* Update build.ts
* formatting, mostly
* Update debugger.ts
* Update InternalModuleRegistryConstants.h
* wrap
* Update test
* Update test
---------
Co-authored-by: Ashcon Partovi <ashcon@partovi.net>
Co-authored-by: Dylan Conway <dylan.conway567@gmail.com>
Co-authored-by: dave caruso <me@paperdave.net>
Co-authored-by: Tiramify (A.K. Daniel) <94789999+TiranexDev@users.noreply.github.com>
Co-authored-by: Jacques <25390037+jecquas@users.noreply.github.com>
Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
Co-authored-by: Ai Hoshino <ambiguous404@gmail.com>
Co-authored-by: Yash Sharma <yashosharma@gmail.com>
Co-authored-by: Yash Sharma <yashsharma@Yashs-MacBook-Air.local>
Co-authored-by: Colin McDonnell <colinmcd94@gmail.com>
Co-authored-by: jhmaster <32803471+jhmaster2000@users.noreply.github.com>
Co-authored-by: Adhityaa Chandrasekar <github@adtac.in>
Co-authored-by: Dylan Conway <35280289+dylan-conway@users.noreply.github.com>
This commit is contained in:
@@ -496,6 +496,8 @@ pub const VirtualMachine = struct {
|
||||
gc_controller: JSC.GarbageCollectionController = .{},
|
||||
worker: ?*JSC.WebWorker = null,
|
||||
|
||||
debugger: ?Debugger = null,
|
||||
|
||||
pub const OnUnhandledRejection = fn (*VirtualMachine, globalObject: *JSC.JSGlobalObject, JSC.JSValue) void;
|
||||
|
||||
pub const OnException = fn (*ZigException) void;
|
||||
@@ -504,6 +506,10 @@ pub const VirtualMachine = struct {
|
||||
return this.worker == null;
|
||||
}
|
||||
|
||||
pub fn isInspectorEnabled(this: *const VirtualMachine) bool {
|
||||
return this.debugger != null;
|
||||
}
|
||||
|
||||
pub fn setOnException(this: *VirtualMachine, callback: *const OnException) void {
|
||||
this.on_exception = callback;
|
||||
}
|
||||
@@ -706,6 +712,106 @@ pub const VirtualMachine = struct {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn nextAsyncTaskID(this: *VirtualMachine) u64 {
|
||||
var debugger: *Debugger = &(this.debugger orelse return 0);
|
||||
debugger.next_debugger_id +%= 1;
|
||||
return debugger.next_debugger_id;
|
||||
}
|
||||
|
||||
pub const Debugger = struct {
|
||||
path_or_port: []const u8 = "",
|
||||
script_execution_context_id: u32 = 0,
|
||||
next_debugger_id: u64 = 1,
|
||||
poll_ref: JSC.PollRef = .{},
|
||||
auto_pause: bool = false,
|
||||
const debug = Output.scoped(.DEBUGGER, false);
|
||||
|
||||
extern "C" fn Bun__createJSDebugger(*JSC.JSGlobalObject) u32;
|
||||
extern "C" fn Bun__ensureDebugger(u32, bool) void;
|
||||
extern "C" fn Bun__startJSDebuggerThread(*JSC.JSGlobalObject, u32, *bun.String) bun.String;
|
||||
var has_started_debugger_thread: bool = false;
|
||||
var futex_atomic: std.atomic.Atomic(u32) = undefined;
|
||||
|
||||
pub fn create(this: *VirtualMachine, globalObject: *JSGlobalObject) !void {
|
||||
debug("create", .{});
|
||||
this.debugger.?.script_execution_context_id = Bun__createJSDebugger(globalObject);
|
||||
if (!has_started_debugger_thread) {
|
||||
has_started_debugger_thread = true;
|
||||
futex_atomic = std.atomic.Atomic(u32).init(0);
|
||||
var thread = try std.Thread.spawn(.{}, startJSDebuggerThread, .{this});
|
||||
thread.detach();
|
||||
}
|
||||
this.eventLoop().ensureWaker();
|
||||
if (this.debugger.?.auto_pause) {
|
||||
this.debugger.?.poll_ref.ref(this);
|
||||
}
|
||||
debug("spin", .{});
|
||||
while (futex_atomic.load(.Monotonic) > 0) std.Thread.Futex.wait(&futex_atomic, 1);
|
||||
if (comptime Environment.allow_assert)
|
||||
debug("waitForDebugger: {}", .{Output.ElapsedFormatter{
|
||||
.colors = Output.enable_ansi_colors_stderr,
|
||||
.duration_ns = @truncate(@as(u128, @intCast(std.time.nanoTimestamp() - bun.CLI.start_time))),
|
||||
}});
|
||||
|
||||
Bun__ensureDebugger(this.debugger.?.script_execution_context_id, this.debugger.?.auto_pause);
|
||||
}
|
||||
|
||||
pub fn startJSDebuggerThread(other_vm: *VirtualMachine) void {
|
||||
var arena = bun.MimallocArena.init() catch unreachable;
|
||||
Output.Source.configureNamedThread("Debugger");
|
||||
debug("startJSDebuggerThread", .{});
|
||||
|
||||
var vm = JSC.VirtualMachine.init(.{
|
||||
.allocator = arena.allocator(),
|
||||
.args = std.mem.zeroes(Api.TransformOptions),
|
||||
.store_fd = false,
|
||||
}) catch @panic("Failed to create Debugger VM");
|
||||
vm.allocator = arena.allocator();
|
||||
vm.arena = &arena;
|
||||
|
||||
vm.bundler.configureDefines() catch @panic("Failed to configure defines");
|
||||
vm.is_main_thread = false;
|
||||
vm.eventLoop().ensureWaker();
|
||||
|
||||
vm.global.vm().holdAPILock(other_vm, @ptrCast(&start));
|
||||
}
|
||||
|
||||
pub export var Bun__debugger_server_url: bun.String = undefined;
|
||||
|
||||
fn start(other_vm: *VirtualMachine) void {
|
||||
var this = VirtualMachine.get();
|
||||
var str = bun.String.create(other_vm.debugger.?.path_or_port);
|
||||
Bun__debugger_server_url = Bun__startJSDebuggerThread(this.global, other_vm.debugger.?.script_execution_context_id, &str);
|
||||
Bun__debugger_server_url.toThreadSafe();
|
||||
|
||||
this.global.handleRejectedPromises();
|
||||
|
||||
if (this.log.msgs.items.len > 0) {
|
||||
if (Output.enable_ansi_colors) {
|
||||
this.log.printForLogLevelWithEnableAnsiColors(Output.errorWriter(), true) catch {};
|
||||
} else {
|
||||
this.log.printForLogLevelWithEnableAnsiColors(Output.errorWriter(), false) catch {};
|
||||
}
|
||||
Output.prettyErrorln("\n", .{});
|
||||
Output.flush();
|
||||
}
|
||||
|
||||
futex_atomic.store(0, .Monotonic);
|
||||
std.Thread.Futex.wake(&futex_atomic, 1);
|
||||
debug("wake", .{});
|
||||
this.eventLoop().tick();
|
||||
|
||||
while (true) {
|
||||
while (this.eventLoop().tasks.count > 0 or this.active_tasks > 0 or this.uws_event_loop.?.active > 0) {
|
||||
this.tick();
|
||||
this.eventLoop().autoTickActive();
|
||||
}
|
||||
|
||||
this.eventLoop().tickPossiblyForever();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
pub inline fn enqueueTask(this: *VirtualMachine, task: Task) void {
|
||||
this.eventLoop().enqueueTask(task);
|
||||
}
|
||||
@@ -917,6 +1023,8 @@ pub const VirtualMachine = struct {
|
||||
source_code_printer.?.ctx.append_null_byte = false;
|
||||
}
|
||||
|
||||
vm.configureDebugger(opts.debugger);
|
||||
|
||||
return vm;
|
||||
}
|
||||
|
||||
@@ -928,6 +1036,7 @@ pub const VirtualMachine = struct {
|
||||
store_fd: bool = false,
|
||||
smol: bool = false,
|
||||
graph: ?*bun.StandaloneModuleGraph = null,
|
||||
debugger: bun.CLI.Command.Debugger = .{ .unspecified = {} },
|
||||
};
|
||||
|
||||
pub fn init(opts: Options) !*VirtualMachine {
|
||||
@@ -1023,9 +1132,32 @@ pub const VirtualMachine = struct {
|
||||
source_code_printer.?.ctx.append_null_byte = false;
|
||||
}
|
||||
|
||||
vm.configureDebugger(opts.debugger);
|
||||
|
||||
return vm;
|
||||
}
|
||||
|
||||
fn configureDebugger(this: *VirtualMachine, debugger: bun.CLI.Command.Debugger) void {
|
||||
switch (debugger) {
|
||||
.unspecified => {},
|
||||
.enable => {
|
||||
this.debugger = Debugger{};
|
||||
},
|
||||
.path_or_port => {
|
||||
this.debugger = Debugger{
|
||||
.path_or_port = debugger.path_or_port,
|
||||
};
|
||||
},
|
||||
}
|
||||
|
||||
if (debugger != .unspecified) {
|
||||
this.bundler.options.minify_identifiers = false;
|
||||
this.bundler.options.minify_syntax = false;
|
||||
this.bundler.options.minify_whitespace = false;
|
||||
this.bundler.options.debugger = true;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn initWorker(
|
||||
worker: *WebWorker,
|
||||
opts: Options,
|
||||
@@ -1126,11 +1258,6 @@ pub const VirtualMachine = struct {
|
||||
return vm;
|
||||
}
|
||||
|
||||
// dynamic import
|
||||
// pub fn import(global: *JSGlobalObject, specifier: ZigString, source: ZigString) callconv(.C) ErrorableZigString {
|
||||
|
||||
// }
|
||||
|
||||
pub threadlocal var source_code_printer: ?*js_printer.BufferPrinter = null;
|
||||
|
||||
pub fn clearRefString(_: *anyopaque, ref_string: *JSC.RefString) void {
|
||||
@@ -1771,6 +1898,10 @@ pub const VirtualMachine = struct {
|
||||
|
||||
var promise: *JSInternalPromise = undefined;
|
||||
|
||||
if (this.debugger != null) {
|
||||
try Debugger.create(this, this.global);
|
||||
}
|
||||
|
||||
if (!this.bundler.options.disable_transpilation) {
|
||||
{
|
||||
this.is_in_preload = true;
|
||||
|
||||
Reference in New Issue
Block a user