1use crate::ArrayBuffer;
2use crate::Context;
3use crate::Exception;
4use crate::Global;
5use crate::Isolate;
6use crate::Local;
7use crate::Object;
8use crate::PinScope;
9use crate::SharedArrayBuffer;
10use crate::String;
11use crate::Value;
12use crate::WasmModuleObject;
13use crate::isolate::RealIsolate;
14use crate::scope::CallbackScope;
15use crate::scope::ContextScope;
16use crate::scope::GetIsolate;
17
18use std::alloc::Layout;
19use std::alloc::alloc;
20use std::alloc::dealloc;
21use std::alloc::realloc;
22use std::mem::MaybeUninit;
23use std::pin::pin;
24use std::ptr::addr_of;
25use std::sync::atomic::AtomicUsize;
26
27use crate::support::CxxVTable;
28use crate::support::FieldOffset;
29use crate::support::MaybeBool;
30
31use std::ffi::c_void;
32use std::pin::Pin;
33
34#[repr(C)]
37pub struct CxxValueSerializerDelegate {
38 _cxx_vtable: CxxVTable,
39}
40
41#[unsafe(no_mangle)]
42unsafe extern "C" fn v8__ValueSerializer__Delegate__ThrowDataCloneError(
43 this: &CxxValueSerializerDelegate,
44 message: Local<String>,
45) {
46 let value_serializer_heap = unsafe { ValueSerializerHeap::dispatch(this) };
47 let mut isolate =
48 unsafe { Isolate::from_raw_ptr(value_serializer_heap.isolate_ptr) };
49 let scope = unsafe { CallbackScope::new(&mut isolate) };
50 let scope = pin!(scope);
51 let scope = &mut scope.init();
52 let context = Local::new(scope, &value_serializer_heap.context);
53 let mut scope = ContextScope::new(scope, context);
54 value_serializer_heap
55 .value_serializer_impl
56 .throw_data_clone_error(&mut scope, message);
57}
58
59#[unsafe(no_mangle)]
60unsafe extern "C" fn v8__ValueSerializer__Delegate__HasCustomHostObject(
61 this: &CxxValueSerializerDelegate,
62 isolate: *mut RealIsolate,
63) -> bool {
64 let value_serializer_heap = unsafe { ValueSerializerHeap::dispatch(this) };
65 let isolate = unsafe { Isolate::from_raw_ptr(isolate) };
66 value_serializer_heap
67 .value_serializer_impl
68 .has_custom_host_object(&isolate)
69}
70
71#[unsafe(no_mangle)]
72unsafe extern "C" fn v8__ValueSerializer__Delegate__IsHostObject(
73 this: &CxxValueSerializerDelegate,
74 isolate: *mut RealIsolate,
75 object: Local<Object>,
76) -> MaybeBool {
77 let value_serializer_heap = unsafe { ValueSerializerHeap::dispatch(this) };
78 let mut isolate = unsafe { Isolate::from_raw_ptr(isolate) };
79 let scope = unsafe { CallbackScope::new(&mut isolate) };
80 let scope = pin!(scope);
81 let scope = &mut scope.init();
82 let context = Local::new(scope, &value_serializer_heap.context);
83 let mut scope = ContextScope::new(scope, context);
84
85 MaybeBool::from(
86 value_serializer_heap
87 .value_serializer_impl
88 .is_host_object(&mut scope, object),
89 )
90}
91
92#[unsafe(no_mangle)]
93unsafe extern "C" fn v8__ValueSerializer__Delegate__WriteHostObject(
94 this: &CxxValueSerializerDelegate,
95 isolate: *mut RealIsolate,
96 object: Local<Object>,
97) -> MaybeBool {
98 let value_serializer_heap = unsafe { ValueSerializerHeap::dispatch(this) };
99 let mut isolate = unsafe { Isolate::from_raw_ptr(isolate) };
100 let scope = unsafe { CallbackScope::new(&mut isolate) };
101 let scope = pin!(scope);
102 let scope = &mut scope.init();
103 let context = Local::new(scope, &value_serializer_heap.context);
104 let mut scope = ContextScope::new(scope, context);
105 let value_serializer_impl =
106 value_serializer_heap.value_serializer_impl.as_ref();
107 MaybeBool::from(value_serializer_impl.write_host_object(
108 &mut scope,
109 object,
110 &value_serializer_heap.cxx_value_serializer,
111 ))
112}
113
114#[unsafe(no_mangle)]
115unsafe extern "C" fn v8__ValueSerializer__Delegate__GetSharedArrayBufferId(
116 this: &CxxValueSerializerDelegate,
117 isolate: *mut RealIsolate,
118 shared_array_buffer: Local<SharedArrayBuffer>,
119 clone_id: *mut u32,
120) -> bool {
121 let value_serializer_heap = unsafe { ValueSerializerHeap::dispatch(this) };
122 let mut isolate = unsafe { Isolate::from_raw_ptr(isolate) };
123 let scope = unsafe { CallbackScope::new(&mut isolate) };
124 let scope = pin!(scope);
125 let scope = &mut scope.init();
126 let context = Local::new(scope, &value_serializer_heap.context);
127 let mut scope = ContextScope::new(scope, context);
128 match value_serializer_heap
129 .value_serializer_impl
130 .get_shared_array_buffer_id(&mut scope, shared_array_buffer)
131 {
132 Some(x) => {
133 unsafe {
134 *clone_id = x;
135 }
136 true
137 }
138 None => false,
139 }
140}
141
142#[unsafe(no_mangle)]
143unsafe extern "C" fn v8__ValueSerializer__Delegate__GetWasmModuleTransferId(
144 this: &CxxValueSerializerDelegate,
145 isolate: *mut RealIsolate,
146 module: Local<WasmModuleObject>,
147 transfer_id: *mut u32,
148) -> bool {
149 let value_serializer_heap = unsafe { ValueSerializerHeap::dispatch(this) };
150 let mut isolate = unsafe { Isolate::from_raw_ptr(isolate) };
151 let scope = unsafe { CallbackScope::new(&mut isolate) };
152 let scope = pin!(scope);
153 let scope = &mut scope.init();
154 let context = Local::new(scope, &value_serializer_heap.context);
155 let scope = &mut ContextScope::new(scope, context);
156 match value_serializer_heap
157 .value_serializer_impl
158 .get_wasm_module_transfer_id(scope, module)
159 {
160 Some(x) => {
161 unsafe {
162 *transfer_id = x;
163 }
164 true
165 }
166 None => false,
167 }
168}
169
170#[unsafe(no_mangle)]
171unsafe extern "C" fn v8__ValueSerializer__Delegate__ReallocateBufferMemory(
172 this: &CxxValueSerializerDelegate,
173 old_buffer: *mut c_void,
174 size: usize,
175 actual_size: *mut usize,
176) -> *mut c_void {
177 let base = unsafe { ValueSerializerHeap::dispatch(this) };
178
179 let buffer_size = base
180 .buffer_size
181 .swap(size, std::sync::atomic::Ordering::Release);
182 let new_buffer = if old_buffer.is_null() {
183 let layout = Layout::from_size_align(size, 1).unwrap();
184 unsafe { alloc(layout) }
185 } else {
186 let old_layout = Layout::from_size_align(buffer_size, 1).unwrap();
187 unsafe { realloc(old_buffer as *mut _, old_layout, size) }
188 };
189
190 unsafe {
191 *actual_size = size;
192 }
193 new_buffer as *mut c_void
194}
195
196#[unsafe(no_mangle)]
197unsafe extern "C" fn v8__ValueSerializer__Delegate__FreeBufferMemory(
198 this: &mut CxxValueSerializerDelegate,
199 buffer: *mut c_void,
200) {
201 let base = unsafe { ValueSerializerHeap::dispatch(this) };
202 if !buffer.is_null() {
203 let layout = Layout::from_size_align(
204 base.buffer_size.load(std::sync::atomic::Ordering::Relaxed),
205 1,
206 )
207 .unwrap();
208 unsafe { dealloc(buffer as *mut _, layout) };
209 };
210}
211
212unsafe extern "C" {
213 fn v8__ValueSerializer__Delegate__CONSTRUCT(
214 buf: *mut MaybeUninit<CxxValueSerializerDelegate>,
215 );
216}
217
218#[repr(C)]
220pub struct CxxValueSerializer {
221 _cxx_vtable: CxxVTable,
222}
223
224unsafe extern "C" {
225 fn v8__ValueSerializer__CONSTRUCT(
226 buf: *mut MaybeUninit<CxxValueSerializer>,
227 isolate: *mut RealIsolate,
228 delegate: *mut CxxValueSerializerDelegate,
229 );
230
231 fn v8__ValueSerializer__DESTRUCT(this: *mut CxxValueSerializer);
232
233 fn v8__ValueSerializer__Release(
234 this: *mut CxxValueSerializer,
235 ptr: *mut *mut u8,
236 size: *mut usize,
237 );
238
239 fn v8__ValueSerializer__TransferArrayBuffer(
240 this: *mut CxxValueSerializer,
241 transfer_id: u32,
242 array_buffer: Local<ArrayBuffer>,
243 );
244
245 fn v8__ValueSerializer__WriteHeader(this: *mut CxxValueSerializer);
246 fn v8__ValueSerializer__WriteValue(
247 this: *mut CxxValueSerializer,
248 context: Local<Context>,
249 value: Local<Value>,
250 ) -> MaybeBool;
251 fn v8__ValueSerializer__WriteUint32(
252 this: *mut CxxValueSerializer,
253 value: u32,
254 );
255 fn v8__ValueSerializer__WriteUint64(
256 this: *mut CxxValueSerializer,
257 value: u64,
258 );
259 fn v8__ValueSerializer__WriteDouble(
260 this: *mut CxxValueSerializer,
261 value: f64,
262 );
263 fn v8__ValueSerializer__WriteRawBytes(
264 this: *mut CxxValueSerializer,
265 source: *const c_void,
266 length: usize,
267 );
268 fn v8__ValueSerializer__SetTreatArrayBufferViewsAsHostObjects(
269 this: *mut CxxValueSerializer,
270 mode: bool,
271 );
272}
273
274pub trait ValueSerializerImpl {
277 fn throw_data_clone_error<'s>(
278 &self,
279 scope: &mut PinScope<'s, '_>,
280 message: Local<'s, String>,
281 );
282
283 fn has_custom_host_object(&self, _isolate: &Isolate) -> bool {
284 false
285 }
286
287 fn is_host_object<'s>(
288 &self,
289 scope: &mut PinScope<'s, '_>,
290 _object: Local<'s, Object>,
291 ) -> Option<bool> {
292 let msg =
293 String::new(scope, "Deno serializer: is_host_object not implemented")
294 .unwrap();
295 let exc = Exception::error(scope, msg);
296 scope.throw_exception(exc);
297 None
298 }
299
300 fn write_host_object<'s>(
301 &self,
302 scope: &mut PinScope<'s, '_>,
303 _object: Local<'s, Object>,
304 _value_serializer: &dyn ValueSerializerHelper,
305 ) -> Option<bool> {
306 let msg =
307 String::new(scope, "Deno serializer: write_host_object not implemented")
308 .unwrap();
309 let exc = Exception::error(scope, msg);
310 scope.throw_exception(exc);
311 None
312 }
313
314 fn get_shared_array_buffer_id<'s>(
315 &self,
316 _scope: &mut PinScope<'s, '_>,
317 _shared_array_buffer: Local<'s, SharedArrayBuffer>,
318 ) -> Option<u32> {
319 None
320 }
321
322 fn get_wasm_module_transfer_id(
323 &self,
324 scope: &mut PinScope<'_, '_>,
325 _module: Local<WasmModuleObject>,
326 ) -> Option<u32> {
327 let msg = String::new(
328 scope,
329 "Deno serializer: get_wasm_module_transfer_id not implemented",
330 )
331 .unwrap();
332 let exc = Exception::error(scope, msg);
333 scope.throw_exception(exc);
334 None
335 }
336}
337
338pub struct ValueSerializerHeap<'a> {
346 value_serializer_impl: Box<dyn ValueSerializerImpl + 'a>,
347 cxx_value_serializer_delegate: CxxValueSerializerDelegate,
348 cxx_value_serializer: CxxValueSerializer,
349 buffer_size: AtomicUsize,
350 context: Global<Context>,
351 isolate_ptr: *mut RealIsolate,
352}
353
354impl ValueSerializerHeap<'_> {
355 fn get_cxx_value_serializer_delegate_offset()
356 -> FieldOffset<CxxValueSerializerDelegate> {
357 let buf = std::mem::MaybeUninit::<Self>::uninit();
358 let delegate =
359 unsafe { addr_of!((*buf.as_ptr()).cxx_value_serializer_delegate) };
360 FieldOffset::from_ptrs(buf.as_ptr(), delegate)
361 }
362
363 pub unsafe fn dispatch(
365 value_serializer_delegate: &CxxValueSerializerDelegate,
366 ) -> &Self {
367 unsafe {
368 Self::get_cxx_value_serializer_delegate_offset()
369 .to_embedder::<Self>(value_serializer_delegate)
370 }
371 }
372}
373
374impl Drop for ValueSerializerHeap<'_> {
375 fn drop(&mut self) {
376 unsafe { v8__ValueSerializer__DESTRUCT(&mut self.cxx_value_serializer) };
377 }
378}
379
380fn cast_to_ptr<T>(x: &T) -> *mut T {
381 x as *const T as *mut T
382}
383
384pub trait ValueSerializerHelper {
388 fn get_cxx_value_serializer(&self) -> &CxxValueSerializer;
389
390 fn write_header(&self) {
391 unsafe {
392 v8__ValueSerializer__WriteHeader(cast_to_ptr(
393 self.get_cxx_value_serializer(),
394 ));
395 };
396 }
397
398 fn write_value(
399 &self,
400 context: Local<Context>,
401 value: Local<Value>,
402 ) -> Option<bool> {
403 unsafe {
404 v8__ValueSerializer__WriteValue(
405 cast_to_ptr(self.get_cxx_value_serializer()),
406 context,
407 value,
408 )
409 }
410 .into()
411 }
412
413 fn write_uint32(&self, value: u32) {
414 unsafe {
415 v8__ValueSerializer__WriteUint32(
416 cast_to_ptr(self.get_cxx_value_serializer()),
417 value,
418 );
419 };
420 }
421
422 fn write_uint64(&self, value: u64) {
423 unsafe {
424 v8__ValueSerializer__WriteUint64(
425 cast_to_ptr(self.get_cxx_value_serializer()),
426 value,
427 );
428 };
429 }
430
431 fn write_double(&self, value: f64) {
432 unsafe {
433 v8__ValueSerializer__WriteDouble(
434 cast_to_ptr(self.get_cxx_value_serializer()),
435 value,
436 );
437 };
438 }
439
440 fn write_raw_bytes(&self, source: &[u8]) {
441 unsafe {
442 v8__ValueSerializer__WriteRawBytes(
443 cast_to_ptr(self.get_cxx_value_serializer()),
444 source.as_ptr() as *const _,
445 source.len(),
446 );
447 };
448 }
449
450 fn transfer_array_buffer(
451 &self,
452 transfer_id: u32,
453 array_buffer: Local<ArrayBuffer>,
454 ) {
455 unsafe {
456 v8__ValueSerializer__TransferArrayBuffer(
457 cast_to_ptr(self.get_cxx_value_serializer()),
458 transfer_id,
459 array_buffer,
460 );
461 };
462 }
463
464 fn set_treat_array_buffer_views_as_host_objects(&self, mode: bool) {
465 unsafe {
466 v8__ValueSerializer__SetTreatArrayBufferViewsAsHostObjects(
467 cast_to_ptr(self.get_cxx_value_serializer()),
468 mode,
469 );
470 };
471 }
472}
473
474impl ValueSerializerHelper for CxxValueSerializer {
475 fn get_cxx_value_serializer(&self) -> &CxxValueSerializer {
476 self
477 }
478}
479
480impl ValueSerializerHelper for ValueSerializerHeap<'_> {
481 fn get_cxx_value_serializer(&self) -> &CxxValueSerializer {
482 &self.cxx_value_serializer
483 }
484}
485
486impl ValueSerializerHelper for ValueSerializer<'_> {
487 fn get_cxx_value_serializer(&self) -> &CxxValueSerializer {
488 &self.value_serializer_heap.cxx_value_serializer
489 }
490}
491
492pub struct ValueSerializer<'a> {
493 value_serializer_heap: Pin<Box<ValueSerializerHeap<'a>>>,
494 _phantom: std::marker::PhantomData<*mut ()>,
497}
498
499impl<'a> ValueSerializer<'a> {
505 pub fn new<'s, 'i, D: ValueSerializerImpl + 'a>(
506 scope: &PinScope<'s, 'i>,
507 value_serializer_impl: Box<D>,
508 ) -> Self {
509 let context = scope.get_current_context();
510 let value_serializer_heap_ptr =
512 Box::into_raw(Box::new(ValueSerializerHeap {
513 value_serializer_impl,
514 cxx_value_serializer: CxxValueSerializer {
515 _cxx_vtable: CxxVTable(std::ptr::null()),
516 },
517 cxx_value_serializer_delegate: CxxValueSerializerDelegate {
518 _cxx_vtable: CxxVTable(std::ptr::null()),
519 },
520 buffer_size: AtomicUsize::new(0),
521 context: Global::new(scope, context),
522 isolate_ptr: scope.get_isolate_ptr(),
523 }));
524
525 unsafe {
526 let delegate_ptr = std::ptr::addr_of_mut!(
527 (*value_serializer_heap_ptr).cxx_value_serializer_delegate
528 );
529 let serializer_ptr = std::ptr::addr_of_mut!(
530 (*value_serializer_heap_ptr).cxx_value_serializer
531 );
532 v8__ValueSerializer__Delegate__CONSTRUCT(
533 delegate_ptr
534 .cast::<std::mem::MaybeUninit<CxxValueSerializerDelegate>>(),
535 );
536
537 v8__ValueSerializer__CONSTRUCT(
538 serializer_ptr.cast::<std::mem::MaybeUninit<CxxValueSerializer>>(),
539 scope.get_isolate_ptr(),
540 delegate_ptr,
541 );
542 };
543
544 let value_serializer_heap =
546 Pin::new(unsafe { Box::from_raw(value_serializer_heap_ptr) });
547
548 Self {
549 value_serializer_heap,
550 _phantom: std::marker::PhantomData,
551 }
552 }
553}
554
555impl ValueSerializer<'_> {
556 pub fn release(&self) -> Vec<u8> {
557 unsafe {
558 let mut size: usize = 0;
559 let mut ptr: *mut u8 = &mut 0;
560 v8__ValueSerializer__Release(
561 cast_to_ptr(self.get_cxx_value_serializer()),
562 &mut ptr,
563 &mut size,
564 );
565 let capacity = self
566 .value_serializer_heap
567 .buffer_size
568 .swap(0, std::sync::atomic::Ordering::Relaxed);
569 if ptr.is_null() {
570 return Vec::new();
571 }
572 assert!(size <= capacity);
573 Vec::from_raw_parts(ptr, size, capacity)
576 }
577 }
578
579 pub fn write_value(
580 &self,
581 context: Local<Context>,
582 value: Local<Value>,
583 ) -> Option<bool> {
584 self.value_serializer_heap.write_value(context, value)
585 }
586}