diff --git a/src/browser/js/Value.zig b/src/browser/js/Value.zig
index 309bdb6b..8e05690b 100644
--- a/src/browser/js/Value.zig
+++ b/src/browser/js/Value.zig
@@ -245,6 +245,46 @@ pub fn toJson(self: Value, allocator: Allocator) ![]u8 {
return js.String.toSliceWithAlloc(.{ .local = local, .handle = str_handle }, allocator);
}
+// Currently does not support host objects (Blob, File, etc.) or transferables
+// which require delegate callbacks to be implemented.
+pub fn structuredClone(self: Value) !Value {
+ const local = self.local;
+ const v8_context = local.handle;
+ const v8_isolate = local.isolate.handle;
+
+ const size, const data = blk: {
+ const serializer = v8.v8__ValueSerializer__New(v8_isolate, null) orelse return error.JsException;
+ defer v8.v8__ValueSerializer__DELETE(serializer);
+
+ var write_result: v8.MaybeBool = undefined;
+ v8.v8__ValueSerializer__WriteHeader(serializer);
+ v8.v8__ValueSerializer__WriteValue(serializer, v8_context, self.handle, &write_result);
+ if (!write_result.has_value or !write_result.value) {
+ return error.JsException;
+ }
+
+ var size: usize = undefined;
+ const data = v8.v8__ValueSerializer__Release(serializer, &size) orelse return error.JsException;
+ break :blk .{ size, data };
+ };
+
+ defer v8.v8__ValueSerializer__FreeBuffer(data);
+
+ const cloned_handle = blk: {
+ const deserializer = v8.v8__ValueDeserializer__New(v8_isolate, data, size, null) orelse return error.JsException;
+ defer v8.v8__ValueDeserializer__DELETE(deserializer);
+
+ var read_header_result: v8.MaybeBool = undefined;
+ v8.v8__ValueDeserializer__ReadHeader(deserializer, v8_context, &read_header_result);
+ if (!read_header_result.has_value or !read_header_result.value) {
+ return error.JsException;
+ }
+ break :blk v8.v8__ValueDeserializer__ReadValue(deserializer, v8_context) orelse return error.JsException;
+ };
+
+ return .{ .local = local, .handle = cloned_handle };
+}
+
pub fn persist(self: Value) !Global {
return self._persist(true);
}
diff --git a/src/browser/tests/window/window.html b/src/browser/tests/window/window.html
index 5506e327..01025b86 100644
--- a/src/browser/tests/window/window.html
+++ b/src/browser/tests/window/window.html
@@ -125,6 +125,143 @@
testing.expectEqual(screen, window.screen);
+
+