From be83690d1a611ff60535180225d478c8a4407403 Mon Sep 17 00:00:00 2001 From: Alexander Borisov Date: Thu, 29 Aug 2019 16:39:10 +0300 Subject: [PATCH] Fixed Function.prototype.apply() according to the specification. --- src/njs_function.c | 27 +++------------------------ src/test/njs_unit_test.c | 13 +++++-------- 2 files changed, 8 insertions(+), 32 deletions(-) diff --git a/src/njs_function.c b/src/njs_function.c index 8a1f97da..c8136dcc 100644 --- a/src/njs_function.c +++ b/src/njs_function.c @@ -1010,29 +1010,16 @@ njs_function_prototype_call(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } -/* - * Non-primitive length values are not supported yet. To handle non-primitive - * values a continuation is needed. Currently, only one continuation per frame - * is supported. apply() is a special function which can add a second - * continuation to the continuation of the underling function. - * - * TODO: - * String.prototype.concat.apply('a', { length:{ valueOf: - * function() { return 2; } }, - * 0:'b', 1:'c'}) - */ static njs_int_t njs_function_prototype_apply(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t retval) { uint32_t i; njs_int_t ret; - njs_value_t length, name, *this, *arr_like; + njs_value_t name, *this, *arr_like; njs_array_t *arr; njs_function_t *func; - static const njs_value_t string_length = njs_string("length"); - if (!njs_is_function(njs_arg(args, nargs, 0))) { njs_type_error(vm, "\"this\" argument is not a function"); return NJS_ERROR; @@ -1060,19 +1047,11 @@ njs_function_prototype_apply(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return NJS_ERROR; } - ret = njs_value_property(vm, arr_like, njs_value_arg(&string_length), - &length); - if (njs_slow_path(ret == NJS_ERROR)) { + ret = njs_object_length(vm, arr_like, &nargs); + if (njs_slow_path(ret != NJS_OK)) { return ret; } - if (!njs_is_primitive(&length)) { - njs_type_error(vm, "non-primitive length values are not supported"); - return NJS_ERROR; - } - - nargs = njs_primitive_value_to_length(&length); - arr = njs_array_alloc(vm, nargs, NJS_ARRAY_SPARE); if (njs_slow_path(arr == NULL)) { return NJS_ERROR; diff --git a/src/test/njs_unit_test.c b/src/test/njs_unit_test.c index c24bdc5e..2c974997 100644 --- a/src/test/njs_unit_test.c +++ b/src/test/njs_unit_test.c @@ -7143,16 +7143,13 @@ static njs_unit_test_t njs_test[] = "{length:2, 0:{toString:function() {return 'b'}}, 1:'c'})"), njs_str("abc") }, -#if 0 - /* TODO: non-primitive length values are not supported yet. */ { njs_str("String.prototype.concat.apply('a'," - "{length:{valueOf:function() {return 2}}, 0:'b', 1:'c'})"), + "{length: {valueOf: () => 2}, 0:'b', 1:'c'})"), + njs_str("abc") }, + + { njs_str("var o = {0:'b', 1:'c'}; Object.defineProperty(o, 'length', {get: () => 2});" + "String.prototype.concat.apply('a', o)"), njs_str("abc") }, -#else - { njs_str("String.prototype.concat.apply('a'," - "{length:{valueOf:function() {return 2}}, 0:'b', 1:'c'})"), - njs_str("TypeError: non-primitive length values are not supported") }, -#endif { njs_str("var a = function() { return 1 } + ''; a"), njs_str("[object Function]") }, -- 2.47.3