V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
value-serializer.cc
1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/value-serializer.h"
6 
7 #include <type_traits>
8 
9 #include "include/v8-value-serializer-version.h"
10 #include "src/api-inl.h"
11 #include "src/base/logging.h"
12 #include "src/conversions.h"
13 #include "src/flags.h"
14 #include "src/handles-inl.h"
15 #include "src/heap/factory.h"
16 #include "src/isolate.h"
17 #include "src/maybe-handles-inl.h"
18 #include "src/objects-inl.h"
19 #include "src/objects/js-array-inl.h"
20 #include "src/objects/js-collection-inl.h"
21 #include "src/objects/js-regexp-inl.h"
22 #include "src/objects/ordered-hash-table-inl.h"
23 #include "src/objects/smi.h"
24 #include "src/snapshot/code-serializer.h"
25 #include "src/transitions.h"
26 #include "src/wasm/wasm-engine.h"
27 #include "src/wasm/wasm-objects-inl.h"
28 #include "src/wasm/wasm-result.h"
29 #include "src/wasm/wasm-serialization.h"
30 
31 namespace v8 {
32 namespace internal {
33 
34 // Version 9: (imported from Blink)
35 // Version 10: one-byte (Latin-1) strings
36 // Version 11: properly separate undefined from the hole in arrays
37 // Version 12: regexp and string objects share normal string encoding
38 // Version 13: host objects have an explicit tag (rather than handling all
39 // unknown tags)
40 //
41 // WARNING: Increasing this value is a change which cannot safely be rolled
42 // back without breaking compatibility with data stored on disk. It is
43 // strongly recommended that you do not make such changes near a release
44 // milestone branch point.
45 //
46 // Recent changes are routinely reverted in preparation for branch, and this
47 // has been the cause of at least one bug in the past.
48 static const uint32_t kLatestVersion = 13;
49 static_assert(kLatestVersion == v8::CurrentValueSerializerFormatVersion(),
50  "Exported format version must match latest version.");
51 
52 static const int kPretenureThreshold = 100 * KB;
53 
54 template <typename T>
55 static size_t BytesNeededForVarint(T value) {
56  static_assert(std::is_integral<T>::value && std::is_unsigned<T>::value,
57  "Only unsigned integer types can be written as varints.");
58  size_t result = 0;
59  do {
60  result++;
61  value >>= 7;
62  } while (value);
63  return result;
64 }
65 
66 // Note that some additional tag values are defined in Blink's
67 // Source/bindings/core/v8/serialization/SerializationTag.h, which must
68 // not clash with values defined here.
69 enum class SerializationTag : uint8_t {
70  // version:uint32_t (if at beginning of data, sets version > 0)
71  kVersion = 0xFF,
72  // ignore
73  kPadding = '\0',
74  // refTableSize:uint32_t (previously used for sanity checks; safe to ignore)
75  kVerifyObjectCount = '?',
76  // Oddballs (no data).
77  kTheHole = '-',
78  kUndefined = '_',
79  kNull = '0',
80  kTrue = 'T',
81  kFalse = 'F',
82  // Number represented as 32-bit integer, ZigZag-encoded
83  // (like sint32 in protobuf)
84  kInt32 = 'I',
85  // Number represented as 32-bit unsigned integer, varint-encoded
86  // (like uint32 in protobuf)
87  kUint32 = 'U',
88  // Number represented as a 64-bit double.
89  // Host byte order is used (N.B. this makes the format non-portable).
90  kDouble = 'N',
91  // BigInt. Bitfield:uint32_t, then raw digits storage.
92  kBigInt = 'Z',
93  // byteLength:uint32_t, then raw data
94  kUtf8String = 'S',
95  kOneByteString = '"',
96  kTwoByteString = 'c',
97  // Reference to a serialized object. objectID:uint32_t
98  kObjectReference = '^',
99  // Beginning of a JS object.
100  kBeginJSObject = 'o',
101  // End of a JS object. numProperties:uint32_t
102  kEndJSObject = '{',
103  // Beginning of a sparse JS array. length:uint32_t
104  // Elements and properties are written as key/value pairs, like objects.
105  kBeginSparseJSArray = 'a',
106  // End of a sparse JS array. numProperties:uint32_t length:uint32_t
107  kEndSparseJSArray = '@',
108  // Beginning of a dense JS array. length:uint32_t
109  // |length| elements, followed by properties as key/value pairs
110  kBeginDenseJSArray = 'A',
111  // End of a dense JS array. numProperties:uint32_t length:uint32_t
112  kEndDenseJSArray = '$',
113  // Date. millisSinceEpoch:double
114  kDate = 'D',
115  // Boolean object. No data.
116  kTrueObject = 'y',
117  kFalseObject = 'x',
118  // Number object. value:double
119  kNumberObject = 'n',
120  // BigInt object. Bitfield:uint32_t, then raw digits storage.
121  kBigIntObject = 'z',
122  // String object, UTF-8 encoding. byteLength:uint32_t, then raw data.
123  kStringObject = 's',
124  // Regular expression, UTF-8 encoding. byteLength:uint32_t, raw data,
125  // flags:uint32_t.
126  kRegExp = 'R',
127  // Beginning of a JS map.
128  kBeginJSMap = ';',
129  // End of a JS map. length:uint32_t.
130  kEndJSMap = ':',
131  // Beginning of a JS set.
132  kBeginJSSet = '\'',
133  // End of a JS set. length:uint32_t.
134  kEndJSSet = ',',
135  // Array buffer. byteLength:uint32_t, then raw data.
136  kArrayBuffer = 'B',
137  // Array buffer (transferred). transferID:uint32_t
138  kArrayBufferTransfer = 't',
139  // View into an array buffer.
140  // subtag:ArrayBufferViewTag, byteOffset:uint32_t, byteLength:uint32_t
141  // For typed arrays, byteOffset and byteLength must be divisible by the size
142  // of the element.
143  // Note: kArrayBufferView is special, and should have an ArrayBuffer (or an
144  // ObjectReference to one) serialized just before it. This is a quirk arising
145  // from the previous stack-based implementation.
146  kArrayBufferView = 'V',
147  // Shared array buffer. transferID:uint32_t
148  kSharedArrayBuffer = 'u',
149  // Compiled WebAssembly module. encodingType:(one-byte tag).
150  // If encodingType == 'y' (raw bytes):
151  // wasmWireByteLength:uint32_t, then raw data
152  // compiledDataLength:uint32_t, then raw data
153  kWasmModule = 'W',
154  // A wasm module object transfer. next value is its index.
155  kWasmModuleTransfer = 'w',
156  // The delegate is responsible for processing all following data.
157  // This "escapes" to whatever wire format the delegate chooses.
158  kHostObject = '\\',
159  // A transferred WebAssembly.Memory object. maximumPages:int32_t, then by
160  // SharedArrayBuffer tag and its data.
161  kWasmMemoryTransfer = 'm',
162 };
163 
164 namespace {
165 
166 enum class ArrayBufferViewTag : uint8_t {
167  kInt8Array = 'b',
168  kUint8Array = 'B',
169  kUint8ClampedArray = 'C',
170  kInt16Array = 'w',
171  kUint16Array = 'W',
172  kInt32Array = 'd',
173  kUint32Array = 'D',
174  kFloat32Array = 'f',
175  kFloat64Array = 'F',
176  kBigInt64Array = 'q',
177  kBigUint64Array = 'Q',
178  kDataView = '?',
179 };
180 
181 enum class WasmEncodingTag : uint8_t {
182  kRawBytes = 'y',
183 };
184 
185 } // namespace
186 
187 ValueSerializer::ValueSerializer(Isolate* isolate,
189  : isolate_(isolate),
190  delegate_(delegate),
191  zone_(isolate->allocator(), ZONE_NAME),
192  id_map_(isolate->heap(), ZoneAllocationPolicy(&zone_)),
193  array_buffer_transfer_map_(isolate->heap(),
194  ZoneAllocationPolicy(&zone_)) {}
195 
196 ValueSerializer::~ValueSerializer() {
197  if (buffer_) {
198  if (delegate_) {
199  delegate_->FreeBufferMemory(buffer_);
200  } else {
201  free(buffer_);
202  }
203  }
204 }
205 
206 void ValueSerializer::WriteHeader() {
207  WriteTag(SerializationTag::kVersion);
208  WriteVarint(kLatestVersion);
209 }
210 
211 void ValueSerializer::SetTreatArrayBufferViewsAsHostObjects(bool mode) {
212  treat_array_buffer_views_as_host_objects_ = mode;
213 }
214 
215 void ValueSerializer::WriteTag(SerializationTag tag) {
216  uint8_t raw_tag = static_cast<uint8_t>(tag);
217  WriteRawBytes(&raw_tag, sizeof(raw_tag));
218 }
219 
220 template <typename T>
221 void ValueSerializer::WriteVarint(T value) {
222  // Writes an unsigned integer as a base-128 varint.
223  // The number is written, 7 bits at a time, from the least significant to the
224  // most significant 7 bits. Each byte, except the last, has the MSB set.
225  // See also https://developers.google.com/protocol-buffers/docs/encoding
226  static_assert(std::is_integral<T>::value && std::is_unsigned<T>::value,
227  "Only unsigned integer types can be written as varints.");
228  uint8_t stack_buffer[sizeof(T) * 8 / 7 + 1];
229  uint8_t* next_byte = &stack_buffer[0];
230  do {
231  *next_byte = (value & 0x7F) | 0x80;
232  next_byte++;
233  value >>= 7;
234  } while (value);
235  *(next_byte - 1) &= 0x7F;
236  WriteRawBytes(stack_buffer, next_byte - stack_buffer);
237 }
238 
239 template <typename T>
240 void ValueSerializer::WriteZigZag(T value) {
241  // Writes a signed integer as a varint using ZigZag encoding (i.e. 0 is
242  // encoded as 0, -1 as 1, 1 as 2, -2 as 3, and so on).
243  // See also https://developers.google.com/protocol-buffers/docs/encoding
244  // Note that this implementation relies on the right shift being arithmetic.
245  static_assert(std::is_integral<T>::value && std::is_signed<T>::value,
246  "Only signed integer types can be written as zigzag.");
247  using UnsignedT = typename std::make_unsigned<T>::type;
248  WriteVarint((static_cast<UnsignedT>(value) << 1) ^
249  (value >> (8 * sizeof(T) - 1)));
250 }
251 
252 void ValueSerializer::WriteDouble(double value) {
253  // Warning: this uses host endianness.
254  WriteRawBytes(&value, sizeof(value));
255 }
256 
257 void ValueSerializer::WriteOneByteString(Vector<const uint8_t> chars) {
258  WriteVarint<uint32_t>(chars.length());
259  WriteRawBytes(chars.begin(), chars.length() * sizeof(uint8_t));
260 }
261 
262 void ValueSerializer::WriteTwoByteString(Vector<const uc16> chars) {
263  // Warning: this uses host endianness.
264  WriteVarint<uint32_t>(chars.length() * sizeof(uc16));
265  WriteRawBytes(chars.begin(), chars.length() * sizeof(uc16));
266 }
267 
268 void ValueSerializer::WriteBigIntContents(BigInt* bigint) {
269  uint32_t bitfield = bigint->GetBitfieldForSerialization();
270  int bytelength = BigInt::DigitsByteLengthForBitfield(bitfield);
271  WriteVarint<uint32_t>(bitfield);
272  uint8_t* dest;
273  if (ReserveRawBytes(bytelength).To(&dest)) {
274  bigint->SerializeDigits(dest);
275  }
276 }
277 
278 void ValueSerializer::WriteRawBytes(const void* source, size_t length) {
279  uint8_t* dest;
280  if (ReserveRawBytes(length).To(&dest)) {
281  memcpy(dest, source, length);
282  }
283 }
284 
285 Maybe<uint8_t*> ValueSerializer::ReserveRawBytes(size_t bytes) {
286  size_t old_size = buffer_size_;
287  size_t new_size = old_size + bytes;
288  if (V8_UNLIKELY(new_size > buffer_capacity_)) {
289  bool ok;
290  if (!ExpandBuffer(new_size).To(&ok)) {
291  return Nothing<uint8_t*>();
292  }
293  }
294  buffer_size_ = new_size;
295  return Just(&buffer_[old_size]);
296 }
297 
298 Maybe<bool> ValueSerializer::ExpandBuffer(size_t required_capacity) {
299  DCHECK_GT(required_capacity, buffer_capacity_);
300  size_t requested_capacity =
301  std::max(required_capacity, buffer_capacity_ * 2) + 64;
302  size_t provided_capacity = 0;
303  void* new_buffer = nullptr;
304  if (delegate_) {
305  new_buffer = delegate_->ReallocateBufferMemory(buffer_, requested_capacity,
306  &provided_capacity);
307  } else {
308  new_buffer = realloc(buffer_, requested_capacity);
309  provided_capacity = requested_capacity;
310  }
311  if (new_buffer) {
312  DCHECK(provided_capacity >= requested_capacity);
313  buffer_ = reinterpret_cast<uint8_t*>(new_buffer);
314  buffer_capacity_ = provided_capacity;
315  return Just(true);
316  } else {
317  out_of_memory_ = true;
318  return Nothing<bool>();
319  }
320 }
321 
322 void ValueSerializer::WriteUint32(uint32_t value) {
323  WriteVarint<uint32_t>(value);
324 }
325 
326 void ValueSerializer::WriteUint64(uint64_t value) {
327  WriteVarint<uint64_t>(value);
328 }
329 
330 std::vector<uint8_t> ValueSerializer::ReleaseBuffer() {
331  return std::vector<uint8_t>(buffer_, buffer_ + buffer_size_);
332 }
333 
334 std::pair<uint8_t*, size_t> ValueSerializer::Release() {
335  auto result = std::make_pair(buffer_, buffer_size_);
336  buffer_ = nullptr;
337  buffer_size_ = 0;
338  buffer_capacity_ = 0;
339  return result;
340 }
341 
342 void ValueSerializer::TransferArrayBuffer(uint32_t transfer_id,
343  Handle<JSArrayBuffer> array_buffer) {
344  DCHECK(!array_buffer_transfer_map_.Find(array_buffer));
345  DCHECK(!array_buffer->is_shared());
346  array_buffer_transfer_map_.Set(array_buffer, transfer_id);
347 }
348 
349 Maybe<bool> ValueSerializer::WriteObject(Handle<Object> object) {
350  out_of_memory_ = false;
351  if (object->IsSmi()) {
352  WriteSmi(Smi::cast(*object));
353  return ThrowIfOutOfMemory();
354  }
355 
356  DCHECK(object->IsHeapObject());
357  switch (HeapObject::cast(*object)->map()->instance_type()) {
358  case ODDBALL_TYPE:
359  WriteOddball(Oddball::cast(*object));
360  return ThrowIfOutOfMemory();
361  case HEAP_NUMBER_TYPE:
362  WriteHeapNumber(HeapNumber::cast(*object));
363  return ThrowIfOutOfMemory();
364  case MUTABLE_HEAP_NUMBER_TYPE:
365  WriteMutableHeapNumber(MutableHeapNumber::cast(*object));
366  return ThrowIfOutOfMemory();
367  case BIGINT_TYPE:
368  WriteBigInt(BigInt::cast(*object));
369  return ThrowIfOutOfMemory();
370  case JS_TYPED_ARRAY_TYPE:
371  case JS_DATA_VIEW_TYPE: {
372  // Despite being JSReceivers, these have their wrapped buffer serialized
373  // first. That makes this logic a little quirky, because it needs to
374  // happen before we assign object IDs.
375  // TODO(jbroman): It may be possible to avoid materializing a typed
376  // array's buffer here.
377  Handle<JSArrayBufferView> view = Handle<JSArrayBufferView>::cast(object);
378  if (!id_map_.Find(view) && !treat_array_buffer_views_as_host_objects_) {
379  Handle<JSArrayBuffer> buffer(
380  view->IsJSTypedArray()
381  ? Handle<JSTypedArray>::cast(view)->GetBuffer()
382  : handle(JSArrayBuffer::cast(view->buffer()), isolate_));
383  if (!WriteJSReceiver(buffer).FromMaybe(false)) return Nothing<bool>();
384  }
385  return WriteJSReceiver(view);
386  }
387  default:
388  if (object->IsString()) {
389  WriteString(Handle<String>::cast(object));
390  return ThrowIfOutOfMemory();
391  } else if (object->IsJSReceiver()) {
392  return WriteJSReceiver(Handle<JSReceiver>::cast(object));
393  } else {
394  ThrowDataCloneError(MessageTemplate::kDataCloneError, object);
395  return Nothing<bool>();
396  }
397  }
398 }
399 
400 void ValueSerializer::WriteOddball(Oddball* oddball) {
401  SerializationTag tag = SerializationTag::kUndefined;
402  switch (oddball->kind()) {
403  case Oddball::kUndefined:
404  tag = SerializationTag::kUndefined;
405  break;
406  case Oddball::kFalse:
407  tag = SerializationTag::kFalse;
408  break;
409  case Oddball::kTrue:
410  tag = SerializationTag::kTrue;
411  break;
412  case Oddball::kNull:
413  tag = SerializationTag::kNull;
414  break;
415  default:
416  UNREACHABLE();
417  break;
418  }
419  WriteTag(tag);
420 }
421 
422 void ValueSerializer::WriteSmi(Smi smi) {
423  static_assert(kSmiValueSize <= 32, "Expected SMI <= 32 bits.");
424  WriteTag(SerializationTag::kInt32);
425  WriteZigZag<int32_t>(smi->value());
426 }
427 
428 void ValueSerializer::WriteHeapNumber(HeapNumber* number) {
429  WriteTag(SerializationTag::kDouble);
430  WriteDouble(number->value());
431 }
432 
433 void ValueSerializer::WriteMutableHeapNumber(MutableHeapNumber* number) {
434  WriteTag(SerializationTag::kDouble);
435  WriteDouble(number->value());
436 }
437 
438 void ValueSerializer::WriteBigInt(BigInt* bigint) {
439  WriteTag(SerializationTag::kBigInt);
440  WriteBigIntContents(bigint);
441 }
442 
443 void ValueSerializer::WriteString(Handle<String> string) {
444  string = String::Flatten(isolate_, string);
445  DisallowHeapAllocation no_gc;
446  String::FlatContent flat = string->GetFlatContent();
447  DCHECK(flat.IsFlat());
448  if (flat.IsOneByte()) {
449  Vector<const uint8_t> chars = flat.ToOneByteVector();
450  WriteTag(SerializationTag::kOneByteString);
451  WriteOneByteString(chars);
452  } else if (flat.IsTwoByte()) {
453  Vector<const uc16> chars = flat.ToUC16Vector();
454  uint32_t byte_length = chars.length() * sizeof(uc16);
455  // The existing reading code expects 16-byte strings to be aligned.
456  if ((buffer_size_ + 1 + BytesNeededForVarint(byte_length)) & 1)
457  WriteTag(SerializationTag::kPadding);
458  WriteTag(SerializationTag::kTwoByteString);
459  WriteTwoByteString(chars);
460  } else {
461  UNREACHABLE();
462  }
463 }
464 
465 Maybe<bool> ValueSerializer::WriteJSReceiver(Handle<JSReceiver> receiver) {
466  // If the object has already been serialized, just write its ID.
467  uint32_t* id_map_entry = id_map_.Get(receiver);
468  if (uint32_t id = *id_map_entry) {
469  WriteTag(SerializationTag::kObjectReference);
470  WriteVarint(id - 1);
471  return ThrowIfOutOfMemory();
472  }
473 
474  // Otherwise, allocate an ID for it.
475  uint32_t id = next_id_++;
476  *id_map_entry = id + 1;
477 
478  // Eliminate callable and exotic objects, which should not be serialized.
479  InstanceType instance_type = receiver->map()->instance_type();
480  if (receiver->IsCallable() || (IsSpecialReceiverInstanceType(instance_type) &&
481  instance_type != JS_SPECIAL_API_OBJECT_TYPE)) {
482  ThrowDataCloneError(MessageTemplate::kDataCloneError, receiver);
483  return Nothing<bool>();
484  }
485 
486  // If we are at the end of the stack, abort. This function may recurse.
487  STACK_CHECK(isolate_, Nothing<bool>());
488 
489  HandleScope scope(isolate_);
490  switch (instance_type) {
491  case JS_ARRAY_TYPE:
492  return WriteJSArray(Handle<JSArray>::cast(receiver));
493  case JS_OBJECT_TYPE:
494  case JS_API_OBJECT_TYPE: {
495  Handle<JSObject> js_object = Handle<JSObject>::cast(receiver);
496  if (JSObject::GetEmbedderFieldCount(js_object->map())) {
497  return WriteHostObject(js_object);
498  } else {
499  return WriteJSObject(js_object);
500  }
501  }
502  case JS_SPECIAL_API_OBJECT_TYPE:
503  return WriteHostObject(Handle<JSObject>::cast(receiver));
504  case JS_DATE_TYPE:
505  WriteJSDate(JSDate::cast(*receiver));
506  return ThrowIfOutOfMemory();
507  case JS_VALUE_TYPE:
508  return WriteJSValue(Handle<JSValue>::cast(receiver));
509  case JS_REGEXP_TYPE:
510  WriteJSRegExp(JSRegExp::cast(*receiver));
511  return ThrowIfOutOfMemory();
512  case JS_MAP_TYPE:
513  return WriteJSMap(Handle<JSMap>::cast(receiver));
514  case JS_SET_TYPE:
515  return WriteJSSet(Handle<JSSet>::cast(receiver));
516  case JS_ARRAY_BUFFER_TYPE:
517  return WriteJSArrayBuffer(Handle<JSArrayBuffer>::cast(receiver));
518  case JS_TYPED_ARRAY_TYPE:
519  case JS_DATA_VIEW_TYPE:
520  return WriteJSArrayBufferView(JSArrayBufferView::cast(*receiver));
521  case WASM_MODULE_TYPE: {
522  auto enabled_features = wasm::WasmFeaturesFromIsolate(isolate_);
523  if (!FLAG_wasm_disable_structured_cloning || enabled_features.threads) {
524  // Only write WebAssembly modules if not disabled by a flag.
525  return WriteWasmModule(Handle<WasmModuleObject>::cast(receiver));
526  }
527  break;
528  }
529  case WASM_MEMORY_TYPE: {
530  auto enabled_features = wasm::WasmFeaturesFromIsolate(isolate_);
531  if (enabled_features.threads) {
532  return WriteWasmMemory(Handle<WasmMemoryObject>::cast(receiver));
533  }
534  break;
535  }
536  default:
537  break;
538  }
539 
540  ThrowDataCloneError(MessageTemplate::kDataCloneError, receiver);
541  return Nothing<bool>();
542 }
543 
544 Maybe<bool> ValueSerializer::WriteJSObject(Handle<JSObject> object) {
545  DCHECK(!object->map()->IsCustomElementsReceiverMap());
546  const bool can_serialize_fast =
547  object->HasFastProperties() && object->elements()->length() == 0;
548  if (!can_serialize_fast) return WriteJSObjectSlow(object);
549 
550  Handle<Map> map(object->map(), isolate_);
551  WriteTag(SerializationTag::kBeginJSObject);
552 
553  // Write out fast properties as long as they are only data properties and the
554  // map doesn't change.
555  uint32_t properties_written = 0;
556  bool map_changed = false;
557  for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) {
558  Handle<Name> key(map->instance_descriptors()->GetKey(i), isolate_);
559  if (!key->IsString()) continue;
560  PropertyDetails details = map->instance_descriptors()->GetDetails(i);
561  if (details.IsDontEnum()) continue;
562 
563  Handle<Object> value;
564  if (V8_LIKELY(!map_changed)) map_changed = *map == object->map();
565  if (V8_LIKELY(!map_changed && details.location() == kField)) {
566  DCHECK_EQ(kData, details.kind());
567  FieldIndex field_index = FieldIndex::ForDescriptor(*map, i);
568  value = JSObject::FastPropertyAt(object, details.representation(),
569  field_index);
570  } else {
571  // This logic should essentially match WriteJSObjectPropertiesSlow.
572  // If the property is no longer found, do not serialize it.
573  // This could happen if a getter deleted the property.
574  LookupIterator it(isolate_, object, key, LookupIterator::OWN);
575  if (!it.IsFound()) continue;
576  if (!Object::GetProperty(&it).ToHandle(&value)) return Nothing<bool>();
577  }
578 
579  if (!WriteObject(key).FromMaybe(false) ||
580  !WriteObject(value).FromMaybe(false)) {
581  return Nothing<bool>();
582  }
583  properties_written++;
584  }
585 
586  WriteTag(SerializationTag::kEndJSObject);
587  WriteVarint<uint32_t>(properties_written);
588  return ThrowIfOutOfMemory();
589 }
590 
591 Maybe<bool> ValueSerializer::WriteJSObjectSlow(Handle<JSObject> object) {
592  WriteTag(SerializationTag::kBeginJSObject);
593  Handle<FixedArray> keys;
594  uint32_t properties_written = 0;
595  if (!KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly,
596  ENUMERABLE_STRINGS)
597  .ToHandle(&keys) ||
598  !WriteJSObjectPropertiesSlow(object, keys).To(&properties_written)) {
599  return Nothing<bool>();
600  }
601  WriteTag(SerializationTag::kEndJSObject);
602  WriteVarint<uint32_t>(properties_written);
603  return ThrowIfOutOfMemory();
604 }
605 
606 Maybe<bool> ValueSerializer::WriteJSArray(Handle<JSArray> array) {
607  uint32_t length = 0;
608  bool valid_length = array->length()->ToArrayLength(&length);
609  DCHECK(valid_length);
610  USE(valid_length);
611 
612  // To keep things simple, for now we decide between dense and sparse
613  // serialization based on elements kind. A more principled heuristic could
614  // count the elements, but would need to take care to note which indices
615  // existed (as only indices which were enumerable own properties at this point
616  // should be serialized).
617  const bool should_serialize_densely =
618  array->HasFastElements() && !array->HasHoleyElements();
619 
620  if (should_serialize_densely) {
621  DCHECK_LE(length, static_cast<uint32_t>(FixedArray::kMaxLength));
622  WriteTag(SerializationTag::kBeginDenseJSArray);
623  WriteVarint<uint32_t>(length);
624  uint32_t i = 0;
625 
626  // Fast paths. Note that PACKED_ELEMENTS in particular can bail due to the
627  // structure of the elements changing.
628  switch (array->GetElementsKind()) {
629  case PACKED_SMI_ELEMENTS: {
630  Handle<FixedArray> elements(FixedArray::cast(array->elements()),
631  isolate_);
632  for (; i < length; i++) WriteSmi(Smi::cast(elements->get(i)));
633  break;
634  }
635  case PACKED_DOUBLE_ELEMENTS: {
636  // Elements are empty_fixed_array, not a FixedDoubleArray, if the array
637  // is empty. No elements to encode in this case anyhow.
638  if (length == 0) break;
639  Handle<FixedDoubleArray> elements(
640  FixedDoubleArray::cast(array->elements()), isolate_);
641  for (; i < length; i++) {
642  WriteTag(SerializationTag::kDouble);
643  WriteDouble(elements->get_scalar(i));
644  }
645  break;
646  }
647  case PACKED_ELEMENTS: {
648  Handle<Object> old_length(array->length(), isolate_);
649  for (; i < length; i++) {
650  if (array->length() != *old_length ||
651  array->GetElementsKind() != PACKED_ELEMENTS) {
652  // Fall back to slow path.
653  break;
654  }
655  Handle<Object> element(FixedArray::cast(array->elements())->get(i),
656  isolate_);
657  if (!WriteObject(element).FromMaybe(false)) return Nothing<bool>();
658  }
659  break;
660  }
661  default:
662  break;
663  }
664 
665  // If there are elements remaining, serialize them slowly.
666  for (; i < length; i++) {
667  // Serializing the array's elements can have arbitrary side effects, so we
668  // cannot rely on still having fast elements, even if it did to begin
669  // with.
670  Handle<Object> element;
671  LookupIterator it(isolate_, array, i, array, LookupIterator::OWN);
672  if (!it.IsFound()) {
673  // This can happen in the case where an array that was originally dense
674  // became sparse during serialization. It's too late to switch to the
675  // sparse format, but we can mark the elements as absent.
676  WriteTag(SerializationTag::kTheHole);
677  continue;
678  }
679  if (!Object::GetProperty(&it).ToHandle(&element) ||
680  !WriteObject(element).FromMaybe(false)) {
681  return Nothing<bool>();
682  }
683  }
684 
685  KeyAccumulator accumulator(isolate_, KeyCollectionMode::kOwnOnly,
686  ENUMERABLE_STRINGS);
687  if (!accumulator.CollectOwnPropertyNames(array, array).FromMaybe(false)) {
688  return Nothing<bool>();
689  }
690  Handle<FixedArray> keys =
691  accumulator.GetKeys(GetKeysConversion::kConvertToString);
692  uint32_t properties_written;
693  if (!WriteJSObjectPropertiesSlow(array, keys).To(&properties_written)) {
694  return Nothing<bool>();
695  }
696  WriteTag(SerializationTag::kEndDenseJSArray);
697  WriteVarint<uint32_t>(properties_written);
698  WriteVarint<uint32_t>(length);
699  } else {
700  WriteTag(SerializationTag::kBeginSparseJSArray);
701  WriteVarint<uint32_t>(length);
702  Handle<FixedArray> keys;
703  uint32_t properties_written = 0;
704  if (!KeyAccumulator::GetKeys(array, KeyCollectionMode::kOwnOnly,
705  ENUMERABLE_STRINGS)
706  .ToHandle(&keys) ||
707  !WriteJSObjectPropertiesSlow(array, keys).To(&properties_written)) {
708  return Nothing<bool>();
709  }
710  WriteTag(SerializationTag::kEndSparseJSArray);
711  WriteVarint<uint32_t>(properties_written);
712  WriteVarint<uint32_t>(length);
713  }
714  return ThrowIfOutOfMemory();
715 }
716 
717 void ValueSerializer::WriteJSDate(JSDate* date) {
718  WriteTag(SerializationTag::kDate);
719  WriteDouble(date->value()->Number());
720 }
721 
722 Maybe<bool> ValueSerializer::WriteJSValue(Handle<JSValue> value) {
723  Object* inner_value = value->value();
724  if (inner_value->IsTrue(isolate_)) {
725  WriteTag(SerializationTag::kTrueObject);
726  } else if (inner_value->IsFalse(isolate_)) {
727  WriteTag(SerializationTag::kFalseObject);
728  } else if (inner_value->IsNumber()) {
729  WriteTag(SerializationTag::kNumberObject);
730  WriteDouble(inner_value->Number());
731  } else if (inner_value->IsBigInt()) {
732  WriteTag(SerializationTag::kBigIntObject);
733  WriteBigIntContents(BigInt::cast(inner_value));
734  } else if (inner_value->IsString()) {
735  WriteTag(SerializationTag::kStringObject);
736  WriteString(handle(String::cast(inner_value), isolate_));
737  } else {
738  DCHECK(inner_value->IsSymbol());
739  ThrowDataCloneError(MessageTemplate::kDataCloneError, value);
740  return Nothing<bool>();
741  }
742  return ThrowIfOutOfMemory();
743 }
744 
745 void ValueSerializer::WriteJSRegExp(JSRegExp* regexp) {
746  WriteTag(SerializationTag::kRegExp);
747  WriteString(handle(regexp->Pattern(), isolate_));
748  WriteVarint(static_cast<uint32_t>(regexp->GetFlags()));
749 }
750 
751 Maybe<bool> ValueSerializer::WriteJSMap(Handle<JSMap> map) {
752  // First copy the key-value pairs, since getters could mutate them.
753  Handle<OrderedHashMap> table(OrderedHashMap::cast(map->table()), isolate_);
754  int length = table->NumberOfElements() * 2;
755  Handle<FixedArray> entries = isolate_->factory()->NewFixedArray(length);
756  {
757  DisallowHeapAllocation no_gc;
758  Oddball* the_hole = ReadOnlyRoots(isolate_).the_hole_value();
759  int capacity = table->UsedCapacity();
760  int result_index = 0;
761  for (int i = 0; i < capacity; i++) {
762  Object* key = table->KeyAt(i);
763  if (key == the_hole) continue;
764  entries->set(result_index++, key);
765  entries->set(result_index++, table->ValueAt(i));
766  }
767  DCHECK_EQ(result_index, length);
768  }
769 
770  // Then write it out.
771  WriteTag(SerializationTag::kBeginJSMap);
772  for (int i = 0; i < length; i++) {
773  if (!WriteObject(handle(entries->get(i), isolate_)).FromMaybe(false)) {
774  return Nothing<bool>();
775  }
776  }
777  WriteTag(SerializationTag::kEndJSMap);
778  WriteVarint<uint32_t>(length);
779  return ThrowIfOutOfMemory();
780 }
781 
782 Maybe<bool> ValueSerializer::WriteJSSet(Handle<JSSet> set) {
783  // First copy the element pointers, since getters could mutate them.
784  Handle<OrderedHashSet> table(OrderedHashSet::cast(set->table()), isolate_);
785  int length = table->NumberOfElements();
786  Handle<FixedArray> entries = isolate_->factory()->NewFixedArray(length);
787  {
788  DisallowHeapAllocation no_gc;
789  Oddball* the_hole = ReadOnlyRoots(isolate_).the_hole_value();
790  int capacity = table->UsedCapacity();
791  int result_index = 0;
792  for (int i = 0; i < capacity; i++) {
793  Object* key = table->KeyAt(i);
794  if (key == the_hole) continue;
795  entries->set(result_index++, key);
796  }
797  DCHECK_EQ(result_index, length);
798  }
799 
800  // Then write it out.
801  WriteTag(SerializationTag::kBeginJSSet);
802  for (int i = 0; i < length; i++) {
803  if (!WriteObject(handle(entries->get(i), isolate_)).FromMaybe(false)) {
804  return Nothing<bool>();
805  }
806  }
807  WriteTag(SerializationTag::kEndJSSet);
808  WriteVarint<uint32_t>(length);
809  return ThrowIfOutOfMemory();
810 }
811 
812 Maybe<bool> ValueSerializer::WriteJSArrayBuffer(
813  Handle<JSArrayBuffer> array_buffer) {
814  if (array_buffer->is_shared()) {
815  if (!delegate_) {
816  ThrowDataCloneError(MessageTemplate::kDataCloneError, array_buffer);
817  return Nothing<bool>();
818  }
819 
820  v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate_);
821  Maybe<uint32_t> index = delegate_->GetSharedArrayBufferId(
822  v8_isolate, Utils::ToLocalShared(array_buffer));
823  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate_, Nothing<bool>());
824 
825  WriteTag(SerializationTag::kSharedArrayBuffer);
826  WriteVarint(index.FromJust());
827  return ThrowIfOutOfMemory();
828  }
829 
830  uint32_t* transfer_entry = array_buffer_transfer_map_.Find(array_buffer);
831  if (transfer_entry) {
832  WriteTag(SerializationTag::kArrayBufferTransfer);
833  WriteVarint(*transfer_entry);
834  return ThrowIfOutOfMemory();
835  }
836  if (array_buffer->was_neutered()) {
837  ThrowDataCloneError(MessageTemplate::kDataCloneErrorNeuteredArrayBuffer);
838  return Nothing<bool>();
839  }
840  double byte_length = array_buffer->byte_length();
841  if (byte_length > std::numeric_limits<uint32_t>::max()) {
842  ThrowDataCloneError(MessageTemplate::kDataCloneError, array_buffer);
843  return Nothing<bool>();
844  }
845  WriteTag(SerializationTag::kArrayBuffer);
846  WriteVarint<uint32_t>(byte_length);
847  WriteRawBytes(array_buffer->backing_store(), byte_length);
848  return ThrowIfOutOfMemory();
849 }
850 
851 Maybe<bool> ValueSerializer::WriteJSArrayBufferView(JSArrayBufferView* view) {
852  if (treat_array_buffer_views_as_host_objects_) {
853  return WriteHostObject(handle(view, isolate_));
854  }
855  WriteTag(SerializationTag::kArrayBufferView);
856  ArrayBufferViewTag tag = ArrayBufferViewTag::kInt8Array;
857  if (view->IsJSTypedArray()) {
858  switch (JSTypedArray::cast(view)->type()) {
859 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
860  case kExternal##Type##Array: \
861  tag = ArrayBufferViewTag::k##Type##Array; \
862  break;
863  TYPED_ARRAYS(TYPED_ARRAY_CASE)
864 #undef TYPED_ARRAY_CASE
865  }
866  } else {
867  DCHECK(view->IsJSDataView());
868  tag = ArrayBufferViewTag::kDataView;
869  }
870  WriteVarint(static_cast<uint8_t>(tag));
871  WriteVarint(static_cast<uint32_t>(view->byte_offset()));
872  WriteVarint(static_cast<uint32_t>(view->byte_length()));
873  return ThrowIfOutOfMemory();
874 }
875 
876 Maybe<bool> ValueSerializer::WriteWasmModule(Handle<WasmModuleObject> object) {
877  if (delegate_ != nullptr) {
878  // TODO(titzer): introduce a Utils::ToLocal for WasmModuleObject.
879  Maybe<uint32_t> transfer_id = delegate_->GetWasmModuleTransferId(
880  reinterpret_cast<v8::Isolate*>(isolate_),
882  Utils::ToLocal(Handle<JSObject>::cast(object))));
883  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate_, Nothing<bool>());
884  uint32_t id = 0;
885  if (transfer_id.To(&id)) {
886  WriteTag(SerializationTag::kWasmModuleTransfer);
887  WriteVarint<uint32_t>(id);
888  return Just(true);
889  }
890  }
891 
892  WasmEncodingTag encoding_tag = WasmEncodingTag::kRawBytes;
893  WriteTag(SerializationTag::kWasmModule);
894  WriteRawBytes(&encoding_tag, sizeof(encoding_tag));
895 
896  wasm::NativeModule* native_module = object->native_module();
897  Vector<const uint8_t> wire_bytes = native_module->wire_bytes();
898  WriteVarint<uint32_t>(static_cast<uint32_t>(wire_bytes.size()));
899  uint8_t* destination;
900  if (ReserveRawBytes(wire_bytes.size()).To(&destination)) {
901  memcpy(destination, wire_bytes.start(), wire_bytes.size());
902  }
903 
904  wasm::WasmSerializer wasm_serializer(isolate_, native_module);
905  size_t module_size = wasm_serializer.GetSerializedNativeModuleSize();
906  CHECK_GE(std::numeric_limits<uint32_t>::max(), module_size);
907  WriteVarint<uint32_t>(static_cast<uint32_t>(module_size));
908  uint8_t* module_buffer;
909  if (ReserveRawBytes(module_size).To(&module_buffer)) {
910  if (!wasm_serializer.SerializeNativeModule({module_buffer, module_size})) {
911  return Nothing<bool>();
912  }
913  }
914  return ThrowIfOutOfMemory();
915 }
916 
917 Maybe<bool> ValueSerializer::WriteWasmMemory(Handle<WasmMemoryObject> object) {
918  if (!object->array_buffer()->is_shared()) {
919  ThrowDataCloneError(MessageTemplate::kDataCloneError, object);
920  return Nothing<bool>();
921  }
922 
923  WriteTag(SerializationTag::kWasmMemoryTransfer);
924  WriteZigZag<int32_t>(object->maximum_pages());
925  return WriteJSReceiver(Handle<JSReceiver>(object->array_buffer(), isolate_));
926 }
927 
928 Maybe<bool> ValueSerializer::WriteHostObject(Handle<JSObject> object) {
929  WriteTag(SerializationTag::kHostObject);
930  if (!delegate_) {
931  isolate_->Throw(*isolate_->factory()->NewError(
932  isolate_->error_function(), MessageTemplate::kDataCloneError, object));
933  return Nothing<bool>();
934  }
935  v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate_);
936  Maybe<bool> result =
937  delegate_->WriteHostObject(v8_isolate, Utils::ToLocal(object));
938  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate_, Nothing<bool>());
939  DCHECK(!result.IsNothing());
940  return result;
941 }
942 
943 Maybe<uint32_t> ValueSerializer::WriteJSObjectPropertiesSlow(
944  Handle<JSObject> object, Handle<FixedArray> keys) {
945  uint32_t properties_written = 0;
946  int length = keys->length();
947  for (int i = 0; i < length; i++) {
948  Handle<Object> key(keys->get(i), isolate_);
949 
950  bool success;
951  LookupIterator it = LookupIterator::PropertyOrElement(
952  isolate_, object, key, &success, LookupIterator::OWN);
953  DCHECK(success);
954  Handle<Object> value;
955  if (!Object::GetProperty(&it).ToHandle(&value)) return Nothing<uint32_t>();
956 
957  // If the property is no longer found, do not serialize it.
958  // This could happen if a getter deleted the property.
959  if (!it.IsFound()) continue;
960 
961  if (!WriteObject(key).FromMaybe(false) ||
962  !WriteObject(value).FromMaybe(false)) {
963  return Nothing<uint32_t>();
964  }
965 
966  properties_written++;
967  }
968  return Just(properties_written);
969 }
970 
971 void ValueSerializer::ThrowDataCloneError(MessageTemplate template_index) {
972  return ThrowDataCloneError(template_index,
973  isolate_->factory()->empty_string());
974 }
975 
976 Maybe<bool> ValueSerializer::ThrowIfOutOfMemory() {
977  if (out_of_memory_) {
978  ThrowDataCloneError(MessageTemplate::kDataCloneErrorOutOfMemory);
979  return Nothing<bool>();
980  }
981  return Just(true);
982 }
983 
984 void ValueSerializer::ThrowDataCloneError(MessageTemplate index,
985  Handle<Object> arg0) {
986  Handle<String> message =
987  MessageFormatter::FormatMessage(isolate_, index, arg0);
988  if (delegate_) {
989  delegate_->ThrowDataCloneError(Utils::ToLocal(message));
990  } else {
991  isolate_->Throw(
992  *isolate_->factory()->NewError(isolate_->error_function(), message));
993  }
994  if (isolate_->has_scheduled_exception()) {
995  isolate_->PromoteScheduledException();
996  }
997 }
998 
999 ValueDeserializer::ValueDeserializer(Isolate* isolate,
1000  Vector<const uint8_t> data,
1002  : isolate_(isolate),
1003  delegate_(delegate),
1004  position_(data.start()),
1005  end_(data.start() + data.length()),
1006  pretenure_(data.length() > kPretenureThreshold ? TENURED : NOT_TENURED),
1007  id_map_(Handle<FixedArray>::cast(isolate->global_handles()->Create(
1008  ReadOnlyRoots(isolate_).empty_fixed_array()))) {}
1009 
1010 ValueDeserializer::~ValueDeserializer() {
1011  GlobalHandles::Destroy(id_map_.location());
1012 
1013  Handle<Object> transfer_map_handle;
1014  if (array_buffer_transfer_map_.ToHandle(&transfer_map_handle)) {
1015  GlobalHandles::Destroy(transfer_map_handle.location());
1016  }
1017 }
1018 
1019 Maybe<bool> ValueDeserializer::ReadHeader() {
1020  if (position_ < end_ &&
1021  *position_ == static_cast<uint8_t>(SerializationTag::kVersion)) {
1022  ReadTag().ToChecked();
1023  if (!ReadVarint<uint32_t>().To(&version_) || version_ > kLatestVersion) {
1024  isolate_->Throw(*isolate_->factory()->NewError(
1025  MessageTemplate::kDataCloneDeserializationVersionError));
1026  return Nothing<bool>();
1027  }
1028  }
1029  return Just(true);
1030 }
1031 
1032 Maybe<SerializationTag> ValueDeserializer::PeekTag() const {
1033  const uint8_t* peek_position = position_;
1034  SerializationTag tag;
1035  do {
1036  if (peek_position >= end_) return Nothing<SerializationTag>();
1037  tag = static_cast<SerializationTag>(*peek_position);
1038  peek_position++;
1039  } while (tag == SerializationTag::kPadding);
1040  return Just(tag);
1041 }
1042 
1043 void ValueDeserializer::ConsumeTag(SerializationTag peeked_tag) {
1044  SerializationTag actual_tag = ReadTag().ToChecked();
1045  DCHECK(actual_tag == peeked_tag);
1046  USE(actual_tag);
1047 }
1048 
1049 Maybe<SerializationTag> ValueDeserializer::ReadTag() {
1050  SerializationTag tag;
1051  do {
1052  if (position_ >= end_) return Nothing<SerializationTag>();
1053  tag = static_cast<SerializationTag>(*position_);
1054  position_++;
1055  } while (tag == SerializationTag::kPadding);
1056  return Just(tag);
1057 }
1058 
1059 template <typename T>
1060 Maybe<T> ValueDeserializer::ReadVarint() {
1061  // Reads an unsigned integer as a base-128 varint.
1062  // The number is written, 7 bits at a time, from the least significant to the
1063  // most significant 7 bits. Each byte, except the last, has the MSB set.
1064  // If the varint is larger than T, any more significant bits are discarded.
1065  // See also https://developers.google.com/protocol-buffers/docs/encoding
1066  static_assert(std::is_integral<T>::value && std::is_unsigned<T>::value,
1067  "Only unsigned integer types can be read as varints.");
1068  T value = 0;
1069  unsigned shift = 0;
1070  bool has_another_byte;
1071  do {
1072  if (position_ >= end_) return Nothing<T>();
1073  uint8_t byte = *position_;
1074  if (V8_LIKELY(shift < sizeof(T) * 8)) {
1075  value |= static_cast<T>(byte & 0x7F) << shift;
1076  shift += 7;
1077  }
1078  has_another_byte = byte & 0x80;
1079  position_++;
1080  } while (has_another_byte);
1081  return Just(value);
1082 }
1083 
1084 template <typename T>
1085 Maybe<T> ValueDeserializer::ReadZigZag() {
1086  // Writes a signed integer as a varint using ZigZag encoding (i.e. 0 is
1087  // encoded as 0, -1 as 1, 1 as 2, -2 as 3, and so on).
1088  // See also https://developers.google.com/protocol-buffers/docs/encoding
1089  static_assert(std::is_integral<T>::value && std::is_signed<T>::value,
1090  "Only signed integer types can be read as zigzag.");
1091  using UnsignedT = typename std::make_unsigned<T>::type;
1092  UnsignedT unsigned_value;
1093  if (!ReadVarint<UnsignedT>().To(&unsigned_value)) return Nothing<T>();
1094  return Just(static_cast<T>((unsigned_value >> 1) ^
1095  -static_cast<T>(unsigned_value & 1)));
1096 }
1097 
1098 Maybe<double> ValueDeserializer::ReadDouble() {
1099  // Warning: this uses host endianness.
1100  if (position_ > end_ - sizeof(double)) return Nothing<double>();
1101  double value;
1102  memcpy(&value, position_, sizeof(double));
1103  position_ += sizeof(double);
1104  if (std::isnan(value)) value = std::numeric_limits<double>::quiet_NaN();
1105  return Just(value);
1106 }
1107 
1108 Maybe<Vector<const uint8_t>> ValueDeserializer::ReadRawBytes(int size) {
1109  if (size > end_ - position_) return Nothing<Vector<const uint8_t>>();
1110  const uint8_t* start = position_;
1111  position_ += size;
1112  return Just(Vector<const uint8_t>(start, size));
1113 }
1114 
1115 bool ValueDeserializer::ReadUint32(uint32_t* value) {
1116  return ReadVarint<uint32_t>().To(value);
1117 }
1118 
1119 bool ValueDeserializer::ReadUint64(uint64_t* value) {
1120  return ReadVarint<uint64_t>().To(value);
1121 }
1122 
1123 bool ValueDeserializer::ReadDouble(double* value) {
1124  return ReadDouble().To(value);
1125 }
1126 
1127 bool ValueDeserializer::ReadRawBytes(size_t length, const void** data) {
1128  if (length > static_cast<size_t>(end_ - position_)) return false;
1129  *data = position_;
1130  position_ += length;
1131  return true;
1132 }
1133 
1134 void ValueDeserializer::TransferArrayBuffer(
1135  uint32_t transfer_id, Handle<JSArrayBuffer> array_buffer) {
1136  if (array_buffer_transfer_map_.is_null()) {
1137  array_buffer_transfer_map_ =
1138  Handle<SimpleNumberDictionary>::cast(isolate_->global_handles()->Create(
1139  *SimpleNumberDictionary::New(isolate_, 0)));
1140  }
1141  Handle<SimpleNumberDictionary> dictionary =
1142  array_buffer_transfer_map_.ToHandleChecked();
1143  Handle<SimpleNumberDictionary> new_dictionary = SimpleNumberDictionary::Set(
1144  isolate_, dictionary, transfer_id, array_buffer);
1145  if (!new_dictionary.is_identical_to(dictionary)) {
1146  GlobalHandles::Destroy(dictionary.location());
1147  array_buffer_transfer_map_ = Handle<SimpleNumberDictionary>::cast(
1148  isolate_->global_handles()->Create(*new_dictionary));
1149  }
1150 }
1151 
1152 MaybeHandle<Object> ValueDeserializer::ReadObject() {
1153  DisallowJavascriptExecution no_js(isolate_);
1154  MaybeHandle<Object> result = ReadObjectInternal();
1155 
1156  // ArrayBufferView is special in that it consumes the value before it, even
1157  // after format version 0.
1158  Handle<Object> object;
1159  SerializationTag tag;
1160  if (result.ToHandle(&object) && V8_UNLIKELY(object->IsJSArrayBuffer()) &&
1161  PeekTag().To(&tag) && tag == SerializationTag::kArrayBufferView) {
1162  ConsumeTag(SerializationTag::kArrayBufferView);
1163  result = ReadJSArrayBufferView(Handle<JSArrayBuffer>::cast(object));
1164  }
1165 
1166  if (result.is_null() && !isolate_->has_pending_exception()) {
1167  isolate_->Throw(*isolate_->factory()->NewError(
1168  MessageTemplate::kDataCloneDeserializationError));
1169  }
1170 
1171  return result;
1172 }
1173 
1174 MaybeHandle<Object> ValueDeserializer::ReadObjectInternal() {
1175  SerializationTag tag;
1176  if (!ReadTag().To(&tag)) return MaybeHandle<Object>();
1177  switch (tag) {
1178  case SerializationTag::kVerifyObjectCount:
1179  // Read the count and ignore it.
1180  if (ReadVarint<uint32_t>().IsNothing()) return MaybeHandle<Object>();
1181  return ReadObject();
1182  case SerializationTag::kUndefined:
1183  return isolate_->factory()->undefined_value();
1184  case SerializationTag::kNull:
1185  return isolate_->factory()->null_value();
1186  case SerializationTag::kTrue:
1187  return isolate_->factory()->true_value();
1188  case SerializationTag::kFalse:
1189  return isolate_->factory()->false_value();
1190  case SerializationTag::kInt32: {
1191  Maybe<int32_t> number = ReadZigZag<int32_t>();
1192  if (number.IsNothing()) return MaybeHandle<Object>();
1193  return isolate_->factory()->NewNumberFromInt(number.FromJust(),
1194  pretenure_);
1195  }
1196  case SerializationTag::kUint32: {
1197  Maybe<uint32_t> number = ReadVarint<uint32_t>();
1198  if (number.IsNothing()) return MaybeHandle<Object>();
1199  return isolate_->factory()->NewNumberFromUint(number.FromJust(),
1200  pretenure_);
1201  }
1202  case SerializationTag::kDouble: {
1203  Maybe<double> number = ReadDouble();
1204  if (number.IsNothing()) return MaybeHandle<Object>();
1205  return isolate_->factory()->NewNumber(number.FromJust(), pretenure_);
1206  }
1207  case SerializationTag::kBigInt:
1208  return ReadBigInt();
1209  case SerializationTag::kUtf8String:
1210  return ReadUtf8String();
1211  case SerializationTag::kOneByteString:
1212  return ReadOneByteString();
1213  case SerializationTag::kTwoByteString:
1214  return ReadTwoByteString();
1215  case SerializationTag::kObjectReference: {
1216  uint32_t id;
1217  if (!ReadVarint<uint32_t>().To(&id)) return MaybeHandle<Object>();
1218  return GetObjectWithID(id);
1219  }
1220  case SerializationTag::kBeginJSObject:
1221  return ReadJSObject();
1222  case SerializationTag::kBeginSparseJSArray:
1223  return ReadSparseJSArray();
1224  case SerializationTag::kBeginDenseJSArray:
1225  return ReadDenseJSArray();
1226  case SerializationTag::kDate:
1227  return ReadJSDate();
1228  case SerializationTag::kTrueObject:
1229  case SerializationTag::kFalseObject:
1230  case SerializationTag::kNumberObject:
1231  case SerializationTag::kBigIntObject:
1232  case SerializationTag::kStringObject:
1233  return ReadJSValue(tag);
1234  case SerializationTag::kRegExp:
1235  return ReadJSRegExp();
1236  case SerializationTag::kBeginJSMap:
1237  return ReadJSMap();
1238  case SerializationTag::kBeginJSSet:
1239  return ReadJSSet();
1240  case SerializationTag::kArrayBuffer: {
1241  const bool is_shared = false;
1242  return ReadJSArrayBuffer(is_shared);
1243  }
1244  case SerializationTag::kArrayBufferTransfer: {
1245  return ReadTransferredJSArrayBuffer();
1246  }
1247  case SerializationTag::kSharedArrayBuffer: {
1248  const bool is_shared = true;
1249  return ReadJSArrayBuffer(is_shared);
1250  }
1251  case SerializationTag::kWasmModule:
1252  return ReadWasmModule();
1253  case SerializationTag::kWasmModuleTransfer:
1254  return ReadWasmModuleTransfer();
1255  case SerializationTag::kWasmMemoryTransfer:
1256  return ReadWasmMemory();
1257  case SerializationTag::kHostObject:
1258  return ReadHostObject();
1259  default:
1260  // Before there was an explicit tag for host objects, all unknown tags
1261  // were delegated to the host.
1262  if (version_ < 13) {
1263  position_--;
1264  return ReadHostObject();
1265  }
1266  return MaybeHandle<Object>();
1267  }
1268 }
1269 
1270 MaybeHandle<String> ValueDeserializer::ReadString() {
1271  if (version_ < 12) return ReadUtf8String();
1272  Handle<Object> object;
1273  if (!ReadObject().ToHandle(&object) || !object->IsString()) {
1274  return MaybeHandle<String>();
1275  }
1276  return Handle<String>::cast(object);
1277 }
1278 
1279 MaybeHandle<BigInt> ValueDeserializer::ReadBigInt() {
1280  uint32_t bitfield;
1281  if (!ReadVarint<uint32_t>().To(&bitfield)) return MaybeHandle<BigInt>();
1282  int bytelength = BigInt::DigitsByteLengthForBitfield(bitfield);
1283  Vector<const uint8_t> digits_storage;
1284  if (!ReadRawBytes(bytelength).To(&digits_storage)) {
1285  return MaybeHandle<BigInt>();
1286  }
1287  return BigInt::FromSerializedDigits(isolate_, bitfield, digits_storage,
1288  pretenure_);
1289 }
1290 
1291 MaybeHandle<String> ValueDeserializer::ReadUtf8String() {
1292  uint32_t utf8_length;
1293  Vector<const uint8_t> utf8_bytes;
1294  if (!ReadVarint<uint32_t>().To(&utf8_length) ||
1295  utf8_length >
1296  static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) ||
1297  !ReadRawBytes(utf8_length).To(&utf8_bytes)) {
1298  return MaybeHandle<String>();
1299  }
1300  return isolate_->factory()->NewStringFromUtf8(
1301  Vector<const char>::cast(utf8_bytes), pretenure_);
1302 }
1303 
1304 MaybeHandle<String> ValueDeserializer::ReadOneByteString() {
1305  uint32_t byte_length;
1306  Vector<const uint8_t> bytes;
1307  if (!ReadVarint<uint32_t>().To(&byte_length) ||
1308  byte_length >
1309  static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) ||
1310  !ReadRawBytes(byte_length).To(&bytes)) {
1311  return MaybeHandle<String>();
1312  }
1313  return isolate_->factory()->NewStringFromOneByte(bytes, pretenure_);
1314 }
1315 
1316 MaybeHandle<String> ValueDeserializer::ReadTwoByteString() {
1317  uint32_t byte_length;
1318  Vector<const uint8_t> bytes;
1319  if (!ReadVarint<uint32_t>().To(&byte_length) ||
1320  byte_length >
1321  static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) ||
1322  byte_length % sizeof(uc16) != 0 ||
1323  !ReadRawBytes(byte_length).To(&bytes)) {
1324  return MaybeHandle<String>();
1325  }
1326 
1327  // Allocate an uninitialized string so that we can do a raw memcpy into the
1328  // string on the heap (regardless of alignment).
1329  if (byte_length == 0) return isolate_->factory()->empty_string();
1330  Handle<SeqTwoByteString> string;
1331  if (!isolate_->factory()
1332  ->NewRawTwoByteString(byte_length / sizeof(uc16), pretenure_)
1333  .ToHandle(&string)) {
1334  return MaybeHandle<String>();
1335  }
1336 
1337  // Copy the bytes directly into the new string.
1338  // Warning: this uses host endianness.
1339  DisallowHeapAllocation no_gc;
1340  memcpy(string->GetChars(), bytes.begin(), bytes.length());
1341  return string;
1342 }
1343 
1344 bool ValueDeserializer::ReadExpectedString(Handle<String> expected) {
1345  DisallowHeapAllocation no_gc;
1346  // In the case of failure, the position in the stream is reset.
1347  const uint8_t* original_position = position_;
1348 
1349  SerializationTag tag;
1350  uint32_t byte_length;
1351  Vector<const uint8_t> bytes;
1352  if (!ReadTag().To(&tag) || !ReadVarint<uint32_t>().To(&byte_length) ||
1353  byte_length >
1354  static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) ||
1355  !ReadRawBytes(byte_length).To(&bytes)) {
1356  position_ = original_position;
1357  return false;
1358  }
1359 
1360  String::FlatContent flat = expected->GetFlatContent();
1361 
1362  // If the bytes are verbatim what is in the flattened string, then the string
1363  // is successfully consumed.
1364  if (tag == SerializationTag::kOneByteString && flat.IsOneByte()) {
1365  Vector<const uint8_t> chars = flat.ToOneByteVector();
1366  if (byte_length == static_cast<size_t>(chars.length()) &&
1367  memcmp(bytes.begin(), chars.begin(), byte_length) == 0) {
1368  return true;
1369  }
1370  } else if (tag == SerializationTag::kTwoByteString && flat.IsTwoByte()) {
1371  Vector<const uc16> chars = flat.ToUC16Vector();
1372  if (byte_length == static_cast<unsigned>(chars.length()) * sizeof(uc16) &&
1373  memcmp(bytes.begin(), chars.begin(), byte_length) == 0) {
1374  return true;
1375  }
1376  } else if (tag == SerializationTag::kUtf8String && flat.IsOneByte()) {
1377  Vector<const uint8_t> chars = flat.ToOneByteVector();
1378  if (byte_length == static_cast<size_t>(chars.length()) &&
1379  String::IsAscii(chars.begin(), chars.length()) &&
1380  memcmp(bytes.begin(), chars.begin(), byte_length) == 0) {
1381  return true;
1382  }
1383  }
1384 
1385  position_ = original_position;
1386  return false;
1387 }
1388 
1389 MaybeHandle<JSObject> ValueDeserializer::ReadJSObject() {
1390  // If we are at the end of the stack, abort. This function may recurse.
1391  STACK_CHECK(isolate_, MaybeHandle<JSObject>());
1392 
1393  uint32_t id = next_id_++;
1394  HandleScope scope(isolate_);
1395  Handle<JSObject> object =
1396  isolate_->factory()->NewJSObject(isolate_->object_function(), pretenure_);
1397  AddObjectWithID(id, object);
1398 
1399  uint32_t num_properties;
1400  uint32_t expected_num_properties;
1401  if (!ReadJSObjectProperties(object, SerializationTag::kEndJSObject, true)
1402  .To(&num_properties) ||
1403  !ReadVarint<uint32_t>().To(&expected_num_properties) ||
1404  num_properties != expected_num_properties) {
1405  return MaybeHandle<JSObject>();
1406  }
1407 
1408  DCHECK(HasObjectWithID(id));
1409  return scope.CloseAndEscape(object);
1410 }
1411 
1412 MaybeHandle<JSArray> ValueDeserializer::ReadSparseJSArray() {
1413  // If we are at the end of the stack, abort. This function may recurse.
1414  STACK_CHECK(isolate_, MaybeHandle<JSArray>());
1415 
1416  uint32_t length;
1417  if (!ReadVarint<uint32_t>().To(&length)) return MaybeHandle<JSArray>();
1418 
1419  uint32_t id = next_id_++;
1420  HandleScope scope(isolate_);
1421  Handle<JSArray> array = isolate_->factory()->NewJSArray(
1422  0, TERMINAL_FAST_ELEMENTS_KIND, pretenure_);
1423  JSArray::SetLength(array, length);
1424  AddObjectWithID(id, array);
1425 
1426  uint32_t num_properties;
1427  uint32_t expected_num_properties;
1428  uint32_t expected_length;
1429  if (!ReadJSObjectProperties(array, SerializationTag::kEndSparseJSArray, false)
1430  .To(&num_properties) ||
1431  !ReadVarint<uint32_t>().To(&expected_num_properties) ||
1432  !ReadVarint<uint32_t>().To(&expected_length) ||
1433  num_properties != expected_num_properties || length != expected_length) {
1434  return MaybeHandle<JSArray>();
1435  }
1436 
1437  DCHECK(HasObjectWithID(id));
1438  return scope.CloseAndEscape(array);
1439 }
1440 
1441 MaybeHandle<JSArray> ValueDeserializer::ReadDenseJSArray() {
1442  // If we are at the end of the stack, abort. This function may recurse.
1443  STACK_CHECK(isolate_, MaybeHandle<JSArray>());
1444 
1445  // We shouldn't permit an array larger than the biggest we can request from
1446  // V8. As an additional sanity check, since each entry will take at least one
1447  // byte to encode, if there are fewer bytes than that we can also fail fast.
1448  uint32_t length;
1449  if (!ReadVarint<uint32_t>().To(&length) ||
1450  length > static_cast<uint32_t>(FixedArray::kMaxLength) ||
1451  length > static_cast<size_t>(end_ - position_)) {
1452  return MaybeHandle<JSArray>();
1453  }
1454 
1455  uint32_t id = next_id_++;
1456  HandleScope scope(isolate_);
1457  Handle<JSArray> array = isolate_->factory()->NewJSArray(
1458  HOLEY_ELEMENTS, length, length, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE,
1459  pretenure_);
1460  AddObjectWithID(id, array);
1461 
1462  Handle<FixedArray> elements(FixedArray::cast(array->elements()), isolate_);
1463  for (uint32_t i = 0; i < length; i++) {
1464  SerializationTag tag;
1465  if (PeekTag().To(&tag) && tag == SerializationTag::kTheHole) {
1466  ConsumeTag(SerializationTag::kTheHole);
1467  continue;
1468  }
1469 
1470  Handle<Object> element;
1471  if (!ReadObject().ToHandle(&element)) return MaybeHandle<JSArray>();
1472 
1473  // Serialization versions less than 11 encode the hole the same as
1474  // undefined. For consistency with previous behavior, store these as the
1475  // hole. Past version 11, undefined means undefined.
1476  if (version_ < 11 && element->IsUndefined(isolate_)) continue;
1477 
1478  // Safety check.
1479  CHECK_LT(i, static_cast<uint32_t>(elements->length()));
1480 
1481  elements->set(i, *element);
1482  }
1483 
1484  uint32_t num_properties;
1485  uint32_t expected_num_properties;
1486  uint32_t expected_length;
1487  if (!ReadJSObjectProperties(array, SerializationTag::kEndDenseJSArray, false)
1488  .To(&num_properties) ||
1489  !ReadVarint<uint32_t>().To(&expected_num_properties) ||
1490  !ReadVarint<uint32_t>().To(&expected_length) ||
1491  num_properties != expected_num_properties || length != expected_length) {
1492  return MaybeHandle<JSArray>();
1493  }
1494 
1495  DCHECK(HasObjectWithID(id));
1496  return scope.CloseAndEscape(array);
1497 }
1498 
1499 MaybeHandle<JSDate> ValueDeserializer::ReadJSDate() {
1500  double value;
1501  if (!ReadDouble().To(&value)) return MaybeHandle<JSDate>();
1502  uint32_t id = next_id_++;
1503  Handle<JSDate> date;
1504  if (!JSDate::New(isolate_->date_function(), isolate_->date_function(), value)
1505  .ToHandle(&date)) {
1506  return MaybeHandle<JSDate>();
1507  }
1508  AddObjectWithID(id, date);
1509  return date;
1510 }
1511 
1512 MaybeHandle<JSValue> ValueDeserializer::ReadJSValue(SerializationTag tag) {
1513  uint32_t id = next_id_++;
1514  Handle<JSValue> value;
1515  switch (tag) {
1516  case SerializationTag::kTrueObject:
1517  value = Handle<JSValue>::cast(isolate_->factory()->NewJSObject(
1518  isolate_->boolean_function(), pretenure_));
1519  value->set_value(ReadOnlyRoots(isolate_).true_value());
1520  break;
1521  case SerializationTag::kFalseObject:
1522  value = Handle<JSValue>::cast(isolate_->factory()->NewJSObject(
1523  isolate_->boolean_function(), pretenure_));
1524  value->set_value(ReadOnlyRoots(isolate_).false_value());
1525  break;
1526  case SerializationTag::kNumberObject: {
1527  double number;
1528  if (!ReadDouble().To(&number)) return MaybeHandle<JSValue>();
1529  value = Handle<JSValue>::cast(isolate_->factory()->NewJSObject(
1530  isolate_->number_function(), pretenure_));
1531  Handle<Object> number_object =
1532  isolate_->factory()->NewNumber(number, pretenure_);
1533  value->set_value(*number_object);
1534  break;
1535  }
1536  case SerializationTag::kBigIntObject: {
1537  Handle<BigInt> bigint;
1538  if (!ReadBigInt().ToHandle(&bigint)) return MaybeHandle<JSValue>();
1539  value = Handle<JSValue>::cast(isolate_->factory()->NewJSObject(
1540  isolate_->bigint_function(), pretenure_));
1541  value->set_value(*bigint);
1542  break;
1543  }
1544  case SerializationTag::kStringObject: {
1545  Handle<String> string;
1546  if (!ReadString().ToHandle(&string)) return MaybeHandle<JSValue>();
1547  value = Handle<JSValue>::cast(isolate_->factory()->NewJSObject(
1548  isolate_->string_function(), pretenure_));
1549  value->set_value(*string);
1550  break;
1551  }
1552  default:
1553  UNREACHABLE();
1554  }
1555  AddObjectWithID(id, value);
1556  return value;
1557 }
1558 
1559 MaybeHandle<JSRegExp> ValueDeserializer::ReadJSRegExp() {
1560  uint32_t id = next_id_++;
1561  Handle<String> pattern;
1562  uint32_t raw_flags;
1563  Handle<JSRegExp> regexp;
1564  if (!ReadString().ToHandle(&pattern) ||
1565  !ReadVarint<uint32_t>().To(&raw_flags)) {
1566  return MaybeHandle<JSRegExp>();
1567  }
1568 
1569  // Ensure the deserialized flags are valid.
1570  // TODO(adamk): Can we remove this check now that dotAll is always-on?
1571  uint32_t flags_mask = static_cast<uint32_t>(-1) << JSRegExp::FlagCount();
1572  if ((raw_flags & flags_mask) ||
1573  !JSRegExp::New(isolate_, pattern, static_cast<JSRegExp::Flags>(raw_flags))
1574  .ToHandle(&regexp)) {
1575  return MaybeHandle<JSRegExp>();
1576  }
1577 
1578  AddObjectWithID(id, regexp);
1579  return regexp;
1580 }
1581 
1582 MaybeHandle<JSMap> ValueDeserializer::ReadJSMap() {
1583  // If we are at the end of the stack, abort. This function may recurse.
1584  STACK_CHECK(isolate_, MaybeHandle<JSMap>());
1585 
1586  HandleScope scope(isolate_);
1587  uint32_t id = next_id_++;
1588  Handle<JSMap> map = isolate_->factory()->NewJSMap();
1589  AddObjectWithID(id, map);
1590 
1591  Handle<JSFunction> map_set = isolate_->map_set();
1592  uint32_t length = 0;
1593  while (true) {
1594  SerializationTag tag;
1595  if (!PeekTag().To(&tag)) return MaybeHandle<JSMap>();
1596  if (tag == SerializationTag::kEndJSMap) {
1597  ConsumeTag(SerializationTag::kEndJSMap);
1598  break;
1599  }
1600 
1601  Handle<Object> argv[2];
1602  if (!ReadObject().ToHandle(&argv[0]) || !ReadObject().ToHandle(&argv[1])) {
1603  return MaybeHandle<JSMap>();
1604  }
1605 
1606  AllowJavascriptExecution allow_js(isolate_);
1607  if (Execution::Call(isolate_, map_set, map, arraysize(argv), argv)
1608  .is_null()) {
1609  return MaybeHandle<JSMap>();
1610  }
1611  length += 2;
1612  }
1613 
1614  uint32_t expected_length;
1615  if (!ReadVarint<uint32_t>().To(&expected_length) ||
1616  length != expected_length) {
1617  return MaybeHandle<JSMap>();
1618  }
1619  DCHECK(HasObjectWithID(id));
1620  return scope.CloseAndEscape(map);
1621 }
1622 
1623 MaybeHandle<JSSet> ValueDeserializer::ReadJSSet() {
1624  // If we are at the end of the stack, abort. This function may recurse.
1625  STACK_CHECK(isolate_, MaybeHandle<JSSet>());
1626 
1627  HandleScope scope(isolate_);
1628  uint32_t id = next_id_++;
1629  Handle<JSSet> set = isolate_->factory()->NewJSSet();
1630  AddObjectWithID(id, set);
1631  Handle<JSFunction> set_add = isolate_->set_add();
1632  uint32_t length = 0;
1633  while (true) {
1634  SerializationTag tag;
1635  if (!PeekTag().To(&tag)) return MaybeHandle<JSSet>();
1636  if (tag == SerializationTag::kEndJSSet) {
1637  ConsumeTag(SerializationTag::kEndJSSet);
1638  break;
1639  }
1640 
1641  Handle<Object> argv[1];
1642  if (!ReadObject().ToHandle(&argv[0])) return MaybeHandle<JSSet>();
1643 
1644  AllowJavascriptExecution allow_js(isolate_);
1645  if (Execution::Call(isolate_, set_add, set, arraysize(argv), argv)
1646  .is_null()) {
1647  return MaybeHandle<JSSet>();
1648  }
1649  length++;
1650  }
1651 
1652  uint32_t expected_length;
1653  if (!ReadVarint<uint32_t>().To(&expected_length) ||
1654  length != expected_length) {
1655  return MaybeHandle<JSSet>();
1656  }
1657  DCHECK(HasObjectWithID(id));
1658  return scope.CloseAndEscape(set);
1659 }
1660 
1661 MaybeHandle<JSArrayBuffer> ValueDeserializer::ReadJSArrayBuffer(
1662  bool is_shared) {
1663  uint32_t id = next_id_++;
1664  if (is_shared) {
1665  uint32_t clone_id;
1666  Local<SharedArrayBuffer> sab_value;
1667  if (!ReadVarint<uint32_t>().To(&clone_id) || delegate_ == nullptr ||
1668  !delegate_
1669  ->GetSharedArrayBufferFromId(
1670  reinterpret_cast<v8::Isolate*>(isolate_), clone_id)
1671  .ToLocal(&sab_value)) {
1672  RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate_, JSArrayBuffer);
1673  return MaybeHandle<JSArrayBuffer>();
1674  }
1675  Handle<JSArrayBuffer> array_buffer = Utils::OpenHandle(*sab_value);
1676  DCHECK_EQ(is_shared, array_buffer->is_shared());
1677  AddObjectWithID(id, array_buffer);
1678  return array_buffer;
1679  }
1680  uint32_t byte_length;
1681  if (!ReadVarint<uint32_t>().To(&byte_length) ||
1682  byte_length > static_cast<size_t>(end_ - position_)) {
1683  return MaybeHandle<JSArrayBuffer>();
1684  }
1685  const bool should_initialize = false;
1686  Handle<JSArrayBuffer> array_buffer =
1687  isolate_->factory()->NewJSArrayBuffer(SharedFlag::kNotShared, pretenure_);
1688  if (!JSArrayBuffer::SetupAllocatingData(array_buffer, isolate_, byte_length,
1689  should_initialize)) {
1690  return MaybeHandle<JSArrayBuffer>();
1691  }
1692  memcpy(array_buffer->backing_store(), position_, byte_length);
1693  position_ += byte_length;
1694  AddObjectWithID(id, array_buffer);
1695  return array_buffer;
1696 }
1697 
1698 MaybeHandle<JSArrayBuffer> ValueDeserializer::ReadTransferredJSArrayBuffer() {
1699  uint32_t id = next_id_++;
1700  uint32_t transfer_id;
1701  Handle<SimpleNumberDictionary> transfer_map;
1702  if (!ReadVarint<uint32_t>().To(&transfer_id) ||
1703  !array_buffer_transfer_map_.ToHandle(&transfer_map)) {
1704  return MaybeHandle<JSArrayBuffer>();
1705  }
1706  int index = transfer_map->FindEntry(isolate_, transfer_id);
1707  if (index == SimpleNumberDictionary::kNotFound) {
1708  return MaybeHandle<JSArrayBuffer>();
1709  }
1710  Handle<JSArrayBuffer> array_buffer(
1711  JSArrayBuffer::cast(transfer_map->ValueAt(index)), isolate_);
1712  AddObjectWithID(id, array_buffer);
1713  return array_buffer;
1714 }
1715 
1716 MaybeHandle<JSArrayBufferView> ValueDeserializer::ReadJSArrayBufferView(
1717  Handle<JSArrayBuffer> buffer) {
1718  uint32_t buffer_byte_length = static_cast<uint32_t>(buffer->byte_length());
1719  uint8_t tag = 0;
1720  uint32_t byte_offset = 0;
1721  uint32_t byte_length = 0;
1722  if (!ReadVarint<uint8_t>().To(&tag) ||
1723  !ReadVarint<uint32_t>().To(&byte_offset) ||
1724  !ReadVarint<uint32_t>().To(&byte_length) ||
1725  byte_offset > buffer_byte_length ||
1726  byte_length > buffer_byte_length - byte_offset) {
1727  return MaybeHandle<JSArrayBufferView>();
1728  }
1729  uint32_t id = next_id_++;
1730  ExternalArrayType external_array_type = kExternalInt8Array;
1731  unsigned element_size = 0;
1732 
1733  switch (static_cast<ArrayBufferViewTag>(tag)) {
1734  case ArrayBufferViewTag::kDataView: {
1735  Handle<JSDataView> data_view =
1736  isolate_->factory()->NewJSDataView(buffer, byte_offset, byte_length);
1737  AddObjectWithID(id, data_view);
1738  return data_view;
1739  }
1740 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
1741  case ArrayBufferViewTag::k##Type##Array: \
1742  external_array_type = kExternal##Type##Array; \
1743  element_size = sizeof(ctype); \
1744  break;
1745  TYPED_ARRAYS(TYPED_ARRAY_CASE)
1746 #undef TYPED_ARRAY_CASE
1747  }
1748  if (element_size == 0 || byte_offset % element_size != 0 ||
1749  byte_length % element_size != 0) {
1750  return MaybeHandle<JSArrayBufferView>();
1751  }
1752  Handle<JSTypedArray> typed_array = isolate_->factory()->NewJSTypedArray(
1753  external_array_type, buffer, byte_offset, byte_length / element_size,
1754  pretenure_);
1755  AddObjectWithID(id, typed_array);
1756  return typed_array;
1757 }
1758 
1759 MaybeHandle<JSObject> ValueDeserializer::ReadWasmModuleTransfer() {
1760  auto enabled_features = wasm::WasmFeaturesFromIsolate(isolate_);
1761  if ((FLAG_wasm_disable_structured_cloning && !enabled_features.threads) ||
1762  expect_inline_wasm()) {
1763  return MaybeHandle<JSObject>();
1764  }
1765 
1766  uint32_t transfer_id = 0;
1767  Local<Value> module_value;
1768  if (!ReadVarint<uint32_t>().To(&transfer_id) || delegate_ == nullptr ||
1769  !delegate_
1770  ->GetWasmModuleFromId(reinterpret_cast<v8::Isolate*>(isolate_),
1771  transfer_id)
1772  .ToLocal(&module_value)) {
1773  RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate_, JSObject);
1774  return MaybeHandle<JSObject>();
1775  }
1776  uint32_t id = next_id_++;
1777  Handle<JSObject> module =
1778  Handle<JSObject>::cast(Utils::OpenHandle(*module_value));
1779  AddObjectWithID(id, module);
1780  return module;
1781 }
1782 
1783 MaybeHandle<JSObject> ValueDeserializer::ReadWasmModule() {
1784  auto enabled_features = wasm::WasmFeaturesFromIsolate(isolate_);
1785  if ((FLAG_wasm_disable_structured_cloning && !enabled_features.threads) ||
1786  !expect_inline_wasm()) {
1787  return MaybeHandle<JSObject>();
1788  }
1789 
1790  Vector<const uint8_t> encoding_tag;
1791  if (!ReadRawBytes(sizeof(WasmEncodingTag)).To(&encoding_tag) ||
1792  encoding_tag[0] != static_cast<uint8_t>(WasmEncodingTag::kRawBytes)) {
1793  return MaybeHandle<JSObject>();
1794  }
1795 
1796  // Extract the data from the buffer: wasm wire bytes, followed by V8 compiled
1797  // script data.
1798  static_assert(sizeof(int) <= sizeof(uint32_t),
1799  "max int must fit in uint32_t");
1800  const uint32_t max_valid_size = std::numeric_limits<int>::max();
1801  uint32_t wire_bytes_length = 0;
1802  Vector<const uint8_t> wire_bytes;
1803  uint32_t compiled_bytes_length = 0;
1804  Vector<const uint8_t> compiled_bytes;
1805  if (!ReadVarint<uint32_t>().To(&wire_bytes_length) ||
1806  wire_bytes_length > max_valid_size ||
1807  !ReadRawBytes(wire_bytes_length).To(&wire_bytes) ||
1808  !ReadVarint<uint32_t>().To(&compiled_bytes_length) ||
1809  compiled_bytes_length > max_valid_size ||
1810  !ReadRawBytes(compiled_bytes_length).To(&compiled_bytes)) {
1811  return MaybeHandle<JSObject>();
1812  }
1813 
1814  // Try to deserialize the compiled module first.
1815  MaybeHandle<WasmModuleObject> result =
1816  wasm::DeserializeNativeModule(isolate_, compiled_bytes, wire_bytes);
1817  if (result.is_null()) {
1818  wasm::ErrorThrower thrower(isolate_, "ValueDeserializer::ReadWasmModule");
1819  // TODO(titzer): are the current features appropriate for deserializing?
1820  auto enabled_features = wasm::WasmFeaturesFromIsolate(isolate_);
1821  result = isolate_->wasm_engine()->SyncCompile(
1822  isolate_, enabled_features, &thrower,
1823  wasm::ModuleWireBytes(wire_bytes));
1824  }
1825  uint32_t id = next_id_++;
1826  if (!result.is_null()) {
1827  AddObjectWithID(id, result.ToHandleChecked());
1828  }
1829  return result;
1830 }
1831 
1832 MaybeHandle<WasmMemoryObject> ValueDeserializer::ReadWasmMemory() {
1833  uint32_t id = next_id_++;
1834 
1835  auto enabled_features = wasm::WasmFeaturesFromIsolate(isolate_);
1836  if (!enabled_features.threads) {
1837  return MaybeHandle<WasmMemoryObject>();
1838  }
1839 
1840  int32_t maximum_pages;
1841  if (!ReadZigZag<int32_t>().To(&maximum_pages)) {
1842  return MaybeHandle<WasmMemoryObject>();
1843  }
1844 
1845  SerializationTag tag;
1846  if (!ReadTag().To(&tag) || tag != SerializationTag::kSharedArrayBuffer) {
1847  return MaybeHandle<WasmMemoryObject>();
1848  }
1849 
1850  const bool is_shared = true;
1851  Handle<JSArrayBuffer> buffer;
1852  if (!ReadJSArrayBuffer(is_shared).ToHandle(&buffer)) {
1853  return MaybeHandle<WasmMemoryObject>();
1854  }
1855 
1856  Handle<WasmMemoryObject> result =
1857  WasmMemoryObject::New(isolate_, buffer, maximum_pages);
1858 
1859  AddObjectWithID(id, result);
1860  return result;
1861 }
1862 
1863 MaybeHandle<JSObject> ValueDeserializer::ReadHostObject() {
1864  if (!delegate_) return MaybeHandle<JSObject>();
1865  STACK_CHECK(isolate_, MaybeHandle<JSObject>());
1866  uint32_t id = next_id_++;
1867  v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate_);
1868  v8::Local<v8::Object> object;
1869  if (!delegate_->ReadHostObject(v8_isolate).ToLocal(&object)) {
1870  RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate_, JSObject);
1871  return MaybeHandle<JSObject>();
1872  }
1873  Handle<JSObject> js_object =
1874  Handle<JSObject>::cast(Utils::OpenHandle(*object));
1875  AddObjectWithID(id, js_object);
1876  return js_object;
1877 }
1878 
1879 // Copies a vector of property values into an object, given the map that should
1880 // be used.
1881 static void CommitProperties(Handle<JSObject> object, Handle<Map> map,
1882  const std::vector<Handle<Object>>& properties) {
1883  JSObject::AllocateStorageForMap(object, map);
1884  DCHECK(!object->map()->is_dictionary_map());
1885 
1886  DisallowHeapAllocation no_gc;
1887  DescriptorArray* descriptors = object->map()->instance_descriptors();
1888  for (unsigned i = 0; i < properties.size(); i++) {
1889  // Initializing store.
1890  object->WriteToField(i, descriptors->GetDetails(i), *properties[i]);
1891  }
1892 }
1893 
1894 static bool IsValidObjectKey(Handle<Object> value) {
1895  return value->IsName() || value->IsNumber();
1896 }
1897 
1898 Maybe<uint32_t> ValueDeserializer::ReadJSObjectProperties(
1899  Handle<JSObject> object, SerializationTag end_tag,
1900  bool can_use_transitions) {
1901  uint32_t num_properties = 0;
1902 
1903  // Fast path (following map transitions).
1904  if (can_use_transitions) {
1905  bool transitioning = true;
1906  Handle<Map> map(object->map(), isolate_);
1907  DCHECK(!map->is_dictionary_map());
1908  DCHECK_EQ(0, map->instance_descriptors()->number_of_descriptors());
1909  std::vector<Handle<Object>> properties;
1910  properties.reserve(8);
1911 
1912  while (transitioning) {
1913  // If there are no more properties, finish.
1914  SerializationTag tag;
1915  if (!PeekTag().To(&tag)) return Nothing<uint32_t>();
1916  if (tag == end_tag) {
1917  ConsumeTag(end_tag);
1918  CommitProperties(object, map, properties);
1919  CHECK_LT(properties.size(), std::numeric_limits<uint32_t>::max());
1920  return Just(static_cast<uint32_t>(properties.size()));
1921  }
1922 
1923  // Determine the key to be used and the target map to transition to, if
1924  // possible. Transitioning may abort if the key is not a string, or if no
1925  // transition was found.
1926  Handle<Object> key;
1927  Handle<Map> target;
1928  TransitionsAccessor transitions(isolate_, map);
1929  Handle<String> expected_key = transitions.ExpectedTransitionKey();
1930  if (!expected_key.is_null() && ReadExpectedString(expected_key)) {
1931  key = expected_key;
1932  target = transitions.ExpectedTransitionTarget();
1933  } else {
1934  if (!ReadObject().ToHandle(&key) || !IsValidObjectKey(key)) {
1935  return Nothing<uint32_t>();
1936  }
1937  if (key->IsString()) {
1938  key =
1939  isolate_->factory()->InternalizeString(Handle<String>::cast(key));
1940  // Don't reuse |transitions| because it could be stale.
1941  transitioning = TransitionsAccessor(isolate_, map)
1942  .FindTransitionToField(Handle<String>::cast(key))
1943  .ToHandle(&target);
1944  } else {
1945  transitioning = false;
1946  }
1947  }
1948 
1949  // Read the value that corresponds to it.
1950  Handle<Object> value;
1951  if (!ReadObject().ToHandle(&value)) return Nothing<uint32_t>();
1952 
1953  // If still transitioning and the value fits the field representation
1954  // (though generalization may be required), store the property value so
1955  // that we can copy them all at once. Otherwise, stop transitioning.
1956  if (transitioning) {
1957  int descriptor = static_cast<int>(properties.size());
1958  PropertyDetails details =
1959  target->instance_descriptors()->GetDetails(descriptor);
1960  Representation expected_representation = details.representation();
1961  if (value->FitsRepresentation(expected_representation)) {
1962  if (expected_representation.IsHeapObject() &&
1963  !target->instance_descriptors()
1964  ->GetFieldType(descriptor)
1965  ->NowContains(value)) {
1966  Handle<FieldType> value_type =
1967  value->OptimalType(isolate_, expected_representation);
1968  Map::GeneralizeField(isolate_, target, descriptor,
1969  details.constness(), expected_representation,
1970  value_type);
1971  }
1972  DCHECK(target->instance_descriptors()
1973  ->GetFieldType(descriptor)
1974  ->NowContains(value));
1975  properties.push_back(value);
1976  map = target;
1977  continue;
1978  } else {
1979  transitioning = false;
1980  }
1981  }
1982 
1983  // Fell out of transitioning fast path. Commit the properties gathered so
1984  // far, and then start setting properties slowly instead.
1985  DCHECK(!transitioning);
1986  CHECK_LT(properties.size(), std::numeric_limits<uint32_t>::max());
1987  CommitProperties(object, map, properties);
1988  num_properties = static_cast<uint32_t>(properties.size());
1989 
1990  bool success;
1991  LookupIterator it = LookupIterator::PropertyOrElement(
1992  isolate_, object, key, &success, LookupIterator::OWN);
1993  CHECK_EQ(LookupIterator::NOT_FOUND, it.state());
1994  if (!success ||
1995  JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, NONE)
1996  .is_null()) {
1997  return Nothing<uint32_t>();
1998  }
1999  num_properties++;
2000  }
2001 
2002  // At this point, transitioning should be done, but at least one property
2003  // should have been written (in the zero-property case, there is an early
2004  // return).
2005  DCHECK(!transitioning);
2006  DCHECK_GE(num_properties, 1u);
2007  }
2008 
2009  // Slow path.
2010  for (;; num_properties++) {
2011  SerializationTag tag;
2012  if (!PeekTag().To(&tag)) return Nothing<uint32_t>();
2013  if (tag == end_tag) {
2014  ConsumeTag(end_tag);
2015  return Just(num_properties);
2016  }
2017 
2018  Handle<Object> key;
2019  if (!ReadObject().ToHandle(&key) || !IsValidObjectKey(key)) {
2020  return Nothing<uint32_t>();
2021  }
2022  Handle<Object> value;
2023  if (!ReadObject().ToHandle(&value)) return Nothing<uint32_t>();
2024 
2025  bool success;
2026  LookupIterator it = LookupIterator::PropertyOrElement(
2027  isolate_, object, key, &success, LookupIterator::OWN);
2028  CHECK_EQ(LookupIterator::NOT_FOUND, it.state());
2029  if (!success ||
2030  JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, NONE)
2031  .is_null()) {
2032  return Nothing<uint32_t>();
2033  }
2034  }
2035 }
2036 
2037 bool ValueDeserializer::HasObjectWithID(uint32_t id) {
2038  return id < static_cast<unsigned>(id_map_->length()) &&
2039  !id_map_->get(id)->IsTheHole(isolate_);
2040 }
2041 
2042 MaybeHandle<JSReceiver> ValueDeserializer::GetObjectWithID(uint32_t id) {
2043  if (id >= static_cast<unsigned>(id_map_->length())) {
2044  return MaybeHandle<JSReceiver>();
2045  }
2046  Object* value = id_map_->get(id);
2047  if (value->IsTheHole(isolate_)) return MaybeHandle<JSReceiver>();
2048  DCHECK(value->IsJSReceiver());
2049  return Handle<JSReceiver>(JSReceiver::cast(value), isolate_);
2050 }
2051 
2052 void ValueDeserializer::AddObjectWithID(uint32_t id,
2053  Handle<JSReceiver> object) {
2054  DCHECK(!HasObjectWithID(id));
2055  Handle<FixedArray> new_array =
2056  FixedArray::SetAndGrow(isolate_, id_map_, id, object);
2057 
2058  // If the dictionary was reallocated, update the global handle.
2059  if (!new_array.is_identical_to(id_map_)) {
2060  GlobalHandles::Destroy(id_map_.location());
2061  id_map_ = Handle<FixedArray>::cast(
2062  isolate_->global_handles()->Create(*new_array));
2063  }
2064 }
2065 
2066 static Maybe<bool> SetPropertiesFromKeyValuePairs(Isolate* isolate,
2067  Handle<JSObject> object,
2068  Handle<Object>* data,
2069  uint32_t num_properties) {
2070  for (unsigned i = 0; i < 2 * num_properties; i += 2) {
2071  Handle<Object> key = data[i];
2072  if (!IsValidObjectKey(key)) return Nothing<bool>();
2073  Handle<Object> value = data[i + 1];
2074  bool success;
2075  LookupIterator it = LookupIterator::PropertyOrElement(
2076  isolate, object, key, &success, LookupIterator::OWN);
2077  CHECK_EQ(LookupIterator::NOT_FOUND, it.state());
2078  if (!success ||
2079  JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, NONE)
2080  .is_null()) {
2081  return Nothing<bool>();
2082  }
2083  }
2084  return Just(true);
2085 }
2086 
2087 namespace {
2088 
2089 // Throws a generic "deserialization failed" exception by default, unless a more
2090 // specific exception has already been thrown.
2091 void ThrowDeserializationExceptionIfNonePending(Isolate* isolate) {
2092  if (!isolate->has_pending_exception()) {
2093  isolate->Throw(*isolate->factory()->NewError(
2094  MessageTemplate::kDataCloneDeserializationError));
2095  }
2096  DCHECK(isolate->has_pending_exception());
2097 }
2098 
2099 } // namespace
2100 
2101 MaybeHandle<Object>
2102 ValueDeserializer::ReadObjectUsingEntireBufferForLegacyFormat() {
2103  DCHECK_EQ(version_, 0u);
2104  HandleScope scope(isolate_);
2105  std::vector<Handle<Object>> stack;
2106  while (position_ < end_) {
2107  SerializationTag tag;
2108  if (!PeekTag().To(&tag)) break;
2109 
2110  Handle<Object> new_object;
2111  switch (tag) {
2112  case SerializationTag::kEndJSObject: {
2113  ConsumeTag(SerializationTag::kEndJSObject);
2114 
2115  // JS Object: Read the last 2*n values from the stack and use them as
2116  // key-value pairs.
2117  uint32_t num_properties;
2118  if (!ReadVarint<uint32_t>().To(&num_properties) ||
2119  stack.size() / 2 < num_properties) {
2120  isolate_->Throw(*isolate_->factory()->NewError(
2121  MessageTemplate::kDataCloneDeserializationError));
2122  return MaybeHandle<Object>();
2123  }
2124 
2125  size_t begin_properties =
2126  stack.size() - 2 * static_cast<size_t>(num_properties);
2127  Handle<JSObject> js_object = isolate_->factory()->NewJSObject(
2128  isolate_->object_function(), pretenure_);
2129  if (num_properties &&
2130  !SetPropertiesFromKeyValuePairs(
2131  isolate_, js_object, &stack[begin_properties], num_properties)
2132  .FromMaybe(false)) {
2133  ThrowDeserializationExceptionIfNonePending(isolate_);
2134  return MaybeHandle<Object>();
2135  }
2136 
2137  stack.resize(begin_properties);
2138  new_object = js_object;
2139  break;
2140  }
2141  case SerializationTag::kEndSparseJSArray: {
2142  ConsumeTag(SerializationTag::kEndSparseJSArray);
2143 
2144  // Sparse JS Array: Read the last 2*|num_properties| from the stack.
2145  uint32_t num_properties;
2146  uint32_t length;
2147  if (!ReadVarint<uint32_t>().To(&num_properties) ||
2148  !ReadVarint<uint32_t>().To(&length) ||
2149  stack.size() / 2 < num_properties) {
2150  isolate_->Throw(*isolate_->factory()->NewError(
2151  MessageTemplate::kDataCloneDeserializationError));
2152  return MaybeHandle<Object>();
2153  }
2154 
2155  Handle<JSArray> js_array = isolate_->factory()->NewJSArray(
2156  0, TERMINAL_FAST_ELEMENTS_KIND, pretenure_);
2157  JSArray::SetLength(js_array, length);
2158  size_t begin_properties =
2159  stack.size() - 2 * static_cast<size_t>(num_properties);
2160  if (num_properties &&
2161  !SetPropertiesFromKeyValuePairs(
2162  isolate_, js_array, &stack[begin_properties], num_properties)
2163  .FromMaybe(false)) {
2164  ThrowDeserializationExceptionIfNonePending(isolate_);
2165  return MaybeHandle<Object>();
2166  }
2167 
2168  stack.resize(begin_properties);
2169  new_object = js_array;
2170  break;
2171  }
2172  case SerializationTag::kEndDenseJSArray: {
2173  // This was already broken in Chromium, and apparently wasn't missed.
2174  isolate_->Throw(*isolate_->factory()->NewError(
2175  MessageTemplate::kDataCloneDeserializationError));
2176  return MaybeHandle<Object>();
2177  }
2178  default:
2179  if (!ReadObject().ToHandle(&new_object)) return MaybeHandle<Object>();
2180  break;
2181  }
2182  stack.push_back(new_object);
2183  }
2184 
2185 // Nothing remains but padding.
2186 #ifdef DEBUG
2187  while (position_ < end_) {
2188  DCHECK(*position_++ == static_cast<uint8_t>(SerializationTag::kPadding));
2189  }
2190 #endif
2191  position_ = end_;
2192 
2193  if (stack.size() != 1) {
2194  isolate_->Throw(*isolate_->factory()->NewError(
2195  MessageTemplate::kDataCloneDeserializationError));
2196  return MaybeHandle<Object>();
2197  }
2198  return scope.CloseAndEscape(stack[0]);
2199 }
2200 
2201 } // namespace internal
2202 } // namespace v8
virtual Maybe< uint32_t > GetSharedArrayBufferId(Isolate *isolate, Local< SharedArrayBuffer > shared_array_buffer)
Definition: api.cc:3049
virtual void * ReallocateBufferMemory(void *old_buffer, size_t size, size_t *actual_size)
Definition: api.cc:3063
Definition: v8.h:85
virtual void FreeBufferMemory(void *buffer)
Definition: api.cc:3070
Definition: libplatform.h:13
virtual MaybeLocal< Object > ReadHostObject(Isolate *isolate)
Definition: api.cc:3144
virtual MaybeLocal< WasmCompiledModule > GetWasmModuleFromId(Isolate *isolate, uint32_t transfer_id)
Definition: api.cc:3153
virtual Maybe< bool > WriteHostObject(Isolate *isolate, Local< Object > object)
Definition: api.cc:3040
virtual void ThrowDataCloneError(Local< String > message)=0