This closes #144 issue on Github.
}
+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)
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));
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;
+ /* Year. */
+ if (values[1] > 99) {
+ values[1] -= 1900;
+ }
- time = (int64_t) mktime(&tm) * 1000 + values[7];
+ 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;
- } else {
- time = values[1];
- }
+ time = (int64_t) mktime(&tm) * 1000 + values[7];
}
done:
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;
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;
}
}
-nxt_inline int64_t
+int64_t
njs_number_to_int64(double num)
{
#if (NXT_NAN_TO_UINT_CONVERSION != 0)
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);
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,
case NJS_TRAP_NUMBER_ARG:
case NJS_TRAP_STRING_ARG:
+ case NJS_TRAP_PRIMITIVE_ARG:
njs_vm_trap_argument(vm, trap);
};
+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 },
};
}
+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)
{
NJS_TRAP_PROPERTY,
NJS_TRAP_NUMBER_ARG,
NJS_TRAP_STRING_ARG,
+ NJS_TRAP_PRIMITIVE_ARG,
} njs_trap_t;
{ 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") },