1use serde::Deserialize;
4use serde::de::SeqAccess as _;
5use serde::de::Visitor;
6use serde::de::{self};
7
8use crate::AnyValue;
9use crate::BigInt;
10use crate::ByteString;
11use crate::DetachedBuffer;
12use crate::JsBuffer;
13use crate::StringOrBuffer;
14use crate::U16String;
15use crate::error::Error;
16use crate::error::Result;
17use crate::keys::KeyCache;
18use crate::keys::v8_struct_key;
19use crate::magic;
20use crate::magic::transl8::FromV8;
21use crate::magic::transl8::MagicType;
22use crate::magic::transl8::visit_magic;
23use crate::payload::ValueType;
24
25pub struct Deserializer<'b, 's, 'i> {
26 input: v8::Local<'s, v8::Value>,
27 scope: &'b mut v8::PinScope<'s, 'i>,
28 _key_cache: Option<&'b mut KeyCache>,
29}
30
31impl<'b, 's, 'i> Deserializer<'b, 's, 'i> {
32 pub fn new(
33 scope: &'b mut v8::PinScope<'s, 'i>,
34 input: v8::Local<'s, v8::Value>,
35 key_cache: Option<&'b mut KeyCache>,
36 ) -> Self {
37 Deserializer {
38 input,
39 scope,
40 _key_cache: key_cache,
41 }
42 }
43}
44
45pub fn from_v8<'de, 'b, 's, 'i, T>(
47 scope: &'b mut v8::PinScope<'s, 'i>,
48 input: v8::Local<'s, v8::Value>,
49) -> Result<T>
50where
51 T: Deserialize<'de>,
52{
53 let mut deserializer = Deserializer::new(scope, input, None);
54 let t = T::deserialize(&mut deserializer)?;
55 Ok(t)
56}
57
58pub fn from_v8_cached<'de, 'b, 's, 'i, T>(
60 scope: &'b mut v8::PinScope<'s, 'i>,
61 input: v8::Local<'s, v8::Value>,
62 key_cache: &mut KeyCache,
63) -> Result<T>
64where
65 T: Deserialize<'de>,
66{
67 let mut deserializer = Deserializer::new(scope, input, Some(key_cache));
68 let t = T::deserialize(&mut deserializer)?;
69 Ok(t)
70}
71
72macro_rules! deserialize_signed {
73 ($dmethod:ident, $vmethod:ident, $t:tt) => {
74 fn $dmethod<V>(self, visitor: V) -> Result<V::Value>
75 where
76 V: Visitor<'de>,
77 {
78 visitor.$vmethod(
79 if let Ok(x) = v8::Local::<v8::Number>::try_from(self.input) {
80 x.value() as $t
81 } else if let Ok(x) = v8::Local::<v8::BigInt>::try_from(self.input) {
82 x.i64_value().0 as $t
83 } else {
84 return Err(Error::ExpectedInteger(self.input.type_repr()));
85 },
86 )
87 }
88 };
89}
90
91macro_rules! deserialize_unsigned {
92 ($dmethod:ident, $vmethod:ident, $t:tt) => {
93 fn $dmethod<V>(self, visitor: V) -> Result<V::Value>
94 where
95 V: Visitor<'de>,
96 {
97 visitor.$vmethod(
98 if let Ok(x) = v8::Local::<v8::Number>::try_from(self.input) {
99 x.value() as $t
100 } else if let Ok(x) = v8::Local::<v8::BigInt>::try_from(self.input) {
101 x.u64_value().0 as $t
102 } else {
103 return Err(Error::ExpectedInteger(self.input.type_repr()));
104 },
105 )
106 }
107 };
108}
109
110impl<'de> de::Deserializer<'de> for &'_ mut Deserializer<'_, '_, '_> {
111 type Error = Error;
112
113 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
114 where
115 V: Visitor<'de>,
116 {
117 match ValueType::from_v8(self.input) {
118 ValueType::Null => self.deserialize_unit(visitor),
119 ValueType::Bool => self.deserialize_bool(visitor),
120 ValueType::Number => {
122 if self.input.is_uint32() {
123 self.deserialize_u32(visitor)
124 } else if self.input.is_int32() {
125 self.deserialize_i32(visitor)
126 } else {
127 self.deserialize_f64(visitor)
128 }
129 }
130 ValueType::BigInt => Err(Error::UnsupportedType),
131 ValueType::String => self.deserialize_string(visitor),
132 ValueType::Array => self.deserialize_seq(visitor),
133 ValueType::Object => self.deserialize_map(visitor),
134 ValueType::ArrayBufferView | ValueType::ArrayBuffer => {
137 magic::v8slice::V8Slice::from_v8(&mut *self.scope, self.input)
138 .and_then(|zb| visitor.visit_byte_buf(Vec::from(&*zb)))
139 }
140 }
141 }
142
143 fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value>
144 where
145 V: Visitor<'de>,
146 {
147 visitor.visit_bool(self.input.is_true())
149 }
150
151 deserialize_signed!(deserialize_i8, visit_i8, i8);
153 deserialize_signed!(deserialize_i16, visit_i16, i16);
154 deserialize_signed!(deserialize_i32, visit_i32, i32);
155 deserialize_signed!(deserialize_i64, visit_i64, i64);
156 deserialize_unsigned!(deserialize_u8, visit_u8, u8);
158 deserialize_unsigned!(deserialize_u16, visit_u16, u16);
159 deserialize_unsigned!(deserialize_u32, visit_u32, u32);
160 deserialize_unsigned!(deserialize_u64, visit_u64, u64);
161
162 fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value>
163 where
164 V: Visitor<'de>,
165 {
166 self.deserialize_f64(visitor)
167 }
168 fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value>
169 where
170 V: Visitor<'de>,
171 {
172 visitor.visit_f64(
173 if let Ok(x) = v8::Local::<v8::Number>::try_from(self.input) {
174 x.value()
175 } else if let Ok(x) = v8::Local::<v8::BigInt>::try_from(self.input) {
176 bigint_to_f64(x)
177 } else {
178 return Err(Error::ExpectedNumber(self.input.type_repr()));
179 },
180 )
181 }
182
183 fn deserialize_char<V>(self, visitor: V) -> Result<V::Value>
184 where
185 V: Visitor<'de>,
186 {
187 self.deserialize_str(visitor)
188 }
189
190 fn deserialize_str<V>(self, visitor: V) -> Result<V::Value>
191 where
192 V: Visitor<'de>,
193 {
194 self.deserialize_string(visitor)
195 }
196
197 fn deserialize_string<V>(self, visitor: V) -> Result<V::Value>
198 where
199 V: Visitor<'de>,
200 {
201 if self.input.is_string() || self.input.is_string_object() {
202 let v8_string = self.input.to_string(self.scope).unwrap();
204 let string = to_utf8(v8_string, self.scope);
205 visitor.visit_string(string)
206 } else {
207 Err(Error::ExpectedString(self.input.type_repr()))
208 }
209 }
210
211 fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
212 where
213 V: Visitor<'de>,
214 {
215 if self.input.is_null_or_undefined() {
216 visitor.visit_none()
217 } else {
218 visitor.visit_some(self)
219 }
220 }
221
222 fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value>
223 where
224 V: Visitor<'de>,
225 {
226 visitor.visit_unit()
227 }
228
229 fn deserialize_unit_struct<V>(
230 self,
231 _name: &'static str,
232 visitor: V,
233 ) -> Result<V::Value>
234 where
235 V: Visitor<'de>,
236 {
237 self.deserialize_unit(visitor)
238 }
239
240 fn deserialize_newtype_struct<V>(
244 self,
245 _name: &'static str,
246 visitor: V,
247 ) -> Result<V::Value>
248 where
249 V: Visitor<'de>,
250 {
251 visitor.visit_newtype_struct(self)
252 }
253
254 fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value>
255 where
256 V: Visitor<'de>,
257 {
258 let arr = v8::Local::<v8::Array>::try_from(self.input)
259 .map_err(|_| Error::ExpectedArray(self.input.type_repr()))?;
260 visitor.visit_seq(SeqAccess::new(arr.into(), self.scope, 0..arr.length()))
261 }
262
263 fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value>
265 where
266 V: Visitor<'de>,
267 {
268 let obj = v8::Local::<v8::Object>::try_from(self.input)
269 .map_err(|_| Error::ExpectedObject(self.input.type_repr()))?;
270 if let Ok(array) = v8::Local::<v8::Array>::try_from(obj) {
271 let array_len = array.length() as usize;
273 if array_len != len {
274 return Err(Error::LengthMismatch(array_len, len));
275 }
276 }
277 visitor.visit_seq(SeqAccess::new(obj, self.scope, 0..len as u32))
278 }
279
280 fn deserialize_tuple_struct<V>(
282 self,
283 _name: &'static str,
284 len: usize,
285 visitor: V,
286 ) -> Result<V::Value>
287 where
288 V: Visitor<'de>,
289 {
290 self.deserialize_tuple(len, visitor)
291 }
292
293 fn deserialize_map<V>(self, visitor: V) -> Result<V::Value>
294 where
295 V: de::Visitor<'de>,
296 {
297 let obj = v8::Local::<v8::Object>::try_from(self.input)
299 .map_err(|_| Error::ExpectedObject(self.input.type_repr()))?;
300
301 if let Ok(map) = v8::Local::<v8::Map>::try_from(self.input) {
302 let pairs_array = map.as_array(self.scope);
303 let map = MapPairsAccess {
304 pos: 0,
305 len: pairs_array.length(),
306 obj: pairs_array,
307 scope: self.scope,
308 };
309 visitor.visit_map(map)
310 } else {
311 visitor.visit_map(MapObjectAccess::new(obj, self.scope))
312 }
313 }
314
315 fn deserialize_struct<V>(
316 self,
317 name: &'static str,
318 fields: &'static [&'static str],
319 visitor: V,
320 ) -> Result<V::Value>
321 where
322 V: Visitor<'de>,
323 {
324 match name {
325 JsBuffer::MAGIC_NAME => {
326 visit_magic(visitor, JsBuffer::from_v8(self.scope, self.input)?)
327 }
328 DetachedBuffer::MAGIC_NAME => {
329 visit_magic(visitor, DetachedBuffer::from_v8(self.scope, self.input)?)
330 }
331 ByteString::MAGIC_NAME => {
332 visit_magic(visitor, ByteString::from_v8(self.scope, self.input)?)
333 }
334 U16String::MAGIC_NAME => {
335 visit_magic(visitor, U16String::from_v8(self.scope, self.input)?)
336 }
337 StringOrBuffer::MAGIC_NAME => {
338 visit_magic(visitor, StringOrBuffer::from_v8(self.scope, self.input)?)
339 }
340 BigInt::MAGIC_NAME => {
341 visit_magic(visitor, BigInt::from_v8(self.scope, self.input)?)
342 }
343 magic::GlobalValue::MAGIC_NAME => visit_magic(
344 visitor,
345 magic::GlobalValue::from_v8(self.scope, self.input)?,
346 ),
347 magic::Value::MAGIC_NAME => {
348 visit_magic(visitor, magic::Value::from_v8(self.scope, self.input)?)
349 }
350 AnyValue::MAGIC_NAME => {
351 visit_magic(visitor, AnyValue::from_v8(self.scope, self.input)?)
352 }
353 _ => {
354 let obj = v8::Local::<v8::Object>::try_from(self.input)
356 .map_err(|_| Error::ExpectedObject(self.input.type_repr()))?;
357
358 if fields.is_empty() {
360 visitor.visit_map(MapObjectAccess::new(obj, self.scope))
361 } else {
362 visitor.visit_map(StructAccess {
363 obj,
364 scope: self.scope,
365 keys: fields.iter(),
366 next_value: None,
367 })
368 }
369 }
370 }
371 }
372
373 fn deserialize_enum<V>(
377 self,
378 _name: &str,
379 _variants: &'static [&'static str],
380 visitor: V,
381 ) -> Result<V::Value>
382 where
383 V: Visitor<'de>,
384 {
385 if self.input.is_string() || self.input.is_string_object() {
387 let payload = v8::undefined(self.scope).into();
388 visitor.visit_enum(EnumAccess {
389 scope: self.scope,
390 tag: self.input,
391 payload,
392 })
393 }
394 else if let Ok(obj) = v8::Local::<v8::Object>::try_from(self.input) {
396 let tag = {
398 let prop_names =
399 obj.get_own_property_names(self.scope, Default::default());
400 let prop_names = prop_names
401 .ok_or_else(|| Error::ExpectedEnum(self.input.type_repr()))?;
402 let prop_names_len = prop_names.length();
403 if prop_names_len != 1 {
404 return Err(Error::LengthMismatch(prop_names_len as usize, 1));
405 }
406 prop_names.get_index(self.scope, 0).unwrap()
408 };
409
410 let payload = obj.get(self.scope, tag).unwrap();
412 visitor.visit_enum(EnumAccess {
413 scope: self.scope,
414 tag,
415 payload,
416 })
417 } else {
418 Err(Error::ExpectedEnum(self.input.type_repr()))
419 }
420 }
421
422 fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value>
427 where
428 V: Visitor<'de>,
429 {
430 self.deserialize_str(visitor)
431 }
432
433 fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value>
434 where
435 V: Visitor<'de>,
436 {
437 visitor.visit_none()
438 }
439
440 fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value>
441 where
442 V: Visitor<'de>,
443 {
444 magic::buffer::JsBuffer::from_v8(self.scope, self.input)
445 .and_then(|zb| visitor.visit_bytes(&zb))
446 }
447
448 fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value>
449 where
450 V: Visitor<'de>,
451 {
452 magic::buffer::JsBuffer::from_v8(self.scope, self.input)
453 .and_then(|zb| visitor.visit_byte_buf(Vec::from(&*zb)))
454 }
455}
456
457struct MapObjectAccess<'a, 's, 'i> {
458 obj: v8::Local<'a, v8::Object>,
459 keys: SeqAccess<'a, 's, 'i>,
460 next_value: Option<v8::Local<'s, v8::Value>>,
461}
462
463impl<'a, 's, 'i> MapObjectAccess<'a, 's, 'i> {
464 pub fn new(
465 obj: v8::Local<'a, v8::Object>,
466 scope: &'a mut v8::PinScope<'s, 'i>,
467 ) -> Self {
468 let keys = match obj.get_own_property_names(
469 scope,
470 v8::GetPropertyNamesArgsBuilder::new()
471 .key_conversion(v8::KeyConversionMode::ConvertToString)
472 .build(),
473 ) {
474 Some(keys) => SeqAccess::new(keys.into(), scope, 0..keys.length()),
475 None => SeqAccess::new(obj, scope, 0..0),
476 };
477
478 Self {
479 obj,
480 keys,
481 next_value: None,
482 }
483 }
484}
485
486impl<'de> de::MapAccess<'de> for MapObjectAccess<'_, '_, '_> {
487 type Error = Error;
488
489 fn next_key_seed<K: de::DeserializeSeed<'de>>(
490 &mut self,
491 seed: K,
492 ) -> Result<Option<K::Value>> {
493 while let Some(key) = self.keys.next_element::<magic::Value>()? {
494 let v8_val = self.obj.get(self.keys.scope, key.v8_value).unwrap();
495 if v8_val.is_undefined() {
496 continue;
498 }
499 self.next_value = Some(v8_val);
500 let mut deserializer =
501 Deserializer::new(self.keys.scope, key.v8_value, None);
502 return seed.deserialize(&mut deserializer).map(Some);
503 }
504 Ok(None)
505 }
506
507 fn next_value_seed<V: de::DeserializeSeed<'de>>(
508 &mut self,
509 seed: V,
510 ) -> Result<V::Value> {
511 let v8_val = self
512 .next_value
513 .take()
514 .expect("Call next_key_seed before next_value_seed");
515 let mut deserializer = Deserializer::new(self.keys.scope, v8_val, None);
516 seed.deserialize(&mut deserializer)
517 }
518
519 fn size_hint(&self) -> Option<usize> {
520 self.keys.size_hint()
521 }
522}
523
524struct MapPairsAccess<'a, 's, 'i> {
525 obj: v8::Local<'a, v8::Array>,
526 pos: u32,
527 len: u32,
528 scope: &'a mut v8::PinScope<'s, 'i>,
529}
530
531impl<'de> de::MapAccess<'de> for MapPairsAccess<'_, '_, '_> {
532 type Error = Error;
533
534 fn next_key_seed<K: de::DeserializeSeed<'de>>(
535 &mut self,
536 seed: K,
537 ) -> Result<Option<K::Value>> {
538 if self.pos < self.len {
539 let v8_key = self.obj.get_index(self.scope, self.pos).unwrap();
540 self.pos += 1;
541 let mut deserializer = Deserializer::new(self.scope, v8_key, None);
542 let k = seed.deserialize(&mut deserializer)?;
543 Ok(Some(k))
544 } else {
545 Ok(None)
546 }
547 }
548
549 fn next_value_seed<V: de::DeserializeSeed<'de>>(
550 &mut self,
551 seed: V,
552 ) -> Result<V::Value> {
553 debug_assert!(self.pos < self.len);
554 let v8_val = self.obj.get_index(self.scope, self.pos).unwrap();
555 self.pos += 1;
556 let mut deserializer = Deserializer::new(self.scope, v8_val, None);
557 seed.deserialize(&mut deserializer)
558 }
559
560 fn size_hint(&self) -> Option<usize> {
561 Some((self.len - self.pos) as usize / 2)
562 }
563}
564
565struct StructAccess<'a, 's, 'i> {
566 obj: v8::Local<'a, v8::Object>,
567 scope: &'a mut v8::PinScope<'s, 'i>,
568 keys: std::slice::Iter<'static, &'static str>,
569 next_value: Option<v8::Local<'s, v8::Value>>,
570}
571
572impl<'de> de::MapAccess<'de> for StructAccess<'_, '_, '_> {
573 type Error = Error;
574
575 fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
576 where
577 K: de::DeserializeSeed<'de>,
578 {
579 for field in self.keys.by_ref() {
580 let key = v8_struct_key(self.scope, field).into();
581 let val = self.obj.get(self.scope, key).unwrap();
582 if val.is_undefined() {
583 continue;
585 }
586 self.next_value = Some(val);
587 let mut deserializer = Deserializer::new(self.scope, key, None);
588 return seed.deserialize(&mut deserializer).map(Some);
589 }
590 Ok(None)
591 }
592
593 fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
594 where
595 V: de::DeserializeSeed<'de>,
596 {
597 let val = self
598 .next_value
599 .take()
600 .expect("Call next_key_seed before next_value_seed");
601 let mut deserializer = Deserializer::new(self.scope, val, None);
602 seed.deserialize(&mut deserializer)
603 }
604}
605
606struct SeqAccess<'a, 's, 'i> {
607 obj: v8::Local<'a, v8::Object>,
608 scope: &'a mut v8::PinScope<'s, 'i>,
609 range: std::ops::Range<u32>,
610}
611
612impl<'a, 's, 'i> SeqAccess<'a, 's, 'i> {
613 pub fn new(
614 obj: v8::Local<'a, v8::Object>,
615 scope: &'a mut v8::PinScope<'s, 'i>,
616 range: std::ops::Range<u32>,
617 ) -> Self {
618 Self { obj, scope, range }
619 }
620}
621
622impl<'de> de::SeqAccess<'de> for SeqAccess<'_, '_, '_> {
623 type Error = Error;
624
625 fn next_element_seed<T: de::DeserializeSeed<'de>>(
626 &mut self,
627 seed: T,
628 ) -> Result<Option<T::Value>> {
629 if let Some(pos) = self.range.next() {
630 let val = self.obj.get_index(self.scope, pos).unwrap();
632 let mut deserializer = Deserializer::new(self.scope, val, None);
633 seed.deserialize(&mut deserializer).map(Some)
634 } else {
635 Ok(None)
636 }
637 }
638
639 fn size_hint(&self) -> Option<usize> {
640 self.range.size_hint().1
641 }
642}
643
644struct EnumAccess<'b, 's, 'i> {
645 tag: v8::Local<'s, v8::Value>,
646 payload: v8::Local<'s, v8::Value>,
647 scope: &'b mut v8::PinScope<'s, 'i>,
648 }
650
651impl<'de, 'b, 's, 'i> de::EnumAccess<'de> for EnumAccess<'b, 's, 'i> {
652 type Error = Error;
653 type Variant = VariantDeserializer<'b, 's, 'i>;
654
655 fn variant_seed<V: de::DeserializeSeed<'de>>(
656 self,
657 seed: V,
658 ) -> Result<(V::Value, Self::Variant)> {
659 let seed = {
660 let mut dtag = Deserializer::new(self.scope, self.tag, None);
661 seed.deserialize(&mut dtag)
662 };
663 let dpayload = VariantDeserializer::<'b, 's, 'i> {
664 scope: self.scope,
665 value: self.payload,
666 };
667
668 Ok((seed?, dpayload))
669 }
670}
671
672struct VariantDeserializer<'b, 's, 'i> {
673 value: v8::Local<'s, v8::Value>,
674 scope: &'b mut v8::PinScope<'s, 'i>,
675}
676
677impl<'de> de::VariantAccess<'de> for VariantDeserializer<'_, '_, '_> {
678 type Error = Error;
679
680 fn unit_variant(self) -> Result<()> {
681 let mut d = Deserializer::new(self.scope, self.value, None);
682 de::Deserialize::deserialize(&mut d)
683 }
684
685 fn newtype_variant_seed<T: de::DeserializeSeed<'de>>(
686 self,
687 seed: T,
688 ) -> Result<T::Value> {
689 let mut d = Deserializer::new(self.scope, self.value, None);
690 seed.deserialize(&mut d)
691 }
692
693 fn tuple_variant<V: de::Visitor<'de>>(
694 self,
695 len: usize,
696 visitor: V,
697 ) -> Result<V::Value> {
698 let mut d = Deserializer::new(self.scope, self.value, None);
699 de::Deserializer::deserialize_tuple(&mut d, len, visitor)
700 }
701
702 fn struct_variant<V: de::Visitor<'de>>(
703 self,
704 fields: &'static [&'static str],
705 visitor: V,
706 ) -> Result<V::Value> {
707 let mut d = Deserializer::new(self.scope, self.value, None);
708 de::Deserializer::deserialize_struct(&mut d, "", fields, visitor)
709 }
710}
711
712fn bigint_to_f64(b: v8::Local<v8::BigInt>) -> f64 {
713 let mut words: [u64; 16] = [0; 16]; let (neg, words) = b.to_words_array(&mut words);
716 if b.word_count() > 16 {
717 return match neg {
718 true => f64::NEG_INFINITY,
719 false => f64::INFINITY,
720 };
721 }
722 let sign = if neg { -1.0 } else { 1.0 };
723 let x: f64 = words
724 .iter()
725 .enumerate()
726 .map(|(i, w)| (*w as f64) * 2.0f64.powi(64 * i as i32))
727 .sum();
728 sign * x
729}
730
731pub fn to_utf8(s: v8::Local<v8::String>, scope: &mut v8::PinScope) -> String {
732 to_utf8_fast(s, scope).unwrap_or_else(|| to_utf8_slow(s, scope))
733}
734
735fn to_utf8_fast(
736 s: v8::Local<v8::String>,
737 scope: &mut v8::PinScope,
738) -> Option<String> {
739 let str_chars = s.length();
741 let capacity = (str_chars as f64 * 1.2) as usize;
742 let mut buf = Vec::with_capacity(capacity);
743
744 let mut nchars = 0;
745 let bytes_len = s.write_utf8_uninit_v2(
746 scope,
747 buf.spare_capacity_mut(),
748 v8::WriteFlags::kReplaceInvalidUtf8,
749 Some(&mut nchars),
750 );
751
752 if nchars < str_chars {
753 return None;
754 }
755
756 unsafe {
758 buf.set_len(bytes_len);
759 Some(String::from_utf8_unchecked(buf))
760 }
761}
762
763fn to_utf8_slow(s: v8::Local<v8::String>, scope: &mut v8::PinScope) -> String {
764 let capacity = s.utf8_length(scope);
765 let mut buf = Vec::with_capacity(capacity);
766
767 s.write_utf8_uninit_v2(
768 scope,
769 buf.spare_capacity_mut(),
770 v8::WriteFlags::kReplaceInvalidUtf8,
771 None,
772 );
773
774 unsafe {
776 buf.set_len(capacity);
777 String::from_utf8_unchecked(buf)
778 }
779}