Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # HG changeset patch
- # User Dmitry Volyntsev <xeioex@nginx.com>
- # Date 1562352328 -10800
- # Fri Jul 05 21:45:28 2019 +0300
- # Node ID 23ac9dad4973023117aaa36331645ebb415531e0
- # Parent b946c107396835be316b192154feb9bb7efaa175
- Refactored working with non-primitive types.
- Traps mechanism is remove.
- diff --git a/njs/njs.c b/njs/njs.c
- --- a/njs/njs.c
- +++ b/njs/njs.c
- @@ -984,8 +984,6 @@ again:
- /* value evaluation threw an exception. */
- - vm->top_frame->trap_tries = 0;
- -
- src = &vm->retval;
- goto again;
- }
- @@ -1006,6 +1004,10 @@ njs_vm_retval_string(njs_vm_t *vm, nxt_s
- njs_vm_init(vm);
- }
- + if (vm->current == NULL) {
- + vm->current = (u_char *) njs_stop;
- + }
- +
- return njs_vm_value_string(vm, dst, &vm->retval);
- }
- @@ -1019,6 +1021,10 @@ njs_vm_retval_dump(njs_vm_t *vm, nxt_str
- njs_vm_init(vm);
- }
- + if (vm->current == NULL) {
- + vm->current = (u_char *) njs_stop;
- + }
- +
- return njs_vm_value_dump(vm, dst, &vm->retval, 0, 1);
- }
- diff --git a/njs/njs_array.c b/njs/njs_array.c
- --- a/njs/njs_array.c
- +++ b/njs/njs_array.c
- @@ -528,10 +528,7 @@ njs_array_prototype_slice(njs_vm_t *vm,
- ret = njs_value_property(vm, &args[0], &njs_string_length, &slice->length,
- 0);
- - if (nxt_slow_path(ret == NXT_ERROR
- - || ret == NJS_TRAP
- - || ret == NJS_APPLIED))
- - {
- + if (nxt_slow_path(ret == NXT_ERROR || ret == NJS_APPLIED)) {
- return ret;
- }
- @@ -544,13 +541,16 @@ njs_array_prototype_slice_continuation(n
- nxt_uint_t nargs, njs_index_t unused)
- {
- int64_t start, end, length;
- + njs_ret_t ret;
- njs_array_slice_t *slice;
- slice = njs_vm_continuation(vm);
- if (nxt_slow_path(!njs_is_primitive(&slice->length))) {
- - njs_vm_trap_value(vm, &slice->length);
- - return njs_trap(vm, NJS_TRAP_NUMBER_ARG);
- + ret = njs_value_to_numeric(vm, &slice->length, &slice->length);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- }
- start = njs_primitive_value_to_integer(njs_arg(args, nargs, 1));
- @@ -958,7 +958,7 @@ njs_array_prototype_reverse(njs_vm_t *vm
- 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_index_t unused)
- {
- njs_object_prop_t *prop;
- nxt_lvlhsh_query_t lhq;
- @@ -970,12 +970,12 @@ njs_array_prototype_to_string(njs_vm_t *
- prop = njs_object_property(vm, njs_object(&args[0]), &lhq);
- if (nxt_fast_path(prop != NULL && njs_is_function(&prop->value))) {
- - return njs_function_replace(vm, njs_function(&prop->value),
- - args, nargs, retval);
- + return njs_function_call(vm, njs_function(&prop->value), args,
- + nargs, (njs_index_t) &vm->retval);
- }
- }
- - return njs_object_prototype_to_string(vm, args, nargs, retval);
- + return njs_object_prototype_to_string(vm, args, nargs, unused);
- }
- @@ -1063,6 +1063,7 @@ njs_array_prototype_join_continuation(nj
- u_char *p;
- size_t size, length, mask;
- uint32_t max;
- + njs_ret_t ret;
- nxt_uint_t i, n;
- njs_array_t *array;
- njs_value_t *value, *values;
- @@ -1089,9 +1090,10 @@ njs_array_prototype_join_continuation(nj
- value = &values[n++];
- if (!njs_is_string(value)) {
- - njs_vm_trap_value(vm, value);
- -
- - return njs_trap(vm, NJS_TRAP_STRING_ARG);
- + ret = njs_value_to_string(vm, value, value);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- }
- }
- @@ -1438,10 +1440,7 @@ njs_array_prototype_fill(njs_vm_t *vm, n
- ret = njs_value_property(vm, this, &njs_string_length, &fill->length,
- 0);
- - if (nxt_slow_path(ret == NXT_ERROR
- - || ret == NJS_TRAP
- - || ret == NJS_APPLIED))
- - {
- + if (nxt_slow_path(ret == NXT_ERROR || ret == NJS_APPLIED)) {
- return ret;
- }
- }
- @@ -1455,6 +1454,7 @@ njs_array_prototype_fill_continuation(nj
- nxt_uint_t nargs, njs_index_t unused)
- {
- nxt_int_t i, start, end, length;
- + njs_ret_t ret;
- njs_array_t *array;
- njs_object_t *object;
- njs_array_fill_t *fill;
- @@ -1484,8 +1484,10 @@ njs_array_prototype_fill_continuation(nj
- } else {
- if (nxt_slow_path(!njs_is_primitive(&fill->length))) {
- - njs_vm_trap_value(vm, &fill->length);
- - return njs_trap(vm, NJS_TRAP_NUMBER_ARG);
- + ret = njs_value_to_numeric(vm, &fill->length, &fill->length);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- }
- length = njs_primitive_value_to_length(&fill->length);
- @@ -2198,9 +2200,10 @@ njs_array_string_sort(njs_vm_t *vm, njs_
- for (i = 1; i < nargs; i++) {
- if (!njs_is_string(&args[i])) {
- - njs_vm_trap_value(vm, &args[i]);
- -
- - return njs_trap(vm, NJS_TRAP_STRING_ARG);
- + ret = njs_value_to_string(vm, &args[i], &args[i]);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- }
- }
- diff --git a/njs/njs_date.c b/njs/njs_date.c
- --- a/njs/njs_date.c
- +++ b/njs/njs_date.c
- @@ -73,6 +73,7 @@ njs_date_constructor(njs_vm_t *vm, njs_v
- {
- double num, time;
- int64_t values[8];
- + njs_ret_t ret;
- nxt_uint_t i, n;
- njs_date_t *date;
- struct tm tm;
- @@ -85,11 +86,14 @@ njs_date_constructor(njs_vm_t *vm, njs_v
- } 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);
- + ret = njs_value_to_primitive(vm, &args[1], &args[1], 0);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- }
- -
- + }
- +
- + if (njs_is_date(&args[1])) {
- time = njs_date(&args[1])->time;
- } else if (njs_is_string(&args[1])) {
- @@ -108,9 +112,10 @@ njs_date_constructor(njs_vm_t *vm, njs_v
- for (i = 1; i < n; i++) {
- if (!njs_is_numeric(&args[i])) {
- - njs_vm_trap_value(vm, &args[i]);
- -
- - return njs_trap(vm, NJS_TRAP_NUMBER_ARG);
- + ret = njs_value_to_numeric(vm, &args[i], &args[i]);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- }
- num = njs_number(&args[i]);
- @@ -171,6 +176,7 @@ njs_date_utc(njs_vm_t *vm, njs_value_t *
- {
- double num, time;
- struct tm tm;
- + njs_ret_t ret;
- nxt_uint_t i, n;
- int32_t values[8];
- @@ -183,9 +189,10 @@ njs_date_utc(njs_vm_t *vm, njs_value_t *
- for (i = 1; i < n; i++) {
- if (!njs_is_numeric(&args[i])) {
- - njs_vm_trap_value(vm, &args[i]);
- -
- - return njs_trap(vm, NJS_TRAP_NUMBER_ARG);
- + ret = njs_value_to_numeric(vm, &args[i], &args[i]);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- }
- num = njs_number(&args[i]);
- @@ -1902,8 +1909,8 @@ njs_date_prototype_to_json(njs_vm_t *vm,
- prop = njs_object_property(vm, njs_object(&args[0]), &lhq);
- if (nxt_fast_path(prop != NULL && njs_is_function(&prop->value))) {
- - return njs_function_replace(vm, njs_function(&prop->value),
- - args, nargs, retval);
- + return njs_function_call(vm, njs_function(&prop->value), args,
- + nargs, (njs_index_t) &vm->retval);
- }
- }
- diff --git a/njs/njs_function.c b/njs/njs_function.c
- --- a/njs/njs_function.c
- +++ b/njs/njs_function.c
- @@ -473,6 +473,48 @@ njs_function_frame_alloc(njs_vm_t *vm, s
- njs_ret_t
- +njs_function_call(njs_vm_t *vm, njs_function_t *function, njs_value_t *args,
- + nxt_uint_t nargs, njs_index_t retval)
- +{
- + u_char *return_address;
- + njs_ret_t ret;
- + njs_native_frame_t *frame;
- + njs_continuation_t *cont;
- +
- + ret = njs_function_frame(vm, function, &args[0], &args[1], nargs - 1, 0, 0);
- + if (nxt_slow_path(ret != NXT_OK)) {
- + return ret;
- + }
- +
- + frame = vm->top_frame;
- + frame->call = 1;
- +
- + return_address = vm->current;
- +
- + if (function->native) {
- +
- + if (function->continuation_size != 0) {
- + cont = njs_vm_continuation(vm);
- + cont->return_address = return_address;
- + }
- +
- + ret = njs_function_native_call(vm, function->u.native, frame->arguments,
- + function->args_types, frame->nargs,
- + (njs_index_t) retval, return_address);
- +
- + } else {
- + ret = njs_function_lambda_call(vm, retval, return_address);
- +
- + if (nxt_fast_path(ret == NJS_APPLIED)) {
- + ret = njs_vmcode_run(vm);
- + }
- + }
- +
- + return ret;
- +}
- +
- +
- +njs_ret_t
- njs_function_lambda_call(njs_vm_t *vm, njs_index_t retval,
- u_char *return_address)
- {
- @@ -636,8 +678,8 @@ static njs_ret_t
- njs_normalize_args(njs_vm_t *vm, njs_value_t *args, uint8_t *args_types,
- nxt_uint_t nargs)
- {
- + njs_ret_t ret;
- nxt_uint_t n;
- - njs_trap_t trap;
- n = nxt_min(nargs, NJS_ARGS_TYPES_MAX);
- @@ -655,43 +697,47 @@ njs_normalize_args(njs_vm_t *vm, njs_val
- case NJS_STRING_ARG:
- - if (njs_is_string(args)) {
- - break;
- + if (!njs_is_string(args)) {
- + ret = njs_value_to_string(vm, args, args);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- }
- - trap = NJS_TRAP_STRING_ARG;
- - goto trap;
- + break;
- case NJS_NUMBER_ARG:
- - if (njs_is_numeric(args)) {
- - break;
- + if (!njs_is_numeric(args)) {
- + ret = njs_value_to_numeric(vm, args, args);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- }
- - trap = NJS_TRAP_NUMBER_ARG;
- - goto trap;
- + break;
- case NJS_INTEGER_ARG:
- - if (njs_is_numeric(args)) {
- + if (!njs_is_numeric(args)) {
- + ret = njs_value_to_numeric(vm, args, args);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- + }
- - /* Numbers are truncated to fit in 32-bit integers. */
- + /* Numbers are truncated to fit in 32-bit integers. */
- - if (isnan(njs_number(args))) {
- - njs_number(args) = 0;
- -
- - } else if (njs_number(args) > 2147483647.0) {
- + if (!isnan(njs_number(args))) {
- + if (njs_number(args) > 2147483647.0) {
- njs_number(args) = 2147483647.0;
- } else if (njs_number(args) < -2147483648.0) {
- njs_number(args) = -2147483648.0;
- }
- -
- - break;
- }
- - trap = NJS_TRAP_NUMBER_ARG;
- - goto trap;
- + break;
- case NJS_FUNCTION_ARG:
- @@ -701,8 +747,10 @@ njs_normalize_args(njs_vm_t *vm, njs_val
- break;
- default:
- - trap = NJS_TRAP_STRING_ARG;
- - goto trap;
- + ret = njs_value_to_string(vm, args, args);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- }
- break;
- @@ -716,8 +764,10 @@ njs_normalize_args(njs_vm_t *vm, njs_val
- break;
- default:
- - trap = NJS_TRAP_STRING_ARG;
- - goto trap;
- + ret = njs_value_to_string(vm, args, args);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- }
- break;
- @@ -751,12 +801,6 @@ njs_normalize_args(njs_vm_t *vm, njs_val
- return NJS_OK;
- -trap:
- -
- - njs_vm_trap_value(vm, args);
- -
- - return njs_trap(vm, trap);
- -
- type_error:
- njs_type_error(vm, "cannot convert %s to %s", njs_type_string(args->type),
- diff --git a/njs/njs_function.h b/njs/njs_function.h
- --- a/njs/njs_function.h
- +++ b/njs/njs_function.h
- @@ -74,11 +74,6 @@ typedef struct {
- #define NJS_CONTINUATION_SIZE njs_continuation_size(njs_continuation_t)
- -#define njs_vm_trap_value(vm, val) \
- - (vm)->top_frame->trap_scratch.data.u.value = val
- -
- -
- -
- typedef struct njs_exception_s njs_exception_t;
- struct njs_exception_s {
- @@ -92,10 +87,6 @@ struct njs_exception_s {
- struct njs_native_frame_s {
- - njs_value_t trap_scratch;
- - njs_value_t trap_values[2];
- - u_char *trap_restart;
- -
- u_char *free;
- njs_function_t *function;
- @@ -118,14 +109,7 @@ struct njs_native_frame_s {
- /* Skip the Function.call() and Function.apply() methods frames. */
- uint8_t skip; /* 1 bit */
- - /* A number of trap tries, it can be no more than three. */
- - uint8_t trap_tries; /* 2 bits */
- -
- - /*
- - * The first operand in trap is reference to original value,
- - * it is used to increment or decrement this value.
- - */
- - uint8_t trap_reference; /* 1 bit */
- + uint8_t call; /* 1 bit */
- };
- @@ -168,6 +152,8 @@ njs_ret_t njs_function_lambda_frame(njs_
- njs_ret_t njs_function_activate(njs_vm_t *vm, njs_function_t *function,
- const njs_value_t *this, const njs_value_t *args, nxt_uint_t nargs,
- njs_index_t retval, size_t advance);
- +njs_ret_t njs_function_call(njs_vm_t *vm, njs_function_t *function,
- + njs_value_t *args, nxt_uint_t nargs, njs_index_t retval);
- njs_ret_t njs_function_lambda_call(njs_vm_t *vm, njs_index_t retval,
- u_char *return_address);
- njs_ret_t njs_function_native_call(njs_vm_t *vm, njs_function_native_t native,
- @@ -215,36 +201,6 @@ 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 --git a/njs/njs_math.c b/njs/njs_math.c
- --- a/njs/njs_math.c
- +++ b/njs/njs_math.c
- @@ -359,13 +359,15 @@ njs_object_math_hypot(njs_vm_t *vm, njs_
- njs_index_t unused)
- {
- double num;
- + njs_ret_t ret;
- nxt_uint_t i;
- for (i = 1; i < nargs; i++) {
- if (!njs_is_numeric(&args[i])) {
- - njs_vm_trap_value(vm, &args[i]);
- -
- - return njs_trap(vm, NJS_TRAP_NUMBER_ARG);
- + ret = njs_value_to_numeric(vm, &args[i], &args[i]);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- }
- }
- @@ -498,6 +500,7 @@ njs_object_math_max(njs_vm_t *vm, njs_va
- njs_index_t unused)
- {
- double num;
- + njs_ret_t ret;
- nxt_uint_t i;
- if (nargs > 1) {
- @@ -507,9 +510,10 @@ njs_object_math_max(njs_vm_t *vm, njs_va
- goto done;
- } else if (!njs_is_numeric(&args[i])) {
- - njs_vm_trap_value(vm, &args[i]);
- -
- - return njs_trap(vm, NJS_TRAP_NUMBER_ARG);
- + ret = njs_value_to_numeric(vm, &args[i], &args[i]);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- }
- }
- @@ -536,14 +540,16 @@ njs_object_math_min(njs_vm_t *vm, njs_va
- njs_index_t unused)
- {
- double num;
- + njs_ret_t ret;
- nxt_uint_t i;
- if (nargs > 1) {
- for (i = 1; i < nargs; i++) {
- if (!njs_is_numeric(&args[i])) {
- - njs_vm_trap_value(vm, &args[i]);
- -
- - return njs_trap(vm, NJS_TRAP_NUMBER_ARG);
- + ret = njs_value_to_numeric(vm, &args[i], &args[i]);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- }
- }
- diff --git a/njs/njs_object.c b/njs/njs_object.c
- --- a/njs/njs_object.c
- +++ b/njs/njs_object.c
- @@ -2144,7 +2144,6 @@ njs_object_prototype_has_own_property(nj
- vm->retval = njs_value_false;
- return NXT_OK;
- - case NJS_TRAP:
- case NXT_ERROR:
- default:
- return ret;
- @@ -2185,7 +2184,6 @@ njs_object_prototype_prop_is_enumerable(
- retval = &njs_value_false;
- break;
- - case NJS_TRAP:
- case NXT_ERROR:
- default:
- return ret;
- diff --git a/njs/njs_object_property.c b/njs/njs_object_property.c
- --- a/njs/njs_object_property.c
- +++ b/njs/njs_object_property.c
- @@ -38,7 +38,6 @@ static njs_object_prop_t *njs_descriptor
- * NXT_DECLINED property was not found in object,
- * if pq->lhq.value != NULL it contains retval of type
- * njs_object_prop_t * where prop->type is NJS_WHITEOUT
- - * NJS_TRAP the property trap must be called,
- * NXT_ERROR exception has been thrown.
- *
- * TODO:
- @@ -53,10 +52,16 @@ njs_property_query(njs_vm_t *vm, njs_pro
- uint32_t (*hash)(const void *, size_t);
- njs_ret_t ret;
- njs_object_t *obj;
- + njs_value_t prop;
- njs_function_t *function;
- if (nxt_slow_path(!njs_is_primitive(property))) {
- - return njs_trap(vm, NJS_TRAP_PROPERTY);
- + ret = njs_value_to_string(vm, &prop, (njs_value_t *) property);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- +
- + property = ∝
- }
- hash = nxt_djb_hash;
- @@ -473,7 +478,6 @@ njs_external_property_delete(njs_vm_t *v
- * retval will contain the property's value
- *
- * NXT_DECLINED property was not found in object
- - * NJS_TRAP the property trap must be called
- * NJS_APPLIED the property getter was applied
- * NXT_ERROR exception has been thrown.
- * retval will contain undefined
- @@ -553,7 +557,6 @@ njs_value_property(njs_vm_t *vm, const n
- return NXT_DECLINED;
- - case NJS_TRAP:
- case NXT_ERROR:
- default:
- @@ -566,7 +569,6 @@ njs_value_property(njs_vm_t *vm, const n
- /*
- * NXT_OK property has been set successfully
- - * NJS_TRAP the property trap must be called
- * NJS_APPLIED the property setter was applied
- * NXT_ERROR exception has been thrown.
- */
- @@ -669,7 +671,6 @@ njs_value_property_set(njs_vm_t *vm, njs
- break;
- - case NJS_TRAP:
- case NXT_ERROR:
- default:
- @@ -1152,7 +1153,6 @@ njs_object_prop_descriptor(njs_vm_t *vm,
- *dest = njs_value_undefined;
- return NXT_OK;
- - case NJS_TRAP:
- case NXT_ERROR:
- default:
- return ret;
- diff --git a/njs/njs_regexp.c b/njs/njs_regexp.c
- --- a/njs/njs_regexp.c
- +++ b/njs/njs_regexp.c
- @@ -112,17 +112,19 @@ njs_regexp_constructor(njs_vm_t *vm, njs
- pattern = njs_arg(args, nargs, 1);
- if (!njs_is_regexp(pattern) && !njs_is_primitive(pattern)) {
- - njs_vm_trap_value(vm, &args[1]);
- -
- - return njs_trap(vm, NJS_TRAP_STRING_ARG);
- + ret = njs_value_to_string(vm, &args[1], &args[1]);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- }
- flags = njs_arg(args, nargs, 2);
- if (!njs_is_primitive(flags)) {
- - njs_vm_trap_value(vm, &args[2]);
- -
- - return njs_trap(vm, NJS_TRAP_STRING_ARG);
- + ret = njs_value_to_string(vm, &args[2], &args[2]);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- }
- re_flags = 0;
- diff --git a/njs/njs_string.c b/njs/njs_string.c
- --- a/njs/njs_string.c
- +++ b/njs/njs_string.c
- @@ -853,6 +853,7 @@ njs_string_prototype_concat(njs_vm_t *vm
- {
- u_char *p, *start;
- uint64_t size, length, mask;
- + njs_ret_t ret;
- nxt_uint_t i;
- njs_string_prop_t string;
- @@ -863,9 +864,10 @@ njs_string_prototype_concat(njs_vm_t *vm
- for (i = 0; i < nargs; i++) {
- if (!njs_is_string(&args[i])) {
- - njs_vm_trap_value(vm, &args[i]);
- -
- - return njs_trap(vm, NJS_TRAP_STRING_ARG);
- + ret = njs_value_to_string(vm, &args[i], &args[i]);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- }
- }
- @@ -1222,16 +1224,12 @@ njs_string_prototype_char_at(njs_vm_t *v
- slice.string_length = njs_string_prop(&string, &args[0]);
- - start = 0;
- + start = njs_primitive_value_to_integer(njs_arg(args, nargs, 1));
- length = 1;
- - if (nargs > 1) {
- - start = njs_number(&args[1]);
- -
- - if (start < 0 || start >= (ssize_t) slice.string_length) {
- - start = 0;
- - length = 0;
- - }
- + if (start < 0 || start >= (ssize_t) slice.string_length) {
- + start = 0;
- + length = 0;
- }
- slice.start = start;
- @@ -1448,6 +1446,7 @@ njs_string_bytes_from_array(njs_vm_t *vm
- {
- u_char *p;
- uint32_t i, length;
- + njs_ret_t ret;
- njs_array_t *array;
- njs_value_t *octet;
- @@ -1456,9 +1455,10 @@ njs_string_bytes_from_array(njs_vm_t *vm
- for (i = 0; i < length; i++) {
- if (!njs_is_numeric(&array->start[i])) {
- - njs_vm_trap_value(vm, &array->start[i]);
- -
- - return njs_trap(vm, NJS_TRAP_NUMBER_ARG);
- + ret = njs_value_to_numeric(vm, &array->start[i], &array->start[i]);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- }
- }
- @@ -1684,13 +1684,15 @@ njs_string_from_char_code(njs_vm_t *vm,
- double num;
- size_t size;
- int32_t code;
- + njs_ret_t ret;
- nxt_uint_t i;
- for (i = 1; i < nargs; i++) {
- if (!njs_is_numeric(&args[i])) {
- - njs_vm_trap_value(vm, &args[i]);
- -
- - return njs_trap(vm, NJS_TRAP_NUMBER_ARG);
- + ret = njs_value_to_numeric(vm, &args[i], &args[i]);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- }
- }
- @@ -2397,20 +2399,16 @@ njs_string_prototype_repeat(njs_vm_t *vm
- uint32_t size, length;
- njs_string_prop_t string;
- - n = 0;
- + n = njs_primitive_value_to_integer(njs_arg(args, nargs, 1));
- (void) njs_string_prop(&string, &args[0]);
- - if (nargs > 1) {
- - max = (string.size > 1) ? NJS_STRING_MAX_LENGTH / string.size
- - : NJS_STRING_MAX_LENGTH;
- -
- - n = njs_number(&args[1]);
- -
- - if (nxt_slow_path(n < 0 || n >= max)) {
- - njs_range_error(vm, NULL);
- - return NXT_ERROR;
- - }
- + max = (string.size > 1) ? NJS_STRING_MAX_LENGTH / string.size
- + : NJS_STRING_MAX_LENGTH;
- +
- + if (nxt_slow_path(n < 0 || n >= max)) {
- + njs_range_error(vm, NULL);
- + return NXT_ERROR;
- }
- if (string.size == 0) {
- @@ -3390,8 +3388,10 @@ njs_string_replace_search_continuation(n
- r = njs_vm_continuation(vm);
- if (!njs_is_primitive(&r->retval)) {
- - njs_vm_trap_value(vm, &r->retval);
- - return njs_trap(vm, NJS_TRAP_STRING_ARG);
- + ret = njs_value_to_string(vm, &r->retval, &r->retval);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- }
- ret = njs_primitive_value_to_string(vm, &string, &r->retval);
- diff --git a/njs/njs_value.c b/njs/njs_value.c
- --- a/njs/njs_value.c
- +++ b/njs/njs_value.c
- @@ -169,11 +169,12 @@ njs_values_strict_equal(const njs_value_
- */
- njs_ret_t
- -njs_value_to_primitive(njs_vm_t *vm, njs_value_t *value, nxt_uint_t hint)
- +njs_value_to_primitive(njs_vm_t *vm, njs_value_t *dst, njs_value_t *value,
- + nxt_uint_t hint)
- {
- njs_ret_t ret;
- - njs_value_t *retval;
- - njs_function_t *function;
- + nxt_uint_t trap_tries;
- + njs_value_t retval;
- njs_object_prop_t *prop;
- nxt_lvlhsh_query_t lhq;
- @@ -187,76 +188,100 @@ njs_value_to_primitive(njs_vm_t *vm, njs
- nxt_string("toString"),
- };
- - if (!njs_is_primitive(value)) {
- - retval = &vm->top_frame->trap_scratch;
- - if (!njs_is_primitive(retval)) {
- + if (njs_is_primitive(value)) {
- + /* GC */
- + *dst = *value;
- + return NXT_OK;
- + }
- - for ( ;; ) {
- - ret = NXT_ERROR;
- + trap_tries = 0;
- - if (njs_is_object(value) && vm->top_frame->trap_tries < 2) {
- - hint ^= vm->top_frame->trap_tries++;
- + for ( ;; ) {
- + ret = NXT_ERROR;
- - lhq.key_hash = hashes[hint];
- - lhq.key = names[hint];
- + if (njs_is_object(value) && trap_tries < 2) {
- + hint ^= trap_tries++;
- - prop = njs_object_property(vm, njs_object(value), &lhq);
- + lhq.key_hash = hashes[hint];
- + lhq.key = names[hint];
- - if (nxt_fast_path(prop != NULL)) {
- + prop = njs_object_property(vm, njs_object(value), &lhq);
- - if (!njs_is_function(&prop->value)) {
- - /* Try the second method. */
- - continue;
- - }
- + if (prop == NULL || !njs_is_function(&prop->value)) {
- + /* Try the second method. */
- + continue;
- + }
- - function = njs_function(&prop->value);
- + ret = njs_function_call(vm, njs_function(&prop->value), value, 1,
- + (njs_index_t) &retval);
- - ret = njs_function_apply(vm, function, value, 1,
- - (njs_index_t) retval);
- - /*
- - * njs_function_apply() can return
- - * NXT_OK, NJS_APPLIED, NXT_ERROR, NXT_AGAIN.
- - */
- - if (nxt_fast_path(ret == NXT_OK)) {
- + if (nxt_fast_path(ret == NXT_OK)) {
- + if (njs_is_primitive(&retval)) {
- + break;
- + }
- - if (njs_is_primitive(&vm->retval)) {
- - retval = &vm->retval;
- - break;
- - }
- + /* Try the second method. */
- + continue;
- + }
- - /* Try the second method. */
- - continue;
- - }
- + /* NXT_ERROR */
- - if (ret == NJS_APPLIED) {
- - /*
- - * A user-defined method or continuation have
- - * been prepared to run. The method will return
- - * to the current instruction and will restart it.
- - */
- - ret = 0;
- - }
- - }
- - }
- + return ret;
- + }
- - if (ret == NXT_ERROR) {
- - njs_type_error(vm,
- - "Cannot convert object to primitive value");
- - }
- + njs_type_error(vm, "Cannot convert object to primitive value");
- - return ret;
- - }
- + return ret;
- + }
- +
- + *dst = retval;
- +
- + return NXT_OK;
- +}
- +
- +
- +njs_ret_t
- +njs_value_to_numeric(njs_vm_t *vm, njs_value_t *dst, njs_value_t *value)
- +{
- + double num;
- + njs_ret_t ret;
- +
- + ret = njs_value_to_primitive(vm, dst, value, 0);
- + if (nxt_slow_path(ret != NXT_OK)) {
- + return ret;
- + }
- +
- + if (!njs_is_numeric(dst)) {
- + num = NAN;
- +
- + if (njs_is_string(dst)) {
- + num = njs_string_to_number(dst, 0);
- }
- - *value = *retval;
- -
- - njs_set_invalid(retval);
- + njs_set_number(dst, num);
- }
- - vm->top_frame->trap_tries = 0;
- + return NXT_OK;
- +}
- - return 1;
- +
- +njs_ret_t
- +njs_value_to_string(njs_vm_t *vm, njs_value_t *dst, njs_value_t *value)
- +{
- + njs_ret_t ret;
- + njs_value_t primitive;
- +
- + if (nxt_slow_path(!njs_is_primitive(value))) {
- + ret = njs_value_to_primitive(vm, &primitive, value, 1);
- + if (nxt_slow_path(ret != NXT_OK)) {
- + return ret;
- + }
- +
- + value = &primitive;
- + }
- +
- + return njs_primitive_value_to_string(vm, dst, value);
- }
- diff --git a/njs/njs_value.h b/njs/njs_value.h
- --- a/njs/njs_value.h
- +++ b/njs/njs_value.h
- @@ -561,7 +561,7 @@ typedef enum {
- #define njs_set_boolean(value, yn) \
- - *(value) = yn ? njs_value_true : njs_value_false
- + *(value) = (yn) ? njs_value_true : njs_value_false
- #define njs_set_true(value) \
- @@ -687,8 +687,12 @@ void njs_value_retain(njs_value_t *value
- void njs_value_release(njs_vm_t *vm, njs_value_t *value);
- nxt_bool_t njs_values_strict_equal(const njs_value_t *val1,
- const njs_value_t *val2);
- -njs_ret_t njs_value_to_primitive(njs_vm_t *vm, njs_value_t *value,
- - nxt_uint_t hint);
- +njs_ret_t njs_value_to_primitive(njs_vm_t *vm, njs_value_t *dst,
- + njs_value_t *value, nxt_uint_t hint);
- +njs_ret_t njs_value_to_numeric(njs_vm_t *vm, njs_value_t *dst,
- + njs_value_t *value);
- +njs_ret_t njs_value_to_string(njs_vm_t *vm, njs_value_t *dst,
- + njs_value_t *value);
- njs_array_t *njs_value_enumerate(njs_vm_t *vm, const njs_value_t *value,
- njs_object_enum_t kind, nxt_bool_t all);
- njs_array_t *njs_value_own_enumerate(njs_vm_t *vm, const njs_value_t *value,
- diff --git a/njs/njs_vm.c b/njs/njs_vm.c
- --- a/njs/njs_vm.c
- +++ b/njs/njs_vm.c
- @@ -23,10 +23,10 @@ struct njs_property_next_s {
- static njs_ret_t njs_string_concat(njs_vm_t *vm, njs_value_t *val1,
- njs_value_t *val2);
- -static njs_ret_t njs_values_equal(njs_vm_t *vm, const njs_value_t *val1,
- - const njs_value_t *val2);
- -static njs_ret_t njs_values_compare(njs_vm_t *vm, const njs_value_t *val1,
- - const njs_value_t *val2);
- +static njs_ret_t njs_values_equal(njs_vm_t *vm, njs_value_t *val1,
- + njs_value_t *val2);
- +static njs_ret_t njs_values_compare(njs_vm_t *vm, njs_value_t *val1,
- + njs_value_t *val2);
- static njs_ret_t njs_function_frame_create(njs_vm_t *vm, njs_value_t *value,
- const njs_value_t *this, uintptr_t nargs, nxt_bool_t ctor);
- static njs_object_t *njs_function_new_object(njs_vm_t *vm, njs_value_t *value);
- @@ -35,29 +35,6 @@ static void njs_vm_scopes_restore(njs_vm
- static njs_ret_t njs_vmcode_continuation(njs_vm_t *vm, njs_value_t *invld1,
- njs_value_t *invld2);
- -static void njs_vm_trap(njs_vm_t *vm, njs_trap_t trap, njs_value_t *value1,
- - njs_value_t *value2);
- -static void njs_vm_trap_argument(njs_vm_t *vm, njs_trap_t trap);
- -static njs_ret_t njs_vmcode_number_primitive(njs_vm_t *vm, njs_value_t *invld,
- - njs_value_t *narg);
- -static njs_ret_t njs_vmcode_string_primitive(njs_vm_t *vm, njs_value_t *invld,
- - njs_value_t *narg);
- -static njs_ret_t njs_vmcode_addition_primitive(njs_vm_t *vm, njs_value_t *invld,
- - njs_value_t *narg);
- -static njs_ret_t njs_vmcode_comparison_primitive(njs_vm_t *vm,
- - njs_value_t *invld, njs_value_t *narg);
- -static njs_ret_t njs_vmcode_number_argument(njs_vm_t *vm, njs_value_t *invld1,
- - 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_vmcode_restart(njs_vm_t *vm, njs_value_t *invld1,
- - njs_value_t *invld2);
- -static njs_ret_t njs_object_value_to_string(njs_vm_t *vm, njs_value_t *value);
- -static njs_ret_t njs_vmcode_value_to_string(njs_vm_t *vm, njs_value_t *invld1,
- - njs_value_t *invld2);
- -
- static njs_ret_t njs_vm_add_backtrace_entry(njs_vm_t *vm, njs_frame_t *frame);
- void njs_debug(njs_index_t index, njs_value_t *value);
- @@ -79,9 +56,8 @@ const nxt_str_t njs_entry_anonymous =
- nxt_int_t
- njs_vmcode_interpreter(njs_vm_t *vm)
- {
- - u_char *catch;
- + u_char *catch, call;
- njs_ret_t ret;
- - njs_trap_t trap;
- njs_value_t *retval, *value1, *value2;
- njs_frame_t *frame;
- njs_native_frame_t *previous;
- @@ -147,40 +123,6 @@ start:
- }
- }
- - if (ret == NJS_TRAP) {
- - trap = vm->trap;
- -
- - switch (trap) {
- -
- - case NJS_TRAP_NUMBER:
- - value2 = value1;
- -
- - /* Fall through. */
- -
- - case NJS_TRAP_NUMBERS:
- - case NJS_TRAP_ADDITION:
- - case NJS_TRAP_COMPARISON:
- - case NJS_TRAP_INCDEC:
- - case NJS_TRAP_PROPERTY:
- -
- - njs_vm_trap(vm, trap, value1, value2);
- -
- - goto start;
- -
- - case NJS_TRAP_NUMBER_ARG:
- - case NJS_TRAP_STRING_ARG:
- - case NJS_TRAP_PRIMITIVE_ARG:
- -
- - njs_vm_trap_argument(vm, trap);
- -
- - goto start;
- -
- - default:
- - ret = NXT_ERROR;
- - break;
- - }
- - }
- -
- if (ret == NXT_ERROR) {
- for ( ;; ) {
- @@ -210,14 +152,44 @@ start:
- njs_vm_scopes_restore(vm, frame, previous);
- + call = frame->native.call;
- +
- if (frame->native.size != 0) {
- vm->stack_size -= frame->native.size;
- nxt_mp_free(vm->mem_pool, frame);
- }
- +
- + if (call) {
- + return NXT_ERROR;
- + }
- +
- }
- }
- - /* NXT_AGAIN, NJS_STOP. */
- + /* NXT_ERROR, NJS_STOP. */
- +
- + return ret;
- +}
- +
- +
- +nxt_int_t
- +njs_vmcode_run(njs_vm_t *vm)
- +{
- + njs_ret_t ret;
- +
- + if (nxt_slow_path(vm->count > 128)) {
- + njs_internal_error(vm, "recursion limit reached");
- + return NXT_ERROR;
- + }
- +
- + vm->count++;
- +
- + ret = njs_vmcode_interpreter(vm);
- + if (ret == NJS_STOP) {
- + ret = NJS_OK;
- + }
- +
- + vm->count--;
- return ret;
- }
- @@ -620,7 +592,6 @@ njs_vmcode_property_in(njs_vm_t *vm, njs
- break;
- - case NJS_TRAP:
- case NXT_ERROR:
- default:
- @@ -715,7 +686,6 @@ njs_vmcode_property_delete(njs_vm_t *vm,
- case NXT_DECLINED:
- break;
- - case NJS_TRAP:
- case NXT_ERROR:
- default:
- @@ -892,40 +862,60 @@ njs_vmcode_instance_of(njs_vm_t *vm, njs
- njs_ret_t
- njs_vmcode_increment(njs_vm_t *vm, njs_value_t *reference, njs_value_t *value)
- {
- - double num;
- -
- - if (nxt_fast_path(njs_is_numeric(value))) {
- - num = njs_number(value) + 1.0;
- -
- - njs_release(vm, reference);
- -
- - njs_set_number(reference, num);
- - vm->retval = *reference;
- -
- - return sizeof(njs_vmcode_3addr_t);
- + double num;
- + njs_ret_t ret;
- + njs_value_t numeric;
- +
- + if (nxt_slow_path(!njs_is_numeric(value))) {
- + ret = njs_value_to_numeric(vm, &numeric, value);
- + if (nxt_slow_path(ret != NXT_OK)) {
- + return ret;
- + }
- +
- + num = njs_number(&numeric);
- +
- + } else {
- + num = njs_number(value);
- }
- - return njs_trap(vm, NJS_TRAP_INCDEC);
- + num += 1.0;
- +
- + njs_release(vm, reference);
- +
- + njs_set_number(reference, num);
- + vm->retval = *reference;
- +
- + return sizeof(njs_vmcode_3addr_t);
- }
- njs_ret_t
- njs_vmcode_decrement(njs_vm_t *vm, njs_value_t *reference, njs_value_t *value)
- {
- - double num;
- -
- - if (nxt_fast_path(njs_is_numeric(value))) {
- - num = njs_number(value) - 1.0;
- -
- - njs_release(vm, reference);
- -
- - njs_set_number(reference, num);
- - vm->retval = *reference;
- -
- - return sizeof(njs_vmcode_3addr_t);
- + double num;
- + njs_ret_t ret;
- + njs_value_t numeric;
- +
- + if (nxt_slow_path(!njs_is_numeric(value))) {
- + ret = njs_value_to_numeric(vm, &numeric, value);
- + if (nxt_slow_path(ret != NXT_OK)) {
- + return ret;
- + }
- +
- + num = njs_number(&numeric);
- +
- + } else {
- + num = njs_number(value);
- }
- - return njs_trap(vm, NJS_TRAP_INCDEC);
- + num -= 1.0;
- +
- + njs_release(vm, reference);
- +
- + njs_set_number(reference, num);
- + vm->retval = *reference;
- +
- + return sizeof(njs_vmcode_3addr_t);
- }
- @@ -934,19 +924,27 @@ njs_vmcode_post_increment(njs_vm_t *vm,
- njs_value_t *value)
- {
- double num;
- -
- - if (nxt_fast_path(njs_is_numeric(value))) {
- + njs_ret_t ret;
- + njs_value_t numeric;
- +
- + if (nxt_slow_path(!njs_is_numeric(value))) {
- + ret = njs_value_to_numeric(vm, &numeric, value);
- + if (nxt_slow_path(ret != NXT_OK)) {
- + return ret;
- + }
- +
- + num = njs_number(&numeric);
- +
- + } else {
- num = njs_number(value);
- -
- - njs_release(vm, reference);
- -
- - njs_set_number(reference, num + 1.0);
- - njs_set_number(&vm->retval, num);
- -
- - return sizeof(njs_vmcode_3addr_t);
- }
- - return njs_trap(vm, NJS_TRAP_INCDEC);
- + njs_release(vm, reference);
- +
- + njs_set_number(reference, num + 1.0);
- + njs_set_number(&vm->retval, num);
- +
- + return sizeof(njs_vmcode_3addr_t);
- }
- @@ -954,20 +952,28 @@ njs_ret_t
- njs_vmcode_post_decrement(njs_vm_t *vm, njs_value_t *reference,
- njs_value_t *value)
- {
- - double num;
- -
- - if (nxt_fast_path(njs_is_numeric(value))) {
- + double num;
- + njs_ret_t ret;
- + njs_value_t numeric;
- +
- + if (nxt_slow_path(!njs_is_numeric(value))) {
- + ret = njs_value_to_numeric(vm, &numeric, value);
- + if (nxt_slow_path(ret != NXT_OK)) {
- + return ret;
- + }
- +
- + num = njs_number(&numeric);
- +
- + } else {
- num = njs_number(value);
- -
- - njs_release(vm, reference);
- -
- - njs_set_number(reference, num - 1.0);
- - njs_set_number(&vm->retval, num);
- -
- - return sizeof(njs_vmcode_3addr_t);
- }
- - return njs_trap(vm, NJS_TRAP_INCDEC);
- + njs_release(vm, reference);
- +
- + njs_set_number(reference, num - 1.0);
- + njs_set_number(&vm->retval, num);
- +
- + return sizeof(njs_vmcode_3addr_t);
- }
- @@ -1042,69 +1048,105 @@ njs_vmcode_delete(njs_vm_t *vm, njs_valu
- njs_ret_t
- njs_vmcode_unary_plus(njs_vm_t *vm, njs_value_t *value, njs_value_t *invld)
- {
- - if (nxt_fast_path(njs_is_numeric(value))) {
- - njs_set_number(&vm->retval, njs_number(value));
- - return sizeof(njs_vmcode_2addr_t);
- + njs_ret_t ret;
- + njs_value_t numeric;
- +
- + if (nxt_slow_path(!njs_is_numeric(value))) {
- + ret = njs_value_to_numeric(vm, &numeric, value);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- +
- + value = &numeric;
- }
- - return njs_trap(vm, NJS_TRAP_NUMBER);
- + njs_set_number(&vm->retval, njs_number(value));
- +
- + return sizeof(njs_vmcode_2addr_t);
- }
- njs_ret_t
- njs_vmcode_unary_negation(njs_vm_t *vm, njs_value_t *value, njs_value_t *invld)
- {
- - if (nxt_fast_path(njs_is_numeric(value))) {
- - njs_set_number(&vm->retval, - njs_number(value));
- - return sizeof(njs_vmcode_2addr_t);
- + njs_ret_t ret;
- + njs_value_t numeric;
- +
- + if (nxt_slow_path(!njs_is_numeric(value))) {
- + ret = njs_value_to_numeric(vm, &numeric, value);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- +
- + value = &numeric;
- }
- - return njs_trap(vm, NJS_TRAP_NUMBER);
- + njs_set_number(&vm->retval, -njs_number(value));
- +
- + return sizeof(njs_vmcode_2addr_t);
- }
- njs_ret_t
- njs_vmcode_addition(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
- {
- - double num;
- njs_ret_t ret;
- - njs_value_t *s1, *s2, *src, dst;
- +
- + njs_value_t primitive1, primitive2, dst, *s1, *s2, *src;
- +
- + if (nxt_slow_path(!njs_is_primitive(val1))) {
- +
- + /*
- + * ECMAScript 5.1:
- + * Date should return String, other types sould return Number.
- + */
- +
- + ret = njs_value_to_primitive(vm, &primitive1, val1, njs_is_date(val1));
- + if (ret != NXT_OK) {
- + return ret;
- + }
- +
- + val1 = &primitive1;
- + }
- +
- + if (nxt_slow_path(!njs_is_primitive(val2))) {
- +
- + /*
- + * ECMAScript 5.1:
- + * Date should return String, other types sould return Number.
- + */
- +
- + ret = njs_value_to_primitive(vm, &primitive2, val2, njs_is_date(val2));
- + if (ret != NXT_OK) {
- + return ret;
- + }
- +
- + val2 = &primitive2;
- + }
- if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) {
- -
- - num = njs_number(val1) + njs_number(val2);
- - njs_set_number(&vm->retval, num);
- -
- + njs_set_number(&vm->retval, njs_number(val1) + njs_number(val2));
- return sizeof(njs_vmcode_3addr_t);
- }
- - if (nxt_fast_path(njs_is_string(val1) && njs_is_string(val2))) {
- - return njs_string_concat(vm, val1, val2);
- + if (njs_is_string(val1)) {
- + s1 = val1;
- + s2 = &dst;
- + src = val2;
- +
- + } else {
- + s1 = &dst;
- + s2 = val2;
- + src = val1;
- }
- - if (nxt_fast_path(njs_is_primitive(val1) && njs_is_primitive(val2))) {
- -
- - if (njs_is_string(val1)) {
- - s1 = val1;
- - s2 = &dst;
- - src = val2;
- -
- - } else {
- - s1 = &dst;
- - s2 = val2;
- - src = val1;
- - }
- -
- - ret = njs_primitive_value_to_string(vm, &dst, src);
- -
- - if (nxt_fast_path(ret == NXT_OK)) {
- - return njs_string_concat(vm, s1, s2);
- - }
- -
- - return ret;
- + ret = njs_primitive_value_to_string(vm, &dst, src);
- +
- + if (nxt_fast_path(ret == NXT_OK)) {
- + return njs_string_concat(vm, s1, s2);
- }
- - return njs_trap(vm, NJS_TRAP_ADDITION);
- + return ret;
- }
- @@ -1149,140 +1191,238 @@ njs_string_concat(njs_vm_t *vm, njs_valu
- njs_ret_t
- njs_vmcode_substraction(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
- {
- - double num;
- -
- - if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) {
- -
- - num = njs_number(val1) - njs_number(val2);
- - njs_set_number(&vm->retval, num);
- -
- - return sizeof(njs_vmcode_3addr_t);
- + njs_ret_t ret;
- + njs_value_t numeric1, numeric2;
- +
- + if (nxt_slow_path(!njs_is_numeric(val1))) {
- + ret = njs_value_to_numeric(vm, &numeric1, val1);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- +
- + val1 = &numeric1;
- }
- - return njs_trap(vm, NJS_TRAP_NUMBERS);
- + if (nxt_slow_path(!njs_is_numeric(val2))) {
- + ret = njs_value_to_numeric(vm, &numeric2, val2);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- +
- + val2 = &numeric2;
- + }
- +
- + njs_set_number(&vm->retval, njs_number(val1) - njs_number(val2));
- +
- + return sizeof(njs_vmcode_3addr_t);
- }
- njs_ret_t
- njs_vmcode_multiplication(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
- {
- - double num;
- -
- - if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) {
- -
- - num = njs_number(val1) * njs_number(val2);
- - njs_set_number(&vm->retval, num);
- -
- - return sizeof(njs_vmcode_3addr_t);
- + njs_ret_t ret;
- + njs_value_t numeric1, numeric2;
- +
- + if (nxt_slow_path(!njs_is_numeric(val1))) {
- + ret = njs_value_to_numeric(vm, &numeric1, val1);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- +
- + val1 = &numeric1;
- }
- - return njs_trap(vm, NJS_TRAP_NUMBERS);
- + if (nxt_slow_path(!njs_is_numeric(val2))) {
- + ret = njs_value_to_numeric(vm, &numeric2, val2);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- +
- + val2 = &numeric2;
- + }
- +
- + njs_set_number(&vm->retval, njs_number(val1) * njs_number(val2));
- +
- + return sizeof(njs_vmcode_3addr_t);
- }
- njs_ret_t
- njs_vmcode_exponentiation(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
- {
- - double num, base, exponent;
- - nxt_bool_t valid;
- -
- - if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) {
- - base = njs_number(val1);
- - exponent = njs_number(val2);
- -
- - /*
- - * According to ES7:
- - * 1. If exponent is NaN, the result should be NaN;
- - * 2. The result of +/-1 ** +/-Infinity should be NaN.
- - */
- - valid = nxt_expect(1, fabs(base) != 1
- - || (!isnan(exponent) && !isinf(exponent)));
- -
- - if (valid) {
- - num = pow(base, exponent);
- -
- - } else {
- - num = NAN;
- + double num, base, exponent;
- + njs_ret_t ret;
- + nxt_bool_t valid;
- + njs_value_t numeric1, numeric2;
- +
- + if (nxt_slow_path(!njs_is_numeric(val1))) {
- + ret = njs_value_to_numeric(vm, &numeric1, val1);
- + if (ret != NXT_OK) {
- + return ret;
- }
- - njs_set_number(&vm->retval, num);
- -
- - return sizeof(njs_vmcode_3addr_t);
- + val1 = &numeric1;
- }
- - return njs_trap(vm, NJS_TRAP_NUMBERS);
- + if (nxt_slow_path(!njs_is_numeric(val2))) {
- + ret = njs_value_to_numeric(vm, &numeric2, val2);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- +
- + val2 = &numeric2;
- + }
- +
- + base = njs_number(val1);
- + exponent = njs_number(val2);
- +
- + /*
- + * According to ES7:
- + * 1. If exponent is NaN, the result should be NaN;
- + * 2. The result of +/-1 ** +/-Infinity should be NaN.
- + */
- + valid = nxt_expect(1, fabs(base) != 1
- + || (!isnan(exponent) && !isinf(exponent)));
- +
- + if (valid) {
- + num = pow(base, exponent);
- +
- + } else {
- + num = NAN;
- + }
- +
- + njs_set_number(&vm->retval, num);
- +
- + return sizeof(njs_vmcode_3addr_t);
- }
- njs_ret_t
- njs_vmcode_division(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
- {
- - double num;
- -
- - if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) {
- -
- - num = njs_number(val1) / njs_number(val2);
- - njs_set_number(&vm->retval, num);
- -
- - return sizeof(njs_vmcode_3addr_t);
- + njs_ret_t ret;
- + njs_value_t numeric1, numeric2;
- +
- + if (nxt_slow_path(!njs_is_numeric(val1))) {
- + ret = njs_value_to_numeric(vm, &numeric1, val1);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- +
- + val1 = &numeric1;
- }
- - return njs_trap(vm, NJS_TRAP_NUMBERS);
- + if (nxt_slow_path(!njs_is_numeric(val2))) {
- + ret = njs_value_to_numeric(vm, &numeric2, val2);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- +
- + val2 = &numeric2;
- + }
- +
- + njs_set_number(&vm->retval, njs_number(val1) / njs_number(val2));
- +
- + return sizeof(njs_vmcode_3addr_t);
- }
- njs_ret_t
- njs_vmcode_remainder(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
- {
- - double num;
- -
- - if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) {
- -
- - num = fmod(njs_number(val1), njs_number(val2));
- - njs_set_number(&vm->retval, num);
- -
- - return sizeof(njs_vmcode_3addr_t);
- + njs_ret_t ret;
- + njs_value_t numeric1, numeric2;
- +
- + if (nxt_slow_path(!njs_is_numeric(val1))) {
- + ret = njs_value_to_numeric(vm, &numeric1, val1);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- +
- + val1 = &numeric1;
- }
- - return njs_trap(vm, NJS_TRAP_NUMBERS);
- + if (nxt_slow_path(!njs_is_numeric(val2))) {
- + ret = njs_value_to_numeric(vm, &numeric2, val2);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- +
- + val2 = &numeric2;
- + }
- +
- + njs_set_number(&vm->retval, fmod(njs_number(val1), njs_number(val2)));
- +
- + return sizeof(njs_vmcode_3addr_t);
- }
- njs_ret_t
- njs_vmcode_left_shift(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
- {
- - int32_t num1;
- - uint32_t num2;
- -
- - if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) {
- -
- - num1 = njs_number_to_int32(njs_number(val1));
- - num2 = njs_number_to_uint32(njs_number(val2));
- - njs_set_number(&vm->retval, num1 << (num2 & 0x1f));
- -
- - return sizeof(njs_vmcode_3addr_t);
- + int32_t num1;
- + uint32_t num2;
- + njs_ret_t ret;
- + njs_value_t numeric1, numeric2;
- +
- + if (nxt_slow_path(!njs_is_numeric(val1))) {
- + ret = njs_value_to_numeric(vm, &numeric1, val1);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- +
- + val1 = &numeric1;
- }
- - return njs_trap(vm, NJS_TRAP_NUMBERS);
- + if (nxt_slow_path(!njs_is_numeric(val2))) {
- + ret = njs_value_to_numeric(vm, &numeric2, val2);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- +
- + val2 = &numeric2;
- + }
- +
- + num1 = njs_number_to_int32(njs_number(val1));
- + num2 = njs_number_to_uint32(njs_number(val2));
- + njs_set_number(&vm->retval, num1 << (num2 & 0x1f));
- +
- + return sizeof(njs_vmcode_3addr_t);
- }
- njs_ret_t
- njs_vmcode_right_shift(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
- {
- - int32_t num1;
- - uint32_t num2;
- -
- - if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) {
- -
- - num1 = njs_number_to_int32(njs_number(val1));
- - num2 = njs_number_to_uint32(njs_number(val2));
- - njs_set_number(&vm->retval, num1 >> (num2 & 0x1f));
- -
- - return sizeof(njs_vmcode_3addr_t);
- + int32_t num1;
- + uint32_t num2;
- + njs_ret_t ret;
- + njs_value_t numeric1, numeric2;
- +
- + if (nxt_slow_path(!njs_is_numeric(val1))) {
- + ret = njs_value_to_numeric(vm, &numeric1, val1);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- +
- + val1 = &numeric1;
- }
- - return njs_trap(vm, NJS_TRAP_NUMBERS);
- + if (nxt_slow_path(!njs_is_numeric(val2))) {
- + ret = njs_value_to_numeric(vm, &numeric2, val2);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- +
- + val2 = &numeric2;
- + }
- +
- + num1 = njs_number_to_int32(njs_number(val1));
- + num2 = njs_number_to_uint32(njs_number(val2));
- + njs_set_number(&vm->retval, num1 >> (num2 & 0x1f));
- +
- + return sizeof(njs_vmcode_3addr_t);
- }
- @@ -1290,34 +1430,40 @@ njs_ret_t
- njs_vmcode_unsigned_right_shift(njs_vm_t *vm, njs_value_t *val1,
- njs_value_t *val2)
- {
- - uint32_t num1, num2;
- -
- - if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) {
- -
- - num1 = njs_number_to_uint32(njs_number(val1));
- - num2 = njs_number_to_uint32(njs_number(val2));
- - njs_set_number(&vm->retval, num1 >> (num2 & 0x1f));
- -
- - return sizeof(njs_vmcode_3addr_t);
- + uint32_t num1, num2;
- + njs_ret_t ret;
- + njs_value_t numeric1, numeric2;
- +
- + if (nxt_slow_path(!njs_is_numeric(val1))) {
- + ret = njs_value_to_numeric(vm, &numeric1, val1);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- +
- + val1 = &numeric1;
- }
- - return njs_trap(vm, NJS_TRAP_NUMBERS);
- + if (nxt_slow_path(!njs_is_numeric(val2))) {
- + ret = njs_value_to_numeric(vm, &numeric2, val2);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- +
- + val2 = &numeric2;
- + }
- +
- + num1 = njs_number_to_uint32(njs_number(val1));
- + num2 = njs_number_to_uint32(njs_number(val2));
- + njs_set_number(&vm->retval, num1 >> (num2 & 0x1f));
- +
- + return sizeof(njs_vmcode_3addr_t);
- }
- njs_ret_t
- njs_vmcode_logical_not(njs_vm_t *vm, njs_value_t *value, njs_value_t *inlvd)
- {
- - const njs_value_t *retval;
- -
- - if (njs_is_true(value)) {
- - retval = &njs_value_false;
- -
- - } else {
- - retval = &njs_value_true;
- - }
- -
- - vm->retval = *retval;
- + njs_set_boolean(&vm->retval, !njs_is_true(value));
- return sizeof(njs_vmcode_2addr_t);
- }
- @@ -1358,85 +1504,133 @@ njs_vmcode_test_if_false(njs_vm_t *vm, n
- njs_ret_t
- njs_vmcode_bitwise_not(njs_vm_t *vm, njs_value_t *value, njs_value_t *invld)
- {
- - int32_t num;
- -
- - if (nxt_fast_path(njs_is_numeric(value))) {
- - num = njs_number_to_integer(njs_number(value));
- - njs_set_number(&vm->retval, ~num);
- -
- - return sizeof(njs_vmcode_2addr_t);
- + njs_ret_t ret;
- + njs_value_t numeric;
- +
- + if (nxt_slow_path(!njs_is_numeric(value))) {
- + ret = njs_value_to_numeric(vm, &numeric, value);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- +
- + value = &numeric;
- }
- - return njs_trap(vm, NJS_TRAP_NUMBER);
- + njs_set_number(&vm->retval, ~njs_number_to_integer(njs_number(value)));
- +
- + return sizeof(njs_vmcode_2addr_t);
- }
- njs_ret_t
- njs_vmcode_bitwise_and(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
- {
- - int32_t num1, num2;
- -
- - if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) {
- -
- - num1 = njs_number_to_integer(njs_number(val1));
- - num2 = njs_number_to_integer(njs_number(val2));
- - njs_set_number(&vm->retval, num1 & num2);
- -
- - return sizeof(njs_vmcode_3addr_t);
- + int32_t num1, num2;
- + njs_ret_t ret;
- + njs_value_t numeric1, numeric2;
- +
- + if (nxt_slow_path(!njs_is_numeric(val1))) {
- + ret = njs_value_to_numeric(vm, &numeric1, val1);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- +
- + val1 = &numeric1;
- }
- - return njs_trap(vm, NJS_TRAP_NUMBERS);
- + if (nxt_slow_path(!njs_is_numeric(val2))) {
- + ret = njs_value_to_numeric(vm, &numeric2, val2);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- +
- + val2 = &numeric2;
- + }
- +
- + num1 = njs_number_to_integer(njs_number(val1));
- + num2 = njs_number_to_integer(njs_number(val2));
- + njs_set_number(&vm->retval, num1 & num2);
- +
- + return sizeof(njs_vmcode_3addr_t);
- }
- njs_ret_t
- njs_vmcode_bitwise_xor(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
- {
- - int32_t num1, num2;
- -
- - if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) {
- -
- - num1 = njs_number_to_integer(njs_number(val1));
- - num2 = njs_number_to_integer(njs_number(val2));
- - njs_set_number(&vm->retval, num1 ^ num2);
- -
- - return sizeof(njs_vmcode_3addr_t);
- + int32_t num1, num2;
- + njs_ret_t ret;
- + njs_value_t numeric1, numeric2;
- +
- + if (nxt_slow_path(!njs_is_numeric(val1))) {
- + ret = njs_value_to_numeric(vm, &numeric1, val1);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- +
- + val1 = &numeric1;
- }
- - return njs_trap(vm, NJS_TRAP_NUMBERS);
- + if (nxt_slow_path(!njs_is_numeric(val2))) {
- + ret = njs_value_to_numeric(vm, &numeric2, val2);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- +
- + val2 = &numeric2;
- + }
- +
- + num1 = njs_number_to_integer(njs_number(val1));
- + num2 = njs_number_to_integer(njs_number(val2));
- + njs_set_number(&vm->retval, num1 ^ num2);
- +
- + return sizeof(njs_vmcode_3addr_t);
- }
- njs_ret_t
- njs_vmcode_bitwise_or(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
- {
- - int32_t num1, num2;
- -
- - if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) {
- -
- - num1 = njs_number_to_uint32(njs_number(val1));
- - num2 = njs_number_to_uint32(njs_number(val2));
- - njs_set_number(&vm->retval, num1 | num2);
- -
- - return sizeof(njs_vmcode_3addr_t);
- + int32_t num1, num2;
- + njs_ret_t ret;
- + njs_value_t numeric1, numeric2;
- +
- + if (nxt_slow_path(!njs_is_numeric(val1))) {
- + ret = njs_value_to_numeric(vm, &numeric1, val1);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- +
- + val1 = &numeric1;
- }
- - return njs_trap(vm, NJS_TRAP_NUMBERS);
- + if (nxt_slow_path(!njs_is_numeric(val2))) {
- + ret = njs_value_to_numeric(vm, &numeric2, val2);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- +
- + val2 = &numeric2;
- + }
- +
- + num1 = njs_number_to_integer(njs_number(val1));
- + num2 = njs_number_to_integer(njs_number(val2));
- + njs_set_number(&vm->retval, num1 | num2);
- +
- + return sizeof(njs_vmcode_3addr_t);
- }
- njs_ret_t
- njs_vmcode_equal(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
- {
- - njs_ret_t ret;
- - const njs_value_t *retval;
- + njs_ret_t ret;
- ret = njs_values_equal(vm, val1, val2);
- if (nxt_fast_path(ret >= 0)) {
- - retval = (ret != 0) ? &njs_value_true : &njs_value_false;
- - vm->retval = *retval;
- + njs_set_boolean(&vm->retval, ret != 0);
- return sizeof(njs_vmcode_3addr_t);
- }
- @@ -1466,10 +1660,14 @@ njs_vmcode_not_equal(njs_vm_t *vm, njs_v
- static njs_ret_t
- -njs_values_equal(njs_vm_t *vm, const njs_value_t *val1, const njs_value_t *val2)
- +njs_values_equal(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
- {
- - nxt_bool_t nv1, nv2;
- - const njs_value_t *hv, *lv;
- + njs_ret_t ret;
- + nxt_bool_t nv1, nv2;
- + njs_value_t primitive;
- + njs_value_t *hv, *lv;
- +
- +again:
- nv1 = njs_is_null_or_undefined(val1);
- nv2 = njs_is_null_or_undefined(val2);
- @@ -1515,22 +1713,29 @@ njs_values_equal(njs_vm_t *vm, const njs
- }
- /* "hv" is an object and "lv" is either a string or a numeric. */
- - return njs_trap(vm, NJS_TRAP_COMPARISON);
- +
- + ret = njs_value_to_primitive(vm, &primitive, hv, 0);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- +
- + val1 = &primitive;
- + val2 = lv;
- +
- + goto again;
- }
- njs_ret_t
- njs_vmcode_less(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
- {
- - njs_ret_t ret;
- - const njs_value_t *retval;
- + njs_ret_t ret;
- ret = njs_values_compare(vm, val1, val2);
- if (nxt_fast_path(ret >= -1)) {
- - retval = (ret > 0) ? &njs_value_true : &njs_value_false;
- - vm->retval = *retval;
- + njs_set_boolean(&vm->retval, ret > 0);
- return sizeof(njs_vmcode_3addr_t);
- }
- @@ -1556,15 +1761,13 @@ njs_vmcode_less_or_equal(njs_vm_t *vm, n
- njs_ret_t
- njs_vmcode_greater_or_equal(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
- {
- - njs_ret_t ret;
- - const njs_value_t *retval;
- + njs_ret_t ret;
- ret = njs_values_compare(vm, val1, val2);
- if (nxt_fast_path(ret >= -1)) {
- - retval = (ret == 0) ? &njs_value_true : &njs_value_false;
- - vm->retval = *retval;
- + njs_set_boolean(&vm->retval, ret == 0);
- return sizeof(njs_vmcode_3addr_t);
- }
- @@ -1578,62 +1781,66 @@ njs_vmcode_greater_or_equal(njs_vm_t *vm
- * njs_values_compare() returns
- * 1 if val1 is less than val2,
- * 0 if val1 is greater than or equal to val2,
- - * -1 if the values are not comparable,
- - * or negative trap number if convertion to primitive is required.
- + * -1 if the values are not comparable.
- */
- static njs_ret_t
- -njs_values_compare(njs_vm_t *vm, const njs_value_t *val1,
- - const njs_value_t *val2)
- +njs_values_compare(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
- {
- - double num1, num2;
- -
- - if (nxt_fast_path(njs_is_primitive(val1) && njs_is_primitive(val2))) {
- -
- - if (nxt_fast_path(njs_is_numeric(val1))) {
- - num1 = njs_number(val1);
- -
- - if (nxt_fast_path(njs_is_numeric(val2))) {
- - num2 = njs_number(val2);
- -
- - } else {
- - num2 = njs_string_to_number(val2, 0);
- - }
- -
- - } else if (njs_is_numeric(val2)) {
- - num1 = njs_string_to_number(val1, 0);
- + double num1, num2;
- + njs_ret_t ret;
- + njs_value_t primitive1, primitive2;
- +
- + if (nxt_slow_path(!njs_is_primitive(val1))) {
- + ret = njs_value_to_primitive(vm, &primitive1, val1, 0);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- +
- + val1 = &primitive1;
- + }
- +
- + if (nxt_slow_path(!njs_is_primitive(val2))) {
- + ret = njs_value_to_primitive(vm, &primitive2, val2, 0);
- + if (ret != NXT_OK) {
- + return ret;
- + }
- +
- + val2 = &primitive2;
- + }
- +
- + if (nxt_fast_path(njs_is_numeric(val1))) {
- + num1 = njs_number(val1);
- +
- + if (nxt_fast_path(njs_is_numeric(val2))) {
- num2 = njs_number(val2);
- } else {
- - return (njs_string_cmp(val1, val2) < 0) ? 1 : 0;
- + num2 = njs_string_to_number(val2, 0);
- }
- - /* NaN and void values are not comparable with anything. */
- - if (isnan(num1) || isnan(num2)) {
- - return -1;
- - }
- -
- - /* Infinities are handled correctly by comparision. */
- - return (num1 < num2);
- + } else if (njs_is_numeric(val2)) {
- + num1 = njs_string_to_number(val1, 0);
- + num2 = njs_number(val2);
- +
- + } else {
- + return (njs_string_cmp(val1, val2) < 0) ? 1 : 0;
- }
- - return njs_trap(vm, NJS_TRAP_COMPARISON);
- + /* NaN and void values are not comparable with anything. */
- + if (isnan(num1) || isnan(num2)) {
- + return -1;
- + }
- +
- + /* Infinities are handled correctly by comparision. */
- + return (num1 < num2);
- }
- njs_ret_t
- njs_vmcode_strict_equal(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
- {
- - const njs_value_t *retval;
- -
- - if (njs_values_strict_equal(val1, val2)) {
- - retval = &njs_value_true;
- -
- - } else {
- - retval = &njs_value_false;
- - }
- -
- - vm->retval = *retval;
- + njs_set_boolean(&vm->retval, njs_values_strict_equal(val1, val2));
- return sizeof(njs_vmcode_3addr_t);
- }
- @@ -1642,16 +1849,7 @@ njs_vmcode_strict_equal(njs_vm_t *vm, nj
- njs_ret_t
- njs_vmcode_strict_not_equal(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
- {
- - const njs_value_t *retval;
- -
- - if (njs_values_strict_equal(val1, val2)) {
- - retval = &njs_value_false;
- -
- - } else {
- - retval = &njs_value_true;
- - }
- -
- - vm->retval = *retval;
- + njs_set_boolean(&vm->retval, !njs_values_strict_equal(val1, val2));
- return sizeof(njs_vmcode_3addr_t);
- }
- @@ -1863,7 +2061,6 @@ njs_vmcode_method_frame(njs_vm_t *vm, nj
- case NXT_DECLINED:
- break;
- - case NJS_TRAP:
- case NXT_ERROR:
- default:
- @@ -1871,6 +2068,11 @@ njs_vmcode_method_frame(njs_vm_t *vm, nj
- }
- if (value == NULL || !njs_is_function(value)) {
- + ret = njs_value_to_string(vm, name, name);
- + if (nxt_slow_path(ret != NXT_OK)) {
- + return NXT_ERROR;
- + }
- +
- njs_string_get(name, &string);
- njs_type_error(vm, "(intermediate value)[\"%V\"] is not a function",
- &string);
- @@ -1935,6 +2137,7 @@ njs_vmcode_function_call(njs_vm_t *vm, n
- njs_ret_t
- njs_vmcode_return(njs_vm_t *vm, njs_value_t *invld, njs_value_t *retval)
- {
- + uint8_t call;
- njs_value_t *value;
- njs_frame_t *frame;
- njs_native_frame_t *previous;
- @@ -1967,9 +2170,11 @@ njs_vmcode_return(njs_vm_t *vm, njs_valu
- vm->current = frame->return_address;
- + call = frame->native.call;
- +
- njs_function_frame_free(vm, &frame->native);
- - return 0;
- + return call ? NJS_STOP : 0;
- }
- @@ -2037,6 +2242,14 @@ const njs_vmcode_generic_t njs_continua
- };
- +const njs_vmcode_generic_t njs_stop[] = {
- + { .code = { .operation = njs_vmcode_stop,
- + .operands = NJS_VMCODE_1OPERAND,
- + .retval = NJS_VMCODE_NO_RETVAL },
- + .operand1 = NJS_INDEX_GLOBAL_RETVAL },
- +};
- +
- +
- static njs_ret_t
- njs_vmcode_continuation(njs_vm_t *vm, njs_value_t *invld1, njs_value_t *invld2)
- {
- @@ -2289,384 +2502,6 @@ njs_vmcode_reference_error(njs_vm_t *vm,
- }
- -static const njs_vmcode_1addr_t njs_trap_number[] = {
- - { .code = { .operation = njs_vmcode_number_primitive,
- - .operands = NJS_VMCODE_1OPERAND,
- - .retval = NJS_VMCODE_NO_RETVAL },
- - .index = 0 },
- - { .code = { .operation = njs_vmcode_restart,
- - .operands = NJS_VMCODE_NO_OPERAND,
- - .retval = NJS_VMCODE_NO_RETVAL } },
- -};
- -
- -
- -static const njs_vmcode_1addr_t njs_trap_numbers[] = {
- - { .code = { .operation = njs_vmcode_number_primitive,
- - .operands = NJS_VMCODE_1OPERAND,
- - .retval = NJS_VMCODE_NO_RETVAL },
- - .index = 0 },
- - { .code = { .operation = njs_vmcode_number_primitive,
- - .operands = NJS_VMCODE_1OPERAND,
- - .retval = NJS_VMCODE_NO_RETVAL },
- - .index = 1 },
- - { .code = { .operation = njs_vmcode_restart,
- - .operands = NJS_VMCODE_NO_OPERAND,
- - .retval = NJS_VMCODE_NO_RETVAL } },
- -};
- -
- -
- -static const njs_vmcode_1addr_t njs_trap_addition[] = {
- - { .code = { .operation = njs_vmcode_addition_primitive,
- - .operands = NJS_VMCODE_1OPERAND,
- - .retval = NJS_VMCODE_NO_RETVAL },
- - .index = 0 },
- - { .code = { .operation = njs_vmcode_addition_primitive,
- - .operands = NJS_VMCODE_1OPERAND,
- - .retval = NJS_VMCODE_NO_RETVAL },
- - .index = 1 },
- - { .code = { .operation = njs_vmcode_restart,
- - .operands = NJS_VMCODE_NO_OPERAND,
- - .retval = NJS_VMCODE_NO_RETVAL } },
- -};
- -
- -
- -static const njs_vmcode_1addr_t njs_trap_comparison[] = {
- - { .code = { .operation = njs_vmcode_comparison_primitive,
- - .operands = NJS_VMCODE_1OPERAND,
- - .retval = NJS_VMCODE_NO_RETVAL },
- - .index = 0 },
- - { .code = { .operation = njs_vmcode_comparison_primitive,
- - .operands = NJS_VMCODE_1OPERAND,
- - .retval = NJS_VMCODE_NO_RETVAL },
- - .index = 1 },
- - { .code = { .operation = njs_vmcode_restart,
- - .operands = NJS_VMCODE_NO_OPERAND,
- - .retval = NJS_VMCODE_NO_RETVAL } },
- -};
- -
- -
- -static const njs_vmcode_1addr_t njs_trap_property[] = {
- - { .code = { .operation = njs_vmcode_string_primitive,
- - .operands = NJS_VMCODE_1OPERAND,
- - .retval = NJS_VMCODE_NO_RETVAL },
- - .index = 1 },
- - { .code = { .operation = njs_vmcode_restart,
- - .operands = NJS_VMCODE_NO_OPERAND,
- - .retval = NJS_VMCODE_NO_RETVAL } },
- -};
- -
- -
- -static const njs_vmcode_1addr_t njs_trap_number_argument = {
- - .code = { .operation = njs_vmcode_number_argument,
- - .operands = NJS_VMCODE_NO_OPERAND,
- - .retval = NJS_VMCODE_NO_RETVAL }
- -};
- -
- -
- -static const njs_vmcode_1addr_t njs_trap_string_argument = {
- - .code = { .operation = njs_vmcode_string_argument,
- - .operands = NJS_VMCODE_NO_OPERAND,
- - .retval = NJS_VMCODE_NO_RETVAL }
- -};
- -
- -
- -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_PRIMITIVE_ARG */ { .code = &njs_trap_primitive_argument },
- -};
- -
- -
- -static void
- -njs_vm_trap(njs_vm_t *vm, njs_trap_t trap, njs_value_t *value1,
- - njs_value_t *value2)
- -{
- - njs_native_frame_t *frame;
- -
- - frame = vm->top_frame;
- -
- - /*
- - * The trap_scratch value is for results of "valueOf" and "toString"
- - * methods. The trap_values[] are original operand values which will
- - * be replaced with primitive values returned by "valueOf" or "toString"
- - * methods. The scratch value is stored separately to preserve the
- - * original operand values for the second method call if the first
- - * method call will return non-primitive value.
- - */
- - njs_set_invalid(&frame->trap_scratch);
- - frame->trap_values[1] = *value2;
- - frame->trap_reference = njs_vm_traps[trap].reference;
- -
- - if (njs_vm_traps[trap].reference) {
- - frame->trap_values[0].data.u.value = value1;
- -
- - } else {
- - frame->trap_values[0] = *value1;
- - }
- -
- - frame->trap_restart = vm->current;
- - vm->current = (u_char *) njs_vm_traps[trap].code;
- -}
- -
- -
- -static void
- -njs_vm_trap_argument(njs_vm_t *vm, njs_trap_t trap)
- -{
- - njs_value_t *value;
- - njs_native_frame_t *frame;
- -
- - frame = vm->top_frame;
- - value = frame->trap_scratch.data.u.value;
- - njs_set_invalid(&frame->trap_scratch);
- -
- - frame->trap_values[1].data.u.value = value;
- - frame->trap_values[0] = *value;
- -
- - frame->trap_restart = vm->current;
- - vm->current = (u_char *) njs_vm_traps[trap].code;
- -}
- -
- -
- -static njs_ret_t
- -njs_vmcode_number_primitive(njs_vm_t *vm, njs_value_t *invld, njs_value_t *narg)
- -{
- - double num;
- - njs_ret_t ret;
- - njs_value_t *value;
- -
- - value = &vm->top_frame->trap_values[(uintptr_t) narg];
- -
- - ret = njs_value_to_primitive(vm, value, 0);
- -
- - if (nxt_fast_path(ret > 0)) {
- -
- - if (!njs_is_numeric(value)) {
- - num = NAN;
- -
- - if (njs_is_string(value)) {
- - num = njs_string_to_number(value, 0);
- - }
- -
- - njs_set_number(value, num);
- - }
- -
- - ret = sizeof(njs_vmcode_1addr_t);
- - }
- -
- - return ret;
- -}
- -
- -
- -static njs_ret_t
- -njs_vmcode_string_primitive(njs_vm_t *vm, njs_value_t *invld, njs_value_t *narg)
- -{
- - njs_ret_t ret;
- - njs_value_t *value;
- -
- - value = &vm->top_frame->trap_values[(uintptr_t) narg];
- -
- - ret = njs_value_to_primitive(vm, value, 1);
- -
- - if (nxt_fast_path(ret > 0)) {
- - ret = njs_primitive_value_to_string(vm, value, value);
- -
- - if (nxt_fast_path(ret == NXT_OK)) {
- - return sizeof(njs_vmcode_1addr_t);
- - }
- - }
- -
- - return ret;
- -}
- -
- -
- -static njs_ret_t
- -njs_vmcode_addition_primitive(njs_vm_t *vm, njs_value_t *invld,
- - njs_value_t *narg)
- -{
- - njs_ret_t ret;
- - nxt_uint_t hint;
- - njs_value_t *value;
- -
- - value = &vm->top_frame->trap_values[(uintptr_t) narg];
- -
- - /*
- - * ECMAScript 5.1:
- - * Date should return String, other types sould return Number.
- - */
- - hint = njs_is_date(value);
- -
- - ret = njs_value_to_primitive(vm, value, hint);
- -
- - if (nxt_fast_path(ret > 0)) {
- - return sizeof(njs_vmcode_1addr_t);
- - }
- -
- - return ret;
- -}
- -
- -
- -static njs_ret_t
- -njs_vmcode_comparison_primitive(njs_vm_t *vm, njs_value_t *invld,
- - njs_value_t *narg)
- -{
- - njs_ret_t ret;
- - njs_value_t *value;
- -
- - value = &vm->top_frame->trap_values[(uintptr_t) narg];
- -
- - ret = njs_value_to_primitive(vm, value, 0);
- -
- - if (nxt_fast_path(ret > 0)) {
- - return sizeof(njs_vmcode_1addr_t);
- - }
- -
- - return ret;
- -}
- -
- -
- -static njs_ret_t
- -njs_vmcode_number_argument(njs_vm_t *vm, njs_value_t *invld1,
- - njs_value_t *inlvd2)
- -{
- - double num;
- - njs_ret_t ret;
- - njs_value_t *value;
- -
- - value = &vm->top_frame->trap_values[0];
- -
- - ret = njs_value_to_primitive(vm, value, 0);
- -
- - if (nxt_fast_path(ret > 0)) {
- -
- - if (!njs_is_numeric(value)) {
- - num = NAN;
- -
- - if (njs_is_string(value)) {
- - num = njs_string_to_number(value, 0);
- - }
- -
- - njs_set_number(value, num);
- - }
- -
- - *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_string_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_value_to_primitive(vm, value, 1);
- -
- - if (nxt_fast_path(ret > 0)) {
- - ret = njs_primitive_value_to_string(vm, value, value);
- -
- - if (nxt_fast_path(ret == NXT_OK)) {
- - *vm->top_frame->trap_values[1].data.u.value = *value;
- -
- - vm->current = vm->top_frame->trap_restart;
- - vm->top_frame->trap_restart = NULL;
- - }
- - }
- -
- - return ret;
- -}
- -
- -
- -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_value_to_primitive(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;
- - njs_ret_t ret;
- - njs_value_t *retval, *value1;
- - njs_native_frame_t *frame;
- - njs_vmcode_generic_t *vmcode;
- -
- - frame = vm->top_frame;
- - restart = frame->trap_restart;
- - frame->trap_restart = NULL;
- - vm->current = restart;
- - vmcode = (njs_vmcode_generic_t *) restart;
- -
- - value1 = &frame->trap_values[0];
- -
- - if (frame->trap_reference) {
- - value1 = value1->data.u.value;
- - }
- -
- - ret = vmcode->code.operation(vm, value1, &frame->trap_values[1]);
- -
- - if (nxt_slow_path(ret == NJS_ERROR)) {
- - return ret;
- - }
- -
- - if (nxt_slow_path(ret == NJS_TRAP)) {
- - /* Trap handlers are not reentrant. */
- - njs_internal_error(vm, "trap inside restart instruction");
- - return NXT_ERROR;
- - }
- -
- - if (vmcode->code.retval) {
- - retval = njs_vmcode_operand(vm, vmcode->operand1);
- - njs_release(vm, retval);
- - *retval = vm->retval;
- - }
- -
- - return ret;
- -}
- -
- -
- njs_ret_t
- njs_vm_value_to_string(njs_vm_t *vm, nxt_str_t *dst, const njs_value_t *src)
- {
- @@ -2689,14 +2524,7 @@ njs_vm_value_to_string(njs_vm_t *vm, nxt
- value = *src;
- - if (nxt_slow_path(!njs_is_primitive(&value))) {
- - ret = njs_object_value_to_string(vm, &value);
- - if (nxt_slow_path(ret != NXT_OK)) {
- - return ret;
- - }
- - }
- -
- - ret = njs_primitive_value_to_string(vm, &value, &value);
- + ret = njs_value_to_string(vm, &value, &value);
- if (nxt_fast_path(ret == NXT_OK)) {
- size = value.short_string.size;
- @@ -2723,73 +2551,6 @@ njs_vm_value_to_string(njs_vm_t *vm, nxt
- }
- -static njs_ret_t
- -njs_object_value_to_string(njs_vm_t *vm, njs_value_t *value)
- -{
- - u_char *current;
- - njs_ret_t ret;
- - njs_native_frame_t *previous;
- -
- - static const njs_vmcode_1addr_t value_to_string[] = {
- - { .code = { .operation = njs_vmcode_value_to_string,
- - .operands = NJS_VMCODE_NO_OPERAND,
- - .retval = NJS_VMCODE_NO_RETVAL } },
- - };
- -
- - /*
- - * Execute the single njs_vmcode_value_to_string() instruction.
- - * The trap_scratch value is for results of "toString" or "valueOf"
- - * methods. The trap_values[0] is an original object value which will
- - * be replaced with primitive value returned by "toString" or "valueOf"
- - * methods. The scratch value is stored separately to preserve the
- - * original object value for the second "valueOf" method call if the
- - * first "toString" method call will return non-primitive value.
- - */
- -
- - current = vm->current;
- - vm->current = (u_char *) value_to_string;
- -
- - njs_set_invalid(&vm->top_frame->trap_scratch);
- - vm->top_frame->trap_values[0] = *value;
- -
- - /*
- - * Prevent njs_vmcode_interpreter() to unwind the current frame if
- - * an exception happens. It preserves the current frame state if
- - * njs_vm_value_string() is called from within njs_vm_run().
- - */
- - previous = vm->top_frame->previous;
- - vm->top_frame->previous = NULL;
- -
- - ret = njs_vmcode_interpreter(vm);
- -
- - if (ret == NJS_STOP) {
- - ret = NXT_OK;
- - *value = vm->top_frame->trap_values[0];
- - }
- -
- - vm->current = current;
- - vm->top_frame->previous = previous;
- -
- - return ret;
- -}
- -
- -
- -static njs_ret_t
- -njs_vmcode_value_to_string(njs_vm_t *vm, njs_value_t *invld1,
- - njs_value_t *invld2)
- -{
- - njs_ret_t ret;
- -
- - ret = njs_value_to_primitive(vm, &vm->top_frame->trap_values[0], 1);
- -
- - if (nxt_fast_path(ret > 0)) {
- - return NJS_STOP;
- - }
- -
- - return ret;
- -}
- -
- -
- nxt_int_t
- njs_vm_value_string_copy(njs_vm_t *vm, nxt_str_t *retval,
- const njs_value_t *value, uintptr_t *next)
- diff --git a/njs/njs_vm.h b/njs/njs_vm.h
- --- a/njs/njs_vm.h
- +++ b/njs/njs_vm.h
- @@ -19,33 +19,14 @@
- * -3: not used;
- * -4 (NJS_STOP/NXT_DONE): njs_vmcode_stop() has stopped execution,
- * execution has completed successfully;
- - * -5 (NJS_TRAP) trap to convert objects to primitive values;
- - * -6 .. -11: not used.
- + * -5 .. -11: not used.
- */
- #define NJS_STOP NXT_DONE
- -#define NJS_TRAP (-5)
- /* The last return value which preempts execution. */
- #define NJS_PREEMPT (-11)
- -/* Traps events. */
- -typedef enum {
- - NJS_TRAP_NUMBER = 0,
- - NJS_TRAP_NUMBERS,
- - NJS_TRAP_ADDITION,
- - NJS_TRAP_COMPARISON,
- - NJS_TRAP_INCDEC,
- - NJS_TRAP_PROPERTY,
- - NJS_TRAP_NUMBER_ARG,
- - NJS_TRAP_STRING_ARG,
- - NJS_TRAP_PRIMITIVE_ARG,
- -} njs_trap_t;
- -
- -
- -#define njs_trap(vm, code) \
- - vm->trap = code, NJS_TRAP;
- -
- /*
- * A user-defined function is prepared to run. This code is never
- @@ -532,12 +513,6 @@ enum njs_function_e {
- typedef struct {
- - const njs_vmcode_1addr_t *code;
- - nxt_bool_t reference;
- -} njs_vm_trap_t;
- -
- -
- -typedef struct {
- uint32_t line;
- nxt_str_t file;
- nxt_str_t name;
- @@ -549,6 +524,8 @@ struct njs_vm_s {
- /* njs_vm_t must be aligned to njs_value_t due to scratch value. */
- njs_value_t retval;
- + nxt_uint_t count;
- +
- nxt_array_t *paths;
- u_char *current;
- @@ -613,8 +590,6 @@ struct njs_vm_s {
- nxt_array_t *debug;
- nxt_array_t *backtrace;
- - njs_trap_t trap:8;
- -
- /*
- * njs_property_query() uses it to store reference to a temporary
- * PROPERTY_HANDLERs for NJS_EXTERNAL values in NJS_PROPERTY_QUERY_SET
- @@ -659,6 +634,7 @@ struct njs_vm_shared_s {
- nxt_int_t njs_vmcode_interpreter(njs_vm_t *vm);
- +nxt_int_t njs_vmcode_run(njs_vm_t *vm);
- njs_ret_t njs_vmcode_object(njs_vm_t *vm, njs_value_t *inlvd1,
- njs_value_t *inlvd2);
- @@ -821,6 +797,7 @@ extern const nxt_mem_proto_t njs_arr
- extern const nxt_lvlhsh_proto_t njs_object_hash_proto;
- extern const njs_vmcode_generic_t njs_continuation_nexus[];
- +extern const njs_vmcode_generic_t njs_stop[];
- #endif /* _NJS_VM_H_INCLUDED_ */
- diff --git a/njs/test/njs_interactive_test.c b/njs/test/njs_interactive_test.c
- --- a/njs/test/njs_interactive_test.c
- +++ b/njs/test/njs_interactive_test.c
- @@ -230,8 +230,7 @@ static njs_interactive_test_t njs_test[
- { nxt_string("var o = { toString: function() { return [1] } }" ENTER
- "o" ENTER),
- - nxt_string("TypeError: Cannot convert object to primitive value\n"
- - " at main (native)\n") },
- + nxt_string("TypeError: Cannot convert object to primitive value") },
- /* line numbers */
- diff --git a/njs/test/njs_unit_test.c b/njs/test/njs_unit_test.c
- --- a/njs/test/njs_unit_test.c
- +++ b/njs/test/njs_unit_test.c
- @@ -450,6 +450,49 @@ static njs_unit_test_t njs_test[] =
- "var b = { toString: function() { return a+'b' } }; '0'+b"),
- nxt_string("0ab") },
- + { nxt_string("({valueOf:()=>'4'}) / ({valueOf:()=>2})"),
- + nxt_string("2") },
- +
- + { nxt_string("({valueOf:()=>{throw 'x'}}) / ({valueOf:()=>{throw 'y'}});"
- + "var e; try { x/y } catch(ex) {e = ex}; ex"),
- + nxt_string("x") },
- +
- + { nxt_string("({valueOf:()=>2}) / ({valueOf:()=>{throw 'y'}});"
- + "var e; try { x/y } catch(ex) {e = ex}; ex"),
- + nxt_string("y") },
- +
- + { nxt_string("({valueOf:()=>'4'}) % ({valueOf:()=>3})"),
- + nxt_string("1") },
- +
- + { nxt_string("({valueOf:()=>9}) >>> ({valueOf:()=>2})"),
- + nxt_string("2") },
- +
- + { nxt_string("({valueOf:()=>0x1f}) & ({valueOf:()=>0xf})"),
- + nxt_string("15") },
- +
- + { nxt_string("({valueOf:()=>0x1f}) ^ ({valueOf:()=>0xf})"),
- + nxt_string("16") },
- +
- + { nxt_string("({valueOf:()=>0xf}) == ({valueOf:()=>0xf})"),
- + nxt_string("false") },
- +
- + { nxt_string("({valueOf:()=>0xf}) == 0xf"),
- + nxt_string("true") },
- +
- + { nxt_string("0xf == ({valueOf:()=>0xf})"),
- + nxt_string("true") },
- +
- + { nxt_string("({valueOf:()=>'0xf'}) == 0xf"),
- + nxt_string("true") },
- +
- + { nxt_string("0xf == ({valueOf:()=>'0xf'})"),
- + nxt_string("true") },
- +
- + { nxt_string("({valueOf:()=>0xf}) == '0xf'"),
- + nxt_string("true") },
- +
- + { nxt_string("'0xf' == ({valueOf:()=>0xf})"),
- + nxt_string("true") },
- /**/
- { nxt_string("1 + undefined"),
- @@ -1648,6 +1691,9 @@ static njs_unit_test_t njs_test[] =
- { nxt_string("new 0[isNaN]"),
- nxt_string("TypeError: (intermediate value)[\"[object Function]\"] is not a function") },
- + { nxt_string("new 0[undefined]"),
- + nxt_string("TypeError: (intermediate value)[\"undefined\"] is not a function") },
- +
- /**/
- { nxt_string("var a; a = 1 ? 2 : 3"),
- @@ -4766,6 +4812,9 @@ static njs_unit_test_t njs_test[] =
- { nxt_string("String.prototype.substring(1, 5)"),
- nxt_string("") },
- + { nxt_string("String.prototype.substr.call({toString:()=>{throw new Error('Oops')}})"),
- + nxt_string("Error: Oops") },
- +
- { nxt_string("String.prototype.slice(1, 5)"),
- nxt_string("") },
- @@ -6418,6 +6467,9 @@ static njs_unit_test_t njs_test[] =
- { nxt_string("(function(){ function f() {return f}; return f()})()"),
- nxt_string("[object Function]") },
- + { nxt_string("function f() {}; f.toString = ()=> 'F'; ({'F':1})[f]"),
- + nxt_string("1") },
- +
- { nxt_string("var a = ''; "
- "function f(list) {"
- " function add(v) {a+=v};"
- @@ -10324,6 +10376,9 @@ static njs_unit_test_t njs_test[] =
- { nxt_string("Date.UTC(2011, 5, 24, 6, 0)"),
- nxt_string("1308895200000") },
- + { nxt_string("Date.UTC({valueOf:()=>2011}, 5, 24, 6, 0)"),
- + nxt_string("1308895200000") },
- +
- { nxt_string("Date.parse()"),
- nxt_string("NaN") },
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement