11#include < debugger.h>
22
3- #include < decode.h>
4- #include < encode.h>
3+ #ifdef ENABLE_JS_DEBUGGER
4+
5+ #include " decode.h"
6+ #include " encode.h"
7+ #include " sockets.h"
8+
59#include < js/CompilationAndEvaluation.h>
610#include < js/SourceText.h>
11+
712#include < string_view>
13+ #include < wasi/libc-environ.h>
14+
15+ namespace {
816
917mozilla::Maybe<std::string> main_path;
18+ bool debugger_initialized = false ;
1019
1120namespace SocketErrors {
1221DEF_ERR (SendFailed, JSEXN_TYPEERR, " Failed to send message via TCP socket" , 0 )
1322} // namespace SocketErrors
1423
15- static bool dbg_set_content_path (JSContext *cx, unsigned argc, Value *vp) {
24+ bool dbg_set_content_path (JSContext *cx, unsigned argc, Value *vp) {
1625 CallArgs args = CallArgsFromVp (argc, vp);
1726 auto path = core::encode (cx, args.get (0 ));
1827 if (!path) {
@@ -24,7 +33,7 @@ static bool dbg_set_content_path(JSContext *cx, unsigned argc, Value *vp) {
2433 return true ;
2534}
2635
27- static bool print_location (JSContext *cx, FILE *fp = stdout) {
36+ bool print_location (JSContext *cx, FILE *fp = stdout) {
2837 JS::AutoFilename filename;
2938 uint32_t lineno;
3039 JS::ColumnNumberOneOrigin column;
@@ -35,39 +44,17 @@ static bool print_location(JSContext *cx, FILE *fp = stdout) {
3544 return true ;
3645}
3746
38- bool content_debugger::dbg_print (JSContext *cx, unsigned argc, Value *vp) {
39- CallArgs args = CallArgsFromVp (argc, vp);
40-
41- if (!print_location (cx)) {
42- return false ;
43- }
44-
45- for (size_t i = 0 ; i < args.length (); i++) {
46- auto str = core::encode (cx, args.get (i));
47- if (!str) {
48- return false ;
49- }
50- printf (" %.*s" , static_cast <int >(str.len ), str.begin ());
51- }
52-
53- printf (" \n " );
54- fflush (stdout);
55- args.rval ().setUndefined ();
56- return true ;
57- }
58-
59- static bool dbg_assert (JSContext *cx, unsigned argc, Value *vp) {
47+ bool dbg_assert (JSContext *cx, unsigned argc, Value *vp) {
6048 CallArgs args = CallArgsFromVp (argc, vp);
6149 if (!ToBoolean (args.get (0 ))) {
62-
6350 if (!print_location (cx, stderr)) {
6451 return false ;
6552 }
6653
6754 if (args.length () > 1 ) {
6855 auto message = core::encode (cx, args.get (1 ));
69- fprintf (stderr, " Assert failed in debugger: %.*s" ,
70- static_cast < int >(message. len ), message.begin ());
56+ fprintf (stderr, " Assert failed in debugger: %.*s" , static_cast < int >(message. len ),
57+ message.begin ());
7158 } else {
7259 fprintf (stderr, " Assert failed in debugger" );
7360 }
@@ -77,8 +64,6 @@ static bool dbg_assert(JSContext *cx, unsigned argc, Value *vp) {
7764 return true ;
7865}
7966
80- #include " sockets.h"
81-
8267namespace debugging_socket {
8368
8469class TCPSocket : public builtins ::BuiltinNoConstructor<TCPSocket> {
@@ -127,7 +112,7 @@ bool TCPSocket::receive(JSContext *cx, unsigned argc, JS::Value *vp) {
127112 return true ;
128113}
129114
130- JSObject* TCPSocket::FromSocket (JSContext* cx, host_api::TCPSocket* socket) {
115+ JSObject * TCPSocket::FromSocket (JSContext * cx, host_api::TCPSocket * socket) {
131116 RootedObject instance (cx, JS_NewObjectWithGivenProto (cx, &class_, proto_obj));
132117 if (!instance) {
133118 return nullptr ;
@@ -136,10 +121,8 @@ JSObject* TCPSocket::FromSocket(JSContext* cx, host_api::TCPSocket* socket) {
136121 return instance;
137122}
138123
139- const JSFunctionSpec TCPSocket::methods[] = {
140- JS_FN (" send" , TCPSocket::send, 1 , 0 ),
141- JS_FN (" receive" , TCPSocket::receive, 1 , 0 ), JS_FS_END
142- };
124+ const JSFunctionSpec TCPSocket::methods[] = {JS_FN (" send" , TCPSocket::send, 1 , 0 ),
125+ JS_FN (" receive" , TCPSocket::receive, 1 , 0 ), JS_FS_END};
143126
144127const JSFunctionSpec TCPSocket::static_methods[] = {JS_FS_END};
145128const JSPropertySpec TCPSocket::static_properties[] = {JS_PS_END};
@@ -150,11 +133,13 @@ host_api::HostString read_message(JSContext *cx, host_api::TCPSocket *socket) {
150133 if (!chunk) {
151134 return nullptr ;
152135 }
136+
153137 char *end;
154138 uint16_t message_length = std::strtoul (chunk.begin (), &end, 10 );
155139 if (end == chunk.begin () || *end != ' \n ' ) {
156140 return nullptr ;
157141 }
142+
158143 std::string message = std::string (end + 1 , chunk.end ());
159144 while (message.size () < message_length) {
160145 chunk = socket->receive (message_length - message.size ());
@@ -171,24 +156,26 @@ host_api::HostString read_message(JSContext *cx, host_api::TCPSocket *socket) {
171156bool initialize_debugger (JSContext *cx, uint16_t port, bool content_already_initialized) {
172157 auto socket = host_api::TCPSocket::make (host_api::TCPSocket::IPAddressFamily::IPV4);
173158 MOZ_RELEASE_ASSERT (socket, " Failed to create debugging socket" );
159+
174160 if (!socket->connect ({127 , 0 , 0 , 1 }, port) || !socket->send (" get-session-port" )) {
175161 printf (" Couldn't connect to debugging socket at port %u, continuing without debugging ...\n " ,
176162 port);
177163 return true ;
178164 }
165+
179166 auto response = socket->receive (128 );
180167 if (!response) {
181168 printf (" Couldn't get debugging session port, continuing without debugging ...\n " );
182169 return true ;
183170 }
184- char *end;
185171
186172 // If StarlingMonkey was loaded with debugging enabled, but no session is active,
187173 // we can just silently continue execution.
188174 if (string_view{" no-session" }.compare (0 , response.len , response) == 0 ) {
189175 return true ;
190176 }
191177
178+ char *end;
192179 uint16_t session_port = std::strtoul (response.begin (), &end, 10 );
193180 if (session_port < 1024 || session_port > 65535 ) {
194181 printf (" Invalid debugging session port '%*s' received, continuing without debugging ...\n " ,
@@ -199,12 +186,14 @@ bool initialize_debugger(JSContext *cx, uint16_t port, bool content_already_init
199186
200187 socket = host_api::TCPSocket::make (host_api::TCPSocket::IPAddressFamily::IPV4);
201188 MOZ_RELEASE_ASSERT (socket, " Failed to create debugging session socket" );
189+
202190 if (!socket->connect ({127 , 0 , 0 , 1 }, session_port) || !socket->send (" get-debugger" )) {
203191 printf (" Couldn't connect to debugging session socket at port %u, "
204192 " continuing without debugging ...\n " ,
205193 session_port);
206194 return true ;
207195 }
196+
208197 auto debugging_script = debugging_socket::read_message (cx, socket);
209198 if (!debugging_script) {
210199 printf (" Couldn't get debugger script, continuing without debugging ...\n " );
@@ -244,6 +233,7 @@ bool initialize_debugger(JSContext *cx, uint16_t port, bool content_already_init
244233 if (!socket_obj) {
245234 return false ;
246235 }
236+
247237 if (!JS_DefineProperty (cx, global, " socket" , socket_obj, JSPROP_READONLY)) {
248238 return false ;
249239 }
@@ -264,6 +254,7 @@ bool initialize_debugger(JSContext *cx, uint16_t port, bool content_already_init
264254 if (!script) {
265255 return false ;
266256 }
257+
267258 RootedValue result (cx);
268259 if (!JS_ExecuteScript (cx, script, &result)) {
269260 return false ;
@@ -272,12 +263,40 @@ bool initialize_debugger(JSContext *cx, uint16_t port, bool content_already_init
272263 return true ;
273264}
274265
275- static bool debugger_initialized = false ;
276- void content_debugger::maybe_init_debugger (api::Engine * engine, bool content_already_initialized) {
266+ } // anonymous namespace
267+
268+ namespace content_debugger {
269+
270+ bool dbg_print (JSContext *cx, unsigned argc, Value *vp) {
271+ CallArgs args = CallArgsFromVp (argc, vp);
272+
273+ if (!print_location (cx)) {
274+ return false ;
275+ }
276+
277+ for (size_t i = 0 ; i < args.length (); i++) {
278+ auto str = core::encode (cx, args.get (i));
279+ if (!str) {
280+ return false ;
281+ }
282+ printf (" %.*s" , static_cast <int >(str.len ), str.begin ());
283+ }
284+
285+ printf (" \n " );
286+ fflush (stdout);
287+ args.rval ().setUndefined ();
288+ return true ;
289+ }
290+
291+ void maybe_init_debugger (api::Engine *engine, bool content_already_initialized) {
277292 if (debugger_initialized || !engine->debugging_enabled ()) {
278293 return ;
279294 }
280295 debugger_initialized = true ;
296+
297+ // Resuming a wizer snapshot, so we have to ensure that the environment is reset.
298+ __wasilibc_initialize_environ ();
299+
281300 auto port_str = std::getenv (" DEBUGGER_PORT" );
282301 if (port_str) {
283302 uint32_t port = std::stoi (port_str);
@@ -288,6 +307,31 @@ void content_debugger::maybe_init_debugger(api::Engine * engine, bool content_al
288307 }
289308}
290309
291- mozilla::Maybe<std::string_view> content_debugger::replacement_script_path () {
292- return main_path;
310+ mozilla::Maybe<std::string_view> replacement_script_path () {
311+ if (main_path.isSome ()) {
312+ return mozilla::Some (std::string_view{main_path.ref ()});
313+ }
314+ return mozilla::Nothing ();
315+ }
316+
317+ } // namespace content_debugger
318+
319+ #else // !ENABLE_JS_DEBUGGER
320+
321+ // Stub implementations when debugger is disabled
322+ namespace content_debugger {
323+
324+ void maybe_init_debugger (api::Engine *engine, bool content_already_initialized) {}
325+
326+ bool dbg_print (JSContext *cx, unsigned argc, Value *vp) {
327+ MOZ_ASSERT_UNREACHABLE (" dbg_print only available with ENABLE_JS_DEBUGGER build option set." );
328+ return false ;
293329}
330+
331+ mozilla::Maybe<std::string_view> replacement_script_path () {
332+ return mozilla::Nothing ();
333+ }
334+
335+ } // namespace content_debugger
336+
337+ #endif // ENABLE_JS_DEBUGGER
0 commit comments