Welcome! Log In Create A New Profile

Advanced

[njs] Refactored bound function calls according to the spec.

Dmitry Volyntsev
October 10, 2022 10:36PM
details: https://hg.nginx.org/njs/rev/e4297a78844e
branches:
changeset: 1976:e4297a78844e
user: Dmitry Volyntsev <xeioex@nginx.com>
date: Mon Oct 10 18:45:09 2022 -0700
description:
Refactored bound function calls according to the spec.

This fixes #533, #546, #579 issues on Github.

diffstat:

src/njs_disassembler.c | 14 +---
src/njs_error.c | 9 +-
src/njs_extern.c | 1 -
src/njs_function.c | 171 ++++++++++++++++++++--------------------------
src/njs_function.h | 5 +-
src/njs_generator.c | 10 +-
src/njs_promise.c | 1 -
src/njs_value.h | 6 +-
src/njs_vm.c | 1 -
src/njs_vmcode.c | 63 +++++++++++-----
src/njs_vmcode.h | 9 +--
src/test/njs_unit_test.c | 18 +++-
test/js/async_bind.t.js | 13 +++
13 files changed, 161 insertions(+), 160 deletions(-)

diffs (735 lines):

diff -r 16442fa970ee -r e4297a78844e src/njs_disassembler.c
--- a/src/njs_disassembler.c Thu Oct 06 18:28:52 2022 -0700
+++ b/src/njs_disassembler.c Mon Oct 10 18:45:09 2022 -0700
@@ -17,6 +17,8 @@ typedef struct {

static njs_code_name_t code_names[] = {

+ { NJS_VMCODE_PUT_ARG, sizeof(njs_vmcode_1addr_t),
+ njs_str("PUT ARG ") },
{ NJS_VMCODE_OBJECT, sizeof(njs_vmcode_object_t),
njs_str("OBJECT ") },
{ NJS_VMCODE_FUNCTION, sizeof(njs_vmcode_function_t),
@@ -204,7 +206,6 @@ njs_disassemble(u_char *start, u_char *e
njs_vmcode_import_t *import;
njs_vmcode_finally_t *finally;
njs_vmcode_try_end_t *try_end;
- njs_vmcode_move_arg_t *move_arg;
njs_vmcode_try_start_t *try_start;
njs_vmcode_operation_t operation;
njs_vmcode_cond_jump_t *cond_jump;
@@ -513,17 +514,6 @@ njs_disassemble(u_char *start, u_char *e
continue;
}

- if (operation == NJS_VMCODE_MOVE_ARG) {
- move_arg = (njs_vmcode_move_arg_t *) p;
-
- njs_printf("%5uD | %05uz MOVE ARGUMENT %uD %04Xz\n",
- line, p - start, move_arg->dst, (size_t) move_arg->src);
-
- p += sizeof(njs_vmcode_move_arg_t);
-
- continue;
- }
-
code_name = code_names;
n = njs_nitems(code_names);

diff -r 16442fa970ee -r e4297a78844e src/njs_error.c
--- a/src/njs_error.c Thu Oct 06 18:28:52 2022 -0700
+++ b/src/njs_error.c Mon Oct 10 18:45:09 2022 -0700
@@ -1292,6 +1292,11 @@ njs_add_backtrace_entry(njs_vm_t *vm, nj

function = native_frame->function;

+ if (function != NULL && function->bound != NULL) {
+ /* Skip. */
+ return NJS_OK;
+ }
+
be = njs_arr_add(stack);
if (njs_slow_path(be == NULL)) {
return NJS_ERROR;
@@ -1301,10 +1306,6 @@ njs_add_backtrace_entry(njs_vm_t *vm, nj
be->file = njs_str_value("");

if (function != NULL && function->native) {
- while (function->bound != NULL) {
- function = function->u.bound_target;
- }
-
ret = njs_builtin_match_native_function(vm, function, &be->name);
if (ret == NJS_OK) {
return NJS_OK;
diff -r 16442fa970ee -r e4297a78844e src/njs_extern.c
--- a/src/njs_extern.c Thu Oct 06 18:28:52 2022 -0700
+++ b/src/njs_extern.c Mon Oct 10 18:45:09 2022 -0700
@@ -77,7 +77,6 @@ njs_external_add(njs_vm_t *vm, njs_arr_t
function->object.type = NJS_FUNCTION;
function->object.shared = 1;
function->object.extensible = 1;
- function->args_offset = 1;
function->native = 1;
function->u.native = external->u.method.native;
function->magic8 = external->u.method.magic8;
diff -r 16442fa970ee -r e4297a78844e src/njs_function.c
--- a/src/njs_function.c Thu Oct 06 18:28:52 2022 -0700
+++ b/src/njs_function.c Mon Oct 10 18:45:09 2022 -0700
@@ -30,7 +30,6 @@ njs_function_alloc(njs_vm_t *vm, njs_fun
*/

function->ctor = lambda->ctor;
- function->args_offset = 1;
function->u.lambda = lambda;

if (function->ctor) {
@@ -77,7 +76,6 @@ njs_vm_function_alloc(njs_vm_t *vm, njs_
}

function->native = 1;
- function->args_offset = 1;
function->u.native = native;

return function;
@@ -376,12 +374,10 @@ njs_function_native_frame(njs_vm_t *vm,
njs_bool_t ctor)
{
size_t size;
- njs_uint_t n;
- njs_value_t *value, *bound;
+ njs_value_t *value;
njs_native_frame_t *frame;

- size = NJS_NATIVE_FRAME_SIZE
- + (function->args_offset + nargs) * sizeof(njs_value_t);
+ size = NJS_NATIVE_FRAME_SIZE + (1 /* this */ + nargs) * sizeof(njs_value_t);

frame = njs_function_frame_alloc(vm, size);
if (njs_slow_path(frame == NULL)) {
@@ -389,31 +385,16 @@ njs_function_native_frame(njs_vm_t *vm,
}

frame->function = function;
- frame->nargs = function->args_offset + nargs;
+ frame->nargs = nargs;
frame->ctor = ctor;
frame->native = 1;
frame->pc = NULL;

value = (njs_value_t *) ((u_char *) frame + NJS_NATIVE_FRAME_SIZE);

- frame->arguments = value;
- frame->arguments_offset = value + function->args_offset;
-
- bound = function->bound;
-
- if (bound == NULL) {
- /* GC: njs_retain(this); */
- *value++ = *this;
+ njs_value_assign(value++, this++);

- } else {
- n = function->args_offset;
-
- do {
- /* GC: njs_retain(bound); */
- *value++ = *bound++;
- n--;
- } while (n != 0);
- }
+ frame->arguments = value;

if (args != NULL) {
memcpy(value, args, nargs * sizeof(njs_value_t));
@@ -430,37 +411,15 @@ njs_function_lambda_frame(njs_vm_t *vm,
{
size_t n, frame_size;
uint32_t args_count, value_count, value_size;
- njs_value_t *value, *bound, **new;
+ njs_value_t *value, **new;
njs_frame_t *frame;
- njs_function_t *target;
njs_native_frame_t *native_frame;
njs_function_lambda_t *lambda;

- bound = function->bound;
-
- if (njs_fast_path(bound == NULL)) {
- lambda = function->u.lambda;
- target = function;
-
- } else {
- target = function->u.bound_target;
-
- if (njs_slow_path(target->bound != NULL)) {
+ lambda = function->u.lambda;

- /*
- * FIXME: bound functions should call target function with
- * bound "this" and bound args.
- */
-
- njs_internal_error(vm, "chain of bound function are not supported");
- return NJS_ERROR;
- }
-
- lambda = target->u.lambda;
- }
-
- args_count = function->args_offset + njs_max(nargs, lambda->nargs);
- value_count = args_count + njs_max(args_count, lambda->nlocal);
+ args_count = njs_max(nargs, lambda->nargs);
+ value_count = args_count + lambda->nlocal;

value_size = value_count * sizeof(njs_value_t *);

@@ -485,9 +444,8 @@ njs_function_lambda_frame(njs_vm_t *vm,
}

native_frame->arguments = value;
- native_frame->arguments_offset = value + (function->args_offset - 1);
native_frame->local = new + args_count;
- native_frame->function = target;
+ native_frame->function = function;
native_frame->nargs = nargs;
native_frame->ctor = ctor;
native_frame->native = 0;
@@ -502,28 +460,11 @@ njs_function_lambda_frame(njs_vm_t *vm,
njs_set_object(native_frame->local[0], &vm->global_object);
}

- if (bound != NULL) {
- n = function->args_offset;
- native_frame->nargs += n - 1;
-
- if (!ctor) {
- *native_frame->local[0] = *bound;
- }
-
- bound++;
- n--;
-
- while (n != 0) {
- *value++ = *bound++;
- n--;
- };
- }
-
/* Copy arguments. */

if (args != NULL) {
while (nargs != 0) {
- *value++ = *args++;
+ njs_value_assign(value++, args++);
nargs--;
}
}
@@ -624,7 +565,7 @@ njs_function_lambda_call(njs_vm_t *vm, v
lambda = function->u.lambda;

args = vm->top_frame->arguments;
- local = vm->top_frame->local + function->args_offset;
+ local = vm->top_frame->local + 1 /* this */;

/* Move all arguments. */

@@ -702,7 +643,7 @@ njs_int_t
njs_function_native_call(njs_vm_t *vm)
{
njs_int_t ret;
- njs_function_t *function, *target;
+ njs_function_t *function;
njs_native_frame_t *native, *previous;
njs_function_native_t call;

@@ -723,21 +664,10 @@ njs_function_native_call(njs_vm_t *vm)
}
#endif

- if (njs_fast_path(function->bound == NULL)) {
- call = function->u.native;
-
- } else {
- target = function->u.bound_target;
+ call = function->u.native;

- if (njs_slow_path(target->bound != NULL)) {
- njs_internal_error(vm, "chain of bound function are not supported");
- return NJS_ERROR;
- }
-
- call = target->u.native;
- }
-
- ret = call(vm, native->arguments, native->nargs, function->magic8);
+ ret = call(vm, &native->arguments[-1], 1 /* this */ + native->nargs,
+ function->magic8);

#ifdef NJS_DEBUG_OPCODE
if (vm->options.opcode_debug) {
@@ -833,14 +763,13 @@ njs_function_frame_save(njs_vm_t *vm, nj
function = active->function;
lambda = function->u.lambda;

- args_count = function->args_offset + njs_max(native->nargs, lambda->nargs);
- value_count = args_count + njs_max(args_count, lambda->nlocal);
+ args_count = njs_max(native->nargs, lambda->nargs);
+ value_count = args_count + lambda->nlocal;

new = (njs_value_t **) ((u_char *) native + NJS_FRAME_SIZE);
value = (njs_value_t *) (new + value_count);

native->arguments = value;
- native->arguments_offset = value + (function->args_offset - 1);
native->local = new + njs_function_frame_args_count(active);
native->pc = pc;

@@ -848,14 +777,14 @@ njs_function_frame_save(njs_vm_t *vm, nj
p = native->arguments;

while (start < end) {
- *p = *start++;
+ njs_value_assign(p, start++);
*new++ = p++;
}

/* Move all arguments. */

p = native->arguments;
- local = native->local + function->args_offset;
+ local = native->local + 1 /* this */;

for (n = 0; n < function->args_count; n++) {
if (!njs_is_valid(p)) {
@@ -1461,11 +1390,54 @@ activate:


static njs_int_t
+njs_function_bound_call(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
+ njs_index_t unused)
+{
+ u_char *p;
+ njs_int_t ret;
+ size_t args_count;
+ njs_value_t *arguments;
+ njs_function_t *function, *bound;
+
+ function = vm->top_frame->function;
+ bound = function->context;
+
+ njs_assert(bound != NULL);
+
+ args_count = 1 /* this */ + function->bound_args;
+
+ if (nargs == 1) {
+ return njs_function_apply(vm, bound, function->bound, args_count,
+ &vm->retval);
+ }
+
+ arguments = njs_mp_alloc(vm->mem_pool,
+ (args_count + nargs - 1) * sizeof(njs_value_t));
+ if (njs_slow_path(arguments == NULL)) {
+ njs_memory_error(vm);
+ return NJS_ERROR;
+ }
+
+ p = njs_cpymem(arguments, function->bound,
+ args_count * sizeof(njs_value_t));
+ memcpy(p, &args[1], (nargs - 1) * sizeof(njs_value_t));
+
+ ret = njs_function_apply(vm, bound, arguments, args_count + nargs - 1,
+ &vm->retval);
+
+ njs_mp_free(vm->mem_pool, arguments);
+
+ return ret;
+}
+
+
+static njs_int_t
njs_function_prototype_bind(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
njs_index_t unused)
{
size_t size;
njs_int_t ret;
+ njs_uint_t bound_args;
njs_value_t *values, name;
njs_function_t *function;

@@ -1481,6 +1453,8 @@ njs_function_prototype_bind(njs_vm_t *vm
}

*function = *njs_function(&args[0]);
+ function->native = 1;
+ function->u.native = njs_function_bound_call;

njs_lvlhsh_init(&function->object.hash);

@@ -1490,7 +1464,7 @@ njs_function_prototype_bind(njs_vm_t *vm
function->object.__proto__ = &vm->prototypes[NJS_OBJ_TYPE_FUNCTION].object;
function->object.shared = 0;

- function->u.bound_target = njs_function(&args[0]);
+ function->context = njs_function(&args[0]);

ret = njs_value_property(vm, &args[0], njs_value_arg(&njs_string_name),
&name);
@@ -1509,21 +1483,23 @@ njs_function_prototype_bind(njs_vm_t *vm

if (nargs == 1) {
args = njs_value_arg(&njs_value_undefined);
+ bound_args = 0;

} else {
- nargs--;
args++;
+ bound_args = nargs - 2;
}

- if (nargs > function->args_count) {
+ if (bound_args > function->args_count) {
function->args_count = 0;

} else {
- function->args_count -= nargs - 1;
+ function->args_count -= bound_args;
}

- function->args_offset = nargs;
- size = nargs * sizeof(njs_value_t);
+ function->bound_args = bound_args;
+
+ size = (1 /* this */ + bound_args) * sizeof(njs_value_t);

values = njs_mp_alloc(vm->mem_pool, size);
if (njs_slow_path(values == NULL)) {
@@ -1700,7 +1676,6 @@ const njs_object_type_init_t njs_functi
.constructor_props = &njs_function_constructor_init,
.prototype_props = &njs_function_prototype_init,
.prototype_value = { .function = { .native = 1,
- .args_offset = 1,
.u.native = njs_prototype_function,
.object = { .type = NJS_FUNCTION } } },
};
diff -r 16442fa970ee -r e4297a78844e src/njs_function.h
--- a/src/njs_function.h Thu Oct 06 18:28:52 2022 -0700
+++ b/src/njs_function.h Mon Oct 10 18:45:09 2022 -0700
@@ -47,9 +47,9 @@ struct njs_native_frame_s {
njs_function_t *function;
njs_native_frame_t *previous;

+ /* Points to the first arg after 'this'. */
njs_value_t *arguments;
njs_object_t *arguments_object;
- njs_value_t *arguments_offset;
njs_value_t **local;

uint32_t size;
@@ -57,7 +57,10 @@ struct njs_native_frame_s {

njs_value_t *retval;

+ /* Number of allocated args on the frame. */
uint32_t nargs;
+ /* Number of already put args. */
+ uint32_t put_args;

uint8_t native; /* 1 bit */
/* Function is called as constructor with "new" keyword. */
diff -r 16442fa970ee -r e4297a78844e src/njs_generator.c
--- a/src/njs_generator.c Thu Oct 06 18:28:52 2022 -0700
+++ b/src/njs_generator.c Mon Oct 10 18:45:09 2022 -0700
@@ -4382,22 +4382,20 @@ njs_generate_move_arguments(njs_vm_t *vm
njs_parser_node_t *node)
{
njs_jump_off_t func_offset;
- njs_vmcode_move_arg_t *move_arg;
+ njs_vmcode_1addr_t *put_arg;
njs_vmcode_function_frame_t *func;

if (node == NULL) {
return njs_generator_stack_pop(vm, generator, generator->context);
}

- njs_generate_code(generator, njs_vmcode_move_arg_t, move_arg,
- NJS_VMCODE_MOVE_ARG, 0, node);
- move_arg->src = node->left->index;
+ njs_generate_code(generator, njs_vmcode_1addr_t, put_arg,
+ NJS_VMCODE_PUT_ARG, 0, node);
+ put_arg->index = node->left->index;

func_offset = *((njs_jump_off_t *) generator->context);
func = njs_code_ptr(generator, njs_vmcode_function_frame_t, func_offset);

- move_arg->dst = (njs_uint_t) func->nargs;
-
func->nargs++;

if (node->right == NULL) {
diff -r 16442fa970ee -r e4297a78844e src/njs_promise.c
--- a/src/njs_promise.c Thu Oct 06 18:28:52 2022 -0700
+++ b/src/njs_promise.c Mon Oct 10 18:45:09 2022 -0700
@@ -255,7 +255,6 @@ njs_promise_create_function(njs_vm_t *vm
function->object.shared_hash = vm->shared->arrow_instance_hash;
function->object.type = NJS_FUNCTION;
function->object.extensible = 1;
- function->args_offset = 1;
function->native = 1;
function->context = context;

diff -r 16442fa970ee -r e4297a78844e src/njs_value.h
--- a/src/njs_value.h Thu Oct 06 18:28:52 2022 -0700
+++ b/src/njs_value.h Mon Oct 10 18:45:09 2022 -0700
@@ -250,7 +250,8 @@ struct njs_typed_array_s {
struct njs_function_s {
njs_object_t object;

- uint8_t args_offset;
+ /* Number of bound args excluding 'this'. */
+ uint8_t bound_args;

uint8_t args_count:4;

@@ -265,11 +266,11 @@ struct njs_function_s {
union {
njs_function_lambda_t *lambda;
njs_function_native_t native;
- njs_function_t *bound_target;
} u;

void *context;

+ /* Bound args including 'this'. */
njs_value_t *bound;
};

@@ -428,7 +429,6 @@ typedef struct {
.magic8 = _magic, \
.args_count = _args_count, \
.ctor = _ctor, \
- .args_offset = 1, \
.u.native = _function, \
.object = { .type = NJS_FUNCTION, \
.shared = 1, \
diff -r 16442fa970ee -r e4297a78844e src/njs_vm.c
--- a/src/njs_vm.c Thu Oct 06 18:28:52 2022 -0700
+++ b/src/njs_vm.c Mon Oct 10 18:45:09 2022 -0700
@@ -300,7 +300,6 @@ njs_vm_compile_module(njs_vm_t *vm, njs_
lambda->declarations = (arr != NULL) ? arr->start : NULL;
lambda->ndeclarations = (arr != NULL) ? arr->items : 0;

- module->function.args_offset = 1;
module->function.u.lambda = lambda;

return module;
diff -r 16442fa970ee -r e4297a78844e src/njs_vmcode.c
--- a/src/njs_vmcode.c Thu Oct 06 18:28:52 2022 -0700
+++ b/src/njs_vmcode.c Mon Oct 10 18:45:09 2022 -0700
@@ -98,6 +98,7 @@ njs_vmcode_interpreter(njs_vm_t *vm, u_c
njs_value_t numeric1, numeric2, primitive1, primitive2;
njs_frame_t *frame;
njs_jump_off_t ret;
+ njs_vmcode_1addr_t *put_arg;
njs_vmcode_await_t *await;
njs_native_frame_t *previous, *native;
njs_property_next_t *next;
@@ -105,7 +106,6 @@ njs_vmcode_interpreter(njs_vm_t *vm, u_c
njs_vmcode_finally_t *finally;
njs_vmcode_generic_t *vmcode;
njs_vmcode_variable_t *var;
- njs_vmcode_move_arg_t *move_arg;
njs_vmcode_prop_get_t *get;
njs_vmcode_prop_set_t *set;
njs_vmcode_operation_t op;
@@ -657,18 +657,16 @@ next:
} else {

switch (op) {
- case NJS_VMCODE_MOVE_ARG:
- move_arg = (njs_vmcode_move_arg_t *) pc;
+ case NJS_VMCODE_PUT_ARG:
+ put_arg = (njs_vmcode_1addr_t *) pc;
native = vm->top_frame;

- hint = move_arg->dst;
-
- value1 = &native->arguments_offset[hint];
- njs_vmcode_operand(vm, move_arg->src, value2);
-
- *value1 = *value2;
-
- ret = sizeof(njs_vmcode_move_arg_t);
+ value1 = &native->arguments[native->put_args++];
+ njs_vmcode_operand(vm, put_arg->index, value2);
+
+ njs_value_assign(value1, value2);
+
+ ret = sizeof(njs_vmcode_1addr_t);
break;

case NJS_VMCODE_STOP:
@@ -1290,7 +1288,6 @@ njs_vmcode_template_literal(njs_vm_t *vm

static const njs_function_t concat = {
.native = 1,
- .args_offset = 1,
.u.native = njs_string_prototype_concat
};

@@ -1584,7 +1581,7 @@ njs_vmcode_instance_of(njs_vm_t *vm, njs
function = njs_function(constructor);

if (function->bound != NULL) {
- function = function->u.bound_target;
+ function = function->context;
njs_set_function(&bound, function);
constructor = &bound;
}
@@ -1849,33 +1846,57 @@ static njs_jump_off_t
njs_function_frame_create(njs_vm_t *vm, njs_value_t *value,
const njs_value_t *this, uintptr_t nargs, njs_bool_t ctor)
{
- njs_value_t val;
+ njs_int_t ret;
+ njs_value_t new_target, *args;
njs_object_t *object;
- njs_function_t *function;
+ njs_function_t *function, *target;

if (njs_fast_path(njs_is_function(value))) {

function = njs_function(value);
+ target = function;
+ args = NULL;

if (ctor) {
- if (!function->ctor) {
+ if (function->bound != NULL) {
+ target = function->context;
+ nargs += function->bound_args;
+
+ args = njs_mp_alloc(vm->mem_pool, nargs * sizeof(njs_value_t));
+ if (njs_slow_path(args == NULL)) {
+ njs_memory_error(vm);
+ return NJS_ERROR;
+ }
+
+ memcpy(args, &function->bound[1],
+ function->bound_args * sizeof(njs_value_t));
+ }
+
+ if (!target->ctor) {
njs_type_error(vm, "%s is not a constructor",
njs_type_string(value->type));
return NJS_ERROR;
}

- if (!function->native) {
+ if (!target->native) {
object = njs_function_new_object(vm, value);
if (njs_slow_path(object == NULL)) {
return NJS_ERROR;
}

- njs_set_object(&val, object);
- this = &val;
+ njs_set_object(&new_target, object);
+ this = &new_target;
}
}

- return njs_function_frame(vm, function, this, NULL, nargs, ctor);
+ ret = njs_function_frame(vm, target, this, args, nargs, ctor);
+
+ if (args != NULL) {
+ vm->top_frame->put_args = function->bound_args;
+ njs_mp_free(vm->mem_pool, args);
+ }
+
+ return ret;
}

njs_type_error(vm, "%s is not a function", njs_type_string(value->type));
@@ -1902,7 +1923,7 @@ njs_function_new_object(njs_vm_t *vm, nj
function = njs_function(constructor);

if (function->bound != NULL) {
- function = function->u.bound_target;
+ function = function->context;
njs_set_function(&bound, function);
constructor = &bound;
}
diff -r 16442fa970ee -r e4297a78844e src/njs_vmcode.h
--- a/src/njs_vmcode.h Thu Oct 06 18:28:52 2022 -0700
+++ b/src/njs_vmcode.h Mon Oct 10 18:45:09 2022 -0700
@@ -31,7 +31,7 @@ typedef uint8_t


enum {
- NJS_VMCODE_MOVE_ARG = 0,
+ NJS_VMCODE_PUT_ARG = 0,
NJS_VMCODE_STOP,
NJS_VMCODE_JUMP,
NJS_VMCODE_PROPERTY_SET,
@@ -411,13 +411,6 @@ typedef struct {

typedef struct {
njs_vmcode_t code;
- njs_index_t src;
- njs_uint_t dst;
-} njs_vmcode_move_arg_t;
-
-
-typedef struct {
- njs_vmcode_t code;
njs_value_t *function;
njs_index_t retval;
} njs_vmcode_function_copy_t;
diff -r 16442fa970ee -r e4297a78844e src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c Thu Oct 06 18:28:52 2022 -0700
+++ b/src/test/njs_unit_test.c Mon Oct 10 18:45:09 2022 -0700
@@ -7818,12 +7818,22 @@ static njs_unit_test_t njs_test[] =
{ njs_str("var bArray = Array.bind(null, 10); new bArray(16)"),
njs_str("10,16") },

-#if 0 /* FIXME: refactor Bound calls (9.4.1.1[[Call]]). */
{ njs_str("function f(x,y) {return {args:arguments,length:arguments.length}};"
- "var bf = f.bind({}, 'a'); var bbf = bf.bind({},'b'); var o = bbf('c');"),
- "[o.args[0], o.args[2], o.length]"
+ "var bf = f.bind({}, 'a'); var bbf = bf.bind({},'b'); var o = bbf('c');"
+ "[o.args[0], o.args[2], o.length]"),
njs_str("a,c,3") },
-#endif
+
+ { njs_str("var f = function (a, b) {return [this, a, b]};"
+ "var b1 = f.bind('THIS', 'x');"
+ "var b2 = b1.bind('WAKA', 'y');"
+ "njs.dump([f(2,3), b1(3), b2()])"),
+ njs_str("[[undefined,2,3],['THIS','x',3],['THIS','x','y']]") },
+
+ { njs_str("var f = Math.max;"
+ "var b1 = f.bind('THIS', 4);"
+ "var b2 = b1.bind('WAKA', 5);"
+ "njs.dump([f(2,3), b1(3), b2()])"),
+ njs_str("[3,4,5]") },

{ njs_str("var s = { toString: function() { return '123' } };"
"var a = 'abc'; a.concat('абв', s)"),
diff -r 16442fa970ee -r e4297a78844e test/js/async_bind.t.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/js/async_bind.t.js Mon Oct 10 18:45:09 2022 -0700
@@ -0,0 +1,13 @@
+/*---
+includes: [compareArray.js]
+flags: [async]
+---*/
+
+async function f(a1, a2, a3) {
+ var v = await a1;
+ return [a1, a2, a3];
+}
+
+f.bind(null,1,2)('a')
+.then(v => assert.compareArray(v, [1, 2, 'a']))
+.then($DONE, $DONE);
_______________________________________________
nginx-devel mailing list -- nginx-devel@nginx.org
To unsubscribe send an email to nginx-devel-leave@nginx.org
Subject Author Views Posted

[njs] Refactored bound function calls according to the spec.

Dmitry Volyntsev 321 October 10, 2022 10:36PM



Sorry, you do not have permission to post/reply in this forum.

Online Users

Guests: 313
Record Number of Users: 8 on April 13, 2023
Record Number of Guests: 421 on December 02, 2018
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready