[njs] Fixed Array.prototype.toString() and Date.prototype.toJSON().
Dmitry Volyntsev
xeioex at nginx.com
Fri May 24 15:59:49 UTC 2019
details: https://hg.nginx.org/njs/rev/ff51b3e9ea05
branches:
changeset: 984:ff51b3e9ea05
user: hongzhidao <hongzhidao at gmail.com>
date: Wed May 22 07:54:58 2019 +0800
description:
Fixed Array.prototype.toString() and Date.prototype.toJSON().
This closes #163, #164, #166 issues on Github.
diffstat:
njs/njs_array.c | 28 ++--------------------------
njs/njs_date.c | 27 ++-------------------------
njs/njs_function.h | 30 ++++++++++++++++++++++++++++++
njs/test/njs_unit_test.c | 6 ++++++
4 files changed, 40 insertions(+), 51 deletions(-)
diffs (187 lines):
diff -r 5906cf108796 -r ff51b3e9ea05 njs/njs_array.c
--- a/njs/njs_array.c Thu May 23 16:21:55 2019 +0300
+++ b/njs/njs_array.c Wed May 22 07:54:58 2019 +0800
@@ -85,8 +85,6 @@ static njs_ret_t njs_array_prototype_sli
njs_value_t *args, nxt_uint_t nargs, njs_index_t unused);
static njs_ret_t njs_array_prototype_slice_copy(njs_vm_t *vm,
njs_value_t *this, int64_t start, int64_t length);
-static njs_ret_t njs_array_prototype_to_string_continuation(njs_vm_t *vm,
- njs_value_t *args, nxt_uint_t nargs, njs_index_t retval);
static njs_ret_t njs_array_prototype_join_continuation(njs_vm_t *vm,
njs_value_t *args, nxt_uint_t nargs, njs_index_t unused);
static njs_value_t *njs_array_copy(njs_value_t *dst, njs_value_t *src);
@@ -935,24 +933,13 @@ njs_array_prototype_reverse(njs_vm_t *vm
}
-/*
- * ECMAScript 5.1: try first to use object method "join", then
- * use the standard built-in method Object.prototype.toString().
- * Array.toString() must be a continuation otherwise it may
- * endlessly call Array.join().
- */
-
static njs_ret_t
njs_array_prototype_to_string(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
njs_index_t retval)
{
njs_object_prop_t *prop;
- njs_continuation_t *cont;
nxt_lvlhsh_query_t lhq;
- cont = njs_vm_continuation(vm);
- cont->function = njs_array_prototype_to_string_continuation;
-
if (njs_is_object(&args[0])) {
lhq.key_hash = NJS_JOIN_HASH;
lhq.key = nxt_string_value("join");
@@ -960,8 +947,8 @@ njs_array_prototype_to_string(njs_vm_t *
prop = njs_object_property(vm, args[0].data.u.object, &lhq);
if (nxt_fast_path(prop != NULL && njs_is_function(&prop->value))) {
- return njs_function_apply(vm, prop->value.data.u.function,
- args, nargs, retval);
+ return njs_function_replace(vm, prop->value.data.u.function,
+ args, nargs, retval);
}
}
@@ -970,17 +957,6 @@ njs_array_prototype_to_string(njs_vm_t *
static njs_ret_t
-njs_array_prototype_to_string_continuation(njs_vm_t *vm, njs_value_t *args,
- nxt_uint_t nargs, njs_index_t retval)
-{
- /* Skip retval update. */
- vm->top_frame->skip = 1;
-
- return NXT_OK;
-}
-
-
-static njs_ret_t
njs_array_prototype_join(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
njs_index_t unused)
{
diff -r 5906cf108796 -r ff51b3e9ea05 njs/njs_date.c
--- a/njs/njs_date.c Thu May 23 16:21:55 2019 +0300
+++ b/njs/njs_date.c Wed May 22 07:54:58 2019 +0800
@@ -43,8 +43,6 @@ static nxt_noinline njs_ret_t njs_date_s
double time);
static nxt_noinline double njs_date_time(struct tm *tm, int64_t ms);
static double njs_date_utc_time(struct tm *tm, double time);
-static njs_ret_t njs_date_prototype_to_json_continuation(njs_vm_t *vm,
- njs_value_t *args, nxt_uint_t nargs, njs_index_t retval);
static const njs_value_t njs_string_invalid_date = njs_string("Invalid Date");
@@ -1895,23 +1893,13 @@ njs_date_utc_time(struct tm *tm, double
}
-/*
- * ECMAScript 5.1: call object method "toISOString".
- * Date.toJSON() must be a continuation otherwise it may endlessly
- * call Date.toISOString().
- */
-
static njs_ret_t
njs_date_prototype_to_json(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
njs_index_t retval)
{
njs_object_prop_t *prop;
- njs_continuation_t *cont;
nxt_lvlhsh_query_t lhq;
- cont = njs_vm_continuation(vm);
- cont->function = njs_date_prototype_to_json_continuation;
-
if (njs_is_object(&args[0])) {
lhq.key_hash = NJS_TO_ISO_STRING_HASH;
lhq.key = nxt_string_value("toISOString");
@@ -1919,8 +1907,8 @@ njs_date_prototype_to_json(njs_vm_t *vm,
prop = njs_object_property(vm, args[0].data.u.object, &lhq);
if (nxt_fast_path(prop != NULL && njs_is_function(&prop->value))) {
- return njs_function_apply(vm, prop->value.data.u.function,
- args, nargs, retval);
+ return njs_function_replace(vm, prop->value.data.u.function,
+ args, nargs, retval);
}
}
@@ -1930,17 +1918,6 @@ njs_date_prototype_to_json(njs_vm_t *vm,
}
-static njs_ret_t
-njs_date_prototype_to_json_continuation(njs_vm_t *vm, njs_value_t *args,
- nxt_uint_t nargs, njs_index_t retval)
-{
- /* Skip retval update. */
- vm->top_frame->skip = 1;
-
- return NXT_OK;
-}
-
-
static const njs_object_prop_t njs_date_prototype_properties[] =
{
{
diff -r 5906cf108796 -r ff51b3e9ea05 njs/njs_function.h
--- a/njs/njs_function.h Thu May 23 16:21:55 2019 +0300
+++ b/njs/njs_function.h Wed May 22 07:54:58 2019 +0800
@@ -200,6 +200,36 @@ njs_function_apply(njs_vm_t *vm, njs_fun
}
+/*
+ * Replaces the current function with a new one.
+ * Can only be used for continuation functions
+ * (data.u.function.continuation_size > 0).
+ */
+nxt_inline njs_ret_t
+njs_function_replace(njs_vm_t *vm, njs_function_t *function,
+ const njs_value_t *args, nxt_uint_t nargs, njs_index_t retval)
+{
+ nxt_int_t ret;
+
+ ret = njs_function_apply(vm, function, args, nargs, retval);
+ if (nxt_slow_path(ret == NXT_ERROR)) {
+ return ret;
+ }
+
+ /*
+ * 1) njs_function_apply() allocs a new function frame,
+ * in order to preserve the retval of a new function and ignore
+ * retval of the current function during stack unwinding
+ * skip flag is needed.
+ * 2) it is also needed for correct callee arguments update in
+ * njs_function_native_call() see "Object((new Date(0)).toJSON())".
+ */
+ vm->top_frame->previous->skip = 1;
+
+ return NJS_APPLIED;
+}
+
+
nxt_inline njs_native_frame_t *
njs_function_previous_frame(njs_native_frame_t *frame)
{
diff -r 5906cf108796 -r ff51b3e9ea05 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c Thu May 23 16:21:55 2019 +0300
+++ b/njs/test/njs_unit_test.c Wed May 22 07:54:58 2019 +0800
@@ -6085,6 +6085,12 @@ static njs_unit_test_t njs_test[] =
{ nxt_string("function f(a,b) { }; var ff = f.bind(f, 1); ff.length"),
nxt_string("1") },
+ { nxt_string("Object((new Date(0)).toJSON())+0"),
+ nxt_string("1970-01-01T00:00:00.000Z0") },
+
+ { nxt_string("Object((new Array(0)).toString())+0"),
+ nxt_string("0") },
+
{ nxt_string("JSON.parse.length"),
nxt_string("2") },
More information about the nginx-devel
mailing list