OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/value-serializer.h" | 5 #include "src/value-serializer.h" |
6 | 6 |
7 #include <type_traits> | 7 #include <type_traits> |
8 | 8 |
9 #include "src/base/logging.h" | 9 #include "src/base/logging.h" |
10 #include "src/conversions.h" | 10 #include "src/conversions.h" |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
210 WriteRawBytes(chars.begin(), chars.length() * sizeof(uint8_t)); | 210 WriteRawBytes(chars.begin(), chars.length() * sizeof(uint8_t)); |
211 } | 211 } |
212 | 212 |
213 void ValueSerializer::WriteTwoByteString(Vector<const uc16> chars) { | 213 void ValueSerializer::WriteTwoByteString(Vector<const uc16> chars) { |
214 // Warning: this uses host endianness. | 214 // Warning: this uses host endianness. |
215 WriteVarint<uint32_t>(chars.length() * sizeof(uc16)); | 215 WriteVarint<uint32_t>(chars.length() * sizeof(uc16)); |
216 WriteRawBytes(chars.begin(), chars.length() * sizeof(uc16)); | 216 WriteRawBytes(chars.begin(), chars.length() * sizeof(uc16)); |
217 } | 217 } |
218 | 218 |
219 void ValueSerializer::WriteRawBytes(const void* source, size_t length) { | 219 void ValueSerializer::WriteRawBytes(const void* source, size_t length) { |
220 uint8_t* dest; | 220 memcpy(ReserveRawBytes(length), source, length); |
221 if (ReserveRawBytes(length).To(&dest)) { | |
222 memcpy(dest, source, length); | |
223 } | |
224 } | 221 } |
225 | 222 |
226 Maybe<uint8_t*> ValueSerializer::ReserveRawBytes(size_t bytes) { | 223 uint8_t* ValueSerializer::ReserveRawBytes(size_t bytes) { |
227 size_t old_size = buffer_size_; | 224 size_t old_size = buffer_size_; |
228 size_t new_size = old_size + bytes; | 225 size_t new_size = old_size + bytes; |
229 if (new_size > buffer_capacity_) { | 226 if (new_size > buffer_capacity_) ExpandBuffer(new_size); |
230 bool ok; | |
231 if (!ExpandBuffer(new_size).To(&ok)) { | |
232 return Nothing<uint8_t*>(); | |
233 } | |
234 } | |
235 buffer_size_ = new_size; | 227 buffer_size_ = new_size; |
236 return Just(&buffer_[old_size]); | 228 return &buffer_[old_size]; |
237 } | 229 } |
238 | 230 |
239 Maybe<bool> ValueSerializer::ExpandBuffer(size_t required_capacity) { | 231 void ValueSerializer::ExpandBuffer(size_t required_capacity) { |
240 DCHECK_GT(required_capacity, buffer_capacity_); | 232 DCHECK_GT(required_capacity, buffer_capacity_); |
241 size_t requested_capacity = | 233 size_t requested_capacity = |
242 std::max(required_capacity, buffer_capacity_ * 2) + 64; | 234 std::max(required_capacity, buffer_capacity_ * 2) + 64; |
243 size_t provided_capacity = 0; | 235 size_t provided_capacity = 0; |
244 void* new_buffer = nullptr; | 236 void* new_buffer = nullptr; |
245 if (delegate_) { | 237 if (delegate_) { |
246 new_buffer = delegate_->ReallocateBufferMemory(buffer_, requested_capacity, | 238 new_buffer = delegate_->ReallocateBufferMemory(buffer_, requested_capacity, |
247 &provided_capacity); | 239 &provided_capacity); |
248 } else { | 240 } else { |
249 new_buffer = realloc(buffer_, requested_capacity); | 241 new_buffer = realloc(buffer_, requested_capacity); |
250 provided_capacity = requested_capacity; | 242 provided_capacity = requested_capacity; |
251 } | 243 } |
252 if (new_buffer) { | 244 DCHECK_GE(provided_capacity, requested_capacity); |
253 DCHECK(provided_capacity >= requested_capacity); | 245 buffer_ = reinterpret_cast<uint8_t*>(new_buffer); |
254 buffer_ = reinterpret_cast<uint8_t*>(new_buffer); | 246 buffer_capacity_ = provided_capacity; |
255 buffer_capacity_ = provided_capacity; | |
256 return Just(true); | |
257 } else { | |
258 out_of_memory_ = true; | |
259 return Nothing<bool>(); | |
260 } | |
261 } | 247 } |
262 | 248 |
263 void ValueSerializer::WriteUint32(uint32_t value) { | 249 void ValueSerializer::WriteUint32(uint32_t value) { |
264 WriteVarint<uint32_t>(value); | 250 WriteVarint<uint32_t>(value); |
265 } | 251 } |
266 | 252 |
267 void ValueSerializer::WriteUint64(uint64_t value) { | 253 void ValueSerializer::WriteUint64(uint64_t value) { |
268 WriteVarint<uint64_t>(value); | 254 WriteVarint<uint64_t>(value); |
269 } | 255 } |
270 | 256 |
(...skipping 10 matching lines...) Expand all Loading... |
281 } | 267 } |
282 | 268 |
283 void ValueSerializer::TransferArrayBuffer(uint32_t transfer_id, | 269 void ValueSerializer::TransferArrayBuffer(uint32_t transfer_id, |
284 Handle<JSArrayBuffer> array_buffer) { | 270 Handle<JSArrayBuffer> array_buffer) { |
285 DCHECK(!array_buffer_transfer_map_.Find(array_buffer)); | 271 DCHECK(!array_buffer_transfer_map_.Find(array_buffer)); |
286 DCHECK(!array_buffer->is_shared()); | 272 DCHECK(!array_buffer->is_shared()); |
287 array_buffer_transfer_map_.Set(array_buffer, transfer_id); | 273 array_buffer_transfer_map_.Set(array_buffer, transfer_id); |
288 } | 274 } |
289 | 275 |
290 Maybe<bool> ValueSerializer::WriteObject(Handle<Object> object) { | 276 Maybe<bool> ValueSerializer::WriteObject(Handle<Object> object) { |
291 out_of_memory_ = false; | |
292 if (object->IsSmi()) { | 277 if (object->IsSmi()) { |
293 WriteSmi(Smi::cast(*object)); | 278 WriteSmi(Smi::cast(*object)); |
294 return ThrowIfOutOfMemory(); | 279 return Just(true); |
295 } | 280 } |
296 | 281 |
297 DCHECK(object->IsHeapObject()); | 282 DCHECK(object->IsHeapObject()); |
298 switch (HeapObject::cast(*object)->map()->instance_type()) { | 283 switch (HeapObject::cast(*object)->map()->instance_type()) { |
299 case ODDBALL_TYPE: | 284 case ODDBALL_TYPE: |
300 WriteOddball(Oddball::cast(*object)); | 285 WriteOddball(Oddball::cast(*object)); |
301 return ThrowIfOutOfMemory(); | 286 return Just(true); |
302 case HEAP_NUMBER_TYPE: | 287 case HEAP_NUMBER_TYPE: |
303 case MUTABLE_HEAP_NUMBER_TYPE: | 288 case MUTABLE_HEAP_NUMBER_TYPE: |
304 WriteHeapNumber(HeapNumber::cast(*object)); | 289 WriteHeapNumber(HeapNumber::cast(*object)); |
305 return ThrowIfOutOfMemory(); | 290 return Just(true); |
306 case JS_TYPED_ARRAY_TYPE: | 291 case JS_TYPED_ARRAY_TYPE: |
307 case JS_DATA_VIEW_TYPE: { | 292 case JS_DATA_VIEW_TYPE: { |
308 // Despite being JSReceivers, these have their wrapped buffer serialized | 293 // Despite being JSReceivers, these have their wrapped buffer serialized |
309 // first. That makes this logic a little quirky, because it needs to | 294 // first. That makes this logic a little quirky, because it needs to |
310 // happen before we assign object IDs. | 295 // happen before we assign object IDs. |
311 // TODO(jbroman): It may be possible to avoid materializing a typed | 296 // TODO(jbroman): It may be possible to avoid materializing a typed |
312 // array's buffer here. | 297 // array's buffer here. |
313 Handle<JSArrayBufferView> view = Handle<JSArrayBufferView>::cast(object); | 298 Handle<JSArrayBufferView> view = Handle<JSArrayBufferView>::cast(object); |
314 if (!id_map_.Find(view)) { | 299 if (!id_map_.Find(view)) { |
315 Handle<JSArrayBuffer> buffer( | 300 Handle<JSArrayBuffer> buffer( |
316 view->IsJSTypedArray() | 301 view->IsJSTypedArray() |
317 ? Handle<JSTypedArray>::cast(view)->GetBuffer() | 302 ? Handle<JSTypedArray>::cast(view)->GetBuffer() |
318 : handle(JSArrayBuffer::cast(view->buffer()), isolate_)); | 303 : handle(JSArrayBuffer::cast(view->buffer()), isolate_)); |
319 if (!WriteJSReceiver(buffer).FromMaybe(false)) return Nothing<bool>(); | 304 if (!WriteJSReceiver(buffer).FromMaybe(false)) return Nothing<bool>(); |
320 } | 305 } |
321 return WriteJSReceiver(view); | 306 return WriteJSReceiver(view); |
322 } | 307 } |
323 default: | 308 default: |
324 if (object->IsString()) { | 309 if (object->IsString()) { |
325 WriteString(Handle<String>::cast(object)); | 310 WriteString(Handle<String>::cast(object)); |
326 return ThrowIfOutOfMemory(); | 311 return Just(true); |
327 } else if (object->IsJSReceiver()) { | 312 } else if (object->IsJSReceiver()) { |
328 return WriteJSReceiver(Handle<JSReceiver>::cast(object)); | 313 return WriteJSReceiver(Handle<JSReceiver>::cast(object)); |
329 } else { | 314 } else { |
330 ThrowDataCloneError(MessageTemplate::kDataCloneError, object); | 315 ThrowDataCloneError(MessageTemplate::kDataCloneError, object); |
331 return Nothing<bool>(); | 316 return Nothing<bool>(); |
332 } | 317 } |
333 } | 318 } |
334 } | 319 } |
335 | 320 |
336 void ValueSerializer::WriteOddball(Oddball* oddball) { | 321 void ValueSerializer::WriteOddball(Oddball* oddball) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
377 // TODO(jbroman): In a future format version, consider adding a tag for | 362 // TODO(jbroman): In a future format version, consider adding a tag for |
378 // Latin-1 strings, so that this can be skipped. | 363 // Latin-1 strings, so that this can be skipped. |
379 WriteTag(SerializationTag::kUtf8String); | 364 WriteTag(SerializationTag::kUtf8String); |
380 Vector<const uint8_t> chars = flat.ToOneByteVector(); | 365 Vector<const uint8_t> chars = flat.ToOneByteVector(); |
381 if (String::IsAscii(chars.begin(), chars.length())) { | 366 if (String::IsAscii(chars.begin(), chars.length())) { |
382 WriteOneByteString(chars); | 367 WriteOneByteString(chars); |
383 } else { | 368 } else { |
384 v8::Local<v8::String> api_string = Utils::ToLocal(string); | 369 v8::Local<v8::String> api_string = Utils::ToLocal(string); |
385 uint32_t utf8_length = api_string->Utf8Length(); | 370 uint32_t utf8_length = api_string->Utf8Length(); |
386 WriteVarint(utf8_length); | 371 WriteVarint(utf8_length); |
387 uint8_t* dest; | 372 api_string->WriteUtf8( |
388 if (ReserveRawBytes(utf8_length).To(&dest)) { | 373 reinterpret_cast<char*>(ReserveRawBytes(utf8_length)), utf8_length, |
389 api_string->WriteUtf8(reinterpret_cast<char*>(dest), utf8_length, | 374 nullptr, v8::String::NO_NULL_TERMINATION); |
390 nullptr, v8::String::NO_NULL_TERMINATION); | |
391 } | |
392 } | 375 } |
393 } else if (flat.IsTwoByte()) { | 376 } else if (flat.IsTwoByte()) { |
394 Vector<const uc16> chars = flat.ToUC16Vector(); | 377 Vector<const uc16> chars = flat.ToUC16Vector(); |
395 uint32_t byte_length = chars.length() * sizeof(uc16); | 378 uint32_t byte_length = chars.length() * sizeof(uc16); |
396 // The existing reading code expects 16-byte strings to be aligned. | 379 // The existing reading code expects 16-byte strings to be aligned. |
397 if ((buffer_size_ + 1 + BytesNeededForVarint(byte_length)) & 1) | 380 if ((buffer_size_ + 1 + BytesNeededForVarint(byte_length)) & 1) |
398 WriteTag(SerializationTag::kPadding); | 381 WriteTag(SerializationTag::kPadding); |
399 WriteTag(SerializationTag::kTwoByteString); | 382 WriteTag(SerializationTag::kTwoByteString); |
400 WriteTwoByteString(chars); | 383 WriteTwoByteString(chars); |
401 } else { | 384 } else { |
402 UNREACHABLE(); | 385 UNREACHABLE(); |
403 } | 386 } |
404 } | 387 } |
405 | 388 |
406 Maybe<bool> ValueSerializer::WriteJSReceiver(Handle<JSReceiver> receiver) { | 389 Maybe<bool> ValueSerializer::WriteJSReceiver(Handle<JSReceiver> receiver) { |
407 // If the object has already been serialized, just write its ID. | 390 // If the object has already been serialized, just write its ID. |
408 uint32_t* id_map_entry = id_map_.Get(receiver); | 391 uint32_t* id_map_entry = id_map_.Get(receiver); |
409 if (uint32_t id = *id_map_entry) { | 392 if (uint32_t id = *id_map_entry) { |
410 WriteTag(SerializationTag::kObjectReference); | 393 WriteTag(SerializationTag::kObjectReference); |
411 WriteVarint(id - 1); | 394 WriteVarint(id - 1); |
412 return ThrowIfOutOfMemory(); | 395 return Just(true); |
413 } | 396 } |
414 | 397 |
415 // Otherwise, allocate an ID for it. | 398 // Otherwise, allocate an ID for it. |
416 uint32_t id = next_id_++; | 399 uint32_t id = next_id_++; |
417 *id_map_entry = id + 1; | 400 *id_map_entry = id + 1; |
418 | 401 |
419 // Eliminate callable and exotic objects, which should not be serialized. | 402 // Eliminate callable and exotic objects, which should not be serialized. |
420 InstanceType instance_type = receiver->map()->instance_type(); | 403 InstanceType instance_type = receiver->map()->instance_type(); |
421 if (receiver->IsCallable() || (IsSpecialReceiverInstanceType(instance_type) && | 404 if (receiver->IsCallable() || (IsSpecialReceiverInstanceType(instance_type) && |
422 instance_type != JS_SPECIAL_API_OBJECT_TYPE)) { | 405 instance_type != JS_SPECIAL_API_OBJECT_TYPE)) { |
(...skipping 19 matching lines...) Expand all Loading... |
442 } else if (JSObject::GetInternalFieldCount(map)) { | 425 } else if (JSObject::GetInternalFieldCount(map)) { |
443 return WriteHostObject(js_object); | 426 return WriteHostObject(js_object); |
444 } else { | 427 } else { |
445 return WriteJSObject(js_object); | 428 return WriteJSObject(js_object); |
446 } | 429 } |
447 } | 430 } |
448 case JS_SPECIAL_API_OBJECT_TYPE: | 431 case JS_SPECIAL_API_OBJECT_TYPE: |
449 return WriteHostObject(Handle<JSObject>::cast(receiver)); | 432 return WriteHostObject(Handle<JSObject>::cast(receiver)); |
450 case JS_DATE_TYPE: | 433 case JS_DATE_TYPE: |
451 WriteJSDate(JSDate::cast(*receiver)); | 434 WriteJSDate(JSDate::cast(*receiver)); |
452 return ThrowIfOutOfMemory(); | 435 return Just(true); |
453 case JS_VALUE_TYPE: | 436 case JS_VALUE_TYPE: |
454 return WriteJSValue(Handle<JSValue>::cast(receiver)); | 437 return WriteJSValue(Handle<JSValue>::cast(receiver)); |
455 case JS_REGEXP_TYPE: | 438 case JS_REGEXP_TYPE: |
456 WriteJSRegExp(JSRegExp::cast(*receiver)); | 439 WriteJSRegExp(JSRegExp::cast(*receiver)); |
457 return ThrowIfOutOfMemory(); | 440 return Just(true); |
458 case JS_MAP_TYPE: | 441 case JS_MAP_TYPE: |
459 return WriteJSMap(Handle<JSMap>::cast(receiver)); | 442 return WriteJSMap(Handle<JSMap>::cast(receiver)); |
460 case JS_SET_TYPE: | 443 case JS_SET_TYPE: |
461 return WriteJSSet(Handle<JSSet>::cast(receiver)); | 444 return WriteJSSet(Handle<JSSet>::cast(receiver)); |
462 case JS_ARRAY_BUFFER_TYPE: | 445 case JS_ARRAY_BUFFER_TYPE: |
463 return WriteJSArrayBuffer(Handle<JSArrayBuffer>::cast(receiver)); | 446 return WriteJSArrayBuffer(Handle<JSArrayBuffer>::cast(receiver)); |
464 case JS_TYPED_ARRAY_TYPE: | 447 case JS_TYPED_ARRAY_TYPE: |
465 case JS_DATA_VIEW_TYPE: | 448 case JS_DATA_VIEW_TYPE: |
466 return WriteJSArrayBufferView(JSArrayBufferView::cast(*receiver)); | 449 return WriteJSArrayBufferView(JSArrayBufferView::cast(*receiver)); |
467 default: | 450 default: |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
508 | 491 |
509 if (!WriteObject(key).FromMaybe(false) || | 492 if (!WriteObject(key).FromMaybe(false) || |
510 !WriteObject(value).FromMaybe(false)) { | 493 !WriteObject(value).FromMaybe(false)) { |
511 return Nothing<bool>(); | 494 return Nothing<bool>(); |
512 } | 495 } |
513 properties_written++; | 496 properties_written++; |
514 } | 497 } |
515 | 498 |
516 WriteTag(SerializationTag::kEndJSObject); | 499 WriteTag(SerializationTag::kEndJSObject); |
517 WriteVarint<uint32_t>(properties_written); | 500 WriteVarint<uint32_t>(properties_written); |
518 return ThrowIfOutOfMemory(); | 501 return Just(true); |
519 } | 502 } |
520 | 503 |
521 Maybe<bool> ValueSerializer::WriteJSObjectSlow(Handle<JSObject> object) { | 504 Maybe<bool> ValueSerializer::WriteJSObjectSlow(Handle<JSObject> object) { |
522 WriteTag(SerializationTag::kBeginJSObject); | 505 WriteTag(SerializationTag::kBeginJSObject); |
523 Handle<FixedArray> keys; | 506 Handle<FixedArray> keys; |
524 uint32_t properties_written; | 507 uint32_t properties_written; |
525 if (!KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly, | 508 if (!KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly, |
526 ENUMERABLE_STRINGS) | 509 ENUMERABLE_STRINGS) |
527 .ToHandle(&keys) || | 510 .ToHandle(&keys) || |
528 !WriteJSObjectPropertiesSlow(object, keys).To(&properties_written)) { | 511 !WriteJSObjectPropertiesSlow(object, keys).To(&properties_written)) { |
529 return Nothing<bool>(); | 512 return Nothing<bool>(); |
530 } | 513 } |
531 WriteTag(SerializationTag::kEndJSObject); | 514 WriteTag(SerializationTag::kEndJSObject); |
532 WriteVarint<uint32_t>(properties_written); | 515 WriteVarint<uint32_t>(properties_written); |
533 return ThrowIfOutOfMemory(); | 516 return Just(true); |
534 } | 517 } |
535 | 518 |
536 Maybe<bool> ValueSerializer::WriteJSArray(Handle<JSArray> array) { | 519 Maybe<bool> ValueSerializer::WriteJSArray(Handle<JSArray> array) { |
537 uint32_t length = 0; | 520 uint32_t length = 0; |
538 bool valid_length = array->length()->ToArrayLength(&length); | 521 bool valid_length = array->length()->ToArrayLength(&length); |
539 DCHECK(valid_length); | 522 DCHECK(valid_length); |
540 USE(valid_length); | 523 USE(valid_length); |
541 | 524 |
542 // To keep things simple, for now we decide between dense and sparse | 525 // To keep things simple, for now we decide between dense and sparse |
543 // serialization based on elements kind. A more principled heuristic could | 526 // serialization based on elements kind. A more principled heuristic could |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
628 if (!KeyAccumulator::GetKeys(array, KeyCollectionMode::kOwnOnly, | 611 if (!KeyAccumulator::GetKeys(array, KeyCollectionMode::kOwnOnly, |
629 ENUMERABLE_STRINGS) | 612 ENUMERABLE_STRINGS) |
630 .ToHandle(&keys) || | 613 .ToHandle(&keys) || |
631 !WriteJSObjectPropertiesSlow(array, keys).To(&properties_written)) { | 614 !WriteJSObjectPropertiesSlow(array, keys).To(&properties_written)) { |
632 return Nothing<bool>(); | 615 return Nothing<bool>(); |
633 } | 616 } |
634 WriteTag(SerializationTag::kEndSparseJSArray); | 617 WriteTag(SerializationTag::kEndSparseJSArray); |
635 WriteVarint<uint32_t>(properties_written); | 618 WriteVarint<uint32_t>(properties_written); |
636 WriteVarint<uint32_t>(length); | 619 WriteVarint<uint32_t>(length); |
637 } | 620 } |
638 return ThrowIfOutOfMemory(); | 621 return Just(true); |
639 } | 622 } |
640 | 623 |
641 void ValueSerializer::WriteJSDate(JSDate* date) { | 624 void ValueSerializer::WriteJSDate(JSDate* date) { |
642 WriteTag(SerializationTag::kDate); | 625 WriteTag(SerializationTag::kDate); |
643 WriteDouble(date->value()->Number()); | 626 WriteDouble(date->value()->Number()); |
644 } | 627 } |
645 | 628 |
646 Maybe<bool> ValueSerializer::WriteJSValue(Handle<JSValue> value) { | 629 Maybe<bool> ValueSerializer::WriteJSValue(Handle<JSValue> value) { |
647 Object* inner_value = value->value(); | 630 Object* inner_value = value->value(); |
648 if (inner_value->IsTrue(isolate_)) { | 631 if (inner_value->IsTrue(isolate_)) { |
649 WriteTag(SerializationTag::kTrueObject); | 632 WriteTag(SerializationTag::kTrueObject); |
650 } else if (inner_value->IsFalse(isolate_)) { | 633 } else if (inner_value->IsFalse(isolate_)) { |
651 WriteTag(SerializationTag::kFalseObject); | 634 WriteTag(SerializationTag::kFalseObject); |
652 } else if (inner_value->IsNumber()) { | 635 } else if (inner_value->IsNumber()) { |
653 WriteTag(SerializationTag::kNumberObject); | 636 WriteTag(SerializationTag::kNumberObject); |
654 WriteDouble(inner_value->Number()); | 637 WriteDouble(inner_value->Number()); |
655 } else if (inner_value->IsString()) { | 638 } else if (inner_value->IsString()) { |
656 // TODO(jbroman): Replace UTF-8 encoding with the same options available for | 639 // TODO(jbroman): Replace UTF-8 encoding with the same options available for |
657 // ordinary strings. | 640 // ordinary strings. |
658 WriteTag(SerializationTag::kStringObject); | 641 WriteTag(SerializationTag::kStringObject); |
659 v8::Local<v8::String> api_string = | 642 v8::Local<v8::String> api_string = |
660 Utils::ToLocal(handle(String::cast(inner_value), isolate_)); | 643 Utils::ToLocal(handle(String::cast(inner_value), isolate_)); |
661 uint32_t utf8_length = api_string->Utf8Length(); | 644 uint32_t utf8_length = api_string->Utf8Length(); |
662 WriteVarint(utf8_length); | 645 WriteVarint(utf8_length); |
663 uint8_t* dest; | 646 api_string->WriteUtf8(reinterpret_cast<char*>(ReserveRawBytes(utf8_length)), |
664 if (ReserveRawBytes(utf8_length).To(&dest)) { | 647 utf8_length, nullptr, |
665 api_string->WriteUtf8(reinterpret_cast<char*>(dest), utf8_length, nullptr, | 648 v8::String::NO_NULL_TERMINATION); |
666 v8::String::NO_NULL_TERMINATION); | |
667 } | |
668 } else { | 649 } else { |
669 DCHECK(inner_value->IsSymbol()); | 650 DCHECK(inner_value->IsSymbol()); |
670 ThrowDataCloneError(MessageTemplate::kDataCloneError, value); | 651 ThrowDataCloneError(MessageTemplate::kDataCloneError, value); |
671 return Nothing<bool>(); | 652 return Nothing<bool>(); |
672 } | 653 } |
673 return ThrowIfOutOfMemory(); | 654 return Just(true); |
674 } | 655 } |
675 | 656 |
676 void ValueSerializer::WriteJSRegExp(JSRegExp* regexp) { | 657 void ValueSerializer::WriteJSRegExp(JSRegExp* regexp) { |
677 WriteTag(SerializationTag::kRegExp); | 658 WriteTag(SerializationTag::kRegExp); |
678 v8::Local<v8::String> api_string = | 659 v8::Local<v8::String> api_string = |
679 Utils::ToLocal(handle(regexp->Pattern(), isolate_)); | 660 Utils::ToLocal(handle(regexp->Pattern(), isolate_)); |
680 uint32_t utf8_length = api_string->Utf8Length(); | 661 uint32_t utf8_length = api_string->Utf8Length(); |
681 WriteVarint(utf8_length); | 662 WriteVarint(utf8_length); |
682 uint8_t* dest; | 663 api_string->WriteUtf8(reinterpret_cast<char*>(ReserveRawBytes(utf8_length)), |
683 if (ReserveRawBytes(utf8_length).To(&dest)) { | 664 utf8_length, nullptr, v8::String::NO_NULL_TERMINATION); |
684 api_string->WriteUtf8(reinterpret_cast<char*>(dest), utf8_length, nullptr, | |
685 v8::String::NO_NULL_TERMINATION); | |
686 } | |
687 WriteVarint(static_cast<uint32_t>(regexp->GetFlags())); | 665 WriteVarint(static_cast<uint32_t>(regexp->GetFlags())); |
688 } | 666 } |
689 | 667 |
690 Maybe<bool> ValueSerializer::WriteJSMap(Handle<JSMap> map) { | 668 Maybe<bool> ValueSerializer::WriteJSMap(Handle<JSMap> map) { |
691 // First copy the key-value pairs, since getters could mutate them. | 669 // First copy the key-value pairs, since getters could mutate them. |
692 Handle<OrderedHashMap> table(OrderedHashMap::cast(map->table())); | 670 Handle<OrderedHashMap> table(OrderedHashMap::cast(map->table())); |
693 int length = table->NumberOfElements() * 2; | 671 int length = table->NumberOfElements() * 2; |
694 Handle<FixedArray> entries = isolate_->factory()->NewFixedArray(length); | 672 Handle<FixedArray> entries = isolate_->factory()->NewFixedArray(length); |
695 { | 673 { |
696 DisallowHeapAllocation no_gc; | 674 DisallowHeapAllocation no_gc; |
(...skipping 11 matching lines...) Expand all Loading... |
708 | 686 |
709 // Then write it out. | 687 // Then write it out. |
710 WriteTag(SerializationTag::kBeginJSMap); | 688 WriteTag(SerializationTag::kBeginJSMap); |
711 for (int i = 0; i < length; i++) { | 689 for (int i = 0; i < length; i++) { |
712 if (!WriteObject(handle(entries->get(i), isolate_)).FromMaybe(false)) { | 690 if (!WriteObject(handle(entries->get(i), isolate_)).FromMaybe(false)) { |
713 return Nothing<bool>(); | 691 return Nothing<bool>(); |
714 } | 692 } |
715 } | 693 } |
716 WriteTag(SerializationTag::kEndJSMap); | 694 WriteTag(SerializationTag::kEndJSMap); |
717 WriteVarint<uint32_t>(length); | 695 WriteVarint<uint32_t>(length); |
718 return ThrowIfOutOfMemory(); | 696 return Just(true); |
719 } | 697 } |
720 | 698 |
721 Maybe<bool> ValueSerializer::WriteJSSet(Handle<JSSet> set) { | 699 Maybe<bool> ValueSerializer::WriteJSSet(Handle<JSSet> set) { |
722 // First copy the element pointers, since getters could mutate them. | 700 // First copy the element pointers, since getters could mutate them. |
723 Handle<OrderedHashSet> table(OrderedHashSet::cast(set->table())); | 701 Handle<OrderedHashSet> table(OrderedHashSet::cast(set->table())); |
724 int length = table->NumberOfElements(); | 702 int length = table->NumberOfElements(); |
725 Handle<FixedArray> entries = isolate_->factory()->NewFixedArray(length); | 703 Handle<FixedArray> entries = isolate_->factory()->NewFixedArray(length); |
726 { | 704 { |
727 DisallowHeapAllocation no_gc; | 705 DisallowHeapAllocation no_gc; |
728 Oddball* the_hole = isolate_->heap()->the_hole_value(); | 706 Oddball* the_hole = isolate_->heap()->the_hole_value(); |
729 int capacity = table->UsedCapacity(); | 707 int capacity = table->UsedCapacity(); |
730 int result_index = 0; | 708 int result_index = 0; |
731 for (int i = 0; i < capacity; i++) { | 709 for (int i = 0; i < capacity; i++) { |
732 Object* key = table->KeyAt(i); | 710 Object* key = table->KeyAt(i); |
733 if (key == the_hole) continue; | 711 if (key == the_hole) continue; |
734 entries->set(result_index++, key); | 712 entries->set(result_index++, key); |
735 } | 713 } |
736 DCHECK_EQ(result_index, length); | 714 DCHECK_EQ(result_index, length); |
737 } | 715 } |
738 | 716 |
739 // Then write it out. | 717 // Then write it out. |
740 WriteTag(SerializationTag::kBeginJSSet); | 718 WriteTag(SerializationTag::kBeginJSSet); |
741 for (int i = 0; i < length; i++) { | 719 for (int i = 0; i < length; i++) { |
742 if (!WriteObject(handle(entries->get(i), isolate_)).FromMaybe(false)) { | 720 if (!WriteObject(handle(entries->get(i), isolate_)).FromMaybe(false)) { |
743 return Nothing<bool>(); | 721 return Nothing<bool>(); |
744 } | 722 } |
745 } | 723 } |
746 WriteTag(SerializationTag::kEndJSSet); | 724 WriteTag(SerializationTag::kEndJSSet); |
747 WriteVarint<uint32_t>(length); | 725 WriteVarint<uint32_t>(length); |
748 return ThrowIfOutOfMemory(); | 726 return Just(true); |
749 } | 727 } |
750 | 728 |
751 Maybe<bool> ValueSerializer::WriteJSArrayBuffer( | 729 Maybe<bool> ValueSerializer::WriteJSArrayBuffer( |
752 Handle<JSArrayBuffer> array_buffer) { | 730 Handle<JSArrayBuffer> array_buffer) { |
753 if (array_buffer->is_shared()) { | 731 if (array_buffer->is_shared()) { |
754 if (!delegate_) { | 732 if (!delegate_) { |
755 ThrowDataCloneError(MessageTemplate::kDataCloneError, array_buffer); | 733 ThrowDataCloneError(MessageTemplate::kDataCloneError, array_buffer); |
756 return Nothing<bool>(); | 734 return Nothing<bool>(); |
757 } | 735 } |
758 | 736 |
759 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate_); | 737 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate_); |
760 Maybe<uint32_t> index = delegate_->GetSharedArrayBufferId( | 738 Maybe<uint32_t> index = delegate_->GetSharedArrayBufferId( |
761 v8_isolate, Utils::ToLocalShared(array_buffer)); | 739 v8_isolate, Utils::ToLocalShared(array_buffer)); |
762 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate_, Nothing<bool>()); | 740 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate_, Nothing<bool>()); |
763 | 741 |
764 WriteTag(SerializationTag::kSharedArrayBuffer); | 742 WriteTag(SerializationTag::kSharedArrayBuffer); |
765 WriteVarint(index.FromJust()); | 743 WriteVarint(index.FromJust()); |
766 return ThrowIfOutOfMemory(); | 744 return Just(true); |
767 } | 745 } |
768 | 746 |
769 uint32_t* transfer_entry = array_buffer_transfer_map_.Find(array_buffer); | 747 uint32_t* transfer_entry = array_buffer_transfer_map_.Find(array_buffer); |
770 if (transfer_entry) { | 748 if (transfer_entry) { |
771 WriteTag(SerializationTag::kArrayBufferTransfer); | 749 WriteTag(SerializationTag::kArrayBufferTransfer); |
772 WriteVarint(*transfer_entry); | 750 WriteVarint(*transfer_entry); |
773 return ThrowIfOutOfMemory(); | 751 return Just(true); |
774 } | 752 } |
775 if (array_buffer->was_neutered()) { | 753 if (array_buffer->was_neutered()) { |
776 ThrowDataCloneError(MessageTemplate::kDataCloneErrorNeuteredArrayBuffer); | 754 ThrowDataCloneError(MessageTemplate::kDataCloneErrorNeuteredArrayBuffer); |
777 return Nothing<bool>(); | 755 return Nothing<bool>(); |
778 } | 756 } |
779 double byte_length = array_buffer->byte_length()->Number(); | 757 double byte_length = array_buffer->byte_length()->Number(); |
780 if (byte_length > std::numeric_limits<uint32_t>::max()) { | 758 if (byte_length > std::numeric_limits<uint32_t>::max()) { |
781 ThrowDataCloneError(MessageTemplate::kDataCloneError, array_buffer); | 759 ThrowDataCloneError(MessageTemplate::kDataCloneError, array_buffer); |
782 return Nothing<bool>(); | 760 return Nothing<bool>(); |
783 } | 761 } |
784 WriteTag(SerializationTag::kArrayBuffer); | 762 WriteTag(SerializationTag::kArrayBuffer); |
785 WriteVarint<uint32_t>(byte_length); | 763 WriteVarint<uint32_t>(byte_length); |
786 WriteRawBytes(array_buffer->backing_store(), byte_length); | 764 WriteRawBytes(array_buffer->backing_store(), byte_length); |
787 return ThrowIfOutOfMemory(); | 765 return Just(true); |
788 } | 766 } |
789 | 767 |
790 Maybe<bool> ValueSerializer::WriteJSArrayBufferView(JSArrayBufferView* view) { | 768 Maybe<bool> ValueSerializer::WriteJSArrayBufferView(JSArrayBufferView* view) { |
791 WriteTag(SerializationTag::kArrayBufferView); | 769 WriteTag(SerializationTag::kArrayBufferView); |
792 ArrayBufferViewTag tag = ArrayBufferViewTag::kInt8Array; | 770 ArrayBufferViewTag tag = ArrayBufferViewTag::kInt8Array; |
793 if (view->IsJSTypedArray()) { | 771 if (view->IsJSTypedArray()) { |
794 switch (JSTypedArray::cast(view)->type()) { | 772 switch (JSTypedArray::cast(view)->type()) { |
795 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ | 773 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ |
796 case kExternal##Type##Array: \ | 774 case kExternal##Type##Array: \ |
797 tag = ArrayBufferViewTag::k##Type##Array; \ | 775 tag = ArrayBufferViewTag::k##Type##Array; \ |
798 break; | 776 break; |
799 TYPED_ARRAYS(TYPED_ARRAY_CASE) | 777 TYPED_ARRAYS(TYPED_ARRAY_CASE) |
800 #undef TYPED_ARRAY_CASE | 778 #undef TYPED_ARRAY_CASE |
801 } | 779 } |
802 } else { | 780 } else { |
803 DCHECK(view->IsJSDataView()); | 781 DCHECK(view->IsJSDataView()); |
804 tag = ArrayBufferViewTag::kDataView; | 782 tag = ArrayBufferViewTag::kDataView; |
805 } | 783 } |
806 WriteVarint(static_cast<uint8_t>(tag)); | 784 WriteVarint(static_cast<uint8_t>(tag)); |
807 WriteVarint(NumberToUint32(view->byte_offset())); | 785 WriteVarint(NumberToUint32(view->byte_offset())); |
808 WriteVarint(NumberToUint32(view->byte_length())); | 786 WriteVarint(NumberToUint32(view->byte_length())); |
809 return ThrowIfOutOfMemory(); | 787 return Just(true); |
810 } | 788 } |
811 | 789 |
812 Maybe<bool> ValueSerializer::WriteWasmModule(Handle<JSObject> object) { | 790 Maybe<bool> ValueSerializer::WriteWasmModule(Handle<JSObject> object) { |
813 Handle<WasmCompiledModule> compiled_part( | 791 Handle<WasmCompiledModule> compiled_part( |
814 WasmCompiledModule::cast(object->GetInternalField(0)), isolate_); | 792 WasmCompiledModule::cast(object->GetInternalField(0)), isolate_); |
815 WasmEncodingTag encoding_tag = WasmEncodingTag::kRawBytes; | 793 WasmEncodingTag encoding_tag = WasmEncodingTag::kRawBytes; |
816 WriteTag(SerializationTag::kWasmModule); | 794 WriteTag(SerializationTag::kWasmModule); |
817 WriteRawBytes(&encoding_tag, sizeof(encoding_tag)); | 795 WriteRawBytes(&encoding_tag, sizeof(encoding_tag)); |
818 | 796 |
819 Handle<String> wire_bytes(compiled_part->module_bytes(), isolate_); | 797 Handle<String> wire_bytes(compiled_part->module_bytes(), isolate_); |
820 int wire_bytes_length = wire_bytes->length(); | 798 int wire_bytes_length = wire_bytes->length(); |
821 WriteVarint<uint32_t>(wire_bytes_length); | 799 WriteVarint<uint32_t>(wire_bytes_length); |
822 uint8_t* destination; | 800 uint8_t* destination = ReserveRawBytes(wire_bytes_length); |
823 if (ReserveRawBytes(wire_bytes_length).To(&destination)) { | 801 String::WriteToFlat(*wire_bytes, destination, 0, wire_bytes_length); |
824 String::WriteToFlat(*wire_bytes, destination, 0, wire_bytes_length); | |
825 } | |
826 | 802 |
827 std::unique_ptr<ScriptData> script_data = | 803 std::unique_ptr<ScriptData> script_data = |
828 WasmCompiledModuleSerializer::SerializeWasmModule(isolate_, | 804 WasmCompiledModuleSerializer::SerializeWasmModule(isolate_, |
829 compiled_part); | 805 compiled_part); |
830 int script_data_length = script_data->length(); | 806 int script_data_length = script_data->length(); |
831 WriteVarint<uint32_t>(script_data_length); | 807 WriteVarint<uint32_t>(script_data_length); |
832 WriteRawBytes(script_data->data(), script_data_length); | 808 WriteRawBytes(script_data->data(), script_data_length); |
833 | 809 |
834 return ThrowIfOutOfMemory(); | 810 return Just(true); |
835 } | 811 } |
836 | 812 |
837 Maybe<bool> ValueSerializer::WriteHostObject(Handle<JSObject> object) { | 813 Maybe<bool> ValueSerializer::WriteHostObject(Handle<JSObject> object) { |
838 if (!delegate_) { | 814 if (!delegate_) { |
839 isolate_->Throw(*isolate_->factory()->NewError( | 815 isolate_->Throw(*isolate_->factory()->NewError( |
840 isolate_->error_function(), MessageTemplate::kDataCloneError, object)); | 816 isolate_->error_function(), MessageTemplate::kDataCloneError, object)); |
841 return Nothing<bool>(); | 817 return Nothing<bool>(); |
842 } | 818 } |
843 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate_); | 819 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate_); |
844 Maybe<bool> result = | 820 Maybe<bool> result = |
(...skipping 30 matching lines...) Expand all Loading... |
875 } | 851 } |
876 return Just(properties_written); | 852 return Just(properties_written); |
877 } | 853 } |
878 | 854 |
879 void ValueSerializer::ThrowDataCloneError( | 855 void ValueSerializer::ThrowDataCloneError( |
880 MessageTemplate::Template template_index) { | 856 MessageTemplate::Template template_index) { |
881 return ThrowDataCloneError(template_index, | 857 return ThrowDataCloneError(template_index, |
882 isolate_->factory()->empty_string()); | 858 isolate_->factory()->empty_string()); |
883 } | 859 } |
884 | 860 |
885 Maybe<bool> ValueSerializer::ThrowIfOutOfMemory() { | |
886 if (out_of_memory_) { | |
887 ThrowDataCloneError(MessageTemplate::kDataCloneErrorOutOfMemory); | |
888 return Nothing<bool>(); | |
889 } | |
890 return Just(true); | |
891 } | |
892 | |
893 void ValueSerializer::ThrowDataCloneError( | 861 void ValueSerializer::ThrowDataCloneError( |
894 MessageTemplate::Template template_index, Handle<Object> arg0) { | 862 MessageTemplate::Template template_index, Handle<Object> arg0) { |
895 Handle<String> message = | 863 Handle<String> message = |
896 MessageTemplate::FormatMessage(isolate_, template_index, arg0); | 864 MessageTemplate::FormatMessage(isolate_, template_index, arg0); |
897 if (delegate_) { | 865 if (delegate_) { |
898 delegate_->ThrowDataCloneError(Utils::ToLocal(message)); | 866 delegate_->ThrowDataCloneError(Utils::ToLocal(message)); |
899 } else { | 867 } else { |
900 isolate_->Throw( | 868 isolate_->Throw( |
901 *isolate_->factory()->NewError(isolate_->error_function(), message)); | 869 *isolate_->factory()->NewError(isolate_->error_function(), message)); |
902 } | 870 } |
(...skipping 1013 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1916 if (stack.size() != 1) { | 1884 if (stack.size() != 1) { |
1917 isolate_->Throw(*isolate_->factory()->NewError( | 1885 isolate_->Throw(*isolate_->factory()->NewError( |
1918 MessageTemplate::kDataCloneDeserializationError)); | 1886 MessageTemplate::kDataCloneDeserializationError)); |
1919 return MaybeHandle<Object>(); | 1887 return MaybeHandle<Object>(); |
1920 } | 1888 } |
1921 return scope.CloseAndEscape(stack[0]); | 1889 return scope.CloseAndEscape(stack[0]); |
1922 } | 1890 } |
1923 | 1891 |
1924 } // namespace internal | 1892 } // namespace internal |
1925 } // namespace v8 | 1893 } // namespace v8 |
OLD | NEW |