buffer: switch API to return MaybeLocal<T> · nodejs/node@d6fb710 · GitHub
Skip to content

Commit d6fb710

Browse files
trevnorrisrvagg
authored andcommitted
buffer: switch API to return MaybeLocal<T>
Instead of aborting in case of internal failure, return an empty Local<Object>. Using the MaybeLocal<T> API, users must check their return values. PR-URL: #1825 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
1 parent 8931e5b commit d6fb710

9 files changed

Lines changed: 164 additions & 132 deletions

File tree

src/js_stream.cc

Lines changed: 12 additions & 7 deletions

src/node_buffer.cc

Lines changed: 71 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ using v8::HandleScope;
7474
using v8::Isolate;
7575
using v8::Local;
7676
using v8::Maybe;
77+
using v8::MaybeLocal;
7778
using v8::Number;
7879
using v8::Object;
7980
using v8::Persistent;
@@ -234,7 +235,9 @@ size_t Length(Handle<Object> obj) {
234235
}
235236

236237

237-
Local<Object> New(Isolate* isolate, Handle<String> string, enum encoding enc) {
238+
MaybeLocal<Object> New(Isolate* isolate,
239+
Local<String> string,
240+
enum encoding enc) {
238241
EscapableHandleScope scope(isolate);
239242

240243
size_t length = StringBytes::Size(isolate, string, enc);
@@ -251,19 +254,26 @@ Local<Object> New(Isolate* isolate, Handle<String> string, enum encoding enc) {
251254
CHECK_NE(data, nullptr);
252255
}
253256

254-
Local<Object> buf = Use(isolate, data, actual);
255-
return scope.Escape(buf);
257+
Local<Object> buf;
258+
if (Use(isolate, data, actual).ToLocal(&buf))
259+
return scope.Escape(buf);
260+
261+
// Object failed to be created. Clean up resources.
262+
free(data);
263+
return Local<Object>();
256264
}
257265

258266

259-
Local<Object> New(Isolate* isolate, size_t length) {
267+
MaybeLocal<Object> New(Isolate* isolate, size_t length) {
260268
EscapableHandleScope handle_scope(isolate);
261-
Local<Object> obj = Buffer::New(Environment::GetCurrent(isolate), length);
262-
return handle_scope.Escape(obj);
269+
Local<Object> obj;
270+
if (Buffer::New(Environment::GetCurrent(isolate), length).ToLocal(&obj))
271+
return handle_scope.Escape(obj);
272+
return Local<Object>();
263273
}
264274

265275

266-
Local<Object> New(Environment* env, size_t length) {
276+
MaybeLocal<Object> New(Environment* env, size_t length) {
267277
EscapableHandleScope scope(env->isolate());
268278

269279
if (using_old_buffer) {
@@ -286,13 +296,12 @@ Local<Object> New(Environment* env, size_t length) {
286296
void* data;
287297
if (length > 0) {
288298
data = malloc(length);
289-
// NOTE: API change. Must check .IsEmpty() on the return object to see if
290-
// the data was able to be allocated.
291299
if (data == nullptr)
292300
return Local<Object>();
293301
} else {
294302
data = nullptr;
295303
}
304+
296305
Local<ArrayBuffer> ab =
297306
ArrayBuffer::New(env->isolate(),
298307
data,
@@ -301,25 +310,27 @@ Local<Object> New(Environment* env, size_t length) {
301310
Local<Uint8Array> ui = Uint8Array::New(ab, 0, length);
302311
Maybe<bool> mb =
303312
ui->SetPrototype(env->context(), env->buffer_prototype_object());
304-
if (!mb.FromMaybe(false)) {
305-
FatalError("node::Buffer::New(Environment*, size_t)",
306-
"Could not set Object prototype");
307-
UNREACHABLE();
308-
}
309-
return scope.Escape(ui);
313+
if (mb.FromMaybe(false))
314+
return scope.Escape(ui);
315+
316+
// Object failed to be created. Clean up resources.
317+
free(data);
318+
return Local<Object>();
310319
}
311320

312321

313-
Local<Object> New(Isolate* isolate, const char* data, size_t length) {
322+
MaybeLocal<Object> New(Isolate* isolate, const char* data, size_t length) {
314323
Environment* env = Environment::GetCurrent(isolate);
315324
EscapableHandleScope handle_scope(env->isolate());
316-
Local<Object> obj = Buffer::New(env, data, length);
317-
return handle_scope.Escape(obj);
325+
Local<Object> obj;
326+
if (Buffer::New(env, data, length).ToLocal(&obj))
327+
return handle_scope.Escape(obj);
328+
return Local<Object>();
318329
}
319330

320331

321332
// Make a copy of "data". Why this isn't called "Copy", we'll never know.
322-
Local<Object> New(Environment* env, const char* data, size_t length) {
333+
MaybeLocal<Object> New(Environment* env, const char* data, size_t length) {
323334
EscapableHandleScope scope(env->isolate());
324335

325336
if (using_old_buffer) {
@@ -353,8 +364,6 @@ Local<Object> New(Environment* env, const char* data, size_t length) {
353364
if (length > 0) {
354365
CHECK_NE(data, nullptr);
355366
new_data = malloc(length);
356-
// NOTE: API change. Must check .IsEmpty() on the return object to see if
357-
// the data was able to be allocated.
358367
if (new_data == nullptr)
359368
return Local<Object>();
360369
memcpy(new_data, data, length);
@@ -370,33 +379,34 @@ Local<Object> New(Environment* env, const char* data, size_t length) {
370379
Local<Uint8Array> ui = Uint8Array::New(ab, 0, length);
371380
Maybe<bool> mb =
372381
ui->SetPrototype(env->context(), env->buffer_prototype_object());
373-
if (!mb.FromMaybe(false)) {
374-
FatalError("node::Buffer::New(Environment*, char*, size_t)",
375-
"Could not set Object prototype");
376-
UNREACHABLE();
377-
}
382+
if (mb.FromMaybe(false))
383+
return scope.Escape(ui);
378384

379-
return scope.Escape(ui);
385+
// Object failed to be created. Clean up resources.
386+
free(new_data);
387+
return Local<Object>();
380388
}
381389

382390

383-
Local<Object> New(Isolate* isolate,
384-
char* data,
385-
size_t length,
386-
FreeCallback callback,
387-
void* hint) {
391+
MaybeLocal<Object> New(Isolate* isolate,
392+
char* data,
393+
size_t length,
394+
FreeCallback callback,
395+
void* hint) {
388396
Environment* env = Environment::GetCurrent(isolate);
389397
EscapableHandleScope handle_scope(env->isolate());
390-
Local<Object> obj = Buffer::New(env, data, length, callback, hint);
391-
return handle_scope.Escape(obj);
398+
Local<Object> obj;
399+
if (Buffer::New(env, data, length, callback, hint).ToLocal(&obj))
400+
return handle_scope.Escape(obj);
401+
return Local<Object>();
392402
}
393403

394404

395-
Local<Object> New(Environment* env,
396-
char* data,
397-
size_t length,
398-
FreeCallback callback,
399-
void* hint) {
405+
MaybeLocal<Object> New(Environment* env,
406+
char* data,
407+
size_t length,
408+
FreeCallback callback,
409+
void* hint) {
400410
EscapableHandleScope scope(env->isolate());
401411

402412
if (using_old_buffer) {
@@ -416,26 +426,26 @@ Local<Object> New(Environment* env,
416426
Local<Uint8Array> ui = Uint8Array::New(ab, 0, length);
417427
Maybe<bool> mb =
418428
ui->SetPrototype(env->context(), env->buffer_prototype_object());
419-
if (!mb.FromMaybe(false)) {
420-
FatalError("node::Buffer::New(Environment*, char*, size_t,"
421-
" FreeCallback, void*)",
422-
"Could not set Object prototype");
423-
UNREACHABLE();
424-
}
429+
430+
if (!mb.FromMaybe(false))
431+
return Local<Object>();
432+
425433
CallbackInfo::New(env->isolate(), ui, callback, hint);
426434
return scope.Escape(ui);
427435
}
428436

429437

430-
Local<Object> Use(Isolate* isolate, char* data, size_t length) {
438+
MaybeLocal<Object> Use(Isolate* isolate, char* data, size_t length) {
431439
Environment* env = Environment::GetCurrent(isolate);
432440
EscapableHandleScope handle_scope(env->isolate());
433-
Local<Object> obj = Buffer::Use(env, data, length);
434-
return handle_scope.Escape(obj);
441+
Local<Object> obj;
442+
if (Buffer::Use(env, data, length).ToLocal(&obj))
443+
return handle_scope.Escape(obj);
444+
return Local<Object>();
435445
}
436446

437447

438-
Local<Object> Use(Environment* env, char* data, size_t length) {
448+
MaybeLocal<Object> Use(Environment* env, char* data, size_t length) {
439449
EscapableHandleScope scope(env->isolate());
440450

441451
if (using_old_buffer) {
@@ -463,12 +473,9 @@ Local<Object> Use(Environment* env, char* data, size_t length) {
463473
Local<Uint8Array> ui = Uint8Array::New(ab, 0, length);
464474
Maybe<bool> mb =
465475
ui->SetPrototype(env->context(), env->buffer_prototype_object());
466-
if (!mb.FromMaybe(false)) {
467-
FatalError("node::Buffer::Use(Environment*, char*, size_t)",
468-
"Could not set Object prototype");
469-
UNREACHABLE();
470-
}
471-
return scope.Escape(ui);
476+
if (mb.FromMaybe(false))
477+
return scope.Escape(ui);
478+
return Local<Object>();
472479
}
473480

474481

@@ -501,8 +508,9 @@ void Create(const FunctionCallbackInfo<Value>& args) {
501508
Local<Uint8Array> ui = Uint8Array::New(ab, 0, length);
502509
Maybe<bool> mb =
503510
ui->SetPrototype(env->context(), env->buffer_prototype_object());
504-
if (mb.FromMaybe(false))
505-
args.GetReturnValue().Set(ui);
511+
if (!mb.FromMaybe(false))
512+
return env->ThrowError("Unable to set Object prototype");
513+
args.GetReturnValue().Set(ui);
506514
}
507515

508516

@@ -513,8 +521,9 @@ void CreateFromString(const FunctionCallbackInfo<Value>& args) {
513521
enum encoding enc = ParseEncoding(args.GetIsolate(),
514522
args[1].As<String>(),
515523
UTF8);
516-
Local<Object> buf = New(args.GetIsolate(), args[0].As<String>(), enc);
517-
args.GetReturnValue().Set(buf);
524+
Local<Object> buf;
525+
if (New(args.GetIsolate(), args[0].As<String>(), enc).ToLocal(&buf))
526+
args.GetReturnValue().Set(buf);
518527
}
519528

520529

@@ -535,8 +544,9 @@ void Slice(const FunctionCallbackInfo<Value>& args) {
535544
Local<Uint8Array> ui = Uint8Array::New(ab, start, size);
536545
Maybe<bool> mb =
537546
ui->SetPrototype(env->context(), env->buffer_prototype_object());
538-
if (mb.FromMaybe(false))
539-
args.GetReturnValue().Set(ui);
547+
if (!mb.FromMaybe(false))
548+
env->ThrowError("Unable to set Object prototype");
549+
args.GetReturnValue().Set(ui);
540550
}
541551

542552

src/node_buffer.h

Lines changed: 34 additions & 32 deletions

0 commit comments

Comments
 (0)