Skip to content

Commit 497c76f

Browse files
committed
Rewrite with Zig alloc for C
1 parent 2aafa05 commit 497c76f

File tree

3 files changed

+91
-94
lines changed

3 files changed

+91
-94
lines changed

src/binding.cpp

Lines changed: 41 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1550,6 +1550,13 @@ void v8__base__SetDcheckFunction(void (*func)(const char*, int, const char*)) {
15501550

15511551
// Utils
15521552

1553+
/// Header for Zig
1554+
/// Allocates `bytes` bytes of memory using the allocator.
1555+
/// @param allocator: A Zig std.mem.Allocator
1556+
/// @param bytes: The number of bytes to allocate
1557+
/// @returns A pointer to the allocated memory, null if allocation failed
1558+
char* zigAlloc(void* allocator, uint64_t bytes);
1559+
15531560
static inline v8_inspector::StringView toStringView(const char *str, size_t length) {
15541561
auto* stringView = reinterpret_cast<const uint8_t*>(str);
15551562
return { stringView, length };
@@ -1569,12 +1576,20 @@ static inline std::string fromStringView(v8::Isolate* isolate, const v8_inspecto
15691576
return *result;
15701577
}
15711578

1572-
const char* toHeapCharPtr(const v8_inspector::String16& str) {
1573-
std::string utf8_str = str.utf8(); // Note that this may hold the string on the stack as an SSO
1574-
char* heap_str = new char[utf8_str.length() + 1];
1579+
/// Allocates a string as utf8 on the heap, such that it can be returned to Zig.
1580+
/// @param str: The string to return
1581+
/// @param allocator: A Zig std.mem.Allocator
1582+
/// @returns string pointer with null terminator, null if allocation failed
1583+
const char* toHeapCharPtr(const v8_inspector::String16& str, void* allocator) {
1584+
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.
1585+
char* heap_str = zigAlloc(allocator, utf8_str.length() + 1); // +1 for null terminator, needed to communicate the length to Zig
1586+
if (heap_str == nullptr) {
1587+
return nullptr;
1588+
}
15751589
strcpy(heap_str, utf8_str.c_str());
1576-
return heap_str;
1577-
}
1590+
return heap_str;
1591+
}
1592+
15781593

15791594
// Inspector
15801595

@@ -1642,15 +1657,12 @@ v8_inspector::protocol::Runtime::RemoteObject* v8_inspector__Session__wrapObject
16421657
const char *grpname, int grpname_len, bool generatepreview) {
16431658
auto sv_grpname = toStringView(grpname, grpname_len);
16441659
auto remote_object = session->wrapObject(ptr_to_local(ctx), ptr_to_local(val), sv_grpname, generatepreview);
1645-
assert(remote_object != nullptr);
1646-
auto* not_api = static_cast<v8_inspector::protocol::Runtime::RemoteObject*>(remote_object.release());
1647-
assert(not_api != nullptr);
1648-
return not_api;
1660+
return static_cast<v8_inspector::protocol::Runtime::RemoteObject*>(remote_object.release());
16491661
}
16501662

16511663
// RemoteObject
16521664

1653-
// To prevent extra allocations on every call a single default value value is reused everytime.
1665+
// To prevent extra allocations on every call a single default value is reused everytime.
16541666
// It is expected that the precense of a value is checked before calling get* methods.
16551667
const v8_inspector::String16 DEFAULT_STRING = {"default"};
16561668

@@ -1659,9 +1671,9 @@ void v8_inspector__RemoteObject__DELETE(v8_inspector::protocol::Runtime::RemoteO
16591671
}
16601672

16611673
// RemoteObject - Type
1662-
const char* v8_inspector__RemoteObject__getType(v8_inspector::protocol::Runtime::RemoteObject* self) {
1674+
const char* v8_inspector__RemoteObject__getType(v8_inspector::protocol::Runtime::RemoteObject* self, void* allocator) {
16631675
auto str = self->getType();
1664-
return toHeapCharPtr(str);
1676+
return toHeapCharPtr(str, allocator);
16651677
}
16661678
void v8_inspector__RemoteObject__setType(v8_inspector::protocol::Runtime::RemoteObject* self, const char* type, int type_len) {
16671679
self->setType(v8_inspector::String16::fromUTF8(type, type_len));
@@ -1671,9 +1683,9 @@ void v8_inspector__RemoteObject__setType(v8_inspector::protocol::Runtime::Remote
16711683
bool v8_inspector__RemoteObject__hasSubtype(v8_inspector::protocol::Runtime::RemoteObject* self) {
16721684
return self->hasSubtype();
16731685
}
1674-
const char* v8_inspector__RemoteObject__getSubtype(v8_inspector::protocol::Runtime::RemoteObject* self) {
1686+
const char* v8_inspector__RemoteObject__getSubtype(v8_inspector::protocol::Runtime::RemoteObject* self, void* allocator) {
16751687
auto str = self->getSubtype(DEFAULT_STRING);
1676-
return toHeapCharPtr(str);
1688+
return toHeapCharPtr(str, allocator);
16771689
}
16781690
void v8_inspector__RemoteObject__setSubtype(v8_inspector::protocol::Runtime::RemoteObject* self, const char* subtype, int subtype_len) {
16791691
self->setSubtype(v8_inspector::String16::fromUTF8(subtype, subtype_len));
@@ -1683,9 +1695,9 @@ void v8_inspector__RemoteObject__setSubtype(v8_inspector::protocol::Runtime::Rem
16831695
bool v8_inspector__RemoteObject__hasClassName(v8_inspector::protocol::Runtime::RemoteObject* self) {
16841696
return self->hasClassName();
16851697
}
1686-
const char* v8_inspector__RemoteObject__getClassName(v8_inspector::protocol::Runtime::RemoteObject* self) {
1698+
const char* v8_inspector__RemoteObject__getClassName(v8_inspector::protocol::Runtime::RemoteObject* self, void* allocator) {
16871699
auto str = self->getClassName(DEFAULT_STRING);
1688-
return toHeapCharPtr(str);
1700+
return toHeapCharPtr(str, allocator);
16891701
}
16901702
void v8_inspector__RemoteObject__setClassName(v8_inspector::protocol::Runtime::RemoteObject* self, const char* className, int className_len) {
16911703
self->setClassName(v8_inspector::String16::fromUTF8(className, className_len));
@@ -1706,9 +1718,9 @@ void v8_inspector__RemoteObject__setValue(v8_inspector::protocol::Runtime::Remot
17061718
bool v8_inspector__RemoteObject__hasUnserializableValue(v8_inspector::protocol::Runtime::RemoteObject* self) {
17071719
return self->hasUnserializableValue();
17081720
}
1709-
const char* v8_inspector__RemoteObject__getUnserializableValue(v8_inspector::protocol::Runtime::RemoteObject* self) {
1721+
const char* v8_inspector__RemoteObject__getUnserializableValue(v8_inspector::protocol::Runtime::RemoteObject* self, void* allocator) {
17101722
auto str = self->getUnserializableValue(DEFAULT_STRING);
1711-
return toHeapCharPtr(str);
1723+
return toHeapCharPtr(str, allocator);
17121724
}
17131725
void v8_inspector__RemoteObject__setUnserializableValue(v8_inspector::protocol::Runtime::RemoteObject* self, const char* unserializableValue, int unserializableValue_len) {
17141726
self->setUnserializableValue(v8_inspector::String16::fromUTF8(unserializableValue, unserializableValue_len));
@@ -1718,9 +1730,9 @@ void v8_inspector__RemoteObject__setUnserializableValue(v8_inspector::protocol::
17181730
bool v8_inspector__RemoteObject__hasDescription(v8_inspector::protocol::Runtime::RemoteObject* self) {
17191731
return self->hasDescription();
17201732
}
1721-
const char* v8_inspector__RemoteObject__getDescription(v8_inspector::protocol::Runtime::RemoteObject* self) {
1733+
const char* v8_inspector__RemoteObject__getDescription(v8_inspector::protocol::Runtime::RemoteObject* self, void* allocator) {
17221734
auto str = self->getDescription(DEFAULT_STRING);
1723-
return toHeapCharPtr(str);
1735+
return toHeapCharPtr(str, allocator);
17241736
}
17251737
void v8_inspector__RemoteObject__setDescription(v8_inspector::protocol::Runtime::RemoteObject* self, const char* description, int description_len) {
17261738
self->setDescription(v8_inspector::String16::fromUTF8(description, description_len));
@@ -1739,15 +1751,16 @@ void v8_inspector__RemoteObject__setWebDriverValue(v8_inspector::protocol::Runti
17391751

17401752
// RemoteObject - ObjectId
17411753
bool v8_inspector__RemoteObject__hasObjectId(v8_inspector::protocol::Runtime::RemoteObject* self) {
1742-
return self->hasObjectId();
1743-
}
1744-
const char* v8_inspector__RemoteObject__getObjectId(v8_inspector::protocol::Runtime::RemoteObject* self) {
1745-
auto str = self->getObjectId(DEFAULT_STRING);
1746-
return toHeapCharPtr(str);
1747-
}
1754+
return self->hasObjectId();
1755+
}
1756+
1757+
const char* v8_inspector__RemoteObject__getObjectId(v8_inspector::protocol::Runtime::RemoteObject* self, void* allocator) {
1758+
auto str = self->getObjectId(DEFAULT_STRING);
1759+
return toHeapCharPtr(str, allocator);
1760+
}
17481761
void v8_inspector__RemoteObject__setObjectId(v8_inspector::protocol::Runtime::RemoteObject* self, const char* objectId, int objectId_len) {
1749-
self->setObjectId(v8_inspector::String16::fromUTF8(objectId, objectId_len));
1750-
}
1762+
self->setObjectId(v8_inspector::String16::fromUTF8(objectId, objectId_len));
1763+
}
17511764

17521765
// RemoteObject - Preview
17531766
bool v8_inspector__RemoteObject__hasPreview(v8_inspector::protocol::Runtime::RemoteObject* self) {

src/binding.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,17 +1030,17 @@ void v8_inspector__Inspector__ContextCreated(Inspector *self, const char *name,
10301030
void v8_inspector__RemoteObject__DELETE(RemoteObject *self);
10311031

10321032
// RemoteObject - Type
1033-
const char* v8_inspector__RemoteObject__getType(RemoteObject* self);
1033+
const char* v8_inspector__RemoteObject__getType(RemoteObject* self, void* allocator);
10341034
void v8_inspector__RemoteObject__setType(RemoteObject* self, const char* type, int type_len);
10351035

10361036
// RemoteObject - Subtype
10371037
bool v8_inspector__RemoteObject__hasSubtype(RemoteObject* self);
1038-
const char* v8_inspector__RemoteObject__getSubtype(RemoteObject* self);
1038+
const char* v8_inspector__RemoteObject__getSubtype(RemoteObject* self, void* allocator);
10391039
void v8_inspector__RemoteObject__setSubtype(RemoteObject* self, const char* subtype, int subtype_len);
10401040

10411041
// RemoteObject - ClassName
10421042
bool v8_inspector__RemoteObject__hasClassName(RemoteObject* self);
1043-
const char* v8_inspector__RemoteObject__getClassName(RemoteObject* self);
1043+
const char* v8_inspector__RemoteObject__getClassName(RemoteObject* self, void* allocator);
10441044
void v8_inspector__RemoteObject__setClassName(RemoteObject* self, const char* className, int className_len);
10451045

10461046
// RemoteObject - Value
@@ -1051,12 +1051,12 @@ bool v8_inspector__RemoteObject__hasValue(RemoteObject* self);
10511051

10521052
//RemoteObject - UnserializableValue
10531053
bool v8_inspector__RemoteObject__hasUnserializableValue(RemoteObject* self);
1054-
const char* v8_inspector__RemoteObject__getUnserializableValue(RemoteObject* self);
1054+
const char* v8_inspector__RemoteObject__getUnserializableValue(RemoteObject* self, void* allocator);
10551055
void v8_inspector__RemoteObject__setUnserializableValue(RemoteObject* self, const char* unserializableValue, int unserializableValue_len);
10561056

10571057
// RemoteObject - Description
10581058
bool v8_inspector__RemoteObject__hasDescription(RemoteObject* self);
1059-
const char* v8_inspector__RemoteObject__getDescription(RemoteObject* self);
1059+
const char* v8_inspector__RemoteObject__getDescription(RemoteObject* self, void* allocator);
10601060
void v8_inspector__RemoteObject__setDescription(RemoteObject* self, const char* description, int description_len);
10611061

10621062
// RemoteObject - WebDriverValue
@@ -1066,7 +1066,7 @@ void v8_inspector__RemoteObject__setWebDriverValue(RemoteObject* self, WebDriver
10661066

10671067
// RemoteObject - ObjectId
10681068
bool v8_inspector__RemoteObject__hasObjectId(RemoteObject* self);
1069-
const char* v8_inspector__RemoteObject__getObjectId(RemoteObject* self);
1069+
const char* v8_inspector__RemoteObject__getObjectId(RemoteObject* self, void* allocator);
10701070
void v8_inspector__RemoteObject__setObjectId(RemoteObject* self, const char* objectId, int objectId_len);
10711071

10721072
// RemoteObject - Preview
@@ -1077,4 +1077,4 @@ void v8_inspector__RemoteObject__setPreview(RemoteObject* self, ObjectPreview* p
10771077
// RemoteObject - CustomPreview
10781078
bool v8_inspector__RemoteObject__hasCustomPreview(RemoteObject* self);
10791079
const CustomPreview* v8_inspector__RemoteObject__getCustomPreview(RemoteObject* self);
1080-
void v8_inspector__RemoteObject__setCustomPreview(RemoteObject* self, CustomPreview* customPreview);
1080+
void v8_inspector__RemoteObject__setCustomPreview(RemoteObject* self, CustomPreview* customPreview);

src/v8.zig

Lines changed: 43 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -2679,98 +2679,82 @@ pub const InspectorSession = struct {
26792679
grpname.len,
26802680
generatepreview,
26812681
).?;
2682-
return RemoteObject.init(remote_object);
2682+
return RemoteObject{ .handle = remote_object };
26832683
}
26842684
};
26852685

2686-
/// Currently RemoteObject is implemented as a plain struct as opposed to an interface to its members.
2687-
/// This likely needs to change if we need to call setters in the future, or as more uscases with remoteObject appear.
2688-
/// An interface like implementation is not prefered as V8 is inconsistend with handing out owning an non-owning memory. This is partly due to v8 using UTF16 strings.
2689-
/// For an interface implementation: Some getters return owned memory (strings), while others return memory owned by V8 (objects).
2690-
/// Now instead, we do not have to exposed that to our users, which only have to make a single deinit call.
2686+
/// Note: Some getters return owned memory (strings), while others return memory owned by V8 (objects).
26912687
/// The getters short-circuit if the default values is not available as converting the defaults to V8 causes unnecessary overhead.
26922688
///
26932689
/// https://chromedevtools.github.io/devtools-protocol/tot/Runtime/#type-RemoteObject
26942690
pub const RemoteObject = struct {
26952691
handle: *c.RemoteObject,
2696-
type: []const u8,
2697-
subtype: ?[]const u8,
2698-
class_name: ?[]const u8,
2699-
// NotYetImplemented: value,
2700-
// NotYetImplemented: unserializable_value,
2701-
description: ?[]const u8,
2702-
// NotYetImplemented: web_driver_value,
2703-
object_id: ?[]const u8,
2704-
// NotYetImplemented: preview,
2705-
// NotYetImplemented: custom_preview,
2706-
2707-
pub fn init(handle: *c.RemoteObject) RemoteObject {
2708-
return .{
2709-
.handle = handle,
2710-
.type = RemoteObject.getType(handle),
2711-
.subtype = RemoteObject.getSubtype(handle),
2712-
.class_name = RemoteObject.getClassName(handle),
2713-
.description = RemoteObject.getDescription(handle),
2714-
.object_id = RemoteObject.getObjectId(handle),
2715-
};
2716-
}
27172692

27182693
pub fn deinit(self: RemoteObject) void {
27192694
c.v8_inspector__RemoteObject__DELETE(self.handle);
2720-
std.c.free(self.type);
2721-
if (self.subtype) |subtype| {
2722-
std.c.free(subtype);
2723-
}
2724-
if (self.class_name) |class_name| {
2725-
std.c.free(class_name);
2726-
}
2727-
if (self.description) |description| {
2728-
std.c.free(description);
2729-
}
2730-
if (self.object_id) |object_id| {
2731-
std.c.free(object_id);
2732-
}
27332695
}
27342696

2735-
fn getType(handle: *c.RemoteObject) []const u8 {
2736-
const type_ = c.v8_inspector__RemoteObject__getType(handle);
2697+
pub fn getType(self: RemoteObject, allocator: *std.mem.Allocator) ![:0]const u8 {
2698+
const type_ = c.v8_inspector__RemoteObject__getType(self.handle, allocator);
2699+
if (type_ == null) {
2700+
return error.V8AllocFailed;
2701+
}
27372702
const idx = std.mem.indexOfSentinel(u8, 0, type_);
2738-
return type_[0..idx];
2703+
return type_[0..idx :0];
27392704
}
2740-
fn getSubtype(handle: *c.RemoteObject) ?[]const u8 {
2741-
if (!c.v8_inspector__RemoteObject__hasSubtype(handle)) {
2705+
pub fn getSubtype(self: RemoteObject, allocator: *std.mem.Allocator) !?[:0]const u8 {
2706+
if (!c.v8_inspector__RemoteObject__hasSubtype(self.handle)) {
27422707
return null;
27432708
}
27442709

2745-
const subtype = c.v8_inspector__RemoteObject__getSubtype(handle);
2710+
const subtype = c.v8_inspector__RemoteObject__getSubtype(self.handle, allocator);
2711+
if (subtype == null) {
2712+
return error.V8AllocFailed;
2713+
}
27462714
const idx = std.mem.indexOfSentinel(u8, 0, subtype);
2747-
return subtype[0..idx];
2715+
return subtype[0..idx :0];
27482716
}
2749-
fn getClassName(handle: *c.RemoteObject) ?[]const u8 {
2750-
if (!c.v8_inspector__RemoteObject__hasClassName(handle)) {
2717+
pub fn getClassName(self: RemoteObject, allocator: *std.mem.Allocator) !?[:0]const u8 {
2718+
if (!c.v8_inspector__RemoteObject__hasClassName(self.handle)) {
27512719
return null;
27522720
}
27532721

2754-
const class_name = c.v8_inspector__RemoteObject__getClassName(handle);
2722+
const class_name = c.v8_inspector__RemoteObject__getClassName(self.handle, allocator);
2723+
if (class_name == null) {
2724+
return error.V8AllocFailed;
2725+
}
27552726
const idx = std.mem.indexOfSentinel(u8, 0, class_name);
2756-
return class_name[0..idx];
2727+
return class_name[0..idx :0];
27572728
}
2758-
fn getDescription(handle: *c.RemoteObject) ?[]const u8 {
2759-
if (!c.v8_inspector__RemoteObject__hasDescription(handle)) {
2729+
pub fn getDescription(self: RemoteObject, allocator: *std.mem.Allocator) !?[:0]const u8 {
2730+
if (!c.v8_inspector__RemoteObject__hasDescription(self.handle)) {
27602731
return null;
27612732
}
27622733

2763-
const description = c.v8_inspector__RemoteObject__getDescription(handle);
2734+
const description = c.v8_inspector__RemoteObject__getDescription(self.handle, allocator);
2735+
if (description == null) {
2736+
return error.V8AllocFailed;
2737+
}
27642738
const idx = std.mem.indexOfSentinel(u8, 0, description);
2765-
return description[0..idx];
2739+
return description[0..idx :0];
27662740
}
2767-
fn getObjectId(handle: *c.RemoteObject) ?[]const u8 {
2768-
if (!c.v8_inspector__RemoteObject__hasObjectId(handle)) {
2741+
pub fn getObjectId(self: RemoteObject, allocator: *std.mem.Allocator) !?[:0]const u8 {
2742+
if (!c.v8_inspector__RemoteObject__hasObjectId(self.handle)) {
27692743
return null;
27702744
}
27712745

2772-
const object_id = c.v8_inspector__RemoteObject__getObjectId(handle);
2746+
const object_id = c.v8_inspector__RemoteObject__getObjectId(self.handle, allocator);
2747+
if (object_id == null) {
2748+
return error.V8AllocFailed;
2749+
}
27732750
const idx = std.mem.indexOfSentinel(u8, 0, object_id);
2774-
return object_id[0..idx];
2751+
return object_id[0..idx :0];
27752752
}
27762753
};
2754+
2755+
/// Enables C to allocate using the given Zig allocator
2756+
pub export fn zigAlloc(self: *anyopaque, bytes: usize) callconv(.C) ?[*]u8 {
2757+
const allocator: *std.mem.Allocator = @ptrCast(@alignCast(self));
2758+
const allocated_bytes = allocator.alloc(u8, bytes) catch return null;
2759+
return allocated_bytes.ptr;
2760+
}

0 commit comments

Comments
 (0)