]> git.kaiwu.me - njs.git/commitdiff
Fixed Function.prototype.apply() according to the specification.
authorAlexander Borisov <alexander.borisov@nginx.com>
Thu, 29 Aug 2019 13:39:10 +0000 (16:39 +0300)
committerAlexander Borisov <alexander.borisov@nginx.com>
Thu, 29 Aug 2019 13:39:10 +0000 (16:39 +0300)
src/njs_function.c
src/test/njs_unit_test.c

index 8a1f97da722b3a07ce9ec44a3d12b57e8859a355..c8136dccdfe9377130d3d3bc5fe78955fce7a94b 100644 (file)
@@ -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;
index c24bdc5e14afabb8744ea0e32cd1eea87f807774..2c9749979ded83248497f043ca260427ad15e98d 100644 (file)
@@ -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]") },