http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/5977aa27/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_debugger.c
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_debugger.c
 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_debugger.c
deleted file mode 100644
index e0caff6..0000000
--- 
a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_debugger.c
+++ /dev/null
@@ -1,2773 +0,0 @@
-/*
- *  Duktape debugger
- */
-
-#include "duk_internal.h"
-
-#if defined(DUK_USE_DEBUGGER_SUPPORT)
-
-/*
- *  Helper structs
- */
-
-typedef union {
-       void *p;
-       duk_uint_t b[1];
-       /* Use b[] to access the size of the union, which is strictly not
-        * correct.  Can't use fixed size unless there's feature detection
-        * for pointer byte size.
-        */
-} duk__ptr_union;
-
-/*
- *  Detach handling
- */
-
-#define DUK__SET_CONN_BROKEN(thr,reason) do { \
-               /* For now shared handler is fine. */ \
-               duk__debug_do_detach1((thr)->heap, (reason)); \
-       } while (0)
-
-DUK_LOCAL void duk__debug_do_detach1(duk_heap *heap, duk_int_t reason) {
-       /* Can be called multiple times with no harm.  Mark the transport
-        * bad (dbg_read_cb == NULL) and clear state except for the detached
-        * callback and the udata field.  The detached callback is delayed
-        * to the message loop so that it can be called between messages;
-        * this avoids corner cases related to immediate debugger reattach
-        * inside the detached callback.
-        */
-
-       if (heap->dbg_detaching) {
-               DUK_D(DUK_DPRINT("debugger already detaching, ignore detach1"));
-               return;
-       }
-
-       DUK_D(DUK_DPRINT("debugger transport detaching, marking transport 
broken"));
-
-       heap->dbg_detaching = 1;  /* prevent multiple in-progress detaches */
-
-       if (heap->dbg_write_cb != NULL) {
-               duk_hthread *thr;
-
-               thr = heap->heap_thread;
-               DUK_ASSERT(thr != NULL);
-
-               duk_debug_write_notify(thr, DUK_DBG_CMD_DETACHING);
-               duk_debug_write_int(thr, reason);
-               duk_debug_write_eom(thr);
-       }
-
-       heap->dbg_read_cb = NULL;
-       heap->dbg_write_cb = NULL;
-       heap->dbg_peek_cb = NULL;
-       heap->dbg_read_flush_cb = NULL;
-       heap->dbg_write_flush_cb = NULL;
-       heap->dbg_request_cb = NULL;
-       /* heap->dbg_detached_cb: keep */
-       /* heap->dbg_udata: keep */
-       /* heap->dbg_processing: keep on purpose to avoid debugger re-entry in 
detaching state */
-       heap->dbg_paused = 0;
-       heap->dbg_state_dirty = 0;
-       heap->dbg_force_restart = 0;
-       heap->dbg_step_type = 0;
-       heap->dbg_step_thread = NULL;
-       heap->dbg_step_csindex = 0;
-       heap->dbg_step_startline = 0;
-       heap->dbg_have_next_byte = 0;
-
-       /* Ensure there are no stale active breakpoint pointers.
-        * Breakpoint list is currently kept - we could empty it
-        * here but we'd need to handle refcounts correctly, and
-        * we'd need a 'thr' reference for that.
-        *
-        * XXX: clear breakpoint on either attach or detach?
-        */
-       heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
-}
-
-DUK_LOCAL void duk__debug_do_detach2(duk_heap *heap) {
-       duk_debug_detached_function detached_cb;
-       void *detached_udata;
-
-       /* Safe to call multiple times. */
-
-       detached_cb = heap->dbg_detached_cb;
-       detached_udata = heap->dbg_udata;
-       heap->dbg_detached_cb = NULL;
-       heap->dbg_udata = NULL;
-
-       if (detached_cb) {
-               /* Careful here: state must be wiped before the call
-                * so that we can cleanly handle a re-attach from
-                * inside the callback.
-                */
-               DUK_D(DUK_DPRINT("detached during message loop, delayed call to 
detached_cb"));
-               detached_cb(detached_udata);
-       }
-
-       heap->dbg_detaching = 0;
-}
-
-DUK_INTERNAL void duk_debug_do_detach(duk_heap *heap) {
-       duk__debug_do_detach1(heap, 0);
-       duk__debug_do_detach2(heap);
-}
-
-/* Called on a read/write error: NULL all callbacks except the detached
- * callback so that we never accidentally call them after a read/write
- * error has been indicated.  This is especially important for the transport
- * I/O callbacks to fulfill guaranteed callback semantics.
- */
-DUK_LOCAL void duk__debug_null_most_callbacks(duk_hthread *thr) {
-       duk_heap *heap;
-       heap = thr->heap;
-       DUK_D(DUK_DPRINT("transport read/write error, NULL all callbacks 
expected detached"));
-       heap->dbg_read_cb = NULL;
-       heap->dbg_write_cb = NULL;  /* this is especially critical to avoid 
another write call in detach1() */
-       heap->dbg_peek_cb = NULL;
-       heap->dbg_read_flush_cb = NULL;
-       heap->dbg_write_flush_cb = NULL;
-       heap->dbg_request_cb = NULL;
-       /* keep heap->dbg_detached_cb */
-}
-
-/*
- *  Debug connection peek and flush primitives
- */
-
-DUK_INTERNAL duk_bool_t duk_debug_read_peek(duk_hthread *thr) {
-       duk_heap *heap;
-
-       DUK_ASSERT(thr != NULL);
-       heap = thr->heap;
-       DUK_ASSERT(heap != NULL);
-
-       if (heap->dbg_read_cb == NULL) {
-               DUK_D(DUK_DPRINT("attempt to peek in detached state, return 
zero (= no data)"));
-               return 0;
-       }
-       if (heap->dbg_peek_cb == NULL) {
-               DUK_DD(DUK_DDPRINT("no peek callback, return zero (= no 
data)"));
-               return 0;
-       }
-
-       return (duk_bool_t) (heap->dbg_peek_cb(heap->dbg_udata) > 0);
-}
-
-DUK_INTERNAL void duk_debug_read_flush(duk_hthread *thr) {
-       duk_heap *heap;
-
-       DUK_ASSERT(thr != NULL);
-       heap = thr->heap;
-       DUK_ASSERT(heap != NULL);
-
-       if (heap->dbg_read_cb == NULL) {
-               DUK_D(DUK_DPRINT("attempt to read flush in detached state, 
ignore"));
-               return;
-       }
-       if (heap->dbg_read_flush_cb == NULL) {
-               DUK_DD(DUK_DDPRINT("no read flush callback, ignore"));
-               return;
-       }
-
-       heap->dbg_read_flush_cb(heap->dbg_udata);
-}
-
-DUK_INTERNAL void duk_debug_write_flush(duk_hthread *thr) {
-       duk_heap *heap;
-
-       DUK_ASSERT(thr != NULL);
-       heap = thr->heap;
-       DUK_ASSERT(heap != NULL);
-
-       if (heap->dbg_read_cb == NULL) {
-               DUK_D(DUK_DPRINT("attempt to write flush in detached state, 
ignore"));
-               return;
-       }
-       if (heap->dbg_write_flush_cb == NULL) {
-               DUK_DD(DUK_DDPRINT("no write flush callback, ignore"));
-               return;
-       }
-
-       heap->dbg_write_flush_cb(heap->dbg_udata);
-}
-
-/*
- *  Debug connection skip primitives
- */
-
-/* Skip fully. */
-DUK_INTERNAL void duk_debug_skip_bytes(duk_hthread *thr, duk_size_t length) {
-       duk_uint8_t dummy[64];
-       duk_size_t now;
-
-       DUK_ASSERT(thr != NULL);
-
-       while (length > 0) {
-               now = (length > sizeof(dummy) ? sizeof(dummy) : length);
-               duk_debug_read_bytes(thr, dummy, now);
-               length -= now;
-       }
-}
-
-DUK_INTERNAL void duk_debug_skip_byte(duk_hthread *thr) {
-       DUK_ASSERT(thr != NULL);
-
-       (void) duk_debug_read_byte(thr);
-}
-
-/*
- *  Debug connection read primitives
- */
-
-/* Peek ahead in the stream one byte. */
-DUK_INTERNAL uint8_t duk_debug_peek_byte(duk_hthread *thr) {
-       /* It is important not to call this if the last byte read was an EOM.
-        * Reading ahead in this scenario would cause unnecessary blocking if
-        * another message is not available.
-        */
-
-       duk_uint8_t x;
-
-       x = duk_debug_read_byte(thr);
-       thr->heap->dbg_have_next_byte = 1;
-       thr->heap->dbg_next_byte = x;
-       return x;
-}
-
-/* Read fully. */
-DUK_INTERNAL void duk_debug_read_bytes(duk_hthread *thr, duk_uint8_t *data, 
duk_size_t length) {
-       duk_heap *heap;
-       duk_uint8_t *p;
-       duk_size_t left;
-       duk_size_t got;
-
-       DUK_ASSERT(thr != NULL);
-       heap = thr->heap;
-       DUK_ASSERT(heap != NULL);
-
-       if (heap->dbg_read_cb == NULL) {
-               DUK_D(DUK_DPRINT("attempt to read %ld bytes in detached state, 
return zero data", (long) length));
-               goto fail;
-       }
-
-       /* NOTE: length may be zero */
-       p = data;
-       if (length >= 1 && heap->dbg_have_next_byte) {
-               heap->dbg_have_next_byte = 0;
-               *p++ = heap->dbg_next_byte;
-       }
-       for (;;) {
-               left = (duk_size_t) ((data + length) - p);
-               if (left == 0) {
-                       break;
-               }
-               DUK_ASSERT(heap->dbg_read_cb != NULL);
-               DUK_ASSERT(left >= 1);
-#if defined(DUK_USE_DEBUGGER_TRANSPORT_TORTURE)
-               left = 1;
-#endif
-               got = heap->dbg_read_cb(heap->dbg_udata, (char *) p, left);
-               if (got == 0 || got > left) {
-                       DUK_D(DUK_DPRINT("connection error during read, return 
zero data"));
-                       duk__debug_null_most_callbacks(thr);  /* avoid calling 
write callback in detach1() */
-                       DUK__SET_CONN_BROKEN(thr, 1);
-                       goto fail;
-               }
-               p += got;
-       }
-       return;
-
- fail:
-       DUK_MEMZERO((void *) data, (size_t) length);
-}
-
-DUK_INTERNAL duk_uint8_t duk_debug_read_byte(duk_hthread *thr) {
-       duk_uint8_t x;
-
-       x = 0;  /* just in case callback is broken and won't write 'x' */
-       duk_debug_read_bytes(thr, &x, 1);
-       return x;
-}
-
-DUK_LOCAL duk_uint32_t duk__debug_read_uint32_raw(duk_hthread *thr) {
-       duk_uint8_t buf[4];
-
-       DUK_ASSERT(thr != NULL);
-
-       duk_debug_read_bytes(thr, buf, 4);
-       return ((duk_uint32_t) buf[0] << 24) |
-              ((duk_uint32_t) buf[1] << 16) |
-              ((duk_uint32_t) buf[2] << 8) |
-              (duk_uint32_t) buf[3];
-}
-
-DUK_LOCAL duk_uint32_t duk__debug_read_int32_raw(duk_hthread *thr) {
-       return (duk_int32_t) duk__debug_read_uint32_raw(thr);
-}
-
-DUK_LOCAL duk_uint16_t duk__debug_read_uint16_raw(duk_hthread *thr) {
-       duk_uint8_t buf[2];
-
-       DUK_ASSERT(thr != NULL);
-
-       duk_debug_read_bytes(thr, buf, 2);
-       return ((duk_uint16_t) buf[0] << 8) |
-              (duk_uint16_t) buf[1];
-}
-
-DUK_INTERNAL duk_int32_t duk_debug_read_int(duk_hthread *thr) {
-       duk_small_uint_t x;
-       duk_small_uint_t t;
-
-       DUK_ASSERT(thr != NULL);
-
-       x = duk_debug_read_byte(thr);
-       if (x >= 0xc0) {
-               t = duk_debug_read_byte(thr);
-               return (duk_int32_t) (((x - 0xc0) << 8) + t);
-       } else if (x >= 0x80) {
-               return (duk_int32_t) (x - 0x80);
-       } else if (x == DUK_DBG_IB_INT4) {
-               return (duk_int32_t) duk__debug_read_uint32_raw(thr);
-       }
-
-       DUK_D(DUK_DPRINT("debug connection error: failed to decode int"));
-       DUK__SET_CONN_BROKEN(thr, 1);
-       return 0;
-}
-
-DUK_LOCAL duk_hstring *duk__debug_read_hstring_raw(duk_hthread *thr, 
duk_uint32_t len) {
-       duk_context *ctx = (duk_context *) thr;
-       duk_uint8_t buf[31];
-       duk_uint8_t *p;
-
-       if (len <= sizeof(buf)) {
-               duk_debug_read_bytes(thr, buf, (duk_size_t) len);
-               duk_push_lstring(ctx, (const char *) buf, (duk_size_t) len);
-       } else {
-               p = (duk_uint8_t *) duk_push_fixed_buffer(ctx, (duk_size_t) 
len);
-               DUK_ASSERT(p != NULL);
-               duk_debug_read_bytes(thr, p, (duk_size_t) len);
-               duk_to_string(ctx, -1);
-       }
-
-       return duk_require_hstring(ctx, -1);
-}
-
-DUK_INTERNAL duk_hstring *duk_debug_read_hstring(duk_hthread *thr) {
-       duk_context *ctx = (duk_context *) thr;
-       duk_small_uint_t x;
-       duk_uint32_t len;
-
-       DUK_ASSERT(thr != NULL);
-
-       x = duk_debug_read_byte(thr);
-       if (x >= 0x60 && x <= 0x7f) {
-               /* For short strings, use a fixed temp buffer. */
-               len = (duk_uint32_t) (x - 0x60);
-       } else if (x == DUK_DBG_IB_STR2) {
-               len = (duk_uint32_t) duk__debug_read_uint16_raw(thr);
-       } else if (x == DUK_DBG_IB_STR4) {
-               len = (duk_uint32_t) duk__debug_read_uint32_raw(thr);
-       } else {
-               goto fail;
-       }
-
-       return duk__debug_read_hstring_raw(thr, len);
-
- fail:
-       DUK_D(DUK_DPRINT("debug connection error: failed to decode int"));
-       DUK__SET_CONN_BROKEN(thr, 1);
-       duk_push_hstring_stridx(thr, DUK_STRIDX_EMPTY_STRING);  /* always push 
some string */
-       return duk_require_hstring(ctx, -1);
-}
-
-DUK_LOCAL duk_hbuffer *duk__debug_read_hbuffer_raw(duk_hthread *thr, 
duk_uint32_t len) {
-       duk_context *ctx = (duk_context *) thr;
-       duk_uint8_t *p;
-
-       p = (duk_uint8_t *) duk_push_fixed_buffer(ctx, (duk_size_t) len);
-       DUK_ASSERT(p != NULL);
-       duk_debug_read_bytes(thr, p, (duk_size_t) len);
-
-       return duk_require_hbuffer(ctx, -1);
-}
-
-DUK_LOCAL void *duk__debug_read_pointer_raw(duk_hthread *thr) {
-       duk_small_uint_t x;
-       duk__ptr_union pu;
-
-       DUK_ASSERT(thr != NULL);
-
-       x = duk_debug_read_byte(thr);
-       if (x != sizeof(pu)) {
-               goto fail;
-       }
-       duk_debug_read_bytes(thr, (duk_uint8_t *) &pu.p, sizeof(pu));
-#if defined(DUK_USE_INTEGER_LE)
-       duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
-#endif
-       return (void *) pu.p;
-
- fail:
-       DUK_D(DUK_DPRINT("debug connection error: failed to decode pointer"));
-       DUK__SET_CONN_BROKEN(thr, 1);
-       return (void *) NULL;
-}
-
-DUK_LOCAL duk_double_t duk__debug_read_double_raw(duk_hthread *thr) {
-       duk_double_union du;
-
-       DUK_ASSERT(sizeof(du.uc) == 8);
-       duk_debug_read_bytes(thr, (duk_uint8_t *) du.uc, sizeof(du.uc));
-       DUK_DBLUNION_DOUBLE_NTOH(&du);
-       return du.d;
-}
-
-#if 0
-DUK_INTERNAL duk_heaphdr *duk_debug_read_heapptr(duk_hthread *thr) {
-       duk_small_uint_t x;
-
-       DUK_ASSERT(thr != NULL);
-
-       x = duk_debug_read_byte(thr);
-       if (x != DUK_DBG_IB_HEAPPTR) {
-               goto fail;
-       }
-
-       return (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
-
- fail:
-       DUK_D(DUK_DPRINT("debug connection error: failed to decode heapptr"));
-       DUK__SET_CONN_BROKEN(thr, 1);
-       return NULL;
-}
-#endif
-
-DUK_INTERNAL duk_heaphdr *duk_debug_read_any_ptr(duk_hthread *thr) {
-       duk_small_uint_t x;
-
-       DUK_ASSERT(thr != NULL);
-
-       x = duk_debug_read_byte(thr);
-       switch (x) {
-       case DUK_DBG_IB_OBJECT:
-       case DUK_DBG_IB_POINTER:
-       case DUK_DBG_IB_HEAPPTR:
-               /* Accept any pointer-like value; for 'object' dvalue, read
-                * and ignore the class number.
-                */
-               if (x == DUK_DBG_IB_OBJECT) {
-                       duk_debug_skip_byte(thr);
-               }
-               break;
-       default:
-               goto fail;
-       }
-
-       return (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
-
- fail:
-       DUK_D(DUK_DPRINT("debug connection error: failed to decode any pointer 
(object, pointer, heapptr)"));
-       DUK__SET_CONN_BROKEN(thr, 1);
-       return NULL;
-}
-
-DUK_INTERNAL duk_tval *duk_debug_read_tval(duk_hthread *thr) {
-       duk_context *ctx = (duk_context *) thr;
-       duk_uint8_t x;
-       duk_uint_t t;
-       duk_uint32_t len;
-
-       DUK_ASSERT(thr != NULL);
-
-       x = duk_debug_read_byte(thr);
-
-       if (x >= 0xc0) {
-               t = (duk_uint_t) (x - 0xc0);
-               t = (t << 8) + duk_debug_read_byte(thr);
-               duk_push_uint(ctx, (duk_uint_t) t);
-               goto return_ptr;
-       }
-       if (x >= 0x80) {
-               duk_push_uint(ctx, (duk_uint_t) (x - 0x80));
-               goto return_ptr;
-       }
-       if (x >= 0x60) {
-               len = (duk_uint32_t) (x - 0x60);
-               duk__debug_read_hstring_raw(thr, len);
-               goto return_ptr;
-       }
-
-       switch (x) {
-       case DUK_DBG_IB_INT4: {
-               duk_int32_t i = duk__debug_read_int32_raw(thr);
-               duk_push_i32(ctx, i);
-               break;
-       }
-       case DUK_DBG_IB_STR4: {
-               len = duk__debug_read_uint32_raw(thr);
-               duk__debug_read_hstring_raw(thr, len);
-               break;
-       }
-       case DUK_DBG_IB_STR2: {
-               len = duk__debug_read_uint16_raw(thr);
-               duk__debug_read_hstring_raw(thr, len);
-               break;
-       }
-       case DUK_DBG_IB_BUF4: {
-               len = duk__debug_read_uint32_raw(thr);
-               duk__debug_read_hbuffer_raw(thr, len);
-               break;
-       }
-       case DUK_DBG_IB_BUF2: {
-               len = duk__debug_read_uint16_raw(thr);
-               duk__debug_read_hbuffer_raw(thr, len);
-               break;
-       }
-       case DUK_DBG_IB_UNDEFINED: {
-               duk_push_undefined(ctx);
-               break;
-       }
-       case DUK_DBG_IB_NULL: {
-               duk_push_null(ctx);
-               break;
-       }
-       case DUK_DBG_IB_TRUE: {
-               duk_push_true(ctx);
-               break;
-       }
-       case DUK_DBG_IB_FALSE: {
-               duk_push_false(ctx);
-               break;
-       }
-       case DUK_DBG_IB_NUMBER: {
-               duk_double_t d;
-               d = duk__debug_read_double_raw(thr);
-               duk_push_number(ctx, d);
-               break;
-       }
-       case DUK_DBG_IB_OBJECT: {
-               duk_heaphdr *h;
-               duk_debug_skip_byte(thr);
-               h = (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
-               duk_push_heapptr(thr, (void *) h);
-               break;
-       }
-       case DUK_DBG_IB_POINTER: {
-               void *ptr;
-               ptr = duk__debug_read_pointer_raw(thr);
-               duk_push_pointer(thr, ptr);
-               break;
-       }
-       case DUK_DBG_IB_LIGHTFUNC: {
-               /* XXX: Not needed for now, so not implemented.  Note that
-                * function pointers may have different size/layout than
-                * a void pointer.
-                */
-               DUK_D(DUK_DPRINT("reading lightfunc values unimplemented"));
-               goto fail;
-       }
-       case DUK_DBG_IB_HEAPPTR: {
-               duk_heaphdr *h;
-               h = (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
-               duk_push_heapptr(thr, (void *) h);
-               break;
-       }
-       case DUK_DBG_IB_UNUSED:  /* unused: not accepted in inbound messages */
-       default:
-               goto fail;
-       }
-
- return_ptr:
-       return DUK_GET_TVAL_NEGIDX(thr, -1);
-
- fail:
-       DUK_D(DUK_DPRINT("debug connection error: failed to decode tval"));
-       DUK__SET_CONN_BROKEN(thr, 1);
-       return NULL;
-}
-
-/*
- *  Debug connection write primitives
- */
-
-/* Write fully. */
-DUK_INTERNAL void duk_debug_write_bytes(duk_hthread *thr, const duk_uint8_t 
*data, duk_size_t length) {
-       duk_heap *heap;
-       const duk_uint8_t *p;
-       duk_size_t left;
-       duk_size_t got;
-
-       DUK_ASSERT(thr != NULL);
-       DUK_ASSERT(length == 0 || data != NULL);
-       heap = thr->heap;
-       DUK_ASSERT(heap != NULL);
-
-       if (heap->dbg_write_cb == NULL) {
-               DUK_D(DUK_DPRINT("attempt to write %ld bytes in detached state, 
ignore", (long) length));
-               return;
-       }
-       if (length == 0) {
-               /* Avoid doing an actual write callback with length == 0,
-                * because that's reserved for a write flush.
-                */
-               return;
-       }
-       DUK_ASSERT(data != NULL);
-
-       p = data;
-       for (;;) {
-               left = (duk_size_t) ((data + length) - p);
-               if (left == 0) {
-                       break;
-               }
-               DUK_ASSERT(heap->dbg_write_cb != NULL);
-               DUK_ASSERT(left >= 1);
-#if defined(DUK_USE_DEBUGGER_TRANSPORT_TORTURE)
-               left = 1;
-#endif
-               got = heap->dbg_write_cb(heap->dbg_udata, (const char *) p, 
left);
-               if (got == 0 || got > left) {
-                       duk__debug_null_most_callbacks(thr);  /* avoid calling 
write callback in detach1() */
-                       DUK_D(DUK_DPRINT("connection error during write"));
-                       DUK__SET_CONN_BROKEN(thr, 1);
-                       return;
-               }
-               p += got;
-       }
-}
-
-DUK_INTERNAL void duk_debug_write_byte(duk_hthread *thr, duk_uint8_t x) {
-       duk_debug_write_bytes(thr, (const duk_uint8_t *) &x, 1);
-}
-
-DUK_INTERNAL void duk_debug_write_unused(duk_hthread *thr) {
-       duk_debug_write_byte(thr, DUK_DBG_IB_UNUSED);
-}
-
-DUK_INTERNAL void duk_debug_write_undefined(duk_hthread *thr) {
-       duk_debug_write_byte(thr, DUK_DBG_IB_UNDEFINED);
-}
-
-#if defined(DUK_USE_DEBUGGER_INSPECT)
-DUK_INTERNAL void duk_debug_write_null(duk_hthread *thr) {
-       duk_debug_write_byte(thr, DUK_DBG_IB_NULL);
-}
-#endif
-
-DUK_INTERNAL void duk_debug_write_boolean(duk_hthread *thr, duk_uint_t val) {
-       duk_debug_write_byte(thr, val ? DUK_DBG_IB_TRUE : DUK_DBG_IB_FALSE);
-}
-
-/* Write signed 32-bit integer. */
-DUK_INTERNAL void duk_debug_write_int(duk_hthread *thr, duk_int32_t x) {
-       duk_uint8_t buf[5];
-       duk_size_t len;
-
-       DUK_ASSERT(thr != NULL);
-
-       if (x >= 0 && x <= 0x3fL) {
-               buf[0] = (duk_uint8_t) (0x80 + x);
-               len = 1;
-       } else if (x >= 0 && x <= 0x3fffL) {
-               buf[0] = (duk_uint8_t) (0xc0 + (x >> 8));
-               buf[1] = (duk_uint8_t) (x & 0xff);
-               len = 2;
-       } else {
-               /* Signed integers always map to 4 bytes now. */
-               buf[0] = (duk_uint8_t) DUK_DBG_IB_INT4;
-               buf[1] = (duk_uint8_t) ((x >> 24) & 0xff);
-               buf[2] = (duk_uint8_t) ((x >> 16) & 0xff);
-               buf[3] = (duk_uint8_t) ((x >> 8) & 0xff);
-               buf[4] = (duk_uint8_t) (x & 0xff);
-               len = 5;
-       }
-       duk_debug_write_bytes(thr, buf, len);
-}
-
-/* Write unsigned 32-bit integer. */
-DUK_INTERNAL void duk_debug_write_uint(duk_hthread *thr, duk_uint32_t x) {
-       /* The debugger protocol doesn't support a plain integer encoding for
-        * the full 32-bit unsigned range (only 32-bit signed).  For now,
-        * unsigned 32-bit values simply written as signed ones.  This is not
-        * a concrete issue except for 32-bit heaphdr fields.  Proper solutions
-        * would be to (a) write such integers as IEEE doubles or (b) add an
-        * unsigned 32-bit dvalue.
-        */
-       if (x >= 0x80000000UL) {
-               DUK_D(DUK_DPRINT("writing unsigned integer 0x%08lx as signed 
integer",
-                                (long) x));
-       }
-       duk_debug_write_int(thr, (duk_int32_t) x);
-}
-
-DUK_INTERNAL void duk_debug_write_strbuf(duk_hthread *thr, const char *data, 
duk_size_t length, duk_uint8_t marker_base) {
-       duk_uint8_t buf[5];
-       duk_size_t buflen;
-
-       DUK_ASSERT(thr != NULL);
-       DUK_ASSERT(length == 0 || data != NULL);
-
-       if (length <= 0x1fUL && marker_base == DUK_DBG_IB_STR4) {
-               /* For strings, special form for short lengths. */
-               buf[0] = (duk_uint8_t) (0x60 + length);
-               buflen = 1;
-       } else if (length <= 0xffffUL) {
-               buf[0] = (duk_uint8_t) (marker_base + 1);
-               buf[1] = (duk_uint8_t) (length >> 8);
-               buf[2] = (duk_uint8_t) (length & 0xff);
-               buflen = 3;
-       } else {
-               buf[0] = (duk_uint8_t) marker_base;
-               buf[1] = (duk_uint8_t) (length >> 24);
-               buf[2] = (duk_uint8_t) ((length >> 16) & 0xff);
-               buf[3] = (duk_uint8_t) ((length >> 8) & 0xff);
-               buf[4] = (duk_uint8_t) (length & 0xff);
-               buflen = 5;
-       }
-
-       duk_debug_write_bytes(thr, (const duk_uint8_t *) buf, buflen);
-       duk_debug_write_bytes(thr, (const duk_uint8_t *) data, length);
-}
-
-DUK_INTERNAL void duk_debug_write_string(duk_hthread *thr, const char *data, 
duk_size_t length) {
-       duk_debug_write_strbuf(thr, data, length, DUK_DBG_IB_STR4);
-}
-
-DUK_INTERNAL void duk_debug_write_cstring(duk_hthread *thr, const char *data) {
-       DUK_ASSERT(thr != NULL);
-
-       duk_debug_write_string(thr,
-                              data,
-                              data ? DUK_STRLEN(data) : 0);
-}
-
-DUK_INTERNAL void duk_debug_write_hstring(duk_hthread *thr, duk_hstring *h) {
-       DUK_ASSERT(thr != NULL);
-
-       /* XXX: differentiate null pointer from empty string? */
-       duk_debug_write_string(thr,
-                              (h != NULL ? (const char *) 
DUK_HSTRING_GET_DATA(h) : NULL),
-                              (h != NULL ? (duk_size_t) 
DUK_HSTRING_GET_BYTELEN(h) : 0));
-}
-
-DUK_LOCAL void duk__debug_write_hstring_safe_top(duk_hthread *thr) {
-       duk_context *ctx = (duk_context *) thr;
-       duk_debug_write_hstring(thr, duk_safe_to_hstring(ctx, -1));
-}
-
-DUK_INTERNAL void duk_debug_write_buffer(duk_hthread *thr, const char *data, 
duk_size_t length) {
-       duk_debug_write_strbuf(thr, data, length, DUK_DBG_IB_BUF4);
-}
-
-DUK_INTERNAL void duk_debug_write_hbuffer(duk_hthread *thr, duk_hbuffer *h) {
-       DUK_ASSERT(thr != NULL);
-
-       duk_debug_write_buffer(thr,
-                              (h != NULL ? (const char *) 
DUK_HBUFFER_GET_DATA_PTR(thr->heap, h) : NULL),
-                              (h != NULL ? (duk_size_t) 
DUK_HBUFFER_GET_SIZE(h) : 0));
-}
-
-DUK_LOCAL void duk__debug_write_pointer_raw(duk_hthread *thr, void *ptr, 
duk_uint8_t ibyte) {
-       duk_uint8_t buf[2];
-       duk__ptr_union pu;
-
-       DUK_ASSERT(thr != NULL);
-       DUK_ASSERT(sizeof(ptr) >= 1 && sizeof(ptr) <= 16);
-       /* ptr may be NULL */
-
-       buf[0] = ibyte;
-       buf[1] = sizeof(pu);
-       duk_debug_write_bytes(thr, buf, 2);
-       pu.p = (void *) ptr;
-#if defined(DUK_USE_INTEGER_LE)
-       duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
-#endif
-       duk_debug_write_bytes(thr, (const duk_uint8_t *) &pu.p, (duk_size_t) 
sizeof(pu));
-}
-
-DUK_INTERNAL void duk_debug_write_pointer(duk_hthread *thr, void *ptr) {
-       duk__debug_write_pointer_raw(thr, ptr, DUK_DBG_IB_POINTER);
-}
-
-#if defined(DUK_USE_DEBUGGER_DUMPHEAP) || defined(DUK_USE_DEBUGGER_INSPECT)
-DUK_INTERNAL void duk_debug_write_heapptr(duk_hthread *thr, duk_heaphdr *h) {
-       duk__debug_write_pointer_raw(thr, (void *) h, DUK_DBG_IB_HEAPPTR);
-}
-#endif  /* DUK_USE_DEBUGGER_DUMPHEAP || DUK_USE_DEBUGGER_INSPECT */
-
-DUK_INTERNAL void duk_debug_write_hobject(duk_hthread *thr, duk_hobject *obj) {
-       duk_uint8_t buf[3];
-       duk__ptr_union pu;
-
-       DUK_ASSERT(thr != NULL);
-       DUK_ASSERT(sizeof(obj) >= 1 && sizeof(obj) <= 16);
-       DUK_ASSERT(obj != NULL);
-
-       buf[0] = DUK_DBG_IB_OBJECT;
-       buf[1] = (duk_uint8_t) DUK_HOBJECT_GET_CLASS_NUMBER(obj);
-       buf[2] = sizeof(pu);
-       duk_debug_write_bytes(thr, buf, 3);
-       pu.p = (void *) obj;
-#if defined(DUK_USE_INTEGER_LE)
-       duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
-#endif
-       duk_debug_write_bytes(thr, (const duk_uint8_t *) &pu.p, (duk_size_t) 
sizeof(pu));
-}
-
-DUK_INTERNAL void duk_debug_write_tval(duk_hthread *thr, duk_tval *tv) {
-       duk_c_function lf_func;
-       duk_small_uint_t lf_flags;
-       duk_uint8_t buf[4];
-       duk_double_union du1;
-       duk_double_union du2;
-       duk_int32_t i32;
-
-       DUK_ASSERT(thr != NULL);
-       DUK_ASSERT(tv != NULL);
-
-       switch (DUK_TVAL_GET_TAG(tv)) {
-       case DUK_TAG_UNDEFINED:
-               duk_debug_write_byte(thr, DUK_DBG_IB_UNDEFINED);
-               break;
-       case DUK_TAG_UNUSED:
-               duk_debug_write_byte(thr, DUK_DBG_IB_UNUSED);
-               break;
-       case DUK_TAG_NULL:
-               duk_debug_write_byte(thr, DUK_DBG_IB_NULL);
-               break;
-       case DUK_TAG_BOOLEAN:
-               DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv) == 0 ||
-                          DUK_TVAL_GET_BOOLEAN(tv) == 1);
-               duk_debug_write_boolean(thr, DUK_TVAL_GET_BOOLEAN(tv));
-               break;
-       case DUK_TAG_POINTER:
-               duk_debug_write_pointer(thr, (void *) DUK_TVAL_GET_POINTER(tv));
-               break;
-       case DUK_TAG_LIGHTFUNC:
-               DUK_TVAL_GET_LIGHTFUNC(tv, lf_func, lf_flags);
-               buf[0] = DUK_DBG_IB_LIGHTFUNC;
-               buf[1] = (duk_uint8_t) (lf_flags >> 8);
-               buf[2] = (duk_uint8_t) (lf_flags & 0xff);
-               buf[3] = sizeof(lf_func);
-               duk_debug_write_bytes(thr, buf, 4);
-               duk_debug_write_bytes(thr, (const duk_uint8_t *) &lf_func, 
sizeof(lf_func));
-               break;
-       case DUK_TAG_STRING:
-               duk_debug_write_hstring(thr, DUK_TVAL_GET_STRING(tv));
-               break;
-       case DUK_TAG_OBJECT:
-               duk_debug_write_hobject(thr, DUK_TVAL_GET_OBJECT(tv));
-               break;
-       case DUK_TAG_BUFFER:
-               duk_debug_write_hbuffer(thr, DUK_TVAL_GET_BUFFER(tv));
-               break;
-#if defined(DUK_USE_FASTINT)
-       case DUK_TAG_FASTINT:
-#endif
-       default:
-               /* Numbers are normalized to big (network) endian.  We can
-                * (but are not required) to use integer dvalues when there's
-                * no loss of precision.
-                *
-                * XXX: share check with other code; this check is slow but
-                * reliable and doesn't require careful exponent/mantissa
-                * mask tricks as in the fastint downgrade code.
-                */
-               DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
-               DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
-               du1.d = DUK_TVAL_GET_NUMBER(tv);
-               i32 = (duk_int32_t) du1.d;
-               du2.d = (duk_double_t) i32;
-
-               DUK_DD(DUK_DDPRINT("i32=%ld 
du1=%02x%02x%02x%02x%02x%02x%02x%02x "
-                                  "du2=%02x%02x%02x%02x%02x%02x%02x%02x",
-                                  (long) i32,
-                                  (unsigned int) du1.uc[0], (unsigned int) 
du1.uc[1],
-                                  (unsigned int) du1.uc[2], (unsigned int) 
du1.uc[3],
-                                  (unsigned int) du1.uc[4], (unsigned int) 
du1.uc[5],
-                                  (unsigned int) du1.uc[6], (unsigned int) 
du1.uc[7],
-                                  (unsigned int) du2.uc[0], (unsigned int) 
du2.uc[1],
-                                  (unsigned int) du2.uc[2], (unsigned int) 
du2.uc[3],
-                                  (unsigned int) du2.uc[4], (unsigned int) 
du2.uc[5],
-                                  (unsigned int) du2.uc[6], (unsigned int) 
du2.uc[7]));
-
-               if (DUK_MEMCMP((const void *) du1.uc, (const void *) du2.uc, 
sizeof(du1.uc)) == 0) {
-                       duk_debug_write_int(thr, i32);
-               } else {
-                       DUK_DBLUNION_DOUBLE_HTON(&du1);
-                       duk_debug_write_byte(thr, DUK_DBG_IB_NUMBER);
-                       duk_debug_write_bytes(thr, (const duk_uint8_t *) 
du1.uc, sizeof(du1.uc));
-               }
-       }
-}
-
-#if defined(DUK_USE_DEBUGGER_DUMPHEAP)
-/* Variant for writing duk_tvals so that any heap allocated values are
- * written out as tagged heap pointers.
- */
-DUK_LOCAL void duk__debug_write_tval_heapptr(duk_hthread *thr, duk_tval *tv) {
-       if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
-               duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
-               duk_debug_write_heapptr(thr, h);
-       } else {
-               duk_debug_write_tval(thr, tv);
-       }
-}
-#endif  /* DUK_USE_DEBUGGER_DUMPHEAP */
-
-/*
- *  Debug connection message write helpers
- */
-
-#if 0  /* unused */
-DUK_INTERNAL void duk_debug_write_request(duk_hthread *thr, duk_small_uint_t 
command) {
-       duk_debug_write_byte(thr, DUK_DBG_IB_REQUEST);
-       duk_debug_write_int(thr, command);
-}
-#endif
-
-DUK_INTERNAL void duk_debug_write_reply(duk_hthread *thr) {
-       duk_debug_write_byte(thr, DUK_DBG_IB_REPLY);
-}
-
-DUK_INTERNAL void duk_debug_write_error_eom(duk_hthread *thr, duk_small_uint_t 
err_code, const char *msg) {
-       /* Allow NULL 'msg' */
-       duk_debug_write_byte(thr, DUK_DBG_IB_ERROR);
-       duk_debug_write_int(thr, (duk_int32_t) err_code);
-       duk_debug_write_cstring(thr, msg);
-       duk_debug_write_eom(thr);
-}
-
-DUK_INTERNAL void duk_debug_write_notify(duk_hthread *thr, duk_small_uint_t 
command) {
-       duk_debug_write_byte(thr, DUK_DBG_IB_NOTIFY);
-       duk_debug_write_int(thr, command);
-}
-
-DUK_INTERNAL void duk_debug_write_eom(duk_hthread *thr) {
-       duk_debug_write_byte(thr, DUK_DBG_IB_EOM);
-
-       /* As an initial implementation, write flush after every EOM (and the
-        * version identifier).  A better implementation would flush only when
-        * Duktape is finished processing messages so that a flush only happens
-        * after all outbound messages are finished on that occasion.
-        */
-       duk_debug_write_flush(thr);
-}
-
-/*
- *  Status message and helpers
- */
-
-DUK_INTERNAL duk_uint_fast32_t duk_debug_curr_line(duk_hthread *thr) {
-       duk_context *ctx = (duk_context *) thr;
-       duk_activation *act;
-       duk_uint_fast32_t line;
-       duk_uint_fast32_t pc;
-
-       act = duk_hthread_get_current_activation(thr);  /* may be NULL */
-       if (act == NULL) {
-               return 0;
-       }
-
-       /* We're conceptually between two opcodes; act->pc indicates the next
-        * instruction to be executed.  This is usually the correct pc/line to
-        * indicate in Status.  (For the 'debugger' statement this now reports
-        * the pc/line after the debugger statement because the debugger opcode
-        * has already been executed.)
-        */
-
-       pc = duk_hthread_get_act_curr_pc(thr, act);
-
-       /* XXX: this should be optimized to be a raw query and avoid valstack
-        * operations if possible.
-        */
-       duk_push_tval(ctx, &act->tv_func);
-       line = duk_hobject_pc2line_query(ctx, -1, pc);
-       duk_pop(ctx);
-       return line;
-}
-
-DUK_INTERNAL void duk_debug_send_status(duk_hthread *thr) {
-       duk_context *ctx = (duk_context *) thr;
-       duk_activation *act;
-
-       duk_debug_write_notify(thr, DUK_DBG_CMD_STATUS);
-       duk_debug_write_int(thr, thr->heap->dbg_paused);
-
-       DUK_ASSERT_DISABLE(thr->callstack_top >= 0);  /* unsigned */
-       if (thr->callstack_top == 0) {
-               duk_debug_write_undefined(thr);
-               duk_debug_write_undefined(thr);
-               duk_debug_write_int(thr, 0);
-               duk_debug_write_int(thr, 0);
-       } else {
-               act = thr->callstack + thr->callstack_top - 1;
-               duk_push_tval(ctx, &act->tv_func);
-               duk_get_prop_string(ctx, -1, "fileName");
-               duk__debug_write_hstring_safe_top(thr);
-               duk_get_prop_string(ctx, -2, "name");
-               duk__debug_write_hstring_safe_top(thr);
-               duk_pop_3(ctx);
-               /* Report next pc/line to be executed. */
-               duk_debug_write_uint(thr, (duk_uint32_t) 
duk_debug_curr_line(thr));
-               duk_debug_write_uint(thr, (duk_uint32_t) 
duk_hthread_get_act_curr_pc(thr, act));
-       }
-
-       duk_debug_write_eom(thr);
-}
-
-#if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
-DUK_INTERNAL void duk_debug_send_throw(duk_hthread *thr, duk_bool_t fatal) {
-       /*
-        *  NFY <int: 5> <int: fatal> <str: msg> <str: filename> <int: 
linenumber> EOM
-        */
-
-       duk_context *ctx = (duk_context *) thr;
-       duk_activation *act;
-       duk_uint32_t pc;
-
-       DUK_ASSERT(thr->valstack_top > thr->valstack);  /* At least: ... [err] 
*/
-
-       duk_debug_write_notify(thr, DUK_DBG_CMD_THROW);
-       duk_debug_write_int(thr, fatal);
-
-       /* Report thrown value to client coerced to string */
-       duk_dup(ctx, -1);
-       duk__debug_write_hstring_safe_top(thr);
-       duk_pop(ctx);
-
-       if (duk_is_error(ctx, -1)) {
-               /* Error instance, use augmented error data directly */
-               duk_get_prop_stridx(ctx, -1, DUK_STRIDX_FILE_NAME);
-               duk__debug_write_hstring_safe_top(thr);
-               duk_get_prop_stridx(ctx, -2, DUK_STRIDX_LINE_NUMBER);
-               duk_debug_write_uint(thr, duk_get_uint(ctx, -1));
-       } else {
-               /* For anything other than an Error instance, we calculate the 
error
-                * location directly from the current activation.
-                */
-               act = thr->callstack + thr->callstack_top - 1;
-               duk_push_tval(ctx, &act->tv_func);
-               duk_get_prop_string(ctx, -1, "fileName");
-               duk__debug_write_hstring_safe_top(thr);
-               pc = duk_hthread_get_act_prev_pc(thr, act);
-               duk_debug_write_uint(thr, (duk_uint32_t) 
duk_hobject_pc2line_query(ctx, -2, pc));
-       }
-       duk_pop_2(ctx);  /* shared pop */
-
-       duk_debug_write_eom(thr);
-}
-#endif  /* DUK_USE_DEBUGGER_THROW_NOTIFY */
-
-/*
- *  Debug message processing
- */
-
-/* Skip dvalue. */
-DUK_LOCAL duk_bool_t duk__debug_skip_dvalue(duk_hthread *thr) {
-       duk_uint8_t x;
-       duk_uint32_t len;
-
-       x = duk_debug_read_byte(thr);
-
-       if (x >= 0xc0) {
-               duk_debug_skip_byte(thr);
-               return 0;
-       }
-       if (x >= 0x80) {
-               return 0;
-       }
-       if (x >= 0x60) {
-               duk_debug_skip_bytes(thr, x - 0x60);
-               return 0;
-       }
-       switch(x) {
-       case DUK_DBG_IB_EOM:
-               return 1;  /* Return 1: got EOM */
-       case DUK_DBG_IB_REQUEST:
-       case DUK_DBG_IB_REPLY:
-       case DUK_DBG_IB_ERROR:
-       case DUK_DBG_IB_NOTIFY:
-               break;
-       case DUK_DBG_IB_INT4:
-               (void) duk__debug_read_uint32_raw(thr);
-               break;
-       case DUK_DBG_IB_STR4:
-       case DUK_DBG_IB_BUF4:
-               len = duk__debug_read_uint32_raw(thr);
-               duk_debug_skip_bytes(thr, len);
-               break;
-       case DUK_DBG_IB_STR2:
-       case DUK_DBG_IB_BUF2:
-               len = duk__debug_read_uint16_raw(thr);
-               duk_debug_skip_bytes(thr, len);
-               break;
-       case DUK_DBG_IB_UNUSED:
-       case DUK_DBG_IB_UNDEFINED:
-       case DUK_DBG_IB_NULL:
-       case DUK_DBG_IB_TRUE:
-       case DUK_DBG_IB_FALSE:
-               break;
-       case DUK_DBG_IB_NUMBER:
-               duk_debug_skip_bytes(thr, 8);
-               break;
-       case DUK_DBG_IB_OBJECT:
-               duk_debug_skip_byte(thr);
-               len = duk_debug_read_byte(thr);
-               duk_debug_skip_bytes(thr, len);
-               break;
-       case DUK_DBG_IB_POINTER:
-       case DUK_DBG_IB_HEAPPTR:
-               len = duk_debug_read_byte(thr);
-               duk_debug_skip_bytes(thr, len);
-               break;
-       case DUK_DBG_IB_LIGHTFUNC:
-               duk_debug_skip_bytes(thr, 2);
-               len = duk_debug_read_byte(thr);
-               duk_debug_skip_bytes(thr, len);
-               break;
-       default:
-               goto fail;
-       }
-
-       return 0;
-
- fail:
-       DUK__SET_CONN_BROKEN(thr, 1);
-       return 1;  /* Pretend like we got EOM */
-}
-
-/* Skip dvalues to EOM. */
-DUK_LOCAL void duk__debug_skip_to_eom(duk_hthread *thr) {
-       for (;;) {
-               if (duk__debug_skip_dvalue(thr)) {
-                       break;
-               }
-       }
-}
-
-/*
- *  Simple commands
- */
-
-DUK_LOCAL void duk__debug_handle_basic_info(duk_hthread *thr, duk_heap *heap) {
-       DUK_UNREF(heap);
-       DUK_D(DUK_DPRINT("debug command Version"));
-
-       duk_debug_write_reply(thr);
-       duk_debug_write_int(thr, DUK_VERSION);
-       duk_debug_write_cstring(thr, DUK_GIT_DESCRIBE);
-       duk_debug_write_cstring(thr, DUK_USE_TARGET_INFO);
-#if defined(DUK_USE_DOUBLE_LE)
-       duk_debug_write_int(thr, 1);
-#elif defined(DUK_USE_DOUBLE_ME)
-       duk_debug_write_int(thr, 2);
-#elif defined(DUK_USE_DOUBLE_BE)
-       duk_debug_write_int(thr, 3);
-#else
-       duk_debug_write_int(thr, 0);
-#endif
-       duk_debug_write_int(thr, (duk_int_t) sizeof(void *));
-       duk_debug_write_eom(thr);
-}
-
-DUK_LOCAL void duk__debug_handle_trigger_status(duk_hthread *thr, duk_heap 
*heap) {
-       DUK_UNREF(heap);
-       DUK_D(DUK_DPRINT("debug command TriggerStatus"));
-
-       duk_debug_write_reply(thr);
-       duk_debug_write_eom(thr);
-       heap->dbg_state_dirty = 1;
-}
-
-DUK_LOCAL void duk__debug_handle_pause(duk_hthread *thr, duk_heap *heap) {
-       DUK_D(DUK_DPRINT("debug command Pause"));
-
-       DUK_HEAP_SET_PAUSED(heap);
-       duk_debug_write_reply(thr);
-       duk_debug_write_eom(thr);
-}
-
-DUK_LOCAL void duk__debug_handle_resume(duk_hthread *thr, duk_heap *heap) {
-       DUK_D(DUK_DPRINT("debug command Resume"));
-
-       DUK_HEAP_CLEAR_PAUSED(heap);
-       duk_debug_write_reply(thr);
-       duk_debug_write_eom(thr);
-}
-
-DUK_LOCAL void duk__debug_handle_step(duk_hthread *thr, duk_heap *heap, 
duk_int32_t cmd) {
-       duk_small_uint_t step_type;
-       duk_uint_fast32_t line;
-
-       DUK_D(DUK_DPRINT("debug command StepInto/StepOver/StepOut: %d", (int) 
cmd));
-
-       if (cmd == DUK_DBG_CMD_STEPINTO) {
-               step_type = DUK_STEP_TYPE_INTO;
-       } else if (cmd == DUK_DBG_CMD_STEPOVER) {
-               step_type = DUK_STEP_TYPE_OVER;
-       } else {
-               DUK_ASSERT(cmd == DUK_DBG_CMD_STEPOUT);
-               step_type = DUK_STEP_TYPE_OUT;
-       }
-
-       line = duk_debug_curr_line(thr);
-       if (line > 0) {
-               heap->dbg_paused = 0;
-               heap->dbg_step_type = step_type;
-               heap->dbg_step_thread = thr;
-               heap->dbg_step_csindex = thr->callstack_top - 1;
-               heap->dbg_step_startline = line;
-               heap->dbg_state_dirty = 1;
-       } else {
-               DUK_D(DUK_DPRINT("cannot determine current line, 
stepinto/stepover/stepout ignored"));
-       }
-       duk_debug_write_reply(thr);
-       duk_debug_write_eom(thr);
-}
-
-DUK_LOCAL void duk__debug_handle_list_break(duk_hthread *thr, duk_heap *heap) {
-       duk_small_int_t i;
-
-       DUK_D(DUK_DPRINT("debug command ListBreak"));
-       duk_debug_write_reply(thr);
-       for (i = 0; i < (duk_small_int_t) heap->dbg_breakpoint_count; i++) {
-               duk_debug_write_hstring(thr, heap->dbg_breakpoints[i].filename);
-               duk_debug_write_uint(thr, (duk_uint32_t) 
heap->dbg_breakpoints[i].line);
-       }
-       duk_debug_write_eom(thr);
-}
-
-DUK_LOCAL void duk__debug_handle_add_break(duk_hthread *thr, duk_heap *heap) {
-       duk_hstring *filename;
-       duk_uint32_t linenumber;
-       duk_small_int_t idx;
-
-       DUK_UNREF(heap);
-
-       filename = duk_debug_read_hstring(thr);
-       linenumber = (duk_uint32_t) duk_debug_read_int(thr);
-       DUK_D(DUK_DPRINT("debug command AddBreak: %!O:%ld", (duk_hobject *) 
filename, (long) linenumber));
-       idx = duk_debug_add_breakpoint(thr, filename, linenumber);
-       if (idx >= 0) {
-               duk_debug_write_reply(thr);
-               duk_debug_write_int(thr, (duk_int32_t) idx);
-               duk_debug_write_eom(thr);
-       } else {
-               duk_debug_write_error_eom(thr, DUK_DBG_ERR_TOOMANY, "no space 
for breakpoint");
-       }
-}
-
-DUK_LOCAL void duk__debug_handle_del_break(duk_hthread *thr, duk_heap *heap) {
-       duk_small_uint_t idx;
-
-       DUK_UNREF(heap);
-
-       DUK_D(DUK_DPRINT("debug command DelBreak"));
-       idx = (duk_small_uint_t) duk_debug_read_int(thr);
-       if (duk_debug_remove_breakpoint(thr, idx)) {
-               duk_debug_write_reply(thr);
-               duk_debug_write_eom(thr);
-       } else {
-               duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid 
breakpoint index");
-       }
-}
-
-DUK_LOCAL void duk__debug_handle_get_var(duk_hthread *thr, duk_heap *heap) {
-       duk_context *ctx = (duk_context *) thr;
-       duk_hstring *str;
-       duk_bool_t rc;
-       duk_int32_t level;
-
-       DUK_UNREF(heap);
-       DUK_D(DUK_DPRINT("debug command GetVar"));
-
-       str = duk_debug_read_hstring(thr);  /* push to stack */
-       DUK_ASSERT(str != NULL);
-       if (duk_debug_peek_byte(thr) != DUK_DBG_IB_EOM) {
-               level = duk_debug_read_int(thr);  /* optional callstack level */
-               if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
-                       DUK_D(DUK_DPRINT("invalid callstack level for GetVar"));
-                       duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, 
"invalid callstack level");
-                       return;
-               }
-       } else {
-               level = -1;
-       }
-
-       if (thr->callstack_top > 0) {
-               rc = duk_js_getvar_activation(thr,
-                                             thr->callstack + 
thr->callstack_top + level,
-                                             str,
-                                             0);
-       } else {
-               /* No activation, no variable access.  Could also pretend
-                * we're in the global program context and read stuff off
-                * the global object.
-                */
-               DUK_D(DUK_DPRINT("callstack empty, no activation -> ignore 
getvar"));
-               rc = 0;
-       }
-
-       duk_debug_write_reply(thr);
-       if (rc) {
-               duk_debug_write_int(thr, 1);
-               DUK_ASSERT(duk_get_tval(ctx, -2) != NULL);
-               duk_debug_write_tval(thr, duk_get_tval(ctx, -2));
-       } else {
-               duk_debug_write_int(thr, 0);
-               duk_debug_write_unused(thr);
-       }
-       duk_debug_write_eom(thr);
-}
-
-DUK_LOCAL void duk__debug_handle_put_var(duk_hthread *thr, duk_heap *heap) {
-       duk_hstring *str;
-       duk_tval *tv;
-       duk_int32_t level;
-
-       DUK_UNREF(heap);
-       DUK_D(DUK_DPRINT("debug command PutVar"));
-
-       str = duk_debug_read_hstring(thr);  /* push to stack */
-       DUK_ASSERT(str != NULL);
-       tv = duk_debug_read_tval(thr);
-       if (tv == NULL) {
-               /* detached */
-               return;
-       }
-       if (duk_debug_peek_byte(thr) != DUK_DBG_IB_EOM) {
-               level = duk_debug_read_int(thr);  /* optional callstack level */
-               if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
-                       DUK_D(DUK_DPRINT("invalid callstack level for PutVar"));
-                       duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, 
"invalid callstack level");
-                       return;
-               }
-       } else {
-               level = -1;
-       }
-
-       if (thr->callstack_top > 0) {
-               duk_js_putvar_activation(thr,
-                                        thr->callstack + thr->callstack_top + 
level,
-                                        str,
-                                        tv,
-                                        0);
-       } else {
-               DUK_D(DUK_DPRINT("callstack empty, no activation -> ignore 
putvar"));
-       }
-
-       /* XXX: Current putvar implementation doesn't have a success flag,
-        * add one and send to debug client?
-        */
-       duk_debug_write_reply(thr);
-       duk_debug_write_eom(thr);
-}
-
-DUK_LOCAL void duk__debug_handle_get_call_stack(duk_hthread *thr, duk_heap 
*heap) {
-       duk_context *ctx = (duk_context *) thr;
-       duk_hthread *curr_thr = thr;
-       duk_activation *curr_act;
-       duk_uint_fast32_t pc;
-       duk_uint_fast32_t line;
-       duk_size_t i;
-
-       DUK_ASSERT(thr != NULL);
-       DUK_UNREF(heap);
-
-       duk_debug_write_reply(thr);
-       while (curr_thr != NULL) {
-               i = curr_thr->callstack_top;
-               while (i > 0) {
-                       i--;
-                       curr_act = curr_thr->callstack + i;
-
-                       /* PC/line semantics here are:
-                        *   - For callstack top we're conceptually between two
-                        *     opcodes and current PC indicates next line to
-                        *     execute, so report that (matches Status).
-                        *   - For other activations we're conceptually still
-                        *     executing the instruction at PC-1, so report that
-                        *     (matches error stacktrace behavior).
-                        *   - See: 
https://github.com/svaarala/duktape/issues/281
-                        */
-
-                       /* XXX: optimize to use direct reads, i.e. avoid
-                        * value stack operations.
-                        */
-                       duk_push_tval(ctx, &curr_act->tv_func);
-                       duk_get_prop_stridx(ctx, -1, DUK_STRIDX_FILE_NAME);
-                       duk__debug_write_hstring_safe_top(thr);
-                       duk_get_prop_stridx(ctx, -2, DUK_STRIDX_NAME);
-                       duk__debug_write_hstring_safe_top(thr);
-                       pc = duk_hthread_get_act_curr_pc(thr, curr_act);
-                       if (i != curr_thr->callstack_top - 1 && pc > 0) {
-                               pc--;
-                       }
-                       line = duk_hobject_pc2line_query(ctx, -3, pc);
-                       duk_debug_write_uint(thr, (duk_uint32_t) line);
-                       duk_debug_write_uint(thr, (duk_uint32_t) pc);
-                       duk_pop_3(ctx);
-               }
-               curr_thr = curr_thr->resumer;
-       }
-       /* SCANBUILD: warning about 'thr' potentially being NULL here,
-        * warning is incorrect because thr != NULL always here.
-        */
-       duk_debug_write_eom(thr);
-}
-
-DUK_LOCAL void duk__debug_handle_get_locals(duk_hthread *thr, duk_heap *heap) {
-       duk_context *ctx = (duk_context *) thr;
-       duk_activation *curr_act;
-       duk_int32_t level;
-       duk_hstring *varname;
-
-       DUK_UNREF(heap);
-
-       if (duk_debug_peek_byte(thr) != DUK_DBG_IB_EOM) {
-               level = duk_debug_read_int(thr);  /* optional callstack level */
-               if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
-                       DUK_D(DUK_DPRINT("invalid callstack level for 
GetLocals"));
-                       duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, 
"invalid callstack level");
-                       return;
-               }
-               duk_debug_write_reply(thr);
-       } else {
-               duk_debug_write_reply(thr);
-               if (thr->callstack_top == 0) {
-                       goto callstack_empty;
-               }
-               level = -1;
-       }
-
-       curr_act = thr->callstack + thr->callstack_top + level;
-
-       /* XXX: several nice-to-have improvements here:
-        *   - Use direct reads avoiding value stack operations
-        *   - Avoid triggering getters, indicate getter values to debug client
-        *   - If side effects are possible, add error catching
-        */
-
-       duk_push_tval(ctx, &curr_act->tv_func);
-       duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_VARMAP);
-       if (duk_is_object(ctx, -1)) {
-               duk_enum(ctx, -1, 0 /*enum_flags*/);
-               while (duk_next(ctx, -1 /*enum_index*/, 0 /*get_value*/)) {
-                       varname = duk_get_hstring(ctx, -1);
-                       DUK_ASSERT(varname != NULL);
-
-                       duk_js_getvar_activation(thr, curr_act, varname, 0 
/*throw_flag*/);
-                       /* [ ... func varmap enum key value this ] */
-                       duk_debug_write_hstring(thr, duk_get_hstring(ctx, -3));
-                       duk_debug_write_tval(thr, duk_get_tval(ctx, -2));
-                       duk_pop_3(ctx);  /* -> [ ... func varmap enum ] */
-               }
-       } else {
-               DUK_D(DUK_DPRINT("varmap is not an object in GetLocals, 
ignore"));
-       }
-
- callstack_empty:
-       duk_debug_write_eom(thr);
-}
-
-DUK_LOCAL void duk__debug_handle_eval(duk_hthread *thr, duk_heap *heap) {
-       duk_context *ctx = (duk_context *) thr;
-       duk_small_uint_t call_flags;
-       duk_int_t call_ret;
-       duk_small_int_t eval_err;
-       duk_int32_t level;
-
-       DUK_UNREF(heap);
-
-       DUK_D(DUK_DPRINT("debug command Eval"));
-
-       /* The eval code is executed within the lexical environment of a 
specified
-        * activation.  For now, use global object eval() function, with the 
eval
-        * considered a 'direct call to eval'.
-        *
-        * Callstack level for debug commands only affects scope -- the 
callstack
-        * as seen by, e.g. Duktape.act() will be the same regardless.
-        */
-
-       /* nargs == 2 so we can pass a callstack level to eval(). */
-       duk_push_c_function(ctx, duk_bi_global_object_eval, 2 /*nargs*/);
-       duk_push_undefined(ctx);  /* 'this' binding shouldn't matter here */
-
-       (void) duk_debug_read_hstring(thr);
-       if (duk_debug_peek_byte(thr) != DUK_DBG_IB_EOM) {
-               level = duk_debug_read_int(thr);  /* optional callstack level */
-               if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
-                       DUK_D(DUK_DPRINT("invalid callstack level for Eval"));
-                       duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, 
"invalid callstack level");
-                       return;
-               }
-       }
-       else {
-               level = -1;
-       }
-       DUK_ASSERT(level < 0 && -level <= (duk_int32_t) thr->callstack_top);
-       duk_push_int(ctx, level - 1);  /* compensate for eval() call */
-
-       /* [ ... eval "eval" eval_input level ] */
-
-       call_flags = 0;
-       if (thr->callstack_top >= (duk_size_t) -level) {
-               duk_activation *act;
-               duk_hobject *fun;
-
-               act = thr->callstack + thr->callstack_top + level;
-               fun = DUK_ACT_GET_FUNC(act);
-               if (fun != NULL && DUK_HOBJECT_IS_COMPILEDFUNCTION(fun)) {
-                       /* Direct eval requires that there's a current
-                        * activation and it is an Ecmascript function.
-                        * When Eval is executed from e.g. cooperate API
-                        * call we'll need to do an indirect eval instead.
-                        */
-                       call_flags |= DUK_CALL_FLAG_DIRECT_EVAL;
-               }
-       }
-
-       call_ret = duk_handle_call_protected(thr, 2 /*num_stack_args*/, 
call_flags);
-
-       if (call_ret == DUK_EXEC_SUCCESS) {
-               eval_err = 0;
-               /* Use result value as is. */
-       } else {
-               /* For errors a string coerced result is most informative
-                * right now, as the debug client doesn't have the capability
-                * to traverse the error object.
-                */
-               eval_err = 1;
-               duk_safe_to_string(ctx, -1);
-       }
-
-       /* [ ... result ] */
-
-       duk_debug_write_reply(thr);
-       duk_debug_write_int(thr, (duk_int32_t) eval_err);
-       DUK_ASSERT(duk_get_tval(ctx, -1) != NULL);
-       duk_debug_write_tval(thr, duk_get_tval(ctx, -1));
-       duk_debug_write_eom(thr);
-}
-
-DUK_LOCAL void duk__debug_handle_detach(duk_hthread *thr, duk_heap *heap) {
-       DUK_UNREF(heap);
-       DUK_D(DUK_DPRINT("debug command Detach"));
-
-       duk_debug_write_reply(thr);
-       duk_debug_write_eom(thr);
-
-       DUK_D(DUK_DPRINT("debug connection detached, mark broken"));
-       DUK__SET_CONN_BROKEN(thr, 0);  /* not an error */
-}
-
-DUK_LOCAL void duk__debug_handle_apprequest(duk_hthread *thr, duk_heap *heap) {
-       duk_context *ctx = (duk_context *) thr;
-       duk_idx_t old_top;
-
-       DUK_D(DUK_DPRINT("debug command AppRequest"));
-
-       old_top = duk_get_top(ctx);  /* save stack top */
-
-       if (heap->dbg_request_cb != NULL) {
-               duk_idx_t nrets;
-               duk_idx_t nvalues = 0;
-               duk_idx_t top, idx;
-
-               /* Read tvals from the message and push them onto the valstack,
-                * then call the request callback to process the request.
-                */
-               while (duk_debug_peek_byte(thr) != DUK_DBG_IB_EOM) {
-                       duk_tval *tv;
-                       if (!duk_check_stack(ctx, 1)) {
-                               DUK_D(DUK_DPRINT("failed to allocate space for 
request dvalue(s)"));
-                               goto fail;
-                       }
-                       tv = duk_debug_read_tval(thr);  /* push to stack */
-                       if (tv == NULL) {
-                               /* detached */
-                               return;
-                       }
-                       nvalues++;
-               }
-               DUK_ASSERT(duk_get_top(ctx) == old_top + nvalues);
-
-               /* Request callback should push values for reply to client onto 
valstack */
-               DUK_D(DUK_DPRINT("calling into AppRequest request_cb with 
nvalues=%ld, old_top=%ld, top=%ld",
-                                (long) nvalues, (long) old_top, (long) 
duk_get_top(ctx)));
-               nrets = heap->dbg_request_cb(ctx, heap->dbg_udata, nvalues);
-               DUK_D(DUK_DPRINT("returned from AppRequest request_cb; 
nvalues=%ld -> nrets=%ld, old_top=%ld, top=%ld",
-                                (long) nvalues, (long) nrets, (long) old_top, 
(long) duk_get_top(ctx)));
-               if (nrets >= 0) {
-                       DUK_ASSERT(duk_get_top(ctx) >= old_top + nrets);
-                       if (duk_get_top(ctx) < old_top + nrets) {
-                               DUK_D(DUK_DPRINT("AppRequest callback doesn't 
match value stack configuration, "
-                                                "top=%ld < old_top=%ld + 
nrets=%ld; "
-                                                "this might mean it's unsafe 
to continue!",
-                                                (long) duk_get_top(ctx), 
(long) old_top, (long) nrets));
-                               goto fail;
-                       }
-
-                       /* Reply with tvals pushed by request callback */
-                       duk_debug_write_byte(thr, DUK_DBG_IB_REPLY);
-                       top = duk_get_top(ctx);
-                       for (idx = top - nrets; idx < top; idx++) {
-                               duk_debug_write_tval(thr, 
DUK_GET_TVAL_POSIDX(ctx, idx));
-                       }
-                       duk_debug_write_eom(thr);
-               } else {
-                       DUK_ASSERT(duk_get_top(ctx) >= old_top + 1);
-                       if (duk_get_top(ctx) < old_top + 1) {
-                               DUK_D(DUK_DPRINT("request callback return value 
doesn't match value stack configuration"));
-                               goto fail;
-                       }
-                       duk_debug_write_error_eom(thr, DUK_DBG_ERR_APPLICATION, 
duk_get_string(ctx, -1));
-               }
-
-               duk_set_top(ctx, old_top);  /* restore stack top */
-       } else {
-               DUK_D(DUK_DPRINT("no request callback, treat AppRequest as 
unsupported"));
-               duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNSUPPORTED, 
"AppRequest unsupported by target");
-       }
-
-       return;
-
- fail:
-       duk_set_top(ctx, old_top);  /* restore stack top */
-       DUK__SET_CONN_BROKEN(thr, 1);
-}
-
-/*
- *  DumpHeap command
- */
-
-#if defined(DUK_USE_DEBUGGER_DUMPHEAP)
-/* XXX: this has some overlap with object inspection; remove this and make
- * DumpHeap return lists of heapptrs instead?
- */
-DUK_LOCAL void duk__debug_dump_heaphdr(duk_hthread *thr, duk_heap *heap, 
duk_heaphdr *hdr) {
-       DUK_UNREF(heap);
-
-       duk_debug_write_heapptr(thr, hdr);
-       duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_TYPE(hdr));
-       duk_debug_write_uint(thr, (duk_uint32_t) 
DUK_HEAPHDR_GET_FLAGS_RAW(hdr));
-#if defined(DUK_USE_REFERENCE_COUNTING)
-       duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_REFCOUNT(hdr));
-#else
-       duk_debug_write_int(thr, (duk_int32_t) -1);
-#endif
-
-       switch (DUK_HEAPHDR_GET_TYPE(hdr)) {
-       case DUK_HTYPE_STRING: {
-               duk_hstring *h = (duk_hstring *) hdr;
-
-               duk_debug_write_uint(thr, (duk_int32_t) 
DUK_HSTRING_GET_BYTELEN(h));
-               duk_debug_write_uint(thr, (duk_int32_t) 
DUK_HSTRING_GET_CHARLEN(h));
-               duk_debug_write_uint(thr, (duk_int32_t) 
DUK_HSTRING_GET_HASH(h));
-               duk_debug_write_hstring(thr, h);
-               break;
-       }
-       case DUK_HTYPE_OBJECT: {
-               duk_hobject *h = (duk_hobject *) hdr;
-               duk_hstring *k;
-               duk_uint_fast32_t i;
-
-               duk_debug_write_uint(thr, (duk_uint32_t) 
DUK_HOBJECT_GET_CLASS_NUMBER(h));
-               duk_debug_write_heapptr(thr, (duk_heaphdr *) 
DUK_HOBJECT_GET_PROTOTYPE(heap, h));
-               duk_debug_write_uint(thr, (duk_uint32_t) 
DUK_HOBJECT_GET_ESIZE(h));
-               duk_debug_write_uint(thr, (duk_uint32_t) 
DUK_HOBJECT_GET_ENEXT(h));
-               duk_debug_write_uint(thr, (duk_uint32_t) 
DUK_HOBJECT_GET_ASIZE(h));
-               duk_debug_write_uint(thr, (duk_uint32_t) 
DUK_HOBJECT_GET_HSIZE(h));
-
-               for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); 
i++) {
-                       duk_debug_write_uint(thr, (duk_uint32_t) 
DUK_HOBJECT_E_GET_FLAGS(heap, h, i));
-                       k = DUK_HOBJECT_E_GET_KEY(heap, h, i);
-                       duk_debug_write_heapptr(thr, (duk_heaphdr *) k);
-                       if (k == NULL) {
-                               duk_debug_write_int(thr, 0);  /* isAccessor */
-                               duk_debug_write_unused(thr);
-                               continue;
-                       }
-                       if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, h, i)) {
-                               duk_debug_write_int(thr, 1);  /* isAccessor */
-                               duk_debug_write_heapptr(thr, (duk_heaphdr *) 
DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.get);
-                               duk_debug_write_heapptr(thr, (duk_heaphdr *) 
DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.set);
-                       } else {
-                               duk_debug_write_int(thr, 0);  /* isAccessor */
-
-                               duk__debug_write_tval_heapptr(thr, 
&DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->v);
-                       }
-               }
-
-               for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); 
i++) {
-                       /* Note: array dump will include elements beyond
-                        * 'length'.
-                        */
-                       duk__debug_write_tval_heapptr(thr, 
DUK_HOBJECT_A_GET_VALUE_PTR(heap, h, i));
-               }
-               break;
-       }
-       case DUK_HTYPE_BUFFER: {
-               duk_hbuffer *h = (duk_hbuffer *) hdr;
-
-               duk_debug_write_uint(thr, (duk_uint32_t) 
DUK_HBUFFER_GET_SIZE(h));
-               duk_debug_write_buffer(thr, (const char *) 
DUK_HBUFFER_GET_DATA_PTR(heap, h), (duk_size_t) DUK_HBUFFER_GET_SIZE(h));
-               break;
-       }
-       default: {
-               DUK_D(DUK_DPRINT("invalid htype: %d", (int) 
DUK_HEAPHDR_GET_TYPE(hdr)));
-       }
-       }
-}
-
-DUK_LOCAL void duk__debug_dump_heap_allocated(duk_hthread *thr, duk_heap 
*heap) {
-       duk_heaphdr *hdr;
-
-       hdr = heap->heap_allocated;
-       while (hdr != NULL) {
-               duk__debug_dump_heaphdr(thr, heap, hdr);
-               hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
-       }
-}
-
-#if defined(DUK_USE_STRTAB_CHAIN)
-DUK_LOCAL void duk__debug_dump_strtab_chain(duk_hthread *thr, duk_heap *heap) {
-       duk_uint_fast32_t i, j;
-       duk_strtab_entry *e;
-#if defined(DUK_USE_HEAPPTR16)
-       duk_uint16_t *lst;
-#else
-       duk_hstring **lst;
-#endif
-       duk_hstring *h;
-
-       for (i = 0; i < DUK_STRTAB_CHAIN_SIZE; i++) {
-               e = heap->strtable + i;
-               if (e->listlen > 0) {
-#if defined(DUK_USE_HEAPPTR16)
-                       lst = (duk_uint16_t *) 
DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.strlist16);
-#else
-                       lst = e->u.strlist;
-#endif
-                       DUK_ASSERT(lst != NULL);
-
-                       for (j = 0; j < e->listlen; j++) {
-#if defined(DUK_USE_HEAPPTR16)
-                               h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, 
lst[j]);
-#else
-                               h = lst[j];
-#endif
-                               if (h != NULL) {
-                                       duk__debug_dump_heaphdr(thr, heap, 
(duk_heaphdr *) h);
-                               }
-                       }
-               } else {
-#if defined(DUK_USE_HEAPPTR16)
-                       h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.str16);
-#else
-                       h = e->u.str;
-#endif
-                       if (h != NULL) {
-                               duk__debug_dump_heaphdr(thr, heap, (duk_heaphdr 
*) h);
-                       }
-               }
-       }
-}
-#endif  /* DUK_USE_STRTAB_CHAIN */
-
-#if defined(DUK_USE_STRTAB_PROBE)
-DUK_LOCAL void duk__debug_dump_strtab_probe(duk_hthread *thr, duk_heap *heap) {
-       duk_uint32_t i;
-       duk_hstring *h;
-
-       for (i = 0; i < heap->st_size; i++) {
-#if defined(DUK_USE_HEAPPTR16)
-               h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, 
heap->strtable16[i]);
-#else
-               h = heap->strtable[i];
-#endif
-               if (h == NULL || h == DUK_STRTAB_DELETED_MARKER(heap)) {
-                       continue;
-               }
-
-               duk__debug_dump_heaphdr(thr, heap, (duk_heaphdr *) h);
-       }
-}
-#endif  /* DUK_USE_STRTAB_PROBE */
-
-DUK_LOCAL void duk__debug_handle_dump_heap(duk_hthread *thr, duk_heap *heap) {
-       DUK_D(DUK_DPRINT("debug command DumpHeap"));
-
-       duk_debug_write_reply(thr);
-       duk__debug_dump_heap_allocated(thr, heap);
-#if defined(DUK_USE_STRTAB_CHAIN)
-       duk__debug_dump_strtab_chain(thr, heap);
-#endif
-#if defined(DUK_USE_STRTAB_PROBE)
-       duk__debug_dump_strtab_probe(thr, heap);
-#endif
-       duk_debug_write_eom(thr);
-}
-#endif  /* DUK_USE_DEBUGGER_DUMPHEAP */
-
-DUK_LOCAL void duk__debug_handle_get_bytecode(duk_hthread *thr, duk_heap 
*heap) {
-       duk_activation *act;
-       duk_hcompiledfunction *fun = NULL;
-       duk_size_t i, n;
-       duk_tval *tv;
-       duk_hobject **fn;
-       duk_int32_t level = -1;
-       duk_uint8_t ibyte;
-
-       DUK_UNREF(heap);
-
-       DUK_D(DUK_DPRINT("debug command GetBytecode"));
-
-       ibyte = duk_debug_peek_byte(thr);
-       if (ibyte != DUK_DBG_IB_EOM) {
-               tv = duk_debug_read_tval(thr);
-               if (tv == NULL) {
-                       /* detached */
-                       return;
-               }
-               if (DUK_TVAL_IS_OBJECT(tv)) {
-                       /* tentative, checked later */
-                       fun = (duk_hcompiledfunction *) DUK_TVAL_GET_OBJECT(tv);
-                       DUK_ASSERT(fun != NULL);
-               } else if (DUK_TVAL_IS_NUMBER(tv)) {
-                       level = (duk_int32_t) DUK_TVAL_GET_NUMBER(tv);
-               } else {
-                       DUK_D(DUK_DPRINT("invalid argument to GetBytecode: 
%!T", tv));
-                       goto fail_args;
-               }
-       }
-
-       if (fun == NULL) {
-               if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
-                       DUK_D(DUK_DPRINT("invalid callstack level for 
GetBytecode"));
-                       goto fail_level;
-               }
-               act = thr->callstack + thr->callstack_top + level;
-               fun = (duk_hcompiledfunction *) DUK_ACT_GET_FUNC(act);
-       }
-
-       if (fun == NULL || !DUK_HOBJECT_IS_COMPILEDFUNCTION((duk_hobject *) 
fun)) {
-               DUK_D(DUK_DPRINT("invalid argument to GetBytecode: %!O", fun));
-               goto fail_args;
-       }
-       DUK_ASSERT(fun != NULL && DUK_HOBJECT_IS_COMPILEDFUNCTION((duk_hobject 
*) fun));
-
-       duk_debug_write_reply(thr);
-       n = DUK_HCOMPILEDFUNCTION_GET_CONSTS_COUNT(heap, fun);
-       duk_debug_write_int(thr, (duk_int32_t) n);
-       tv = DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(heap, fun);
-       for (i = 0; i < n; i++) {
-               duk_debug_write_tval(thr, tv);
-               tv++;
-       }
-       n = DUK_HCOMPILEDFUNCTION_GET_FUNCS_COUNT(heap, fun);
-       duk_debug_write_int(thr, (duk_int32_t) n);
-       fn = DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(heap, fun);
-       for (i = 0; i < n; i++) {
-               duk_debug_write_hobject(thr, *fn);
-               fn++;
-       }
-       duk_debug_write_string(thr,
-                              (const char *) 
DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(heap, fun),
-                              (duk_size_t) 
DUK_HCOMPILEDFUNCTION_GET_CODE_SIZE(heap, fun));
-       duk_debug_write_eom(thr);
-       return;
-
- fail_args:
-       duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid argument");
-       return;
-
- fail_level:
-       duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack 
level");
-       return;
-}
-
-/*
- *  Object inspection commands: GetHeapObjInfo, GetObjPropDesc,
- *  GetObjPropDescRange
- */
-
-#if defined(DUK_USE_DEBUGGER_INSPECT)
-
-#if 0 /* pruned */
-DUK_LOCAL const char * const duk__debug_getinfo_heaphdr_keys[] = {
-       "reachable",
-       "temproot",
-       "finalizable",
-       "finalized",
-       "readonly"
-       /* NULL not needed here */
-};
-DUK_LOCAL duk_uint_t duk__debug_getinfo_heaphdr_masks[] = {
-       DUK_HEAPHDR_FLAG_REACHABLE,
-       DUK_HEAPHDR_FLAG_TEMPROOT,
-       DUK_HEAPHDR_FLAG_FINALIZABLE,
-       DUK_HEAPHDR_FLAG_FINALIZED,
-       DUK_HEAPHDR_FLAG_READONLY,
-       0  /* terminator */
-};
-#endif
-DUK_LOCAL const char * const duk__debug_getinfo_hstring_keys[] = {
-#if 0
-       "arridx",
-       "internal",
-       "reserved_word",
-       "strict_reserved_word",
-       "eval_or_arguments",
-#endif
-       "extdata"
-       /* NULL not needed here */
-};
-DUK_LOCAL duk_uint_t duk__debug_getinfo_hstring_masks[] = {
-#if 0
-       DUK_HSTRING_FLAG_ARRIDX,
-       DUK_HSTRING_FLAG_INTERNAL,
-       DUK_HSTRING_FLAG_RESERVED_WORD,
-       DUK_HSTRING_FLAG_STRICT_RESERVED_WORD,
-       DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS,
-#endif
-       DUK_HSTRING_FLAG_EXTDATA,
-       0  /* terminator */
-};
-DUK_LOCAL const char * const duk__debug_getinfo_hobject_keys[] = {
-       "extensible",
-       "constructable",
-       "bound",
-       "compiledfunction",
-       "nativefunction",
-       "bufferobject",
-       "thread",
-       "array_part",
-       "strict",
-       "notail",
-       "newenv",
-       "namebinding",
-       "createargs",
-       "envrecclosed",
-       "exotic_array",
-       "exotic_stringobj",
-       "exotic_arguments",
-       "exotic_dukfunc",
-       "exotic_proxyobj"
-       /* NULL not needed here */
-};
-DUK_LOCAL duk_uint_t duk__debug_getinfo_hobject_masks[] = {
-       DUK_HOBJECT_FLAG_EXTENSIBLE,
-       DUK_HOBJECT_FLAG_CONSTRUCTABLE,
-       DUK_HOBJECT_FLAG_BOUND,
-       DUK_HOBJECT_FLAG_COMPILEDFUNCTION,
-       DUK_HOBJECT_FLAG_NATIVEFUNCTION,
-       DUK_HOBJECT_FLAG_BUFFEROBJECT,
-       DUK_HOBJECT_FLAG_THREAD,
-       DUK_HOBJECT_FLAG_ARRAY_PART,
-       DUK_HOBJECT_FLAG_STRICT,
-       DUK_HOBJECT_FLAG_NOTAIL,
-       DUK_HOBJECT_FLAG_NEWENV,
-       DUK_HOBJECT_FLAG_NAMEBINDING,
-       DUK_HOBJECT_FLAG_CREATEARGS,
-       DUK_HOBJECT_FLAG_ENVRECCLOSED,
-       DUK_HOBJECT_FLAG_EXOTIC_ARRAY,
-       DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ,
-       DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS,
-       DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC,
-       DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ,
-       0  /* terminator */
-};
-DUK_LOCAL const char * const duk__debug_getinfo_hbuffer_keys[] = {
-       "dynamic",
-       "external"
-       /* NULL not needed here */
-};
-DUK_LOCAL duk_uint_t duk__debug_getinfo_hbuffer_masks[] = {
-       DUK_HBUFFER_FLAG_DYNAMIC,
-       DUK_HBUFFER_FLAG_EXTERNAL,
-       0  /* terminator */
-};
-
-DUK_LOCAL void duk__debug_getinfo_flags_key(duk_hthread *thr, const char *key) 
{
-       duk_debug_write_uint(thr, 0);
-       duk_debug_write_cstring(thr, key);
-}
-
-DUK_LOCAL void duk__debug_getinfo_prop_uint(duk_hthread *thr, const char *key, 
duk_uint_t val) {
-       duk_debug_write_uint(thr, 0);
-       duk_debug_write_cstring(thr, key);
-       duk_debug_write_uint(thr, val);
-}
-
-DUK_LOCAL void duk__debug_getinfo_prop_int(duk_hthread *thr, const char *key, 
duk_int_t val) {
-       duk_debug_write_uint(thr, 0);
-       duk_debug_write_cstring(thr, key);
-       duk_debug_write_int(thr, val);
-}
-
-DUK_LOCAL void duk__debug_getinfo_prop_bool(duk_hthread *thr, const char *key, 
duk_bool_t val) {
-       duk_debug_write_uint(thr, 0);
-       duk_debug_write_cstring(thr, key);
-       duk_debug_write_boolean(thr, val);
-}
-
-DUK_LOCAL void duk__debug_getinfo_bitmask(duk_hthread *thr, const char * const 
* keys, duk_uint_t *masks, duk_uint_t flags) {
-       const char *key;
-       duk_uint_t mask;
-
-       for (;;) {
-               mask = *masks++;
-               if (!mask) {
-                       break;
-               }
-               key = *keys++;
-               DUK_ASSERT(key != NULL);
-
-               DUK_DD(DUK_DDPRINT("inspect bitmask: key=%s, mask=0x%08lx, 
flags=0x%08lx", key, (unsigned long) mask, (unsigned long) flags));
-               duk__debug_getinfo_prop_bool(thr, key, flags & mask);
-       }
-}
-
-/* Inspect a property using a virtual index into a conceptual property list
- * consisting of (1) all array part items from [0,a_size[ (even when above
- * .length) and (2) all entry part items from [0,e_next[.  Unused slots are
- * indicated using dvalue 'unused'.
- */
-DUK_LOCAL duk_bool_t duk__debug_getprop_index(duk_hthread *thr, duk_heap 
*heap, duk_hobject *h_obj, duk_uint_t idx) {
-       duk_uint_t a_size;
-       duk_tval *tv;
-       duk_hstring *h_key;
-       duk_hobject *h_getset;
-       duk_uint_t flags;
-
-       DUK_UNREF(heap);
-
-       a_size = DUK_HOBJECT_GET_ASIZE(h_obj);
-       if (idx < a_size) {
-               duk_debug_write_uint(thr, DUK_PROPDESC_FLAGS_WEC);
-               duk_debug_write_uint(thr, idx);
-               tv = DUK_HOBJECT_A_GET_VALUE_PTR(heap, h_obj, idx);
-               duk_debug_write_tval(thr, tv);
-               return 1;
-       }
-
-       idx -= a_size;
-       if (idx >= DUK_HOBJECT_GET_ENEXT(h_obj)) {
-               return 0;
-       }
-
-       h_key = DUK_HOBJECT_E_GET_KEY(heap, h_obj, idx);
-       if (h_key == NULL) {
-               duk_debug_write_uint(thr, 0);
-               duk_debug_write_null(thr);
-               duk_debug_write_unused(thr);
-               return 1;
-       }
-
-       flags = DUK_HOBJECT_E_GET_FLAGS(heap, h_obj, idx);
-       if (DUK_HSTRING_HAS_INTERNAL(h_key)) {
-               flags |= DUK_DBG_PROPFLAG_INTERNAL;
-       }
-       duk_debug_write_uint(thr, flags);
-       duk_debug_write_hstring(thr, h_key);
-       if (flags & DUK_PROPDESC_FLAG_ACCESSOR) {
-               h_getset = DUK_HOBJECT_E_GET_VALUE_GETTER(heap, h_obj, idx);
-               if (h_getset) {
-                       duk_debug_write_hobject(thr, h_getset);
-               } else {
-                       duk_debug_write_null(thr);
-               }
-               h_getset = DUK_HOBJECT_E_GET_VALUE_SETTER(heap, h_obj, idx);
-               if (h_getset) {
-                       duk_debug_write_hobject(thr, h_getset);
-               } else {
-                       duk_debug_write_null(thr);
-               }
-       } else {
-               tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, h_obj, idx);
-               duk_debug_write_tval(thr, tv);
-       }
-       return 1;
-}
-
-DUK_LOCAL void duk__debug_handle_get_heap_obj_info(duk_hthread *thr, duk_heap 
*heap) {
-       duk_heaphdr *h;
-
-       DUK_D(DUK_DPRINT("debug command GetHeapObjInfo"));
-       DUK_UNREF(heap);
-
-       h = duk_debug_read_any_ptr(thr);
-       if (!h) {
-               duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid 
target");
-               return;
-       }
-
-       duk_debug_write_reply(thr);
-
-       /* As with all inspection code, we rely on the debug client providing
-        * a valid, non-stale pointer: there's no portable way to safely
-        * validate the pointer here.
-        */
-
-       duk__debug_getinfo_flags_key(thr, "heapptr");
-       duk_debug_write_heapptr(thr, h);
-
-       /* XXX: comes out as signed now */
-       duk__debug_getinfo_prop_uint(thr, "heaphdr_flags", (duk_uint_t) 
DUK_HEAPHDR_GET_FLAGS(h));
-       duk__debug_getinfo_prop_uint(thr, "heaphdr_type", (duk_uint_t) 
DUK_HEAPHDR_GET_TYPE(h));
-#if defined(DUK_USE_REFERENCE_COUNTING)
-       duk__debug_getinfo_prop_uint(thr, "refcount", (duk_uint_t) 
DUK_HEAPHDR_GET_REFCOUNT(h));
-#endif
-#if 0 /* pruned */
-       duk__debug_getinfo_bitmask(thr,
-                                  duk__debug_getinfo_heaphdr_keys,
-                                  duk__debug_getinfo_heaphdr_masks,
-                                  DUK_HEAPHDR_GET_FLAGS_RAW(h));
-#endif
-
-       switch (DUK_HEAPHDR_GET_TYPE(h)) {
-       case DUK_HTYPE_STRING: {
-               duk_hstring *h_str;
-
-               h_str = (duk_hstring *) h;
-               duk__debug_getinfo_bitmask(thr,
-                                          duk__debug_getinfo_hstring_keys,
-                                          duk__debug_getinfo_hstring_masks,
-                                          DUK_HEAPHDR_GET_FLAGS_RAW(h));
-               duk__debug_getinfo_prop_uint(thr, "bytelen", 
DUK_HSTRING_GET_BYTELEN(h_str));
-               duk__debug_getinfo_prop_uint(thr, "charlen", 
DUK_HSTRING_GET_CHARLEN(h_str));
-               duk__debug_getinfo_prop_uint(thr, "hash", 
DUK_HSTRING_GET_HASH(h_str));
-               duk__debug_getinfo_flags_key(thr, "data");
-               duk_debug_write_hstring(thr, h_str);
-               break;
-       }
-       case DUK_HTYPE_OBJECT: {
-               duk_hobject *h_obj;
-               duk_hobject *h_proto;
-
-               h_obj = (duk_hobject *) h;
-               h_proto = DUK_HOBJECT_GET_PROTOTYPE(heap, h_obj);
-
-               /* duk_hobject specific fields. */
-               duk__debug_getinfo_bitmask(thr,
-                                          duk__debug_getinfo_hobject_keys,
-                                          duk__debug_getinfo_hobject_masks,
-                                          DUK_HEAPHDR_GET_FLAGS_RAW(h));
-               duk__debug_getinfo_prop_uint(thr, "class_number", 
DUK_HOBJECT_GET_CLASS_NUMBER(h_obj));
-               duk__debug_getinfo_flags_key(thr, "class_name");
-               duk_debug_write_hstring(thr, DUK_HOBJECT_GET_CLASS_STRING(heap, 
h_obj));
-               duk__debug_getinfo_flags_key(thr, "prototype");
-               if (h_proto != NULL) {
-                       duk_debug_write_hobject(thr, h_proto);
-               } else {
-                       duk_debug_write_null(thr);
-               }
-               duk__debug_getinfo_flags_key(thr, "props");
-               duk_debug_write_pointer(thr, (void *) 
DUK_HOBJECT_GET_PROPS(heap, h_obj));
-               duk__debug_getinfo_prop_uint(thr, "e_size", (duk_uint_t) 
DUK_HOBJECT_GET_ESIZE(h_obj));
-               duk__debug_getinfo_prop_uint(thr, "e_next", (duk_uint_t) 
DUK_HOBJECT_GET_ENEXT(h_obj));
-               duk__debug_getinfo_prop_uint(thr, "a_size", (duk_uint_t) 
DUK_HOBJECT_GET_ASIZE(h_obj));
-               duk__debug_getinfo_prop_uint(thr, "h_size", (duk_uint_t) 
DUK_HOBJECT_GET_HSIZE(h_obj));
-
-               /* duk_hnativefunction specific fields. */
-               if (DUK_HOBJECT_IS_NATIVEFUNCTION(h_obj)) {
-                       duk_hnativefunction *h_fun;
-                       h_fun = (duk_hnativefunction *) h_obj;
-
-                       duk__debug_getinfo_prop_int(thr, "nargs", h_fun->nargs);
-                       duk__debug_getinfo_prop_int(thr, "magic", h_fun->magic);
-                       duk__debug_getinfo_prop_bool(thr, "varargs", 
h_fun->magic == DUK_HNATIVEFUNCTION_NARGS_VARARGS);
-                       /* Native function pointer may be different from a void 
pointer,
-                        * and we serialize it from memory directly now (no 
byte swapping etc).
-                        */
-                       duk__debug_getinfo_flags_key(thr, "funcptr");
-                       duk_debug_write_buffer(thr, (const char *) 
&h_fun->func, sizeof(h_fun->func));
-               }
-
-               if (DUK_HOBJECT_IS_COMPILEDFUNCTION(h_obj)) {
-                       duk_hcompiledfunction *h_fun;
-                       duk_hbuffer *h_buf;
-                       h_fun = (duk_hcompiledfunction *) h_obj;
-
-                       duk__debug_getinfo_prop_int(thr, "nregs", h_fun->nregs);
-                       duk__debug_getinfo_prop_int(thr, "nargs", h_fun->nargs);
-                       duk__debug_getinfo_prop_uint(thr, "start_line", 
h_fun->start_line);
-                       duk__debug_getinfo_prop_uint(thr, "end_line", 
h_fun->end_line);
-                       h_buf = (duk_hbuffer *) 
DUK_HCOMPILEDFUNCTION_GET_DATA(thr->heap, h_fun);
-                       if (h_buf != NULL) {
-                               duk__debug_getinfo_flags_key(thr, "data");
-                               duk_debug_write_heapptr(thr, (duk_heaphdr *) 
h_buf);
-                       }
-               }
-
-               if (DUK_HOBJECT_IS_THREAD(h_obj)) {
-                       /* XXX: Currently no inspection of threads, e.g. value 
stack, call
-                        * stack, catch stack, etc.
-                        */
-                       duk_hthread *h_thr;
-                       h_thr = (duk_hthread *) h_obj;
-                       DUK_UNREF(h_thr);
-               }
-
-               if (DUK_HOBJECT_IS_BUFFEROBJECT(h_obj)) {
-                       duk_hbufferobject *h_bufobj;
-                       h_bufobj = (duk_hbufferobject *) h_obj;
-
-                       duk__debug_getinfo_prop_uint(thr, "slice_offset", 
h_bufobj->offset);
-                       duk__debug_getinfo_prop_uint(thr, "slice_length", 
h_bufobj->length);
-                       duk__debug_getinfo_prop_uint(thr, "elem_shift", 
(duk_uint_t) h_bufobj->shift);
-                       duk__debug_getinfo_prop_uint(thr, "elem_type", 
(duk_uint_t) h_bufobj->elem_type);
-                       duk__debug_getinfo_prop_bool(thr, "is_view", 
(duk_uint_t) h_bufobj->is_view);
-                       if (h_bufobj->buf != NULL) {
-                               duk__debug_getinfo_flags_key(thr, "buffer");
-                               duk_debug_write_heapptr(thr, (duk_heaphdr *) 
h_bufobj->buf);
-                       }
-               }
-               break;
-       }
-       case DUK_HTYPE_BUFFER: {
-               duk_hbuffer *h_buf;
-
-               h_buf = (duk_hbuffer *) h;
-               duk__debug_getinfo_bitmask(thr,
-                                          duk__debug_getinfo_hbuffer_keys,
-                                          duk__debug_getinfo_hbuffer_masks,
-                                          DUK_HEAPHDR_GET_FLAGS_RAW(h));
-               duk__debug_getinfo_prop_uint(thr, "size", (duk_uint_t) 
DUK_HBUFFER_GET_SIZE(h_buf));
-               duk__debug_getinfo_flags_key(thr, "dataptr");
-               duk_debug_write_pointer(thr, (void *) 
DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_buf));
-               duk__debug_getinfo_flags_key(thr, "data");
-               duk_debug_write_hbuffer(thr, h_buf);  /* tolerates NULL h_buf */
-               break;
-       }
-       default: {
-               /* Since we already started writing the reply, just emit 
nothing. */
-               DUK_D(DUK_DPRINT("inspect target pointer has invalid heaphdr 
type"));
-       }
-       }
-
-       duk_debug_write_eom(thr);
-}
-
-DUK_LOCAL void duk__debug_handle_get_obj_prop_desc(duk_hthread *thr, duk_heap 
*heap) {
-       duk_heaphdr *h;
-       duk_hobject *h_obj;
-       duk_hstring *h_key;
-       duk_propdesc desc;
-
-       DUK_D(DUK_DPRINT("debug command GetObjPropDesc"));
-       DUK_UNREF(heap);
-
-       h = duk_debug_read_any_ptr(thr);
-       if (!h) {
-               duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid 
target");
-               return;
-       }
-       h_key = duk_debug_read_hstring(thr);
-       if (h == NULL || DUK_HEAPHDR_GET_TYPE(h) != DUK_HTYPE_OBJECT || h_key 
== NULL) {
-               goto fail_args;
-       }
-       h_obj = (duk_hobject *) h;
-
-       if (duk_hobject_get_own_propdesc(thr, h_obj, h_key, &desc, 0 
/*flags*/)) {
-               duk_int_t virtual_idx;
-               duk_bool_t rc;
-
-               /* To use the shared helper need the virtual index. */
-               DUK_ASSERT(desc.e_idx >= 0 || desc.a_idx >= 0);
-               virtual_idx = (desc.a_idx >= 0 ? desc.a_idx :
-                              (duk_int_t) DUK_HOBJECT_GET_ASIZE(h_obj) + 
desc.e_idx);
-
-               duk_debug_write_reply(thr);
-               rc = duk__debug_getprop_index(thr, heap, h_obj, (duk_uint_t) 
virtual_idx);
-               DUK_ASSERT(rc == 1);
-               DUK_UNREF(rc);
-               duk_debug_write_eom(thr);
-       } else {
-               duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "not 
found");
-       }
-       return;
-
- fail_args:
-       duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid args");
-}
-
-DUK_LOCAL void duk__debug_handle_get_obj_prop_desc_range(duk_hthread *thr, 
duk_heap *heap) {
-       duk_heaphdr *h;
-       duk_hobject *h_obj;
-       duk_uint_t idx, idx_start, idx_end;
-
-       DUK_D(DUK_DPRINT("debug command GetObjPropDescRange"));
-       DUK_UNREF(heap);
-
-       h = duk_debug_read_any_ptr(thr);
-       idx_start = duk_debug_read_int(thr);
-       idx_end = duk_debug_read_int(thr);
-       if (h == NULL || DUK_HEAPHDR_GET_TYPE(h) != DUK_HTYPE_OBJECT) {
-               goto fail_args;
-       }
-       h_obj = (duk_hobject *) h;
-
-       /* The index range space is conceptually the array part followed by the
-        * entry part.  Unlike normal enumeration all slots are exposed here as
-        * is and return 'unused' if the slots are not in active use.  In 
particular
-        * the array part is included for the full a_size regardless of what the
-        * array .length is.
-        */
-
-       duk_debug_write_reply(thr);
-       for (idx = idx_start; idx < idx_end; idx++) {
-               if (!duk__debug_getprop_index(thr, heap, h_obj, idx)) {
-                       break;
-               }
-       }
-       duk_debug_write_eom(thr);
-       return;
-
- fail_args:
-       duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid args");
-}
-
-#endif  /* DUK_USE_DEBUGGER_INSPECT */
-
-/*
- *  Process incoming debug requests
- *
- *  Individual request handlers can push temporaries on the value stack and
- *  rely on duk__debug_process_message() to restore the value stack top
- *  automatically.
- */
-
-/* Process one debug message.  Automatically restore value stack top to its
- * entry value, so that individual message handlers don't need exact value
- * stack handling which is convenient.
- */
-DUK_LOCAL void duk__debug_process_message(duk_hthread *thr) {
-       duk_context *ctx = (duk_context *) thr;
-       duk_heap *heap;
-       duk_uint8_t x;
-       duk_int32_t cmd;
-       duk_idx_t entry_top;
-
-       DUK_ASSERT(thr != NULL);
-       heap = thr->heap;
-       DUK_ASSERT(heap != NULL);
-       DUK_UNREF(ctx);
-
-       entry_top = duk_get_top(ctx);
-
-       x = duk_debug_read_byte(thr);
-       switch (x) {
-       case DUK_DBG_IB_REQUEST: {
-               cmd = duk_debug_read_int(thr);
-               switch (cmd) {
-               case DUK_DBG_CMD_BASICINFO: {
-                       duk__debug_handle_basic_info(thr, heap);
-                       break;
-               }
-               case DUK_DBG_CMD_TRIGGERSTATUS: {
-                       duk__debug_handle_trigger_status(thr, heap);
-                       break;
-               }
-               case DUK_DBG_CMD_PAUSE: {
-                       duk__debug_handle_pause(thr, heap);
-                       break;
-               }
-               case DUK_DBG_CMD_RESUME: {
-                       duk__debug_handle_resume(thr, heap);
-                       break;
-               }
-               case DUK_DBG_CMD_STEPINTO:
-               case DUK_DBG_CMD_STEPOVER:
-               case DUK_DBG_CMD_STEPOUT: {
-                       duk__debug_handle_step(thr, heap, cmd);
-                       break;
-               }
-               case DUK_DBG_CMD_LISTBREAK: {
-                       duk__debug_handle_list_break(thr, heap);
-                       break;
-               }
-               case DUK_DBG_CMD_ADDBREAK: {
-                       duk__debug_handle_add_break(thr, heap);
-                       break;
-               }
-               case DUK_DBG_CMD_DELBREAK: {
-                       duk__debug_handle_del_break(thr, heap);
-                       break;
-               }
-               case DUK_DBG_CMD_GETVAR: {
-                       duk__debug_handle_get_var(thr, heap);
-                       break;
-               }
-               case DUK_DBG_CMD_PUTVAR: {
-                       duk__debug_handle_put_var(thr, heap);
-                       break;
-               }
-               case DUK_DBG_CMD_GETCALLSTACK: {
-                       duk__debug_handle_get_call_stack(thr, heap);
-                       break;
-               }
-               case DUK_DBG_CMD_GETLOCALS: {
-                       duk__debug_handle_get_locals(thr, heap);
-                       break;
-               }
-               case DUK_DBG_CMD_EVAL: {
-                       duk__debug_handle_eval(thr, heap);
-                       break;
-               }
-               case DUK_DBG_CMD_DETACH: {
-                       /* The actual detached_cb call is postponed to message 
loop so
-                        * we don't need any special precautions here (just 
skip to EOM
-                        * on the already closed connection).
-                        */
-                       duk__debug_handle_detach(thr, heap);
-                       break;
-               }
-#if defined(DUK_USE_DEBUGGER_DUMPHEAP)
-               case DUK_DBG_CMD_DUMPHEAP: {
-                       duk__debug_handle_dump_heap(thr, heap);
-                       break;
-               }
-#endif  /* DUK_USE_DEBUGGER_DUMPHEAP */
-               case DUK_DBG_CMD_GETBYTECODE: {
-                       duk__debug_handle_get_bytecode(thr, heap);
-                       break;
-               }
-               case DUK_DBG_CMD_APPREQUEST: {
-                       duk__debug_handle_apprequest(thr, heap);
-                       break;
-               }
-#if defined(DUK_USE_DEBUGGER_INSPECT)
-               case DUK_DBG_CMD_GETHEAPOBJINFO: {
-                       duk__debug_handle_get_heap_obj_info(thr, heap);
-                       break;
-               }
-               case DUK_DBG_CMD_GETOBJPROPDESC: {
-                       duk__debug_handle_get_obj_prop_desc(thr, heap);
-                       break;
-               }
-               case DUK_DBG_CMD_GETOBJPROPDESCRANGE: {
-                       duk__debug_handle_get_obj_prop_desc_range(thr, heap);
-                       break;
-               }
-#endif  /* DUK_USE_DEBUGGER_INSPECT */
-               default: {
-                       DUK_D(DUK_DPRINT("debug command unsupported: %d", (int) 
cmd));
-                       duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNSUPPORTED, 
"unsupported command");
-               }
-               }  /* switch cmd */
-               break;
-       }
-       case DUK_DBG_IB_REPLY: {
-               DUK_D(DUK_DPRINT("debug reply, skipping"));
-               break;
-       }
-       case DUK_DBG_IB_ERROR: {
-               DUK_D(DUK_DPRINT("debug error, skipping"));
-               break;
-       }
-       case DUK_DBG_IB_NOTIFY: {
-               DUK_D(DUK_DPRINT("debug notify, skipping"));
-               break;
-       }
-       default: {
-               DUK_D(DUK_DPRINT("invalid initial byte, drop connection: %d", 
(int) x));
-               goto fail;
-       }
-       }  /* switch initial byte */
-
-       DUK_ASSERT(duk_get_top(ctx) >= entry_top);
-       duk_set_top(ctx, entry_top);
-       duk__debug_skip_to_eom(thr);
-       return;
-
- fail:
-       DUK_ASSERT(duk_get_top(ctx) >= entry_top);
-       duk_set_top(ctx, entry_top);
-       DUK__SET_CONN_BROKEN(thr, 1);
-       return;
-}
-
-DUK_LOCAL void duk__check_resend_status(duk_hthread *thr) {
-       if (thr->heap->dbg_read_cb != NULL && thr->heap->dbg_state_dirty) {
-               duk_debug_send_status(thr);
-               thr->heap->dbg_state_dirty = 0;
-       }
-}
-
-DUK_INTERNAL duk_bool_t duk_debug_process_messages(duk_hthread *thr, 
duk_bool_t no_block) {
-       duk_context *ctx = (duk_context *) thr;
-#if defined(DUK_USE_ASSERTIONS)
-       duk_idx_t entry_top;
-#endif
-       duk_bool_t retval = 0;
-
-       DUK_ASSERT(thr != NULL);
-       DUK_UNREF(ctx);
-       DUK_ASSERT(thr->heap != NULL);
-#if defined(DUK_USE_ASSERTIONS)
-       entry_top = duk_get_top(ctx);
-#endif
-
-       DUK_D(DUK_DPRINT("process debug messages: read_cb=%s, no_block=%ld, 
detaching=%ld, processing=%ld",
-                        thr->heap->dbg_read_cb ? "not NULL" : "NULL", (long) 
no_block,
-                        (long) thr->heap->dbg_detaching, (long) 
thr->heap->dbg_processing));
-       DUK_DD(DUK_DDPRINT("top at entry: %ld", (long) duk_get_top(ctx)));
-
-       /* thr->heap->dbg_detaching may be != 0 if a debugger write outside
-        * the message loop caused a transport error and detach1() to run.
-        */
-       DUK_ASSERT(thr->heap->dbg_detaching == 0 || thr->heap->dbg_detaching == 
1);
-       DUK_ASSERT(thr->heap->dbg_processing == 0);
-       thr->heap->dbg_processing = 1;
-
-       /* Ensure dirty state causes a Status even if never process any
-        * messages.  This is expected by the bytecode executor when in
-        * the running state.
-        */
-       duk__check_resend_status(thr);
-
-       for (;;) {
-               /* Process messages until we're no longer paused or we peek
-                * and see there's nothing to read right now.
-                */
-               DUK_DD(DUK_DDPRINT("top at loop top: %ld", (long) 
duk_get_top(ctx)));
-               DUK_ASSERT(thr->heap->dbg_processing == 1);
-
-               while (thr->heap->dbg_read_cb == NULL && 
thr->heap->dbg_detaching) {
-                       /* Detach is pending; can be triggered from outside the
-                        * debugger loop (e.g. Status notify write error) or by
-                        * previous message handling.  Call detached callback
-                        * here, in a controlled state, to ensure a possible
-                        * reattach inside the detached_cb is handled correctly.
-                        *
-                        * Recheck for detach in a while loop: an immediate
-                        * reattach involves a call to duk_debugger_attach()
-                        * which writes a debugger handshake line immediately
-                        * inside the API call.  If the transport write fails
-                        * for that handshake, we can immediately end up in a
-                        * "transport broken, detaching" case several times 
here.
-                        * Loop back until we're either cleanly attached or
-                        * fully detached.
-                        *
-                        * NOTE: Reset dbg_processing = 1 forcibly, in case we
-                        * re-attached; duk_debugger_attach() sets 
dbg_processing
-                        * to 0 at the moment.
-                        */
-
-                       DUK_D(DUK_DPRINT("detach pending (dbg_read_cb == NULL, 
dbg_detaching != 0), call detach2"));
-
-                       duk__debug_do_detach2(thr->heap);
-                       thr->heap->dbg_processing = 1;  /* may be set to 0 by 
duk_debugger_attach() inside callback */
-
-                       DUK_D(DUK_DPRINT("after detach2 (and possible 
reattach): dbg_read_cb=%s, dbg_detaching=%ld",
-                                        thr->heap->dbg_read_cb ? "not NULL" : 
"NULL", (long) thr->heap->dbg_detaching));
-               }
-               DUK_ASSERT(thr->heap->dbg_detaching == 0);  /* true even with 
reattach */
-               DUK_ASSERT(thr->heap->dbg_processing == 1);  /* even after a 
detach and possible reattach */
-
-               if (thr->heap->dbg_read_cb == NULL) {
-                       DUK_D(DUK_DPRINT("debug connection broken (and not 
detaching), stop processing messages"));
-                       break;
-               }
-
-               if (!thr->heap->dbg_paused || no_block) {
-                       if (!duk_debug_read_peek(thr)) {
-                               /* Note: peek cannot currently trigger a detach
-                                * so the dbg_detaching == 0 assert outside the
-                                * loop is correct.
-                                */
-                               DUK_D(DUK_DPRINT("processing debug message, 
peek indicated no data, stop processing messages"));
-                               break;
-                       }
-                       DUK_D(DUK_DPRINT("processing debug message, peek 
indicated there is data, handle it"));
-               } else {
-                       DUK_D(DUK_DPRINT("paused, process debug message, 
blocking if necessary"));
-               }
-
-               duk__check_resend_status(thr);
-               duk__debug_process_message(thr);
-               duk__check_resend_status(thr);
-
-               retval = 1;  /* processed one or more messages */
-       }
-
-       DUK_ASSERT(thr->heap->dbg_detaching == 0);
-       DUK_ASSERT(thr->heap->dbg_processing == 1);
-       thr->heap->dbg_processing = 0;
-
-       /* As an initial implementation, read flush after exiting the message
-        * loop.  If transport is broken, this is a no-op (with debug logs).
-        */
-       duk_debug_read_flush(thr);  /* this cannot initiate a detach */
-       DUK_ASSERT(thr->heap->dbg_detaching == 0);
-
-       DUK_DD(DUK_DDPRINT("top at exit: %ld", (long) duk_get_top(ctx)));
-
-#if defined(DUK_USE_ASSERTIONS)
-       /* Easy to get wrong, so assert for it. */
-       DUK_ASSERT(entry_top == duk_get_top(ctx));
-#endif
-
-       return retval;
-}
-
-/*
- *  Halt execution helper
- */
-
-/* Halt execution and enter a debugger message loop until execution is resumed
- * by the client.  PC for the current activation may be temporarily decremented
- * so that the "current" instruction will be shown by the client.  This helper
- * is callable from anywhere, also outside bytecode executor.
- */
-
-DUK_INTERNAL void duk_debug_halt_execution(duk_hthread *thr, duk_bool_t 
use_prev_pc) {
-       duk_activation *act;
-       duk_hcompiledfunction *fun;
-       duk_instr_t *old_pc = NULL;
-
-       DUK_ASSERT(thr != NULL);
-       DUK_ASSERT(thr->heap != NULL);
-       DUK_ASSERT(DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap));
-       DUK_ASSERT(thr->heap->dbg_processing == 0);
-
-       DUK_HEAP_SET_PAUSED(thr->heap);
-
-       act = duk_hthread_get_current_activation(thr);
-
-       /* NOTE: act may be NULL if an error is thrown outside of any 
activation,
-        * which may happen in the case of, e.g. syntax errors.
-        */
-
-       /* Decrement PC if that was requested, this requires a PC sync. */
-       if (act != NULL) {
-               duk_hthread_sync_currpc(thr);
-               old_pc = act->curr_pc;
-               fun = (duk_hcompiledfunction *) DUK_ACT_GET_FUNC(act);
-
-               /* Short circuit if is safe: if act->curr_pc != NULL, 'fun' is
-                * guaranteed to be a non-NULL Ecmascript function.
-                */
-               DUK_ASSERT(act->curr_pc == NULL ||
-                          (fun != NULL && 
DUK_HOBJECT_IS_COMPILEDFUNCTION((duk_hobject *) fun)));
-               if (use_prev_pc &&
-                   act->curr_pc != NULL &&
-                   act->curr_pc > 
DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(thr->heap, fun)) {
-                       act->curr_pc--;
-               }
-       }
-
-       /* Process debug messages until we are no longer paused. */
-
-       /* NOTE: This is a bit fragile.  It's important to ensure that
-        * duk_debug_process_messages() never throws an error or
-        * act->curr_pc will never be reset.
-        */
-
-       thr->heap->dbg_state_dirty = 1;
-       while (thr->heap->dbg_paused) {
-               DUK_ASSERT(DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap));
-               DUK_ASSERT(thr->heap->dbg_processing);
-               duk_debug_process_messages(thr, 0 /*no_block*/);
-       }
-
-       /* XXX: Decrementing and restoring act->curr_pc works now, but if the
-        * debugger message loop gains the ability to adjust the current PC
-        * (e.g. a forced jump) restoring the PC here will break.  Another
-        * approach would be to use a state flag for the "decrement 1 from
-        * topmost activation's PC" and take it into account whenever dealing
-        * with PC values.
-        */
-       if (act != NULL) {
-               act->curr_pc = old_pc;  /* restore PC */
-       }
-}
-
-/*
- *  Breakpoint management
- */
-
-DUK_INTERNAL duk_small_int_t duk_debug_add_breakpoint(duk_hthread *thr, 
duk_hstring *filename, duk_uint32_t line) {
-       duk_heap *heap;
-       duk_breakpoint *b;
-
-       /* Caller must trigger recomputation of active breakpoint list.  To
-        * ensure stale values are not used if that doesn't happen, clear the
-        * active breakpoint list here.
-        */
-
-       DUK_ASSERT(thr != NULL);
-       DUK_ASSERT(filename != NULL);
-       heap = thr->heap;
-       DUK_ASSERT(heap != NULL);
-
-       if (heap->dbg_breakpoint_count >= DUK_HEAP_MAX_BREAKPOINTS) {
-               DUK_D(DUK_DPRINT("failed to add breakpoint for %O:%ld, all 
breakpoint slots used",
-                                (duk_heaphdr *) filename, (long) line));
-               return -1;
-       }
-       heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
-       b = heap->dbg_breakpoints + (heap->dbg_breakpoint_count++);
-       b->filename = filename;
-       b->line = line;
-       DUK_HSTRING_INCREF(thr, filename);
-
-       return heap->dbg_breakpoint_count - 1;  /* index */
-}
-
-DUK_INTERNAL duk_bool_t duk_debug_remove_breakpoint(duk_hthread *thr, 
duk_small_uint_t breakpoint_index) {
-       duk_heap *heap;
-       duk_hstring *h;
-       duk_breakpoint *b;
-       duk_size_t move_size;
-
-       /* Caller must trigger recomputation of active breakpoint list.  To
-        * ensure stale values are not used if that doesn't happen, clear the
-        * active breakpoint list here.
-        */
-
-       DUK_ASSERT(thr != NULL);
-       heap = thr->heap;
-       DUK_ASSERT(heap != NULL);
-       DUK_ASSERT(DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap));
-       DUK_ASSERT_DISABLE(breakpoint_index >= 0);  /* unsigned */
-
-       if (breakpoint_index >= heap->dbg_breakpoint_count) {
-               DUK_D(DUK_DPRINT("invalid breakpoint index: %ld", (long) 
breakpoint_index));
-               return 0;
-       }
-       b = heap->dbg_breakpoints + breakpoint_index;
-
-       h = b->filename;
-       DUK_ASSERT(h != NULL);
-
-       move_size = sizeof(duk_breakpoint) * (heap->dbg_breakpoint_count - 
breakpoint_index - 1);
-       if (move_size > 0) {
-               DUK_MEMMOVE((void *) b,
-                           (const void *) (b + 1),
-                           (size_t) move_size);
-       }
-       heap->dbg_breakpoint_count--;
-       heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
-
-       DUK_HSTRING_DECREF(thr, h);  /* side effects */
-       DUK_UNREF(h);  /* w/o refcounting */
-
-       /* Breakpoint entries above the used area are left as garbage. */
-
-       return 1;
-}
-
-#undef DUK__SET_CONN_BROKEN
-
-#else  /* DUK_USE_DEBUGGER_SUPPORT */
-
-/* No debugger support. */
-
-#endif  /* DUK_USE_DEBUGGER_SUPPORT */

Reply via email to