[njs] Fixed Date() constructor with one argument.
Dmitry Volyntsev
xeioex at nginx.com
Thu Apr 25 16:50:40 UTC 2019
details: https://hg.nginx.org/njs/rev/43dc900bc914
branches:
changeset: 930:43dc900bc914
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Thu Apr 25 19:50:20 2019 +0300
description:
Fixed Date() constructor with one argument.
This closes #144 issue on Github.
diffstat:
njs/njs_date.c | 64 +++++++++++++++++++++++++++++++----------------
njs/njs_number.c | 2 +-
njs/njs_number.h | 1 +
njs/njs_vm.c | 53 +++++++++++++++++++++++++++++++++------
njs/njs_vm.h | 1 +
njs/test/njs_unit_test.c | 36 +++++++++++++++++++++++++++
6 files changed, 125 insertions(+), 32 deletions(-)
diffs (274 lines):
diff -r 65d6076eb349 -r 43dc900bc914 njs/njs_date.c
--- a/njs/njs_date.c Thu Apr 25 19:33:35 2019 +0300
+++ b/njs/njs_date.c Thu Apr 25 19:50:20 2019 +0300
@@ -61,6 +61,17 @@ njs_gettime(void)
}
+static nxt_noinline double
+njs_timeclip(double time)
+{
+ if (isinf(time) || isnan(time) || fabs(time) > 8.64e15) {
+ return NAN;
+ }
+
+ return njs_number_to_int64(time);
+}
+
+
njs_ret_t
njs_date_constructor(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
njs_index_t unused)
@@ -76,8 +87,22 @@ njs_date_constructor(njs_vm_t *vm, njs_v
if (nargs == 1) {
time = njs_gettime();
- } else if (nargs == 2 && njs_is_string(&args[1])) {
- time = njs_date_string_parse(&args[1]);
+ } else if (nargs == 2) {
+ if (njs_is_object(&args[1])) {
+ if (!njs_is_date(&args[1])) {
+ njs_vm_trap_value(vm, &args[1]);
+
+ return njs_trap(vm, NJS_TRAP_PRIMITIVE_ARG);
+ }
+
+ time = args[1].data.u.date->time;
+
+ } else if (njs_is_string(&args[1])) {
+ time = njs_date_string_parse(&args[1]);
+
+ } else {
+ time = args[1].data.u.number;
+ }
} else {
nxt_memzero(values, 8 * sizeof(int64_t));
@@ -103,25 +128,20 @@ njs_date_constructor(njs_vm_t *vm, njs_v
values[i] = num;
}
- if (nargs > 2) {
- /* Year. */
- if (values[1] > 99) {
- values[1] -= 1900;
- }
-
- tm.tm_year = values[1];
- tm.tm_mon = values[2];
- tm.tm_mday = values[3];
- tm.tm_hour = values[4];
- tm.tm_min = values[5];
- tm.tm_sec = values[6];
- tm.tm_isdst = -1;
-
- time = (int64_t) mktime(&tm) * 1000 + values[7];
-
- } else {
- time = values[1];
+ /* Year. */
+ if (values[1] > 99) {
+ values[1] -= 1900;
}
+
+ tm.tm_year = values[1];
+ tm.tm_mon = values[2];
+ tm.tm_mday = values[3];
+ tm.tm_hour = values[4];
+ tm.tm_min = values[5];
+ tm.tm_sec = values[6];
+ tm.tm_isdst = -1;
+
+ time = (int64_t) mktime(&tm) * 1000 + values[7];
}
done:
@@ -139,7 +159,7 @@ njs_date_constructor(njs_vm_t *vm, njs_v
date->object.extensible = 1;
date->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_DATE].object;
- date->time = time;
+ date->time = njs_timeclip(time);
vm->retval.data.u.date = date;
vm->retval.type = NJS_DATE;
@@ -1048,7 +1068,7 @@ njs_date_to_string(njs_vm_t *vm, njs_val
return njs_string_new(vm, retval, buf, p - buf, p - buf);
}
- vm->retval = njs_string_invalid_date;
+ *retval = njs_string_invalid_date;
return NXT_OK;
}
diff -r 65d6076eb349 -r 43dc900bc914 njs/njs_number.c
--- a/njs/njs_number.c Thu Apr 25 19:33:35 2019 +0300
+++ b/njs/njs_number.c Thu Apr 25 19:50:20 2019 +0300
@@ -804,7 +804,7 @@ njs_number_parse_float(njs_vm_t *vm, njs
}
-nxt_inline int64_t
+int64_t
njs_number_to_int64(double num)
{
#if (NXT_NAN_TO_UINT_CONVERSION != 0)
diff -r 65d6076eb349 -r 43dc900bc914 njs/njs_number.h
--- a/njs/njs_number.h Thu Apr 25 19:33:35 2019 +0300
+++ b/njs/njs_number.h Thu Apr 25 19:50:20 2019 +0300
@@ -35,6 +35,7 @@ njs_ret_t njs_number_parse_int(njs_vm_t
nxt_uint_t nargs, njs_index_t unused);
njs_ret_t njs_number_parse_float(njs_vm_t *vm, njs_value_t *args,
nxt_uint_t nargs, njs_index_t unused);
+int64_t njs_number_to_int64(double num);
nxt_noinline int32_t njs_number_to_integer(double num);
nxt_noinline int32_t njs_number_to_int32(double num);
nxt_noinline uint32_t njs_number_to_uint32(double num);
diff -r 65d6076eb349 -r 43dc900bc914 njs/njs_vm.c
--- a/njs/njs_vm.c Thu Apr 25 19:33:35 2019 +0300
+++ b/njs/njs_vm.c Thu Apr 25 19:50:20 2019 +0300
@@ -50,6 +50,8 @@ static njs_ret_t njs_vmcode_number_argum
njs_value_t *inlvd2);
static njs_ret_t njs_vmcode_string_argument(njs_vm_t *vm, njs_value_t *invld1,
njs_value_t *inlvd2);
+static njs_ret_t njs_vmcode_primitive_argument(njs_vm_t *vm,
+ njs_value_t *invld1, njs_value_t *inlvd2);
static njs_ret_t njs_primitive_value(njs_vm_t *vm, njs_value_t *value,
nxt_uint_t hint);
static njs_ret_t njs_vmcode_restart(njs_vm_t *vm, njs_value_t *invld1,
@@ -199,6 +201,7 @@ start:
case NJS_TRAP_NUMBER_ARG:
case NJS_TRAP_STRING_ARG:
+ case NJS_TRAP_PRIMITIVE_ARG:
njs_vm_trap_argument(vm, trap);
@@ -2608,16 +2611,24 @@ static const njs_vmcode_1addr_t njs_tra
};
+static const njs_vmcode_1addr_t njs_trap_primitive_argument = {
+ .code = { .operation = njs_vmcode_primitive_argument,
+ .operands = NJS_VMCODE_NO_OPERAND,
+ .retval = NJS_VMCODE_NO_RETVAL }
+};
+
+
static const njs_vm_trap_t njs_vm_traps[] = {
- /* NJS_TRAP_NUMBER */ { .code = &njs_trap_number[0] },
- /* NJS_TRAP_NUMBERS */ { .code = &njs_trap_numbers[0] },
- /* NJS_TRAP_ADDITION */ { .code = &njs_trap_addition[0] },
- /* NJS_TRAP_COMPARISON */ { .code = &njs_trap_comparison[0] },
- /* NJS_TRAP_INCDEC */ { .code = &njs_trap_numbers[1],
- .reference = 1 },
- /* NJS_TRAP_PROPERTY */ { .code = &njs_trap_property[0] },
- /* NJS_TRAP_NUMBER_ARG */ { .code = &njs_trap_number_argument },
- /* NJS_TRAP_STRING_ARG */ { .code = &njs_trap_string_argument },
+ /* NJS_TRAP_NUMBER */ { .code = &njs_trap_number[0] },
+ /* NJS_TRAP_NUMBERS */ { .code = &njs_trap_numbers[0] },
+ /* NJS_TRAP_ADDITION */ { .code = &njs_trap_addition[0] },
+ /* NJS_TRAP_COMPARISON */ { .code = &njs_trap_comparison[0] },
+ /* NJS_TRAP_INCDEC */ { .code = &njs_trap_numbers[1],
+ .reference = 1 },
+ /* NJS_TRAP_PROPERTY */ { .code = &njs_trap_property[0] },
+ /* NJS_TRAP_NUMBER_ARG */ { .code = &njs_trap_number_argument },
+ /* NJS_TRAP_STRING_ARG */ { .code = &njs_trap_string_argument },
+ /* NJS_TRAP_PRIMITIVE_ARG */ { .code = &njs_trap_primitive_argument },
};
@@ -2831,6 +2842,30 @@ njs_vmcode_string_argument(njs_vm_t *vm,
static njs_ret_t
+njs_vmcode_primitive_argument(njs_vm_t *vm, njs_value_t *invld1,
+ njs_value_t *inlvd2)
+{
+ njs_ret_t ret;
+ njs_value_t *value;
+
+ value = &vm->top_frame->trap_values[0];
+
+ ret = njs_primitive_value(vm, value, 0);
+
+ if (nxt_fast_path(ret > 0)) {
+ *vm->top_frame->trap_values[1].data.u.value = *value;
+
+ vm->current = vm->top_frame->trap_restart;
+ vm->top_frame->trap_restart = NULL;
+
+ return 0;
+ }
+
+ return ret;
+}
+
+
+static njs_ret_t
njs_vmcode_restart(njs_vm_t *vm, njs_value_t *invld1, njs_value_t *invld2)
{
u_char *restart;
diff -r 65d6076eb349 -r 43dc900bc914 njs/njs_vm.h
--- a/njs/njs_vm.h Thu Apr 25 19:33:35 2019 +0300
+++ b/njs/njs_vm.h Thu Apr 25 19:50:20 2019 +0300
@@ -47,6 +47,7 @@ typedef enum {
NJS_TRAP_PROPERTY,
NJS_TRAP_NUMBER_ARG,
NJS_TRAP_STRING_ARG,
+ NJS_TRAP_PRIMITIVE_ARG,
} njs_trap_t;
diff -r 65d6076eb349 -r 43dc900bc914 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c Thu Apr 25 19:33:35 2019 +0300
+++ b/njs/test/njs_unit_test.c Thu Apr 25 19:50:20 2019 +0300
@@ -9563,12 +9563,48 @@ static njs_unit_test_t njs_test[] =
{ nxt_string("Object.isExtensible(Object.freeze([]))"),
nxt_string("false") },
+ { nxt_string("new Date(undefined)"),
+ nxt_string("Invalid Date") },
+
+ { nxt_string("new Date(Infinity)"),
+ nxt_string("Invalid Date") },
+
+ { nxt_string("new Date(NaN)"),
+ nxt_string("Invalid Date") },
+
+ { nxt_string("new Date(8.65e15)"),
+ nxt_string("Invalid Date") },
+
+ { nxt_string("new Date(0e0.o0)"),
+ nxt_string("Invalid Date") },
+
+ { nxt_string("(new Date(8.639e15)).getTime()"),
+ nxt_string("8639000000000000") },
+
+ { nxt_string("new Date(8.641e15)"),
+ nxt_string("Invalid Date") },
+
+ { nxt_string("(new Date(null)).getTime()"),
+ nxt_string("0") },
+
+ { nxt_string("(new Date(86400)).getTime()"),
+ nxt_string("86400") },
+
{ nxt_string("var d = new Date(''); d +' '+ d.getTime()"),
nxt_string("Invalid Date NaN") },
{ nxt_string("var d = new Date(1); d = d + ''; d.slice(0, 33)"),
nxt_string("Thu Jan 01 1970 00:00:00 GMT+0000") },
+ { nxt_string("var d = new Date({valueOf:()=>86400000}); d = d + ''; d.slice(0, 33)"),
+ nxt_string("Fri Jan 02 1970 00:00:00 GMT+0000") },
+
+ { nxt_string("(new Date({toString:()=>'2011'})).getTime()"),
+ nxt_string("1293840000000") },
+
+ { nxt_string("(new Date({valueOf: ()=>86400, toString:()=>'2011'})).getTime()"),
+ nxt_string("86400") },
+
{ nxt_string("var d = new Date(1308895200000); d.getTime()"),
nxt_string("1308895200000") },
More information about the nginx-devel
mailing list