|
2 | 2 |
|
3 | 3 | #include <cassert> |
4 | 4 | #include "include/libplatform/libplatform.h" |
| 5 | +#include "include/v8-inspector.h" |
5 | 6 | #include "include/v8.h" |
6 | 7 | #include "src/api/api.h" |
7 | 8 |
|
| 9 | +#include "inspector.h" |
| 10 | + |
8 | 11 | template <class T, class... Args> |
9 | 12 | class Wrapper { |
10 | 13 | public: |
@@ -1501,4 +1504,236 @@ void v8__base__SetDcheckFunction(void (*func)(const char*, int, const char*)) { |
1501 | 1504 | v8::base::SetDcheckFunction(func); |
1502 | 1505 | } |
1503 | 1506 |
|
| 1507 | +// Inspector |
| 1508 | +// --------- |
| 1509 | + |
| 1510 | +// v8 inspector is not really documented and not easy. |
| 1511 | +// Sources: |
| 1512 | +// - https://v8.dev/docs/inspector |
| 1513 | +// - C++ doc https://v8.github.io/api/head/namespacev8__inspector.html |
| 1514 | +// - Rusty (Deno) bindings https://github.com/denoland/rusty_v8/blob/main/src/binding.cc |
| 1515 | +// - https://github.com/ahmadov/v8_inspector_example |
| 1516 | +// - https://web.archive.org/web/20210918052901/http://hyperandroid.com/2020/02/12/v8-inspector-from-an-embedder-standpoint |
| 1517 | + |
| 1518 | +// Utils |
| 1519 | + |
| 1520 | +static inline v8_inspector::StringView toStringView(const std::string &str) { |
| 1521 | + auto* stringView = reinterpret_cast<const uint8_t*>(str.c_str()); |
| 1522 | + return { stringView, str.length() }; |
| 1523 | +} |
| 1524 | + |
| 1525 | +static inline std::string fromStringView(v8::Isolate* isolate, const v8_inspector::StringView stringView) { |
| 1526 | + int length = static_cast<int>(stringView.length()); |
| 1527 | + v8::Local<v8::String> message = ( |
| 1528 | + stringView.is8Bit() |
| 1529 | + ? v8::String::NewFromOneByte(isolate, reinterpret_cast<const uint8_t*>(stringView.characters8()), v8::NewStringType::kNormal, length) |
| 1530 | + : v8::String::NewFromTwoByte(isolate, reinterpret_cast<const uint16_t*>(stringView.characters16()), v8::NewStringType::kNormal, length) |
| 1531 | + ).ToLocalChecked(); |
| 1532 | + v8::String::Utf8Value result(isolate, message); |
| 1533 | + return *result; |
| 1534 | +} |
| 1535 | + |
| 1536 | +// Inspector |
| 1537 | + |
| 1538 | +v8_inspector::V8Inspector *v8_inspector__Inspector__Create( |
| 1539 | + v8::Isolate* isolate, v8_inspector__Client__IMPL *client) { |
| 1540 | + std::unique_ptr<v8_inspector::V8Inspector> u = |
| 1541 | + v8_inspector::V8Inspector::create(isolate, client); |
| 1542 | + return u.release(); |
| 1543 | +} |
| 1544 | +void v8_inspector__Inspector__DELETE(v8_inspector::V8Inspector* self) { |
| 1545 | + delete self; |
| 1546 | +} |
| 1547 | +v8_inspector::V8InspectorSession *v8_inspector__Inspector__Connect( |
| 1548 | + v8_inspector::V8Inspector *self, int contextGroupId, |
| 1549 | + v8_inspector__Channel__IMPL *channel, |
| 1550 | + v8_inspector::V8Inspector::ClientTrustLevel client_trust_level) { |
| 1551 | + auto state = v8_inspector::StringView(); |
| 1552 | + std::unique_ptr<v8_inspector::V8InspectorSession> u = |
| 1553 | + self->connect(contextGroupId, channel, state, client_trust_level); |
| 1554 | + return u.release(); |
| 1555 | +} |
| 1556 | +void v8_inspector__Inspector__ContextCreated(v8_inspector::V8Inspector *self, |
| 1557 | + const char *name, int name_len, |
| 1558 | + const char *origin, int origin_len, |
| 1559 | + const char *auxData, int auxData_len, |
| 1560 | + int contextGroupId, |
| 1561 | + const v8::Context &ctx) { |
| 1562 | + // create context info |
| 1563 | + std::string name_str; |
| 1564 | + name_str.assign(name, name_len); |
| 1565 | + v8_inspector::StringView name_view(toStringView(name_str)); |
| 1566 | + auto context = ptr_to_local(&ctx); |
| 1567 | + v8_inspector::V8ContextInfo info(context, contextGroupId, name_view); |
| 1568 | + |
| 1569 | + // add origin to context info |
| 1570 | + std::string origin_str; |
| 1571 | + origin_str.assign(origin, origin_len); |
| 1572 | + info.origin = toStringView(origin_str); |
| 1573 | + |
| 1574 | + // add auxData to context info |
| 1575 | + std::string auxData_str; |
| 1576 | + auxData_str.assign(auxData, auxData_len); |
| 1577 | + info.auxData = toStringView(auxData_str); |
| 1578 | + |
| 1579 | + // call contextCreated |
| 1580 | + self->contextCreated(info); |
| 1581 | +} |
| 1582 | + |
| 1583 | +// InspectorSession |
| 1584 | + |
| 1585 | +void v8_inspector__Session__dispatchProtocolMessage( |
| 1586 | + v8_inspector::V8InspectorSession *session, v8::Isolate *isolate, |
| 1587 | + const char *msg, int msg_len) { |
| 1588 | + std::string message; |
| 1589 | + message.assign(msg, msg_len); |
| 1590 | + auto str_view = toStringView(message); |
| 1591 | + session->dispatchProtocolMessage(str_view); |
| 1592 | +} |
| 1593 | + |
| 1594 | +// InspectorChannel |
| 1595 | + |
| 1596 | +v8_inspector__Channel__IMPL * v8_inspector__Channel__IMPL__CREATE(v8::Isolate *isolate) { |
| 1597 | + auto channel = new v8_inspector__Channel__IMPL(); |
| 1598 | + channel->isolate = isolate; |
| 1599 | + return channel; |
| 1600 | +} |
| 1601 | +void v8_inspector__Channel__IMPL__DELETE(v8_inspector__Channel__IMPL *self) { |
| 1602 | + delete self; |
| 1603 | +} |
| 1604 | +void v8_inspector__Channel__IMPL__SET_DATA(v8_inspector__Channel__IMPL *self, void *data) { |
| 1605 | + self->data = data; |
| 1606 | +} |
| 1607 | + |
| 1608 | +// declaration of functions implementations |
| 1609 | +// NOTE: zig project should provide those implementations with C-ABI functions |
| 1610 | +void v8_inspector__Channel__IMPL__sendResponse( |
| 1611 | + v8_inspector__Channel__IMPL* self, void* data, |
| 1612 | + int callId, const char* message, size_t length); |
| 1613 | +void v8_inspector__Channel__IMPL__sendNotification( |
| 1614 | + v8_inspector__Channel__IMPL* self, void *data, |
| 1615 | + const char* msg, size_t length); |
| 1616 | +void v8_inspector__Channel__IMPL__flushProtocolNotifications( |
| 1617 | + v8_inspector__Channel__IMPL* self, void *data); |
| 1618 | + |
| 1619 | +// c++ implementation (just wrappers around the C/zig functions) |
| 1620 | +} // extern "C" |
| 1621 | +void v8_inspector__Channel__IMPL::sendResponse( |
| 1622 | + int callId, std::unique_ptr<v8_inspector::StringBuffer> message) { |
| 1623 | + const std::string resp = fromStringView(this->isolate, message->string()); |
| 1624 | + return v8_inspector__Channel__IMPL__sendResponse(this, this->data, callId, resp.c_str(), resp.length()); |
| 1625 | +} |
| 1626 | +void v8_inspector__Channel__IMPL::sendNotification( |
| 1627 | + std::unique_ptr<v8_inspector::StringBuffer> message) { |
| 1628 | + const std::string notif = fromStringView(this->isolate, message->string()); |
| 1629 | + return v8_inspector__Channel__IMPL__sendNotification(this, this->data, notif.c_str(), notif.length()); |
| 1630 | +} |
| 1631 | +void v8_inspector__Channel__IMPL::flushProtocolNotifications() { |
| 1632 | + return v8_inspector__Channel__IMPL__flushProtocolNotifications(this, this->data); |
| 1633 | +} |
| 1634 | + |
| 1635 | +extern "C" { |
| 1636 | + |
| 1637 | +// wrappers for the public API Interface |
| 1638 | +// NOTE: not sure it's useful to expose those |
| 1639 | +void v8_inspector__Channel__sendResponse( |
| 1640 | + v8_inspector::V8Inspector::Channel* self, int callId, |
| 1641 | + v8_inspector::StringBuffer* message) { |
| 1642 | + self->sendResponse( |
| 1643 | + callId, |
| 1644 | + static_cast<std::unique_ptr<v8_inspector::StringBuffer>>(message)); |
| 1645 | +} |
| 1646 | +void v8_inspector__Channel__sendNotification( |
| 1647 | + v8_inspector::V8Inspector::Channel* self, |
| 1648 | + v8_inspector::StringBuffer* message) { |
| 1649 | + self->sendNotification( |
| 1650 | + static_cast<std::unique_ptr<v8_inspector::StringBuffer>>(message)); |
| 1651 | +} |
| 1652 | +void v8_inspector__Channel__flushProtocolNotifications( |
| 1653 | + v8_inspector::V8Inspector::Channel* self) { |
| 1654 | + self->flushProtocolNotifications(); |
| 1655 | +} |
| 1656 | + |
| 1657 | +// InspectorClient |
| 1658 | + |
| 1659 | +v8_inspector__Client__IMPL *v8_inspector__Client__IMPL__CREATE() { |
| 1660 | + return new v8_inspector__Client__IMPL(); |
| 1661 | +} |
| 1662 | +void v8_inspector__Client__IMPL__DELETE(v8_inspector__Client__IMPL *self) { |
| 1663 | + delete self; |
| 1664 | +} |
| 1665 | +void v8_inspector__Client__IMPL__SET_DATA(v8_inspector__Client__IMPL *self, void *data) { |
| 1666 | + self->data = data; |
| 1667 | +} |
| 1668 | + |
| 1669 | +// declaration of functions implementations |
| 1670 | +// NOTE: zig project should provide those implementations with C-like functions |
| 1671 | +int64_t v8_inspector__Client__IMPL__generateUniqueId(v8_inspector__Client__IMPL* self, void* data); |
| 1672 | +void v8_inspector__Client__IMPL__runMessageLoopOnPause( |
| 1673 | + v8_inspector__Client__IMPL *self, |
| 1674 | + void* data, int contextGroupId); |
| 1675 | +void v8_inspector__Client__IMPL__quitMessageLoopOnPause(v8_inspector__Client__IMPL* self, void* data); |
| 1676 | +void v8_inspector__Client__IMPL__runIfWaitingForDebugger( |
| 1677 | + v8_inspector__Client__IMPL* self, void* data, int contextGroupId); |
| 1678 | +void v8_inspector__Client__IMPL__consoleAPIMessage( |
| 1679 | + v8_inspector__Client__IMPL* self, void* data, int contextGroupId, |
| 1680 | + v8::Isolate::MessageErrorLevel level, |
| 1681 | + const v8_inspector::StringView &message, |
| 1682 | + const v8_inspector::StringView &url, unsigned lineNumber, |
| 1683 | + unsigned columnNumber, v8_inspector::V8StackTrace *stackTrace); |
| 1684 | + |
| 1685 | +// c++ implementation (just wrappers around the c/zig functions) |
| 1686 | +} // extern "C" |
| 1687 | +int64_t v8_inspector__Client__IMPL::generateUniqueId() { |
| 1688 | + return v8_inspector__Client__IMPL__generateUniqueId(this, this->data); |
| 1689 | +} |
| 1690 | +void v8_inspector__Client__IMPL::runMessageLoopOnPause(int contextGroupId) { |
| 1691 | + return v8_inspector__Client__IMPL__runMessageLoopOnPause(this, this->data, contextGroupId); |
| 1692 | +} |
| 1693 | +void v8_inspector__Client__IMPL::quitMessageLoopOnPause() { |
| 1694 | + return v8_inspector__Client__IMPL__quitMessageLoopOnPause(this, this->data); |
| 1695 | +} |
| 1696 | +void v8_inspector__Client__IMPL::runIfWaitingForDebugger(int contextGroupId) { |
| 1697 | + return v8_inspector__Client__IMPL__runIfWaitingForDebugger(this, this->data, contextGroupId); |
| 1698 | +} |
| 1699 | +void v8_inspector__Client__IMPL::consoleAPIMessage( |
| 1700 | + int contextGroupId, v8::Isolate::MessageErrorLevel level, |
| 1701 | + const v8_inspector::StringView &message, |
| 1702 | + const v8_inspector::StringView &url, unsigned lineNumber, |
| 1703 | + unsigned columnNumber, v8_inspector::V8StackTrace *stackTrace) { |
| 1704 | + return v8_inspector__Client__IMPL__consoleAPIMessage( |
| 1705 | + this, this->data, contextGroupId, level, message, url, lineNumber, |
| 1706 | + columnNumber, stackTrace); |
1504 | 1707 | } |
| 1708 | + |
| 1709 | +extern "C" { |
| 1710 | + |
| 1711 | +// wrappers for the public API Interface |
| 1712 | +// NOTE: not sure it's useful to expose those |
| 1713 | +int64_t v8_inspector__Client__generateUniqueId( |
| 1714 | + v8_inspector::V8InspectorClient *self) { |
| 1715 | + return self->generateUniqueId(); |
| 1716 | +} |
| 1717 | +void v8_inspector__Client__runMessageLoopOnPause( |
| 1718 | + v8_inspector::V8InspectorClient* self, int contextGroupId) { |
| 1719 | + self->runMessageLoopOnPause(contextGroupId); |
| 1720 | +} |
| 1721 | +void v8_inspector__Client__quitMessageLoopOnPause( |
| 1722 | + v8_inspector::V8InspectorClient* self) { |
| 1723 | + self->quitMessageLoopOnPause(); |
| 1724 | +} |
| 1725 | +void v8_inspector__Client__runIfWaitingForDebugger( |
| 1726 | + v8_inspector::V8InspectorClient* self, int contextGroupId) { |
| 1727 | + self->runIfWaitingForDebugger(contextGroupId); |
| 1728 | +} |
| 1729 | +void v8_inspector__Client__consoleAPIMessage( |
| 1730 | + v8_inspector::V8InspectorClient* self, int contextGroupId, |
| 1731 | + v8::Isolate::MessageErrorLevel level, |
| 1732 | + const v8_inspector::StringView& message, |
| 1733 | + const v8_inspector::StringView& url, unsigned lineNumber, |
| 1734 | + unsigned columnNumber, v8_inspector::V8StackTrace* stackTrace) { |
| 1735 | + self->consoleAPIMessage(contextGroupId, level, message, url, lineNumber, |
| 1736 | + columnNumber, stackTrace); |
| 1737 | +} |
| 1738 | + |
| 1739 | +} // extern "C" |
0 commit comments