[njs] Fixed "caller" and "arguments" properties of a function instance.

Dmitry Volyntsev xeioex at nginx.com
Fri Oct 18 13:27:45 UTC 2019


details:   https://hg.nginx.org/njs/rev/ed4472f545a1
branches:  
changeset: 1186:ed4472f545a1
user:      Artem S. Povalyukhin <artem.povaluhin at gmail.com>
date:      Sat Aug 24 05:41:46 2019 +0300
description:
Fixed "caller" and "arguments" properties of a function instance.

This closes #209 issue on Github.

diffstat:

 src/njs_function.c       |  40 +++++++++++++++++++++++++++++-----------
 src/test/njs_unit_test.c |  45 +++++++++++++++++++++++++++++++++++++++------
 2 files changed, 68 insertions(+), 17 deletions(-)

diffs (149 lines):

diff -r eae54eb41bfc -r ed4472f545a1 src/njs_function.c
--- a/src/njs_function.c	Tue Oct 15 20:09:49 2019 +0300
+++ b/src/njs_function.c	Sat Aug 24 05:41:46 2019 +0300
@@ -254,10 +254,11 @@ njs_function_rest_parameters_init(njs_vm
 
 
 static njs_int_t
-njs_function_arguments_thrower(njs_vm_t *vm, njs_value_t *value,
-    njs_value_t *setval, njs_value_t *retval)
+njs_function_prototype_thrower(njs_vm_t *vm, njs_value_t *args,
+    njs_uint_t nargs, njs_index_t unused)
 {
-    njs_type_error(vm, "\"caller\", \"callee\" properties may not be accessed");
+    njs_type_error(vm, "\"caller\", \"callee\", \"arguments\" "
+                   "properties may not be accessed");
     return NJS_ERROR;
 }
 
@@ -265,15 +266,12 @@ njs_function_arguments_thrower(njs_vm_t 
 const njs_object_prop_t  njs_arguments_object_instance_properties[] =
 {
     {
-        .type = NJS_PROPERTY_HANDLER,
-        .name = njs_string("caller"),
-        .value = njs_prop_handler(njs_function_arguments_thrower),
-    },
-
-    {
-        .type = NJS_PROPERTY_HANDLER,
+        .type = NJS_PROPERTY,
         .name = njs_string("callee"),
-        .value = njs_prop_handler(njs_function_arguments_thrower),
+        .value = njs_value(NJS_INVALID, 1, NAN),
+        .getter = njs_native_function(njs_function_prototype_thrower, 0, 0),
+        .setter = njs_native_function(njs_function_prototype_thrower, 0, 0),
+        .writable = NJS_ATTRIBUTE_UNSET,
     },
 };
 
@@ -1279,6 +1277,26 @@ static const njs_object_prop_t  njs_func
         .writable = 1,
         .configurable = 1,
     },
+
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("caller"),
+        .value = njs_value(NJS_INVALID, 1, NAN),
+        .getter = njs_native_function(njs_function_prototype_thrower, 0, 0),
+        .setter = njs_native_function(njs_function_prototype_thrower, 0, 0),
+        .writable = NJS_ATTRIBUTE_UNSET,
+        .configurable = 1,
+    },
+
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("arguments"),
+        .value = njs_value(NJS_INVALID, 1, NAN),
+        .getter = njs_native_function(njs_function_prototype_thrower, 0, 0),
+        .setter = njs_native_function(njs_function_prototype_thrower, 0, 0),
+        .writable = NJS_ATTRIBUTE_UNSET,
+        .configurable = 1,
+    },
 };
 
 
diff -r eae54eb41bfc -r ed4472f545a1 src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c	Tue Oct 15 20:09:49 2019 +0300
+++ b/src/test/njs_unit_test.c	Sat Aug 24 05:41:46 2019 +0300
@@ -8025,12 +8025,6 @@ static njs_unit_test_t  njs_test[] =
      { njs_str("(function(){return arguments[3];}).bind(null, 0)('a','b','c')"),
        njs_str("c") },
 
-    { njs_str("(function(){return arguments.callee;})()"),
-      njs_str("TypeError: \"caller\", \"callee\" properties may not be accessed") },
-
-    { njs_str("(function(){return arguments.caller;})()"),
-      njs_str("TypeError: \"caller\", \"callee\" properties may not be accessed") },
-
     { njs_str("function sum() { var args = Array.prototype.slice.call(arguments); "
                  "return args.reduce(function(prev, curr) {return prev + curr})};"
                  "[sum(1), sum(1,2), sum(1,2,3), sum(1,2,3,4)]"),
@@ -8041,6 +8035,39 @@ static njs_unit_test_t  njs_test[] =
                  "[concat('.',1,2,3), concat('+',1,2,3,4)]"),
       njs_str("1.2.3,1+2+3+4") },
 
+    /* strict mode restrictions */
+
+    { njs_str("(function() {}).caller"),
+      njs_str("TypeError: \"caller\", \"callee\", \"arguments\" properties may not be accessed") },
+
+    { njs_str("(function() {}).arguments"),
+      njs_str("TypeError: \"caller\", \"callee\", \"arguments\" properties may not be accessed") },
+
+    { njs_str("var p = Object.getPrototypeOf(function() {});"
+              "var d = Object.getOwnPropertyDescriptor(p, 'caller');"
+              "typeof d.get == 'function' && typeof d.get == typeof d.set"
+              "                           && d.configurable && !d.enumerable"),
+      njs_str("true") },
+
+    { njs_str("var p = Object.getPrototypeOf(function() {});"
+              "var d = Object.getOwnPropertyDescriptor(p, 'arguments');"
+              "typeof d.get == 'function' && typeof d.get == typeof d.set"
+              "                           && d.configurable && !d.enumerable"),
+      njs_str("true") },
+
+    { njs_str("(function(){return arguments.callee;})()"),
+      njs_str("TypeError: \"caller\", \"callee\", \"arguments\" properties may not be accessed") },
+
+    { njs_str("var f = function() { return arguments; };"
+              "Object.getOwnPropertyDescriptor(f(), 'caller')"),
+      njs_str("undefined") },
+
+    { njs_str("var f = function() { return arguments; };"
+              "var d = Object.getOwnPropertyDescriptor(f(), 'callee');"
+              "typeof d.get == 'function' && typeof d.get == typeof d.set"
+              "                           && !d.configurable && !d.enumerable"),
+      njs_str("true") },
+
     /* rest parameters. */
 
     { njs_str("function myFoo(a,b,...other) { return other };"
@@ -11487,6 +11514,8 @@ static njs_unit_test_t  njs_test[] =
         "function isConfigurableMethods(o) {"
         "    var except = ["
         "        'prototype',"
+        "        'caller',"
+        "        'arguments',"
         "    ];"
         "    return Object.getOwnPropertyNames(o)"
         "                 .filter(v => !except.includes(v)"
@@ -11516,6 +11545,8 @@ static njs_unit_test_t  njs_test[] =
         "function isWritableMethods(o) {"
         "    var except = ["
         "        'prototype',"
+        "        'caller',"
+        "        'arguments',"
         "    ];"
         "    return Object.getOwnPropertyNames(o)"
         "                 .filter(v => !except.includes(v)"
@@ -13939,6 +13970,8 @@ static njs_unit_test_t  njs_test[] =
         "    var except = ["
         "        'prototype',"
         "        'constructor',"
+        "        'caller',"
+        "        'arguments',"
         "    ];"
         "    return Object.getOwnPropertyNames(o)"
         "                 .filter(v => !except.includes(v)"


More information about the nginx-devel mailing list