Skip to content

Commit 36f78f4

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 <[email protected]>
1 parent 571ec13 commit 36f78f4

9 files changed

+164
-132
lines changed

src/js_stream.cc

+12-7
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,11 @@ int JSStream::DoWrite(WriteWrap* w,
8888
HandleScope scope(env()->isolate());
8989

9090
Local<Array> bufs_arr = Array::New(env()->isolate(), count);
91-
for (size_t i = 0; i < count; i++)
92-
bufs_arr->Set(i, Buffer::New(env(), bufs[i].base, bufs[i].len));
91+
Local<Object> buf;
92+
for (size_t i = 0; i < count; i++) {
93+
buf = Buffer::New(env(), bufs[i].base, bufs[i].len).ToLocalChecked();
94+
bufs_arr->Set(i, buf);
95+
}
9396

9497
Local<Value> argv[] = {
9598
w->object(),
@@ -134,11 +137,13 @@ void JSStream::DoAlloc(const FunctionCallbackInfo<Value>& args) {
134137

135138
uv_buf_t buf;
136139
wrap->OnAlloc(args[0]->Int32Value(), &buf);
137-
args.GetReturnValue().Set(Buffer::New(wrap->env(),
138-
buf.base,
139-
buf.len,
140-
FreeCallback,
141-
nullptr));
140+
Local<Object> vbuf = Buffer::New(
141+
wrap->env(),
142+
buf.base,
143+
buf.len,
144+
FreeCallback,
145+
nullptr).ToLocalChecked();
146+
return args.GetReturnValue().Set(vbuf);
142147
}
143148

144149

src/node_buffer.cc

+71-61
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

+34-32
Original file line numberDiff line numberDiff line change
@@ -24,50 +24,52 @@ NODE_EXTERN size_t Length(v8::Handle<v8::Value> val);
2424
NODE_EXTERN size_t Length(v8::Handle<v8::Object> val);
2525

2626
// public constructor
27-
NODE_EXTERN v8::Local<v8::Object> New(v8::Isolate* isolate, size_t length);
27+
NODE_EXTERN v8::MaybeLocal<v8::Object> New(v8::Isolate* isolate, size_t length);
2828
NODE_DEPRECATED("Use New(isolate, ...)",
29-
inline v8::Local<v8::Object> New(size_t length) {
29+
inline v8::MaybeLocal<v8::Object> New(size_t length) {
3030
return New(v8::Isolate::GetCurrent(), length);
3131
})
3232
// public constructor from string
33-
NODE_EXTERN v8::Local<v8::Object> New(v8::Isolate* isolate,
34-
v8::Handle<v8::String> string,
35-
enum encoding enc = UTF8);
33+
NODE_EXTERN v8::MaybeLocal<v8::Object> New(v8::Isolate* isolate,
34+
v8::Handle<v8::String> string,
35+
enum encoding enc = UTF8);
3636
NODE_DEPRECATED("Use New(isolate, ...)",
37-
inline v8::Local<v8::Object> New(v8::Handle<v8::String> string,
38-
enum encoding enc = UTF8) {
37+
inline v8::MaybeLocal<v8::Object> New(
38+
v8::Handle<v8::String> string,
39+
enum encoding enc = UTF8) {
3940
return New(v8::Isolate::GetCurrent(), string, enc);
4041
})
4142
// public constructor - data is copied
4243
// TODO(trevnorris): should be something like Copy()
43-
NODE_EXTERN v8::Local<v8::Object> New(v8::Isolate* isolate,
44-
const char* data,
45-
size_t len);
44+
NODE_EXTERN v8::MaybeLocal<v8::Object> New(v8::Isolate* isolate,
45+
const char* data,
46+
size_t len);
4647
NODE_DEPRECATED("Use New(isolate, ...)",
47-
inline v8::Local<v8::Object> New(const char* data, size_t len) {
48+
inline v8::MaybeLocal<v8::Object> New(const char* data,
49+
size_t len) {
4850
return New(v8::Isolate::GetCurrent(), data, len);
4951
})
5052
// public constructor - data is used, callback is passed data on object gc
51-
NODE_EXTERN v8::Local<v8::Object> New(v8::Isolate* isolate,
52-
char* data,
53-
size_t length,
54-
FreeCallback callback,
55-
void* hint);
53+
NODE_EXTERN v8::MaybeLocal<v8::Object> New(v8::Isolate* isolate,
54+
char* data,
55+
size_t length,
56+
FreeCallback callback,
57+
void* hint);
5658
NODE_DEPRECATED("Use New(isolate, ...)",
57-
inline v8::Local<v8::Object> New(char* data,
58-
size_t length,
59-
FreeCallback callback,
60-
void* hint) {
59+
inline v8::MaybeLocal<v8::Object> New(char* data,
60+
size_t length,
61+
FreeCallback callback,
62+
void* hint) {
6163
return New(v8::Isolate::GetCurrent(), data, length, callback, hint);
6264
})
6365

6466
// public constructor - data is used.
6567
// TODO(trevnorris): should be New() for consistency
66-
NODE_EXTERN v8::Local<v8::Object> Use(v8::Isolate* isolate,
67-
char* data,
68-
size_t len);
68+
NODE_EXTERN v8::MaybeLocal<v8::Object> Use(v8::Isolate* isolate,
69+
char* data,
70+
size_t len);
6971
NODE_DEPRECATED("Use Use(isolate, ...)",
70-
inline v8::Local<v8::Object> Use(char* data, size_t len) {
72+
inline v8::MaybeLocal<v8::Object> Use(char* data, size_t len) {
7173
return Use(v8::Isolate::GetCurrent(), data, len);
7274
})
7375

@@ -90,14 +92,14 @@ static inline bool IsWithinBounds(size_t off, size_t len, size_t max) {
9092
// src/node_internals.h due to a circular dependency issue with
9193
// the smalloc.h and node_internals.h headers.
9294
#if defined(NODE_WANT_INTERNALS)
93-
v8::Local<v8::Object> New(Environment* env, size_t size);
94-
v8::Local<v8::Object> New(Environment* env, const char* data, size_t len);
95-
v8::Local<v8::Object> New(Environment* env,
96-
char* data,
97-
size_t length,
98-
FreeCallback callback,
99-
void* hint);
100-
v8::Local<v8::Object> Use(Environment* env, char* data, size_t length);
95+
v8::MaybeLocal<v8::Object> New(Environment* env, size_t size);
96+
v8::MaybeLocal<v8::Object> New(Environment* env, const char* data, size_t len);
97+
v8::MaybeLocal<v8::Object> New(Environment* env,
98+
char* data,
99+
size_t length,
100+
FreeCallback callback,
101+
void* hint);
102+
v8::MaybeLocal<v8::Object> Use(Environment* env, char* data, size_t length);
101103
#endif // defined(NODE_WANT_INTERNALS)
102104

103105
} // namespace Buffer

0 commit comments

Comments
 (0)