mirror of
https://github.com/oven-sh/bun
synced 2026-02-09 10:28:47 +00:00
wip
This commit is contained in:
@@ -1,13 +1,21 @@
|
||||
#include "BunInspector.h"
|
||||
#include <JavaScriptCore/Heap.h>
|
||||
#include <JavaScriptCore/JSGlobalObject.h>
|
||||
#include "JSGlobalObjectInspectorController.h"
|
||||
#include <JavaScriptCore/JSGlobalObjectDebugger.h>
|
||||
|
||||
namespace Zig {
|
||||
|
||||
WTF_MAKE_ISO_ALLOCATED_IMPL(BunInspector);
|
||||
|
||||
extern "C" void Bun__waitForDebuggerToStart();
|
||||
extern "C" void Bun__debuggerIsReady();
|
||||
|
||||
static BunInspector* inspectorFromGlobal(Zig::GlobalObject* globalObject)
|
||||
{
|
||||
RELEASE_ASSERT(globalObject->bunInspectorPtr);
|
||||
return reinterpret_cast<BunInspector*>(globalObject->bunInspectorPtr);
|
||||
}
|
||||
|
||||
class BunInspectorConnection {
|
||||
|
||||
public:
|
||||
@@ -85,25 +93,53 @@ void BunInspector::sendMessageToFrontend(const String& message)
|
||||
}
|
||||
}
|
||||
|
||||
auto utf8Message = out.utf8();
|
||||
if (this->m_pendingMessages.size() > 0) {
|
||||
this->m_pendingMessages.append(WTFMove(utf8Message));
|
||||
return;
|
||||
}
|
||||
{
|
||||
LockHolder locker(this->m_pendingMessagesLock);
|
||||
if (!this->hasSentWelcomeMessage) {
|
||||
this->hasSentWelcomeMessage = true;
|
||||
auto welcomeMessage = makeString(
|
||||
"{ \"method\": \"Runtime.executionContextCreated\", \"params\":{\"context\":{\"id\":"_s,
|
||||
this->scriptExecutionContext()->identifier(),
|
||||
",\"origin\":\"\",\"name\":\""_s,
|
||||
this->identifier(),
|
||||
"\",\"uniqueId\":\"1234\",\"auxData\":{\"isDefault\":true}}}}"_s);
|
||||
this->m_pendingMessages.append(WTFMove(welcomeMessage.isolatedCopy()));
|
||||
}
|
||||
|
||||
std::string_view view { utf8Message.data(), utf8Message.length() };
|
||||
if (!this->server->publish("BunInspectorConnection", view, uWS::OpCode::TEXT, false)) {
|
||||
this->m_pendingMessages.append(WTFMove(utf8Message));
|
||||
this->m_pendingMessages.append(WTFMove(out.isolatedCopy()));
|
||||
}
|
||||
us_wakeup_loop((us_loop_t*)this->loop);
|
||||
}
|
||||
|
||||
void BunInspector::drainIncomingMessages()
|
||||
{
|
||||
LockHolder locker(this->m_incomingMessagesLock);
|
||||
size_t size = this->m_incomingMessages.size();
|
||||
while (size > 0) {
|
||||
auto& message = this->m_incomingMessages.first();
|
||||
this->sendMessageToTargetBackend(message);
|
||||
this->m_incomingMessages.removeFirst();
|
||||
size = this->m_incomingMessages.size();
|
||||
}
|
||||
}
|
||||
|
||||
void BunInspector::didParseSource(SourceID id, const Debugger::Script& script)
|
||||
{
|
||||
}
|
||||
|
||||
void BunInspector::drainOutgoingMessages()
|
||||
{
|
||||
|
||||
if (this->server->numSubscribers("BunInspectorConnection") == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
LockHolder locker(this->m_pendingMessagesLock);
|
||||
size_t size = this->m_pendingMessages.size();
|
||||
while (size > 0) {
|
||||
auto& message = this->m_pendingMessages.first();
|
||||
std::string_view view { message.data(), message.length() };
|
||||
auto utf8 = message.utf8();
|
||||
std::string_view view { utf8.data(), utf8.length() };
|
||||
if (!this->server->publish("BunInspectorConnection", view, uWS::OpCode::TEXT, false)) {
|
||||
return;
|
||||
}
|
||||
@@ -114,28 +150,16 @@ void BunInspector::drainOutgoingMessages()
|
||||
|
||||
extern "C" void Bun__tickWhileWaitingForDebugger(JSC::JSGlobalObject* globalObject);
|
||||
|
||||
RefPtr<BunInspector> BunInspector::startWebSocketServer(
|
||||
WebCore::ScriptExecutionContext& context,
|
||||
WTF::String hostname,
|
||||
uint16_t port,
|
||||
WTF::Function<void(RefPtr<BunInspector>, bool success)>&& callback)
|
||||
void BunInspector::startServer(WTF::String hostname, uint16_t port, WTF::URL url, WTF::String title)
|
||||
{
|
||||
context.ensureURL();
|
||||
auto url = context.url();
|
||||
auto identifier = url.fileSystemPath();
|
||||
|
||||
auto title = makeString(
|
||||
url.fileSystemPath(),
|
||||
" (Bun "_s, Bun__version, ")"_s);
|
||||
|
||||
auto* globalObject = context.jsGlobalObject();
|
||||
|
||||
uWS::App* app = new uWS::App();
|
||||
RefPtr<BunInspector> inspector = adoptRef(*new BunInspector(&context, app, WTFMove(identifier)));
|
||||
this->server = app;
|
||||
this->loop = uWS::Loop::get();
|
||||
|
||||
auto host = hostname.utf8();
|
||||
|
||||
// https://chromedevtools.github.io/devtools-protocol/ GET /json or /json/list
|
||||
app->get("/json", [hostname, port, url, title = title, inspector](auto* res, auto* /*req*/) {
|
||||
app->get("/json", [hostname, port, url, title = title, inspector = this](auto* res, auto* /*req*/) {
|
||||
auto identifier = inspector->identifier();
|
||||
auto jsonString = makeString(
|
||||
"[ {\"faviconUrl\": \"https://bun.sh/favicon.svg\", \"description\": \"\", \"devtoolsFrontendUrl\": \"devtools://devtools/bundled/js_app.html?experiments=true&v8only=true&ws="_s,
|
||||
@@ -182,20 +206,16 @@ RefPtr<BunInspector> BunInspector::startWebSocketServer(
|
||||
.sendPingsAutomatically = true,
|
||||
/* Handlers */
|
||||
.upgrade = nullptr,
|
||||
.open = [inspector](auto* ws) {
|
||||
BunInspectorConnection** connectionPtr = ws->getUserData();
|
||||
*connectionPtr = new BunInspectorConnection(inspector);
|
||||
ws->subscribe("BunInspectorConnection");
|
||||
BunInspectorConnection* connection = *connectionPtr;
|
||||
inspector->connect(Inspector::FrontendChannel::ConnectionType::Local);
|
||||
auto* debugger = reinterpret_cast<Inspector::JSGlobalObjectDebugger*>(inspector->globalObject()->inspectorController().debugger());
|
||||
debugger->runWhilePausedCallback = [](JSC::JSGlobalObject& globalObject, bool& isPaused) {
|
||||
while (isPaused) {
|
||||
Bun__tickWhileWaitingForDebugger(&globalObject);
|
||||
}
|
||||
}; },
|
||||
.open = [inspector = this](auto* ws) {
|
||||
BunInspectorConnection** connectionPtr = ws->getUserData();
|
||||
*connectionPtr = new BunInspectorConnection(inspector);
|
||||
|
||||
.message = [inspector](auto* ws, std::string_view message, uWS::OpCode opCode) {
|
||||
|
||||
ws->subscribe("BunInspectorConnection");
|
||||
BunInspectorConnection* connection = *connectionPtr;
|
||||
Bun__debuggerIsReady(); },
|
||||
|
||||
.message = [inspector = this](auto* ws, std::string_view message, uWS::OpCode opCode) {
|
||||
if (opCode == uWS::OpCode::TEXT) {
|
||||
if (!inspector) {
|
||||
ws->close();
|
||||
@@ -204,27 +224,14 @@ RefPtr<BunInspector> BunInspector::startWebSocketServer(
|
||||
|
||||
BunInspectorConnection** connectionPtr = ws->getUserData();
|
||||
BunInspectorConnection* connection = *connectionPtr;
|
||||
// if (!connection->hasSentWelcomeMessage) {
|
||||
// connection->hasSentWelcomeMessage = true;
|
||||
// auto welcomeMessage = makeString(
|
||||
// "{ \"method\": \"Runtime.executionContextCreated\", \"params\":{\"context\":{\"id\":"_s,
|
||||
// connection->inspector->scriptExecutionContext()->identifier(),
|
||||
// ",\"origin\":\"\",\"name\":\""_s,
|
||||
// connection->inspector->identifier(),
|
||||
// "\",\"uniqueId\":\"1234\",\"auxData\":{\"isDefault\":true}}}}"_s
|
||||
// ).utf8();
|
||||
// std::string_view view { welcomeMessage.data(), welcomeMessage.length() };
|
||||
// if (! ws->send(
|
||||
// view,
|
||||
// uWS::OpCode::TEXT,
|
||||
// false,
|
||||
// false
|
||||
// )) {
|
||||
// connection->m_messages.append(WTFMove(welcomeMessage));
|
||||
// }
|
||||
// }
|
||||
|
||||
inspector->dispatchToBackend(message);
|
||||
|
||||
|
||||
|
||||
connection->inspector->dispatchToBackend(message);
|
||||
connection->inspector->drainOutgoingMessages();
|
||||
|
||||
|
||||
} },
|
||||
.drain = [](auto* ws) {
|
||||
|
||||
@@ -246,7 +253,6 @@ RefPtr<BunInspector> BunInspector::startWebSocketServer(
|
||||
}
|
||||
connection->m_messages.removeFirst();
|
||||
}
|
||||
|
||||
connection->inspector->drainOutgoingMessages(); },
|
||||
.ping = [](auto* /*ws*/, std::string_view) {
|
||||
/* Not implemented yet */ },
|
||||
@@ -271,14 +277,54 @@ RefPtr<BunInspector> BunInspector::startWebSocketServer(
|
||||
res->write(req->getUrl());
|
||||
res->end(" was not found");
|
||||
})
|
||||
.listen(std::string(host.data(), host.length()), port, [inspector, callback = WTFMove(callback)](auto* listen_socket) {
|
||||
if (listen_socket) {
|
||||
callback(inspector, true);
|
||||
} else {
|
||||
callback(inspector, false);
|
||||
}
|
||||
.listen(std::string(host.data(), host.length()), port, [inspector = this](auto* listen_socket) {
|
||||
inspector->loop->addPostHandler(inspector, [inspector = inspector](uWS::Loop* loop) {
|
||||
inspector->drainOutgoingMessages();
|
||||
});
|
||||
WebCore::ScriptExecutionContext::postTaskTo(
|
||||
inspector->scriptExecutionContext()->identifier(),
|
||||
[inspector = inspector](WebCore::ScriptExecutionContext& ctx) mutable {
|
||||
inspector->readyToStartDebugger();
|
||||
});
|
||||
|
||||
inspector->loop->run();
|
||||
});
|
||||
;
|
||||
}
|
||||
|
||||
void BunInspector::readyToStartDebugger()
|
||||
{
|
||||
this->ensureDebugger();
|
||||
|
||||
auto& inspectorController = globalObject()->inspectorController();
|
||||
auto* debugger = inspectorController.debugger();
|
||||
debugger->addObserver(*this);
|
||||
debugger->schedulePauseAtNextOpportunity();
|
||||
}
|
||||
|
||||
BunInspector* BunInspector::startWebSocketServer(
|
||||
Zig::GlobalObject* globalObject,
|
||||
WebCore::ScriptExecutionContext& context,
|
||||
WTF::String hostname,
|
||||
uint16_t port,
|
||||
WTF::Function<void(BunInspector*, bool success)>&& callback)
|
||||
{
|
||||
context.ensureURL();
|
||||
auto url = context.url();
|
||||
auto identifier = url.fileSystemPath();
|
||||
|
||||
auto title = makeString(
|
||||
url.fileSystemPath(),
|
||||
" (Bun "_s, Bun__version, ")"_s);
|
||||
|
||||
auto* inspector = new BunInspector(&context, nullptr, WTFMove(identifier));
|
||||
reinterpret_cast<Zig::GlobalObject*>(globalObject)->bunInspectorPtr = inspector;
|
||||
auto backgroundThreadFunction = [inspector = inspector, hostname = hostname.isolatedCopy(), port = port, url = WTFMove(url), title = WTFMove(title)]() -> void {
|
||||
inspector->startServer(hostname, port, url, WTFMove(title));
|
||||
};
|
||||
WTF::Thread::create("BunInspector", WTFMove(backgroundThreadFunction))->detach();
|
||||
|
||||
callback(inspector, true);
|
||||
Bun__waitForDebuggerToStart();
|
||||
|
||||
return inspector;
|
||||
}
|
||||
@@ -287,55 +333,17 @@ void BunInspector::dispatchToBackend(std::string_view message)
|
||||
{
|
||||
WTF::CString data { message.data(), message.length() };
|
||||
WTF::String msg = WTF::String::fromUTF8(data.data(), data.length());
|
||||
auto jsonObject = WTF::JSONImpl::Value::parseJSON(msg);
|
||||
// if (auto object = jsonObject->asObject()) {
|
||||
// auto method = object->getString("method"_s);
|
||||
|
||||
// if (method == "Profiler.enable"_s || method == "Runtime.runIfWaitingForDebugger"_s || method == "Debugger.setAsyncCallStackDepth"_s || method == "Debugger.setBlackboxPatterns"_s) {
|
||||
|
||||
// if (auto id = object.get()->getInteger("id"_s)) {
|
||||
// auto response = makeString(
|
||||
// "{\"id\":"_s,
|
||||
// id.value(),
|
||||
// "\"result\":{}}"_s);
|
||||
|
||||
// sendMessageToFrontend(response);
|
||||
// return;
|
||||
// }
|
||||
// } else if (method == "Runtime.getHeapUsage"_s) {
|
||||
|
||||
// if (auto id = object.get()->getInteger("id"_s)) {
|
||||
// auto& heap = globalObject()->vm().heap;
|
||||
// int usedSize = heap.size();
|
||||
// int totalSize = heap.capacity();
|
||||
|
||||
// auto response = makeString(
|
||||
// "{\"id\":"_s,
|
||||
// id.value(),
|
||||
// "\"result\":{ "_s,
|
||||
// "\"usedSize\": "_s, usedSize, "\"totalSize\":"_s, totalSize, "}}"_s);
|
||||
|
||||
// sendMessageToFrontend(response);
|
||||
// return;
|
||||
// }
|
||||
// } else if (method == "Runtime.getIsolateId"_s) {
|
||||
|
||||
// if (auto id = object.get()->getInteger("id"_s)) {
|
||||
// auto& heap = globalObject()->vm().heap;
|
||||
// int usedSize = heap.size();
|
||||
// int totalSize = heap.capacity();
|
||||
|
||||
// auto response = makeString(
|
||||
// "{\"id\":"_s,
|
||||
// id.value(),
|
||||
// "\"result\": \"123\"}"_s);
|
||||
|
||||
// sendMessageToFrontend(response);
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
globalObject()->inspectorController().backendDispatcher().dispatch(msg);
|
||||
bool needsTask = true;
|
||||
{
|
||||
LockHolder incomingMessagesLock(this->m_incomingMessagesLock);
|
||||
needsTask = this->m_incomingMessages.isEmpty();
|
||||
this->m_incomingMessages.append(WTFMove(msg.isolatedCopy()));
|
||||
}
|
||||
WebCore::ScriptExecutionContext::postTaskTo(
|
||||
scriptExecutionContext()->identifier(),
|
||||
[inspector = this](WebCore::ScriptExecutionContext& ctx) mutable {
|
||||
inspector->drainIncomingMessages();
|
||||
});
|
||||
}
|
||||
|
||||
void BunInspector::sendMessageToTargetBackend(const WTF::String& message)
|
||||
@@ -353,4 +361,31 @@ void BunInspector::disconnect()
|
||||
globalObject()->inspectorController().disconnectFrontend(*this);
|
||||
}
|
||||
|
||||
void BunInspector::didPause(JSGlobalObject* jsGlobalObject, DebuggerCallFrame& callframe, JSValue exceptionOrCaughtValue)
|
||||
{
|
||||
printf("didPause\n");
|
||||
}
|
||||
void BunInspector::didContinue()
|
||||
{
|
||||
printf("didContinue\n");
|
||||
}
|
||||
|
||||
void BunInspector::waitForMessages()
|
||||
{
|
||||
this->m_incomingMessagesLock.lock();
|
||||
}
|
||||
|
||||
void BunInspector::ensureDebugger()
|
||||
{
|
||||
this->connect(Inspector::FrontendChannel::ConnectionType::Local);
|
||||
|
||||
auto* debugger = reinterpret_cast<Inspector::JSGlobalObjectDebugger*>(this->globalObject()->inspectorController().debugger());
|
||||
debugger->runWhilePausedCallback = [](JSC::JSGlobalObject& globalObject, bool& isResumed) {
|
||||
auto* inspector = inspectorFromGlobal(reinterpret_cast<Zig::GlobalObject*>(&globalObject));
|
||||
while (!isResumed) {
|
||||
inspector->drainIncomingMessages();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace Zig
|
||||
@@ -6,14 +6,16 @@
|
||||
#include <JavaScriptCore/InspectorFrontendChannel.h>
|
||||
#include "ContextDestructionObserver.h"
|
||||
#include <wtf/RefPtr.h>
|
||||
#include <JavaScriptCore/Debugger.h>
|
||||
#include <wtf/Deque.h>
|
||||
#include "JSGlobalObjectInspectorController.h"
|
||||
|
||||
namespace Zig {
|
||||
|
||||
using namespace JSC;
|
||||
using namespace WebCore;
|
||||
|
||||
class BunInspector final : public RefCounted<BunInspector>, ::Inspector::InspectorTarget, ::Inspector::FrontendChannel, public WebCore::ContextDestructionObserver {
|
||||
class BunInspector final : public RefCounted<BunInspector>, ::Inspector::InspectorTarget, ::Inspector::FrontendChannel, public WebCore::ContextDestructionObserver, JSC::Debugger::Observer {
|
||||
public:
|
||||
WTF_MAKE_ISO_ALLOCATED(BunInspector);
|
||||
BunInspector(ScriptExecutionContext* context, uWS::App* server, WTF::String&& identifier)
|
||||
@@ -30,18 +32,44 @@ public:
|
||||
server->close();
|
||||
}
|
||||
|
||||
using RefCounted::deref;
|
||||
using RefCounted::ref;
|
||||
|
||||
bool isProvisional() const override { return false; }
|
||||
String identifier() const override { return m_identifier; }
|
||||
Inspector::InspectorTargetType type() const override { return Inspector::InspectorTargetType::DedicatedWorker; }
|
||||
GlobalObject* globalObject() { return static_cast<GlobalObject*>(scriptExecutionContext()->jsGlobalObject()); }
|
||||
|
||||
static RefPtr<BunInspector> startWebSocketServer(
|
||||
void startServer(WTF::String hostname, uint16_t port, WTF::URL url, WTF::String title);
|
||||
|
||||
Lock m_mutex;
|
||||
|
||||
void ensureDebugger();
|
||||
JSC::Debugger* debugger() { return globalObject()->inspectorController().debugger(); }
|
||||
|
||||
void didPause(JSGlobalObject*, DebuggerCallFrame&, JSValue /* exceptionOrCaughtValue */) override;
|
||||
void didContinue() override;
|
||||
void didParseSource(SourceID, const Debugger::Script&) override;
|
||||
void failedToParseSource(const String& /* url */, const String& /* data */, int /* firstLine */, int /* errorLine */, const String& /* errorMessage */) override {}
|
||||
|
||||
void didCreateNativeExecutable(NativeExecutable&) override {}
|
||||
void willCallNativeExecutable(CallFrame*) override {}
|
||||
|
||||
void willEnter(CallFrame*) override {}
|
||||
|
||||
void didQueueMicrotask(JSGlobalObject*, MicrotaskIdentifier) override {}
|
||||
void willRunMicrotask(JSGlobalObject*, MicrotaskIdentifier) override {}
|
||||
void didRunMicrotask(JSGlobalObject*, MicrotaskIdentifier) override {}
|
||||
|
||||
void applyBreakpoints(CodeBlock*) override {}
|
||||
void breakpointActionLog(JSGlobalObject*, const String& /* data */) override {}
|
||||
void breakpointActionSound(BreakpointActionID) override {}
|
||||
void breakpointActionProbe(JSGlobalObject*, BreakpointActionID, unsigned /* batchId */, unsigned /* sampleId */, JSValue /* result */) override {}
|
||||
void didDeferBreakpointPause(BreakpointID) override {}
|
||||
|
||||
static BunInspector* startWebSocketServer(
|
||||
Zig::GlobalObject* globalObject,
|
||||
WebCore::ScriptExecutionContext& ctx,
|
||||
WTF::String hostname,
|
||||
uint16_t port,
|
||||
WTF::Function<void(RefPtr<BunInspector>, bool success)>&& callback);
|
||||
WTF::Function<void(BunInspector*, bool success)>&& callback);
|
||||
|
||||
// Connection management.
|
||||
void connect(Inspector::FrontendChannel::ConnectionType) override;
|
||||
@@ -53,15 +81,24 @@ public:
|
||||
Inspector::FrontendChannel::ConnectionType connectionType() const override { return Inspector::FrontendChannel::ConnectionType::Remote; }
|
||||
|
||||
int connectionCounter = 0;
|
||||
bool hasSentWelcomeMessage = false;
|
||||
|
||||
void drainOutgoingMessages();
|
||||
void drainIncomingMessages();
|
||||
void waitForMessages();
|
||||
|
||||
void readyToStartDebugger();
|
||||
|
||||
private:
|
||||
void dispatchToBackend(std::string_view message);
|
||||
|
||||
WTF::String m_identifier;
|
||||
WTF::Lock m_pendingMessagesLock;
|
||||
uWS::App* server;
|
||||
Deque<WTF::CString> m_pendingMessages;
|
||||
GlobalObject* globalObject() { return static_cast<GlobalObject*>(scriptExecutionContext()->jsGlobalObject()); }
|
||||
uWS::Loop* loop;
|
||||
Deque<WTF::String> m_pendingMessages;
|
||||
|
||||
Deque<WTF::String> m_incomingMessages;
|
||||
WTF::Lock m_incomingMessagesLock;
|
||||
};
|
||||
}
|
||||
@@ -245,14 +245,14 @@ extern "C" bool JSGlobalObject__startRemoteInspector(Zig::GlobalObject* globalOb
|
||||
#if !ENABLE(REMOTE_INSPECTOR)
|
||||
return false;
|
||||
#else
|
||||
globalObject->setInspectable(true);
|
||||
bool didSucceed = false;
|
||||
|
||||
// This function calls immediately.
|
||||
auto inspector = BunInspector::startWebSocketServer(
|
||||
globalObject,
|
||||
*globalObject->scriptExecutionContext(),
|
||||
WTF::String::fromUTF8(host),
|
||||
port, [port, &didSucceed](RefPtr<BunInspector> inspector, bool success) {
|
||||
port, [port, &didSucceed](BunInspector* inspector, bool success) {
|
||||
didSucceed = success;
|
||||
|
||||
if (success) {
|
||||
@@ -284,6 +284,10 @@ extern "C" JSC__JSGlobalObject* Zig__GlobalObject__create(JSClassRef* globalObje
|
||||
if (count > 0) {
|
||||
globalObject->installAPIGlobals(globalObjectClass, count, vm);
|
||||
}
|
||||
if (inspector != 0) {
|
||||
globalObject->setInspectable(true);
|
||||
globalObject->inspectorController().debugger();
|
||||
}
|
||||
JSC::gcProtect(globalObject);
|
||||
vm.ref();
|
||||
return globalObject;
|
||||
@@ -549,6 +553,9 @@ WebCore::ScriptExecutionContext* GlobalObject::scriptExecutionContext() const
|
||||
void GlobalObject::reportUncaughtExceptionAtEventLoop(JSGlobalObject* globalObject,
|
||||
JSC::Exception* exception)
|
||||
{
|
||||
if (globalObject->hasDebugger()) {
|
||||
globalObject->debugger()->exception(globalObject, nullptr, exception, false);
|
||||
}
|
||||
Bun__reportUnhandledError(globalObject, JSValue::encode(JSValue(exception)));
|
||||
}
|
||||
|
||||
@@ -560,10 +567,16 @@ void GlobalObject::promiseRejectionTracker(JSGlobalObject* obj, JSC::JSPromise*
|
||||
|
||||
// Do this in C++ for now
|
||||
auto* globalObj = reinterpret_cast<GlobalObject*>(obj);
|
||||
|
||||
switch (operation) {
|
||||
case JSPromiseRejectionOperation::Reject:
|
||||
case JSPromiseRejectionOperation::Reject: {
|
||||
if (obj->hasDebugger()) {
|
||||
obj->debugger()->exception(obj, nullptr, promise->result(), false);
|
||||
}
|
||||
|
||||
globalObj->m_aboutToBeNotifiedRejectedPromises.append(JSC::Strong<JSPromise>(obj->vm(), promise));
|
||||
break;
|
||||
}
|
||||
case JSPromiseRejectionOperation::Handle:
|
||||
globalObj->m_aboutToBeNotifiedRejectedPromises.removeFirstMatching([&](Strong<JSPromise>& unhandledPromise) {
|
||||
return unhandledPromise.get() == promise;
|
||||
|
||||
@@ -403,6 +403,8 @@ public:
|
||||
void* napiInstanceDataFinalizer = nullptr;
|
||||
void* napiInstanceDataFinalizerHint = nullptr;
|
||||
|
||||
void* bunInspectorPtr = nullptr;
|
||||
|
||||
#include "ZigGeneratedClasses+lazyStructureHeader.h"
|
||||
|
||||
private:
|
||||
|
||||
@@ -256,6 +256,28 @@ pub export fn Bun__drainMicrotasks() void {
|
||||
JSC.VirtualMachine.get().eventLoop().tick();
|
||||
}
|
||||
|
||||
const WaitForDebugger = struct {
|
||||
var is_debugger_ready = std.atomic.Atomic(u32).init(0);
|
||||
pub fn ready() void {
|
||||
is_debugger_ready.store(1, .Monotonic);
|
||||
std.Thread.Futex.wake(&is_debugger_ready, 1);
|
||||
}
|
||||
|
||||
pub fn wait() void {
|
||||
while (is_debugger_ready.load(.Monotonic) == 0) {
|
||||
std.Thread.Futex.wait(&is_debugger_ready, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
pub export fn Bun__waitForDebuggerToStart() void {
|
||||
WaitForDebugger.wait();
|
||||
}
|
||||
|
||||
pub export fn Bun__debuggerIsReady() void {
|
||||
WaitForDebugger.ready();
|
||||
}
|
||||
|
||||
export fn Bun__readOriginTimer(vm: *JSC.VirtualMachine) u64 {
|
||||
return vm.origin_timer.read();
|
||||
}
|
||||
@@ -2793,6 +2815,9 @@ pub fn NewHotReloader(comptime Ctx: type, comptime EventLoopType: type, comptime
|
||||
}
|
||||
|
||||
comptime {
|
||||
if (!JSC.is_bindgen)
|
||||
if (!JSC.is_bindgen) {
|
||||
_ = Bun__getMainPath;
|
||||
_ = Bun__waitForDebuggerToStart;
|
||||
_ = Bun__debuggerIsReady;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user