[njs] Returning external methods as native Function objects.

Dmitry Volyntsev xeioex at nginx.com
Mon Jul 2 15:04:20 UTC 2018


details:   http://hg.nginx.org/njs/rev/4afaf9e2804c
branches:  
changeset: 549:4afaf9e2804c
user:      xeioex at nginx.com
date:      Tue Jun 26 18:30:10 2018 +0700
description:
Returning external methods as native Function objects.

This fixes #20 issue on GitHub.

diffstat:

 njs/njs_extern.c             |  27 +++++++++++++++++++++------
 njs/njs_vm.c                 |   6 ++++++
 njs/test/njs_expect_test.exp |   5 +++++
 3 files changed, 32 insertions(+), 6 deletions(-)

diffs (78 lines):

diff -r 649e5804b971 -r 4afaf9e2804c njs/njs_extern.c
--- a/njs/njs_extern.c	Tue Jun 26 18:27:33 2018 +0700
+++ b/njs/njs_extern.c	Tue Jun 26 18:30:10 2018 +0700
@@ -75,6 +75,7 @@ njs_vm_external_add(njs_vm_t *vm, nxt_lv
 {
     nxt_int_t           ret;
     njs_extern_t        *ext, *child;
+    njs_function_t      *function;
     nxt_lvlhsh_query_t  lhq;
 
     do {
@@ -96,15 +97,29 @@ njs_vm_external_add(njs_vm_t *vm, nxt_lv
         ext->data = external->data;
 
         if (external->method != NULL) {
-            ext->function = nxt_mem_cache_zalloc(vm->mem_cache_pool,
-                                                 sizeof(njs_function_t));
-            if (nxt_slow_path(ext->function == NULL)) {
+            function = nxt_mem_cache_zalloc(vm->mem_cache_pool,
+                                            sizeof(njs_function_t));
+            if (nxt_slow_path(function == NULL)) {
                 return NULL;
             }
 
-            ext->function->native = 1;
-            ext->function->args_offset = 1;
-            ext->function->u.native = external->method;
+            /*
+             * nxt_mem_cache_zalloc() does also:
+             *   nxt_lvlhsh_init(&function->object.hash);
+             *   function->object.__proto__ = NULL;
+             */
+
+            function->object.__proto__ =
+                              &vm->prototypes[NJS_CONSTRUCTOR_FUNCTION].object;
+            function->object.shared_hash = vm->shared->function_prototype_hash;
+            function->object.type = NJS_FUNCTION;
+            function->object.shared = 1;
+            function->object.extensible = 1;
+            function->args_offset = 1;
+            function->native = 1;
+            function->u.native = external->method;
+
+            ext->function = function;
 
         } else {
             ext->function = NULL;
diff -r 649e5804b971 -r 4afaf9e2804c njs/njs_vm.c
--- a/njs/njs_vm.c	Tue Jun 26 18:27:33 2018 +0700
+++ b/njs/njs_vm.c	Tue Jun 26 18:30:10 2018 +0700
@@ -588,6 +588,12 @@ njs_vmcode_property_get(njs_vm_t *vm, nj
             /* The vm->retval is already retained by ext_proto->get(). */
         }
 
+        if (ext_proto->type == NJS_EXTERN_METHOD) {
+            vm->retval.data.u.function = ext_proto->function;
+            vm->retval.type = NJS_FUNCTION;
+            vm->retval.data.truth = 1;
+        }
+
         return sizeof(njs_vmcode_prop_get_t);
 
     case NJS_TRAP_PROPERTY:
diff -r 649e5804b971 -r 4afaf9e2804c njs/test/njs_expect_test.exp
--- a/njs/test/njs_expect_test.exp	Tue Jun 26 18:27:33 2018 +0700
+++ b/njs/test/njs_expect_test.exp	Tue Jun 26 18:30:10 2018 +0700
@@ -176,6 +176,11 @@ njs_test {
      "console.ll()\r\nTypeError: cannot find property 'll' of an external object"}
 }
 
+njs_test {
+    {"var print = console.log.bind(console); print(1, 'a', [1, 2])\r\n"
+     "var print = console.log.bind(console); print(1, 'a', \\\[1, 2])\r\n1 a 1,2\r\nundefined\r\n>> "}
+}
+
 # Backtraces for external objects
 njs_test {
     {"console.log(console)\r\n"


More information about the nginx-devel mailing list