Skip to content

Commit f8e103e

Browse files
committed
Initial impl of unwrapObject
1 parent 9d0f9b0 commit f8e103e

File tree

3 files changed

+133
-7
lines changed

3 files changed

+133
-7
lines changed

src/binding.cpp

Lines changed: 75 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "include/v8.h"
77
#include "src/api/api.h"
88
#include "src/inspector/protocol/Runtime.h"
9+
#include "src/inspector/v8-string-conversions.h"
910

1011
#include "inspector.h"
1112

@@ -1567,6 +1568,12 @@ static inline v8_inspector::StringView toStringView(const char *str, size_t leng
15671568
auto* stringView = reinterpret_cast<const uint8_t*>(str);
15681569
return { stringView, length };
15691570
}
1571+
/// Overload for safety in case the function is called with a string literal
1572+
static inline v8_inspector::StringView toStringView(const char *str) {
1573+
size_t length = strlen(str);
1574+
auto* stringView = reinterpret_cast<const uint8_t*>(str);
1575+
return { stringView, length };
1576+
}
15701577
static inline v8_inspector::StringView toStringView(const std::string &str) {
15711578
return toStringView(str.c_str(), str.length());
15721579
}
@@ -1586,7 +1593,7 @@ static inline std::string fromStringView(v8::Isolate* isolate, const v8_inspecto
15861593
/// @param str: The string to return
15871594
/// @param allocator: A Zig std.mem.Allocator
15881595
/// @returns string pointer with null terminator, null if allocation failed
1589-
const char* toHeapCharPtr(const v8_inspector::String16& str, const void* allocator) {
1596+
const char* allocStringWith0(const v8_inspector::String16& str, const void* allocator) {
15901597
std::string utf8_str = str.utf8(); // Note the data*'s lifetime is tied to utf8_str and this may hold the string data on the stack as an SSO, so we need to copy it onto the heap.
15911598
char* heap_str = zigAlloc(allocator, utf8_str.length() + 1); // +1 for null terminator, needed to communicate the length to Zig
15921599
if (heap_str == nullptr) {
@@ -1596,6 +1603,37 @@ const char* toHeapCharPtr(const v8_inspector::String16& str, const void* allocat
15961603
return heap_str;
15971604
}
15981605

1606+
/// Allocates a string as utf8 on the allocator without \0 terminator, for use in Zig.
1607+
/// The strings pointer and length should therefore be returned together
1608+
/// @param str: The string contents to allocate
1609+
/// @param allocator: A Zig std.mem.Allocator
1610+
/// @param out_str: Points to the now allocated string on the heap (without sentinel \0)
1611+
/// @param out_len: The corresponding length of the string
1612+
void allocString(const v8_inspector::StringView& str, const void* allocator, const char*& out_str, size_t& out_len) {
1613+
std::string utf8_str; // Harmless if not used by 8bit string
1614+
if (str.is8Bit()) {
1615+
out_len = str.length();
1616+
} else {
1617+
utf8_str = v8_inspector::UTF16ToUTF8(str.characters16(), str.length());
1618+
out_len = utf8_str.length();
1619+
}
1620+
1621+
char* heap_str = zigAlloc(allocator, out_len);
1622+
if (heap_str == nullptr) {
1623+
out_str = nullptr;
1624+
out_len = 0;
1625+
return;
1626+
}
1627+
1628+
if (str.is8Bit()) {
1629+
memcpy(heap_str, str.characters8(), out_len);
1630+
} else {
1631+
memcpy(heap_str, utf8_str.c_str(), out_len);
1632+
}
1633+
out_str = heap_str;
1634+
return;
1635+
}
1636+
15991637

16001638
// Inspector
16011639

@@ -1666,6 +1704,36 @@ v8_inspector::protocol::Runtime::RemoteObject* v8_inspector__Session__wrapObject
16661704
return static_cast<v8_inspector::protocol::Runtime::RemoteObject*>(remote_object.release());
16671705
}
16681706

1707+
bool v8_inspector__Session__unwrapObject(
1708+
v8_inspector::V8InspectorSession *session,
1709+
const void* allocator,
1710+
const char* out_error,
1711+
uint64_t& out_error_len,
1712+
const char *in_objectId,
1713+
int in_objectId_len,
1714+
v8::Local<v8::Value> out_value,
1715+
v8::Local<v8::Context> out_context,
1716+
const char* out_objectGroup,
1717+
uint64_t& out_objectGroup_len
1718+
) {
1719+
auto objectId = toStringView(in_objectId, in_objectId_len);
1720+
auto error = v8_inspector::StringBuffer::create({});
1721+
auto objectGroup = v8_inspector::StringBuffer::create({});
1722+
1723+
// [out optional ] std::unique_ptr<StringBuffer>* error,
1724+
// [in required ] StringView objectId,
1725+
// [out required ] v8::Local<v8::Value> * value
1726+
// [out required ] v8::Local<v8::Context> * context
1727+
// [out optional ] std::unique_ptr<StringBuffer>* objectGroup
1728+
bool result = session->unwrapObject(&error, objectId, &out_value, &out_context, &objectGroup);
1729+
if (!result) {
1730+
allocString(error->string(), allocator, out_error, out_error_len);
1731+
return false;
1732+
}
1733+
allocString(objectGroup->string(), allocator, out_objectGroup, out_objectGroup_len);
1734+
return result;
1735+
}
1736+
16691737
// RemoteObject
16701738

16711739
// To prevent extra allocations on every call a single default value is reused everytime.
@@ -1679,7 +1747,7 @@ void v8_inspector__RemoteObject__DELETE(v8_inspector::protocol::Runtime::RemoteO
16791747
// RemoteObject - Type
16801748
const char* v8_inspector__RemoteObject__getType(v8_inspector::protocol::Runtime::RemoteObject* self, const void* allocator) {
16811749
auto str = self->getType();
1682-
return toHeapCharPtr(str, allocator);
1750+
return allocStringWith0(str, allocator);
16831751
}
16841752
void v8_inspector__RemoteObject__setType(v8_inspector::protocol::Runtime::RemoteObject* self, const char* type, int type_len) {
16851753
self->setType(v8_inspector::String16::fromUTF8(type, type_len));
@@ -1691,7 +1759,7 @@ bool v8_inspector__RemoteObject__hasSubtype(v8_inspector::protocol::Runtime::Rem
16911759
}
16921760
const char* v8_inspector__RemoteObject__getSubtype(v8_inspector::protocol::Runtime::RemoteObject* self, const void* allocator) {
16931761
auto str = self->getSubtype(DEFAULT_STRING);
1694-
return toHeapCharPtr(str, allocator);
1762+
return allocStringWith0(str, allocator);
16951763
}
16961764
void v8_inspector__RemoteObject__setSubtype(v8_inspector::protocol::Runtime::RemoteObject* self, const char* subtype, int subtype_len) {
16971765
self->setSubtype(v8_inspector::String16::fromUTF8(subtype, subtype_len));
@@ -1703,7 +1771,7 @@ bool v8_inspector__RemoteObject__hasClassName(v8_inspector::protocol::Runtime::R
17031771
}
17041772
const char* v8_inspector__RemoteObject__getClassName(v8_inspector::protocol::Runtime::RemoteObject* self, const void* allocator) {
17051773
auto str = self->getClassName(DEFAULT_STRING);
1706-
return toHeapCharPtr(str, allocator);
1774+
return allocStringWith0(str, allocator);
17071775
}
17081776
void v8_inspector__RemoteObject__setClassName(v8_inspector::protocol::Runtime::RemoteObject* self, const char* className, int className_len) {
17091777
self->setClassName(v8_inspector::String16::fromUTF8(className, className_len));
@@ -1726,7 +1794,7 @@ bool v8_inspector__RemoteObject__hasUnserializableValue(v8_inspector::protocol::
17261794
}
17271795
const char* v8_inspector__RemoteObject__getUnserializableValue(v8_inspector::protocol::Runtime::RemoteObject* self, const void* allocator) {
17281796
auto str = self->getUnserializableValue(DEFAULT_STRING);
1729-
return toHeapCharPtr(str, allocator);
1797+
return allocStringWith0(str, allocator);
17301798
}
17311799
void v8_inspector__RemoteObject__setUnserializableValue(v8_inspector::protocol::Runtime::RemoteObject* self, const char* unserializableValue, int unserializableValue_len) {
17321800
self->setUnserializableValue(v8_inspector::String16::fromUTF8(unserializableValue, unserializableValue_len));
@@ -1738,7 +1806,7 @@ bool v8_inspector__RemoteObject__hasDescription(v8_inspector::protocol::Runtime:
17381806
}
17391807
const char* v8_inspector__RemoteObject__getDescription(v8_inspector::protocol::Runtime::RemoteObject* self, const void* allocator) {
17401808
auto str = self->getDescription(DEFAULT_STRING);
1741-
return toHeapCharPtr(str, allocator);
1809+
return allocStringWith0(str, allocator);
17421810
}
17431811
void v8_inspector__RemoteObject__setDescription(v8_inspector::protocol::Runtime::RemoteObject* self, const char* description, int description_len) {
17441812
self->setDescription(v8_inspector::String16::fromUTF8(description, description_len));
@@ -1762,7 +1830,7 @@ bool v8_inspector__RemoteObject__hasObjectId(v8_inspector::protocol::Runtime::Re
17621830

17631831
const char* v8_inspector__RemoteObject__getObjectId(v8_inspector::protocol::Runtime::RemoteObject* self, const void* allocator) {
17641832
auto str = self->getObjectId(DEFAULT_STRING);
1765-
return toHeapCharPtr(str, allocator);
1833+
return allocStringWith0(str, allocator);
17661834
}
17671835
void v8_inspector__RemoteObject__setObjectId(v8_inspector::protocol::Runtime::RemoteObject* self, const char* objectId, int objectId_len) {
17681836
self->setObjectId(v8_inspector::String16::fromUTF8(objectId, objectId_len));

src/binding.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1032,6 +1032,19 @@ RemoteObject* v8_inspector__Session__wrapObject(
10321032
const Context* ctx, const Value* val,
10331033
const char *grpname, usize grpname_len, bool generatepreview);
10341034

1035+
bool v8_inspector__Session__unwrapObject(
1036+
InspectorSession *session,
1037+
const void* allocator,
1038+
const char* out_error,
1039+
uint64_t* out_error_len,
1040+
const char *in_objectId,
1041+
int in_objectId_len,
1042+
Value out_value,
1043+
Context out_context,
1044+
const char* out_objectGroup,
1045+
uint64_t* out_objectGroup_len
1046+
);
1047+
10351048
// Inspector
10361049
typedef struct Inspector Inspector;
10371050
Inspector* v8_inspector__Inspector__Create(Isolate* isolate, InspectorClientImpl* client);

src/v8.zig

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2719,6 +2719,51 @@ pub const InspectorSession = struct {
27192719
).?;
27202720
return RemoteObject{ .handle = remote_object };
27212721
}
2722+
2723+
pub fn unwrapObject(self: InspectorSession, allocator: std.mem.Allocator, objectId: []const u8) !UnwrapResult {
2724+
var out_error: [*c]const u8 = null;
2725+
var out_error_len: i64 = 0;
2726+
2727+
var out_value_handle: ?*c.Value = null;
2728+
var out_context_handle: ?*c.Context = null;
2729+
2730+
var out_objectGroup: [*c]const u8 = null;
2731+
var out_objectGroup_len: i64 = 0;
2732+
2733+
const result = c.v8_inspector__Session__unwrapObject(
2734+
self.handle,
2735+
&allocator,
2736+
&out_error,
2737+
&out_error_len,
2738+
objectId.ptr,
2739+
objectId.len,
2740+
&out_value_handle,
2741+
&out_context_handle,
2742+
&out_objectGroup.ptr,
2743+
&out_objectGroup_len,
2744+
);
2745+
if (!result) {
2746+
return .{ .err = out_error.?[0..out_error_len] };
2747+
}
2748+
return .{
2749+
.ok = .{
2750+
.value = Value{ .handle = out_value_handle.? },
2751+
.context = Context{ .handle = out_context_handle.? },
2752+
.objectGroup = out_objectGroup.?[0..out_objectGroup_len], // TODO can this be null?
2753+
},
2754+
};
2755+
}
2756+
};
2757+
2758+
pub const UnwrappedObject = struct {
2759+
value: Value,
2760+
context: Context,
2761+
objectGroup: []const u8,
2762+
};
2763+
pub const UnwrapResultEnum = enum { ok, err };
2764+
pub const UnwrapResult = union(UnwrapResultEnum) {
2765+
ok: UnwrappedObject,
2766+
err: []const u8,
27222767
};
27232768

27242769
/// Note: Some getters return owned memory (strings), while others return memory owned by V8 (objects).

0 commit comments

Comments
 (0)