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:
Jarred Sumner
2023-08-16 19:40:20 -07:00
committed by GitHub
parent 2634c64aa3
commit 0486cea35a
84 changed files with 12493 additions and 448 deletions

View File

@@ -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;