mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-03-31 17:39:46 +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);
|
return js.String.toSliceWithAlloc(.{ .local = local, .handle = str_handle }, allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Currently does not support host objects (Blob, File, etc.) or transferables
|
// Throws a DataCloneError for host objects (Blob, File, etc.) that cannot be serialized.
|
||||||
// which require delegate callbacks to be implemented.
|
// Does not support transferables which require additional delegate callbacks.
|
||||||
pub fn structuredClone(self: Value) !Value {
|
pub fn structuredClone(self: Value) !Value {
|
||||||
const local = self.local;
|
const local = self.local;
|
||||||
const v8_context = local.handle;
|
const v8_context = local.handle;
|
||||||
const v8_isolate = local.isolate.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 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);
|
defer v8.v8__ValueSerializer__DELETE(serializer);
|
||||||
|
|
||||||
var write_result: v8.MaybeBool = undefined;
|
var write_result: v8.MaybeBool = undefined;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<script src="../testing.js"></script>
|
<script src="../testing.js"></script>
|
||||||
|
<body></body>
|
||||||
|
|
||||||
<script id=window>
|
<script id=window>
|
||||||
testing.expectEqual(window, globalThis);
|
testing.expectEqual(window, globalThis);
|
||||||
@@ -260,6 +261,28 @@
|
|||||||
}
|
}
|
||||||
testing.expectEqual(true, threw);
|
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>
|
||||||
|
|
||||||
<script id=cached_getter_wrong_this>
|
<script id=cached_getter_wrong_this>
|
||||||
|
|||||||
Reference in New Issue
Block a user