DOMArrayBuffer* FileReaderLoader::ArrayBufferResult() { DCHECK_EQ(read_type_, kReadAsArrayBuffer); if (array_buffer_result_) return array_buffer_result_; // If the loading is not started or an error occurs, return an empty result. if (!raw_data_ || error_code_ != FileErrorCode::kOK) returnnullptr; DOMArrayBuffer* result = DOMArrayBuffer::Create(raw_data_->ToArrayBuffer()); if (finished_loading_) { array_buffer_result_ = result; AdjustReportedMemoryUsageToV8( -1 * static_cast<int64_t>(raw_data_->ByteLength())); raw_data_.reset(); } return result; }
DOMArrayBuffer* FileReaderLoader::ArrayBufferResult() { DCHECK_EQ(read_type_, kReadAsArrayBuffer); if (array_buffer_result_) return array_buffer_result_; // If the loading is not started or an error occurs, return an empty result. if (!raw_data_ || error_code_ != FileErrorCode::kOK) returnnullptr; if (!finished_loading_) { return DOMArrayBuffer::Create( ArrayBuffer::Create(raw_data_->Data(), raw_data_->ByteLength())); } array_buffer_result_ = DOMArrayBuffer::Create(raw_data_->ToArrayBuffer()); AdjustReportedMemoryUsageToV8(-1 * static_cast<int64_t>(raw_data_->ByteLength())); raw_data_.reset(); return array_buffer_result_; }
在补丁之前,下面这行代码可能会被多次调用:
1
DOMArrayBuffer* result = DOMArrayBuffer::Create(raw_data_->ToArrayBuffer());
/** * Detaches this ArrayBuffer and all its views (typed arrays). * Detaching sets the byte length of the buffer and all typed arrays to zero, * preventing JavaScript from ever accessing underlying backing store. * ArrayBuffer should have been externalized and must be detachable. */ voidDetach();
// TODO(913887): fix the use of 'neuter' in the API. V8_DEPRECATE_SOON("Use Detach() instead.", inlinevoid Neuter()) { Detach(); }
/** * Make this ArrayBuffer external. The pointer to underlying memory block * and byte length are returned as |Contents| structure. After ArrayBuffer * had been externalized, it does no longer own the memory block. The caller * should take steps to free memory when it is no longer needed. * * The Data pointer of ArrayBuffer::Contents must be freed using the provided * deleter, which will call ArrayBuffer::Allocator::Free if the buffer * was allocated with ArraryBuffer::Allocator::Allocate. */ Contents Externalize();
<!-- main.html 的代码 --> <script> var ab = newArrayBuffer(0x1000); var worker = new Worker('worker.js'); console.log('Main thread: before postMessage, ab.byteLength is ' + ab.byteLength); worker.postMessage(ab, [ab]); console.log('Main thread: after postMessage, ab.byteLength is ' + ab.byteLength); </script>
1 2 3 4 5 6
// worker.js 的代码 onmessage = function(message) { var ab = message.data; console.log('Worker thread: received: ' + ab); console.log('Wroker thread: ArrayBuffer.byteLength is : ' + ab.byteLength); }
输出如下所示:
1 2 3 4
Main thread: before postMessage, ab.byteLength is 4096 Main thread: after postMessage, ab.byteLength is 0 Worker thread: received: [object ArrayBuffer] Wroker thread: ArrayBuffer.byteLength is : 4096
(74c.2a4): Access violation - code c0000005 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=00000004 ebx=02b30ec8 ecx=00000042 edx=00000042 esi=00000042 edi=2b404000 eip=5f625606 esp=0021ecc0 ebp=0021ece8 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010202 chrome_child!ovly_debug_event+0x10c1fa6: 5f625606 881407 mov byte ptr [edi+eax],dl ds:0023:2b404004=??