From d2cd3b6d56082d70c4f2fc42a63a076f1185acfb Mon Sep 17 00:00:00 2001 From: Alexander Borisov Date: Tue, 20 Oct 2020 14:00:40 +0300 Subject: [PATCH] Added support for Object.prototype.valueOf() in Buffer.from(). Missed in 27bb9caf186c. --- src/njs_buffer.c | 17 ++++++++++++++++- src/njs_value.c | 27 +++++++++++++++++++++++++++ src/njs_value.h | 1 + src/test/njs_unit_test.c | 23 +++++++++++++++++++++++ 4 files changed, 67 insertions(+), 1 deletion(-) diff --git a/src/njs_buffer.c b/src/njs_buffer.c index 1142cf7a..f4d1f31d 100644 --- a/src/njs_buffer.c +++ b/src/njs_buffer.c @@ -228,11 +228,13 @@ njs_buffer_from(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { njs_int_t ret; - njs_value_t *value; + njs_value_t *value, retval; const njs_buffer_encoding_t *encoding; value = njs_arg(args, nargs, 1); +next: + switch (value->type) { case NJS_TYPED_ARRAY: return njs_buffer_from_typed_array(vm, value); @@ -251,6 +253,19 @@ njs_buffer_from(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, default: if (njs_is_object(value)) { + ret = njs_value_of(vm, value, &retval); + if (njs_slow_path(ret == NJS_ERROR)) { + return ret; + } + + if (ret == NJS_OK && !njs_is_null(&retval) + && !(njs_is_object(&retval) + && njs_object(&retval) == njs_object(value))) + { + *value = retval; + goto next; + } + ret = njs_buffer_from_object(vm, value); if (njs_slow_path(ret != NJS_DECLINED)) { return ret; diff --git a/src/njs_value.c b/src/njs_value.c index 5cd78d7f..365013fa 100644 --- a/src/njs_value.c +++ b/src/njs_value.c @@ -261,6 +261,33 @@ njs_value_own_enumerate(njs_vm_t *vm, njs_value_t *value, } +njs_int_t +njs_value_of(njs_vm_t *vm, njs_value_t *value, njs_value_t *retval) +{ + + njs_int_t ret; + + static const njs_value_t value_of = njs_string("valueOf"); + + if (njs_slow_path(!njs_is_object(value))) { + return NJS_DECLINED; + } + + ret = njs_value_property(vm, value, njs_value_arg(&value_of), + retval); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + if (!njs_is_function(retval)) { + njs_type_error(vm, "object.valueOf is not a function"); + return NJS_ERROR; + } + + return njs_function_apply(vm, njs_function(retval), value, 1, retval); +} + + njs_int_t njs_value_length(njs_vm_t *vm, njs_value_t *value, int64_t *length) { diff --git a/src/njs_value.h b/src/njs_value.h index 1cf808a1..b8aa7739 100644 --- a/src/njs_value.h +++ b/src/njs_value.h @@ -1053,6 +1053,7 @@ njs_array_t *njs_value_enumerate(njs_vm_t *vm, njs_value_t *value, njs_object_enum_t kind, njs_object_enum_type_t type, njs_bool_t all); njs_array_t *njs_value_own_enumerate(njs_vm_t *vm, njs_value_t *value, njs_object_enum_t kind, njs_object_enum_type_t type, njs_bool_t all); +njs_int_t njs_value_of(njs_vm_t *vm, njs_value_t *value, njs_value_t *retval); njs_int_t njs_value_length(njs_vm_t *vm, njs_value_t *value, int64_t *dst); const char *njs_type_string(njs_value_type_t type); diff --git a/src/test/njs_unit_test.c b/src/test/njs_unit_test.c index ea005574..76a4fa85 100644 --- a/src/test/njs_unit_test.c +++ b/src/test/njs_unit_test.c @@ -18580,6 +18580,29 @@ static njs_unit_test_t njs_test[] = { njs_str("var buf = Buffer.from('α'); njs.dump(buf)"), njs_str("Buffer [206,177]") }, + { njs_str("var arr = new Array(1,2,3); arr.valueOf = () => arr;" + "njs.dump(Buffer.from(arr))"), + njs_str("Buffer [1,2,3]") }, + + { njs_str("var obj = new Object(); obj.valueOf = () => obj;" + "Buffer.from(obj)"), + njs_str("TypeError: first argument object is not a string or Buffer-like object") }, + + { njs_str("var obj = new Object(); obj.valueOf = () => undefined;" + "njs.dump(Buffer.from(obj))"), + njs_str("TypeError: first argument undefined is not a string or Buffer-like object") }, + + { njs_str("var arr = new Array(1,2,3); arr.valueOf = () => null;" + "njs.dump(Buffer.from(arr))"), + njs_str("Buffer [1,2,3]") }, + + { njs_str("var obj = new Object(); obj.valueOf = () => new Array(1,2,3);" + "njs.dump(Buffer.from(obj))"), + njs_str("Buffer [1,2,3]") }, + + { njs_str("njs.dump(Buffer.from(new String('test')))"), + njs_str("Buffer [116,101,115,116]") }, + { njs_str("[" " ['6576696c', 'hex']," " ['ZXZpbA==', 'base64']," -- 2.47.3