mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-03-31 09:29:42 +00:00
Provide a failing callback to ValueSerializer for host objects
V8 needs our help when serializing host (e.g. a Zig dom instance) objects. We don't currently have this implemented, so this provides the callback that throws an error. Our wrapper returns Nothing when no callback is provided, which v8 doesn't allow (via assertion).
This commit is contained in:
@@ -245,15 +245,37 @@ 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.
|
||||
// Throws a DataCloneError for host objects (Blob, File, etc.) that cannot be serialized.
|
||||
// Does not support transferables which require additional delegate callbacks.
|
||||
pub fn structuredClone(self: Value) !Value {
|
||||
const local = self.local;
|
||||
const v8_context = local.handle;
|
||||
const v8_isolate = local.isolate.handle;
|
||||
|
||||
const SerializerDelegate = struct {
|
||||
// Called when V8 encounters a host object it doesn't know how to serialize.
|
||||
// Returns false to indicate the object cannot be cloned, and throws a DataCloneError.
|
||||
// V8 asserts has_exception() after this returns false, so we must throw here.
|
||||
fn writeHostObject(_: ?*anyopaque, isolate: ?*v8.Isolate, _: ?*const v8.Object) callconv(.c) v8.MaybeBool {
|
||||
const iso = isolate orelse return .{ .has_value = true, .value = false };
|
||||
const message = v8.v8__String__NewFromUtf8(iso, "The object cannot be cloned.", v8.kNormal, -1);
|
||||
const error_value = v8.v8__Exception__Error(message) orelse return .{ .has_value = true, .value = false };
|
||||
_ = v8.v8__Isolate__ThrowException(iso, error_value);
|
||||
return .{ .has_value = true, .value = false };
|
||||
}
|
||||
|
||||
// Called by V8 to report serialization errors. The exception should already be thrown.
|
||||
fn throwDataCloneError(_: ?*anyopaque, _: ?*const v8.String) callconv(.c) void {}
|
||||
};
|
||||
|
||||
const size, const data = blk: {
|
||||
const serializer = v8.v8__ValueSerializer__New(v8_isolate, null) orelse return error.JsException;
|
||||
const serializer = v8.v8__ValueSerializer__New(v8_isolate, &.{
|
||||
.data = null,
|
||||
.get_shared_array_buffer_id = null,
|
||||
.write_host_object = SerializerDelegate.writeHostObject,
|
||||
.throw_data_clone_error = SerializerDelegate.throwDataCloneError,
|
||||
}) orelse return error.JsException;
|
||||
|
||||
defer v8.v8__ValueSerializer__DELETE(serializer);
|
||||
|
||||
var write_result: v8.MaybeBool = undefined;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<!DOCTYPE html>
|
||||
<script src="../testing.js"></script>
|
||||
<body></body>
|
||||
|
||||
<script id=window>
|
||||
testing.expectEqual(window, globalThis);
|
||||
@@ -260,6 +261,28 @@
|
||||
}
|
||||
testing.expectEqual(true, threw);
|
||||
}
|
||||
|
||||
// Host objects (DOM elements) cannot be cloned - should throw, not crash
|
||||
{
|
||||
let threw = false;
|
||||
try {
|
||||
structuredClone(document.body);
|
||||
} catch (err) {
|
||||
threw = true;
|
||||
}
|
||||
testing.expectEqual(true, threw);
|
||||
}
|
||||
|
||||
// Objects containing host objects cannot be cloned - should throw, not crash
|
||||
{
|
||||
let threw = false;
|
||||
try {
|
||||
structuredClone({ element: document.body });
|
||||
} catch (err) {
|
||||
threw = true;
|
||||
}
|
||||
testing.expectEqual(true, threw);
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id=cached_getter_wrong_this>
|
||||
|
||||
Reference in New Issue
Block a user