]> git.kaiwu.me - njs.git/commitdiff
Returning external methods as native Function objects.
authorUnknown <xeioex@nginx.com>
Tue, 26 Jun 2018 11:30:10 +0000 (18:30 +0700)
committerUnknown <xeioex@nginx.com>
Tue, 26 Jun 2018 11:30:10 +0000 (18:30 +0700)
This fixes #20 issue on GitHub.

njs/njs_extern.c
njs/njs_vm.c
njs/test/njs_expect_test.exp

index d24b437d86fc9b23aa25d200d1b3cd287c4055ab..29ff331510929030b3c6e6d4899dcce1b69fadf5 100644 (file)
@@ -75,6 +75,7 @@ njs_vm_external_add(njs_vm_t *vm, nxt_lvlhsh_t *hash, njs_external_t *external,
 {
     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_lvlhsh_t *hash, njs_external_t *external,
         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;
index 111927218d5971d24fb39856289024f95d1af2c0..5c577031fd93691d461b537ea7922b481dd68ab7 100644 (file)
@@ -588,6 +588,12 @@ njs_vmcode_property_get(njs_vm_t *vm, njs_value_t *object,
             /* 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:
index ef9b5e52fb58e198ac9d01f787696c137b479468..81150a029a55b8b6aa171ebc1286873f8a0e2d08 100644 (file)
@@ -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"