@@ -19,6 +19,7 @@ namespace node { |
19 | 19 |
|
20 | 20 | using v8::Array; |
21 | 21 | using v8::ArrayBuffer; |
| 22 | +using v8::BackingStore; |
22 | 23 | using v8::ConstructorBehavior; |
23 | 24 | using v8::Context; |
24 | 25 | using v8::DontDelete; |
@@ -29,6 +30,7 @@ using v8::FunctionCallbackInfo; |
29 | 30 | using v8::FunctionTemplate; |
30 | 31 | using v8::HandleScope; |
31 | 32 | using v8::Integer; |
| 33 | +using v8::Isolate; |
32 | 34 | using v8::Local; |
33 | 35 | using v8::MaybeLocal; |
34 | 36 | using v8::Object; |
@@ -80,6 +82,8 @@ void StreamBase::SetWriteResult(const StreamWriteResult& res) { |
80 | 82 |
|
81 | 83 | int StreamBase::Writev(const FunctionCallbackInfo<Value>& args) { |
82 | 84 | Environment* env = Environment::GetCurrent(args); |
| 85 | + Isolate* isolate = env->isolate(); |
| 86 | + Local<Context> context = env->context(); |
83 | 87 |
|
84 | 88 | CHECK(args[0]->IsObject()); |
85 | 89 | CHECK(args[1]->IsArray()); |
@@ -102,21 +106,21 @@ int StreamBase::Writev(const FunctionCallbackInfo<Value>& args) { |
102 | 106 | if (!all_buffers) { |
103 | 107 | // Determine storage size first |
104 | 108 | for (size_t i = 0; i < count; i++) { |
105 | | - Local<Value> chunk = chunks->Get(env->context(), i * 2).ToLocalChecked(); |
| 109 | + Local<Value> chunk = chunks->Get(context, i * 2).ToLocalChecked(); |
106 | 110 |
|
107 | 111 | if (Buffer::HasInstance(chunk)) |
108 | 112 | continue; |
109 | 113 | // Buffer chunk, no additional storage required |
110 | 114 |
|
111 | 115 | // String chunk |
112 | | - Local<String> string = chunk->ToString(env->context()).ToLocalChecked(); |
113 | | - enum encoding encoding = ParseEncoding(env->isolate(), |
114 | | - chunks->Get(env->context(), i * 2 + 1).ToLocalChecked()); |
| 116 | + Local<String> string = chunk->ToString(context).ToLocalChecked(); |
| 117 | + enum encoding encoding = ParseEncoding(isolate, |
| 118 | + chunks->Get(context, i * 2 + 1).ToLocalChecked()); |
115 | 119 | size_t chunk_size; |
116 | 120 | if (encoding == UTF8 && string->Length() > 65535 && |
117 | | - !StringBytes::Size(env->isolate(), string, encoding).To(&chunk_size)) |
| 121 | + !StringBytes::Size(isolate, string, encoding).To(&chunk_size)) |
118 | 122 | return 0; |
119 | | - else if (!StringBytes::StorageSize(env->isolate(), string, encoding) |
| 123 | + else if (!StringBytes::StorageSize(isolate, string, encoding) |
120 | 124 | .To(&chunk_size)) |
121 | 125 | return 0; |
122 | 126 | storage_size += chunk_size; |
@@ -126,20 +130,22 @@ int StreamBase::Writev(const FunctionCallbackInfo<Value>& args) { |
126 | 130 | return UV_ENOBUFS; |
127 | 131 | } else { |
128 | 132 | for (size_t i = 0; i < count; i++) { |
129 | | - Local<Value> chunk = chunks->Get(env->context(), i).ToLocalChecked(); |
| 133 | + Local<Value> chunk = chunks->Get(context, i).ToLocalChecked(); |
130 | 134 | bufs[i].base = Buffer::Data(chunk); |
131 | 135 | bufs[i].len = Buffer::Length(chunk); |
132 | 136 | } |
133 | 137 | } |
134 | 138 |
|
135 | | - AllocatedBuffer storage; |
136 | | - if (storage_size > 0) |
137 | | - storage = AllocatedBuffer::AllocateManaged(env, storage_size); |
| 139 | + std::unique_ptr<BackingStore> bs; |
| 140 | + if (storage_size > 0) { |
| 141 | + NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data()); |
| 142 | + bs = ArrayBuffer::NewBackingStore(isolate, storage_size); |
| 143 | + } |
138 | 144 |
|
139 | 145 | offset = 0; |
140 | 146 | if (!all_buffers) { |
141 | 147 | for (size_t i = 0; i < count; i++) { |
142 | | - Local<Value> chunk = chunks->Get(env->context(), i * 2).ToLocalChecked(); |
| 148 | + Local<Value> chunk = chunks->Get(context, i * 2).ToLocalChecked(); |
143 | 149 |
|
144 | 150 | // Write buffer |
145 | 151 | if (Buffer::HasInstance(chunk)) { |
@@ -150,13 +156,14 @@ int StreamBase::Writev(const FunctionCallbackInfo<Value>& args) { |
150 | 156 |
|
151 | 157 | // Write string |
152 | 158 | CHECK_LE(offset, storage_size); |
153 | | - char* str_storage = storage.data() + offset; |
154 | | - size_t str_size = storage.size() - offset; |
155 | | - |
156 | | - Local<String> string = chunk->ToString(env->context()).ToLocalChecked(); |
157 | | - enum encoding encoding = ParseEncoding(env->isolate(), |
158 | | - chunks->Get(env->context(), i * 2 + 1).ToLocalChecked()); |
159 | | - str_size = StringBytes::Write(env->isolate(), |
| 159 | + char* str_storage = |
| 160 | + static_cast<char*>(bs ? bs->Data() : nullptr) + offset; |
| 161 | + size_t str_size = (bs ? bs->ByteLength() : 0) - offset; |
| 162 | + |
| 163 | + Local<String> string = chunk->ToString(context).ToLocalChecked(); |
| 164 | + enum encoding encoding = ParseEncoding(isolate, |
| 165 | + chunks->Get(context, i * 2 + 1).ToLocalChecked()); |
| 166 | + str_size = StringBytes::Write(isolate, |
160 | 167 | str_storage, |
161 | 168 | str_size, |
162 | 169 | string, |
@@ -169,9 +176,8 @@ int StreamBase::Writev(const FunctionCallbackInfo<Value>& args) { |
169 | 176 |
|
170 | 177 | StreamWriteResult res = Write(*bufs, count, nullptr, req_wrap_obj); |
171 | 178 | SetWriteResult(res); |
172 | | - if (res.wrap != nullptr && storage_size > 0) { |
173 | | - res.wrap->SetAllocatedStorage(std::move(storage)); |
174 | | - } |
| 179 | + if (res.wrap != nullptr && storage_size > 0) |
| 180 | + res.wrap->SetBackingStore(std::move(bs)); |
175 | 181 | return res.err; |
176 | 182 | } |
177 | 183 |
|
@@ -216,6 +222,7 @@ int StreamBase::WriteBuffer(const FunctionCallbackInfo<Value>& args) { |
216 | 222 | template <enum encoding enc> |
217 | 223 | int StreamBase::WriteString(const FunctionCallbackInfo<Value>& args) { |
218 | 224 | Environment* env = Environment::GetCurrent(args); |
| 225 | + Isolate* isolate = env->isolate(); |
219 | 226 | CHECK(args[0]->IsObject()); |
220 | 227 | CHECK(args[1]->IsString()); |
221 | 228 |
|
@@ -230,9 +237,9 @@ int StreamBase::WriteString(const FunctionCallbackInfo<Value>& args) { |
230 | 237 | // computing their actual size, rather than tripling the storage. |
231 | 238 | size_t storage_size; |
232 | 239 | if (enc == UTF8 && string->Length() > 65535 && |
233 | | - !StringBytes::Size(env->isolate(), string, enc).To(&storage_size)) |
| 240 | + !StringBytes::Size(isolate, string, enc).To(&storage_size)) |
234 | 241 | return 0; |
235 | | - else if (!StringBytes::StorageSize(env->isolate(), string, enc) |
| 242 | + else if (!StringBytes::StorageSize(isolate, string, enc) |
236 | 243 | .To(&storage_size)) |
237 | 244 | return 0; |
238 | 245 |
|
@@ -248,7 +255,7 @@ int StreamBase::WriteString(const FunctionCallbackInfo<Value>& args) { |
248 | 255 | bool try_write = storage_size <= sizeof(stack_storage) && |
249 | 256 | (!IsIPCPipe() || send_handle_obj.IsEmpty()); |
250 | 257 | if (try_write) { |
251 | | - data_size = StringBytes::Write(env->isolate(), |
| 258 | + data_size = StringBytes::Write(isolate, |
252 | 259 | stack_storage, |
253 | 260 | storage_size, |
254 | 261 | string, |
@@ -274,26 +281,28 @@ int StreamBase::WriteString(const FunctionCallbackInfo<Value>& args) { |
274 | 281 | CHECK_EQ(count, 1); |
275 | 282 | } |
276 | 283 |
|
277 | | - AllocatedBuffer data; |
| 284 | + std::unique_ptr<BackingStore> bs; |
278 | 285 |
|
279 | 286 | if (try_write) { |
280 | 287 | // Copy partial data |
281 | | - data = AllocatedBuffer::AllocateManaged(env, buf.len); |
282 | | - memcpy(data.data(), buf.base, buf.len); |
| 288 | + NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data()); |
| 289 | + bs = ArrayBuffer::NewBackingStore(isolate, buf.len); |
| 290 | + memcpy(static_cast<char*>(bs->Data()), buf.base, buf.len); |
283 | 291 | data_size = buf.len; |
284 | 292 | } else { |
285 | 293 | // Write it |
286 | | - data = AllocatedBuffer::AllocateManaged(env, storage_size); |
287 | | - data_size = StringBytes::Write(env->isolate(), |
288 | | - data.data(), |
| 294 | + NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data()); |
| 295 | + bs = ArrayBuffer::NewBackingStore(isolate, storage_size); |
| 296 | + data_size = StringBytes::Write(isolate, |
| 297 | + static_cast<char*>(bs->Data()), |
289 | 298 | storage_size, |
290 | 299 | string, |
291 | 300 | enc); |
292 | 301 | } |
293 | 302 |
|
294 | 303 | CHECK_LE(data_size, storage_size); |
295 | 304 |
|
296 | | - buf = uv_buf_init(data.data(), data_size); |
| 305 | + buf = uv_buf_init(static_cast<char*>(bs->Data()), data_size); |
297 | 306 |
|
298 | 307 | uv_stream_t* send_handle = nullptr; |
299 | 308 |
|
@@ -312,9 +321,8 @@ int StreamBase::WriteString(const FunctionCallbackInfo<Value>& args) { |
312 | 321 | res.bytes += synchronously_written; |
313 | 322 |
|
314 | 323 | SetWriteResult(res); |
315 | | - if (res.wrap != nullptr) { |
316 | | - res.wrap->SetAllocatedStorage(std::move(data)); |
317 | | - } |
| 324 | + if (res.wrap != nullptr) |
| 325 | + res.wrap->SetBackingStore(std::move(bs)); |
318 | 326 |
|
319 | 327 | return res.err; |
320 | 328 | } |
@@ -511,27 +519,28 @@ void StreamResource::ClearError() { |
511 | 519 | uv_buf_t EmitToJSStreamListener::OnStreamAlloc(size_t suggested_size) { |
512 | 520 | CHECK_NOT_NULL(stream_); |
513 | 521 | Environment* env = static_cast<StreamBase*>(stream_)->stream_env(); |
514 | | - return AllocatedBuffer::AllocateManaged(env, suggested_size).release(); |
| 522 | + return env->allocate_managed_buffer(suggested_size); |
515 | 523 | } |
516 | 524 |
|
517 | 525 | void EmitToJSStreamListener::OnStreamRead(ssize_t nread, const uv_buf_t& buf_) { |
518 | 526 | CHECK_NOT_NULL(stream_); |
519 | 527 | StreamBase* stream = static_cast<StreamBase*>(stream_); |
520 | 528 | Environment* env = stream->stream_env(); |
521 | | - HandleScope handle_scope(env->isolate()); |
| 529 | + Isolate* isolate = env->isolate(); |
| 530 | + HandleScope handle_scope(isolate); |
522 | 531 | Context::Scope context_scope(env->context()); |
523 | | - AllocatedBuffer buf(env, buf_); |
| 532 | + std::unique_ptr<BackingStore> bs = env->release_managed_buffer(buf_); |
524 | 533 |
|
525 | 534 | if (nread <= 0) { |
526 | 535 | if (nread < 0) |
527 | 536 | stream->CallJSOnreadMethod(nread, Local<ArrayBuffer>()); |
528 | 537 | return; |
529 | 538 | } |
530 | 539 |
|
531 | | - CHECK_LE(static_cast<size_t>(nread), buf.size()); |
532 | | - buf.Resize(nread); |
| 540 | + CHECK_LE(static_cast<size_t>(nread), bs->ByteLength()); |
| 541 | + bs = BackingStore::Reallocate(isolate, std::move(bs), nread); |
533 | 542 |
|
534 | | - stream->CallJSOnreadMethod(nread, buf.ToArrayBuffer()); |
| 543 | + stream->CallJSOnreadMethod(nread, ArrayBuffer::New(isolate, std::move(bs))); |
535 | 544 | } |
536 | 545 |
|
537 | 546 |
|
|