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