SHARE
TWEET

Untitled

a guest Jul 21st, 2019 71 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. # HG changeset patch
  2. # User Dmitry Volyntsev <xeioex@nginx.com>
  3. # Date 1562352328 -10800
  4. #      Fri Jul 05 21:45:28 2019 +0300
  5. # Node ID 23ac9dad4973023117aaa36331645ebb415531e0
  6. # Parent  b946c107396835be316b192154feb9bb7efaa175
  7. Refactored working with non-primitive types.
  8.  
  9. Traps mechanism is remove.
  10.  
  11. diff --git a/njs/njs.c b/njs/njs.c
  12. --- a/njs/njs.c
  13. +++ b/njs/njs.c
  14. @@ -984,8 +984,6 @@ again:
  15.  
  16.          /* value evaluation threw an exception. */
  17.  
  18. -        vm->top_frame->trap_tries = 0;
  19. -
  20.          src = &vm->retval;
  21.          goto again;
  22.      }
  23. @@ -1006,6 +1004,10 @@ njs_vm_retval_string(njs_vm_t *vm, nxt_s
  24.          njs_vm_init(vm);
  25.      }
  26.  
  27. +    if (vm->current == NULL) {
  28. +        vm->current = (u_char *) njs_stop;
  29. +    }
  30. +
  31.      return njs_vm_value_string(vm, dst, &vm->retval);
  32.  }
  33.  
  34. @@ -1019,6 +1021,10 @@ njs_vm_retval_dump(njs_vm_t *vm, nxt_str
  35.          njs_vm_init(vm);
  36.      }
  37.  
  38. +    if (vm->current == NULL) {
  39. +        vm->current = (u_char *) njs_stop;
  40. +    }
  41. +
  42.      return njs_vm_value_dump(vm, dst, &vm->retval, 0, 1);
  43.  }
  44.  
  45. diff --git a/njs/njs_array.c b/njs/njs_array.c
  46. --- a/njs/njs_array.c
  47. +++ b/njs/njs_array.c
  48. @@ -528,10 +528,7 @@ njs_array_prototype_slice(njs_vm_t *vm,
  49.      ret = njs_value_property(vm, &args[0], &njs_string_length, &slice->length,
  50.                               0);
  51.  
  52. -    if (nxt_slow_path(ret == NXT_ERROR
  53. -                      || ret == NJS_TRAP
  54. -                      || ret == NJS_APPLIED))
  55. -    {
  56. +    if (nxt_slow_path(ret == NXT_ERROR || ret == NJS_APPLIED)) {
  57.          return ret;
  58.      }
  59.  
  60. @@ -544,13 +541,16 @@ njs_array_prototype_slice_continuation(n
  61.      nxt_uint_t nargs, njs_index_t unused)
  62.  {
  63.      int64_t            start, end, length;
  64. +    njs_ret_t          ret;
  65.      njs_array_slice_t  *slice;
  66.  
  67.      slice = njs_vm_continuation(vm);
  68.  
  69.      if (nxt_slow_path(!njs_is_primitive(&slice->length))) {
  70. -        njs_vm_trap_value(vm, &slice->length);
  71. -        return njs_trap(vm, NJS_TRAP_NUMBER_ARG);
  72. +        ret = njs_value_to_numeric(vm, &slice->length, &slice->length);
  73. +        if (ret != NXT_OK) {
  74. +            return ret;
  75. +        }
  76.      }
  77.  
  78.      start = njs_primitive_value_to_integer(njs_arg(args, nargs, 1));
  79. @@ -958,7 +958,7 @@ njs_array_prototype_reverse(njs_vm_t *vm
  80.  
  81.  static njs_ret_t
  82.  njs_array_prototype_to_string(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
  83. -    njs_index_t retval)
  84. +    njs_index_t unused)
  85.  {
  86.      njs_object_prop_t   *prop;
  87.      nxt_lvlhsh_query_t  lhq;
  88. @@ -970,12 +970,12 @@ njs_array_prototype_to_string(njs_vm_t *
  89.          prop = njs_object_property(vm, njs_object(&args[0]), &lhq);
  90.  
  91.          if (nxt_fast_path(prop != NULL && njs_is_function(&prop->value))) {
  92. -            return njs_function_replace(vm, njs_function(&prop->value),
  93. -                                        args, nargs, retval);
  94. +            return njs_function_call(vm, njs_function(&prop->value), args,
  95. +                                     nargs, (njs_index_t) &vm->retval);
  96.          }
  97.      }
  98.  
  99. -    return njs_object_prototype_to_string(vm, args, nargs, retval);
  100. +    return njs_object_prototype_to_string(vm, args, nargs, unused);
  101.  }
  102.  
  103.  
  104. @@ -1063,6 +1063,7 @@ njs_array_prototype_join_continuation(nj
  105.      u_char             *p;
  106.      size_t             size, length, mask;
  107.      uint32_t           max;
  108. +    njs_ret_t          ret;
  109.      nxt_uint_t         i, n;
  110.      njs_array_t        *array;
  111.      njs_value_t        *value, *values;
  112. @@ -1089,9 +1090,10 @@ njs_array_prototype_join_continuation(nj
  113.                  value = &values[n++];
  114.  
  115.                  if (!njs_is_string(value)) {
  116. -                    njs_vm_trap_value(vm, value);
  117. -
  118. -                    return njs_trap(vm, NJS_TRAP_STRING_ARG);
  119. +                    ret = njs_value_to_string(vm, value, value);
  120. +                    if (ret != NXT_OK) {
  121. +                        return ret;
  122. +                    }
  123.                  }
  124.              }
  125.  
  126. @@ -1438,10 +1440,7 @@ njs_array_prototype_fill(njs_vm_t *vm, n
  127.          ret = njs_value_property(vm, this, &njs_string_length, &fill->length,
  128.                                   0);
  129.  
  130. -        if (nxt_slow_path(ret == NXT_ERROR
  131. -                          || ret == NJS_TRAP
  132. -                          || ret == NJS_APPLIED))
  133. -        {
  134. +        if (nxt_slow_path(ret == NXT_ERROR || ret == NJS_APPLIED)) {
  135.              return ret;
  136.          }
  137.      }
  138. @@ -1455,6 +1454,7 @@ njs_array_prototype_fill_continuation(nj
  139.      nxt_uint_t nargs, njs_index_t unused)
  140.  {
  141.      nxt_int_t          i, start, end, length;
  142. +    njs_ret_t          ret;
  143.      njs_array_t        *array;
  144.      njs_object_t       *object;
  145.      njs_array_fill_t   *fill;
  146. @@ -1484,8 +1484,10 @@ njs_array_prototype_fill_continuation(nj
  147.      } else {
  148.  
  149.          if (nxt_slow_path(!njs_is_primitive(&fill->length))) {
  150. -            njs_vm_trap_value(vm, &fill->length);
  151. -            return njs_trap(vm, NJS_TRAP_NUMBER_ARG);
  152. +            ret = njs_value_to_numeric(vm, &fill->length, &fill->length);
  153. +            if (ret != NXT_OK) {
  154. +                return ret;
  155. +            }
  156.          }
  157.  
  158.          length = njs_primitive_value_to_length(&fill->length);
  159. @@ -2198,9 +2200,10 @@ njs_array_string_sort(njs_vm_t *vm, njs_
  160.  
  161.      for (i = 1; i < nargs; i++) {
  162.          if (!njs_is_string(&args[i])) {
  163. -            njs_vm_trap_value(vm, &args[i]);
  164. -
  165. -            return njs_trap(vm, NJS_TRAP_STRING_ARG);
  166. +            ret = njs_value_to_string(vm, &args[i], &args[i]);
  167. +            if (ret != NXT_OK) {
  168. +                return ret;
  169. +            }
  170.          }
  171.      }
  172.  
  173. diff --git a/njs/njs_date.c b/njs/njs_date.c
  174. --- a/njs/njs_date.c
  175. +++ b/njs/njs_date.c
  176. @@ -73,6 +73,7 @@ njs_date_constructor(njs_vm_t *vm, njs_v
  177.  {
  178.      double      num, time;
  179.      int64_t     values[8];
  180. +    njs_ret_t   ret;
  181.      nxt_uint_t  i, n;
  182.      njs_date_t  *date;
  183.      struct tm   tm;
  184. @@ -85,11 +86,14 @@ njs_date_constructor(njs_vm_t *vm, njs_v
  185.          } else if (nargs == 2) {
  186.              if (njs_is_object(&args[1])) {
  187.                  if (!njs_is_date(&args[1])) {
  188. -                    njs_vm_trap_value(vm, &args[1]);
  189. -
  190. -                    return njs_trap(vm, NJS_TRAP_PRIMITIVE_ARG);
  191. +                    ret = njs_value_to_primitive(vm, &args[1], &args[1], 0);
  192. +                    if (ret != NXT_OK) {
  193. +                        return ret;
  194. +                    }
  195.                  }
  196. -
  197. +            }
  198. +
  199. +            if (njs_is_date(&args[1])) {
  200.                  time = njs_date(&args[1])->time;
  201.  
  202.              } else if (njs_is_string(&args[1])) {
  203. @@ -108,9 +112,10 @@ njs_date_constructor(njs_vm_t *vm, njs_v
  204.  
  205.              for (i = 1; i < n; i++) {
  206.                  if (!njs_is_numeric(&args[i])) {
  207. -                    njs_vm_trap_value(vm, &args[i]);
  208. -
  209. -                    return njs_trap(vm, NJS_TRAP_NUMBER_ARG);
  210. +                    ret = njs_value_to_numeric(vm, &args[i], &args[i]);
  211. +                    if (ret != NXT_OK) {
  212. +                        return ret;
  213. +                    }
  214.                  }
  215.  
  216.                  num = njs_number(&args[i]);
  217. @@ -171,6 +176,7 @@ njs_date_utc(njs_vm_t *vm, njs_value_t *
  218.  {
  219.      double      num, time;
  220.      struct tm   tm;
  221. +    njs_ret_t   ret;
  222.      nxt_uint_t  i, n;
  223.      int32_t     values[8];
  224.  
  225. @@ -183,9 +189,10 @@ njs_date_utc(njs_vm_t *vm, njs_value_t *
  226.  
  227.          for (i = 1; i < n; i++) {
  228.              if (!njs_is_numeric(&args[i])) {
  229. -                njs_vm_trap_value(vm, &args[i]);
  230. -
  231. -                return njs_trap(vm, NJS_TRAP_NUMBER_ARG);
  232. +                ret = njs_value_to_numeric(vm, &args[i], &args[i]);
  233. +                if (ret != NXT_OK) {
  234. +                    return ret;
  235. +                }
  236.              }
  237.  
  238.              num = njs_number(&args[i]);
  239. @@ -1902,8 +1909,8 @@ njs_date_prototype_to_json(njs_vm_t *vm,
  240.          prop = njs_object_property(vm, njs_object(&args[0]), &lhq);
  241.  
  242.          if (nxt_fast_path(prop != NULL && njs_is_function(&prop->value))) {
  243. -            return njs_function_replace(vm, njs_function(&prop->value),
  244. -                                        args, nargs, retval);
  245. +            return njs_function_call(vm, njs_function(&prop->value), args,
  246. +                                     nargs, (njs_index_t) &vm->retval);
  247.          }
  248.      }
  249.  
  250. diff --git a/njs/njs_function.c b/njs/njs_function.c
  251. --- a/njs/njs_function.c
  252. +++ b/njs/njs_function.c
  253. @@ -473,6 +473,48 @@ njs_function_frame_alloc(njs_vm_t *vm, s
  254.  
  255.  
  256.  njs_ret_t
  257. +njs_function_call(njs_vm_t *vm, njs_function_t *function, njs_value_t *args,
  258. +    nxt_uint_t nargs, njs_index_t retval)
  259. +{
  260. +    u_char              *return_address;
  261. +    njs_ret_t           ret;
  262. +    njs_native_frame_t  *frame;
  263. +    njs_continuation_t  *cont;
  264. +
  265. +    ret = njs_function_frame(vm, function, &args[0], &args[1], nargs - 1, 0, 0);
  266. +    if (nxt_slow_path(ret != NXT_OK)) {
  267. +        return ret;
  268. +    }
  269. +
  270. +    frame = vm->top_frame;
  271. +    frame->call = 1;
  272. +
  273. +    return_address = vm->current;
  274. +
  275. +    if (function->native) {
  276. +
  277. +        if (function->continuation_size != 0) {
  278. +            cont = njs_vm_continuation(vm);
  279. +            cont->return_address = return_address;
  280. +        }
  281. +
  282. +        ret = njs_function_native_call(vm, function->u.native, frame->arguments,
  283. +                                       function->args_types, frame->nargs,
  284. +                                       (njs_index_t) retval, return_address);
  285. +
  286. +    } else {
  287. +        ret = njs_function_lambda_call(vm, retval, return_address);
  288. +
  289. +        if (nxt_fast_path(ret == NJS_APPLIED)) {
  290. +            ret = njs_vmcode_run(vm);
  291. +        }
  292. +    }
  293. +
  294. +    return ret;
  295. +}
  296. +
  297. +
  298. +njs_ret_t
  299.  njs_function_lambda_call(njs_vm_t *vm, njs_index_t retval,
  300.      u_char *return_address)
  301.  {
  302. @@ -636,8 +678,8 @@ static njs_ret_t
  303.  njs_normalize_args(njs_vm_t *vm, njs_value_t *args, uint8_t *args_types,
  304.      nxt_uint_t nargs)
  305.  {
  306. +    njs_ret_t   ret;
  307.      nxt_uint_t  n;
  308. -    njs_trap_t  trap;
  309.  
  310.      n = nxt_min(nargs, NJS_ARGS_TYPES_MAX);
  311.  
  312. @@ -655,43 +697,47 @@ njs_normalize_args(njs_vm_t *vm, njs_val
  313.  
  314.          case NJS_STRING_ARG:
  315.  
  316. -            if (njs_is_string(args)) {
  317. -                break;
  318. +            if (!njs_is_string(args)) {
  319. +                ret = njs_value_to_string(vm, args, args);
  320. +                if (ret != NXT_OK) {
  321. +                    return ret;
  322. +                }
  323.              }
  324.  
  325. -            trap = NJS_TRAP_STRING_ARG;
  326. -            goto trap;
  327. +            break;
  328.  
  329.          case NJS_NUMBER_ARG:
  330.  
  331. -            if (njs_is_numeric(args)) {
  332. -                break;
  333. +            if (!njs_is_numeric(args)) {
  334. +                ret = njs_value_to_numeric(vm, args, args);
  335. +                if (ret != NXT_OK) {
  336. +                    return ret;
  337. +                }
  338.              }
  339.  
  340. -            trap = NJS_TRAP_NUMBER_ARG;
  341. -            goto trap;
  342. +            break;
  343.  
  344.          case NJS_INTEGER_ARG:
  345.  
  346. -            if (njs_is_numeric(args)) {
  347. +            if (!njs_is_numeric(args)) {
  348. +                ret = njs_value_to_numeric(vm, args, args);
  349. +                if (ret != NXT_OK) {
  350. +                    return ret;
  351. +                }
  352. +            }
  353.  
  354. -                /* Numbers are truncated to fit in 32-bit integers. */
  355. +            /* Numbers are truncated to fit in 32-bit integers. */
  356.  
  357. -                if (isnan(njs_number(args))) {
  358. -                    njs_number(args) = 0;
  359. -
  360. -                } else if (njs_number(args) > 2147483647.0) {
  361. +            if (!isnan(njs_number(args))) {
  362. +                if (njs_number(args) > 2147483647.0) {
  363.                      njs_number(args) = 2147483647.0;
  364.  
  365.                  } else if (njs_number(args) < -2147483648.0) {
  366.                      njs_number(args) = -2147483648.0;
  367.                  }
  368. -
  369. -                break;
  370.              }
  371.  
  372. -            trap = NJS_TRAP_NUMBER_ARG;
  373. -            goto trap;
  374. +            break;
  375.  
  376.          case NJS_FUNCTION_ARG:
  377.  
  378. @@ -701,8 +747,10 @@ njs_normalize_args(njs_vm_t *vm, njs_val
  379.                  break;
  380.  
  381.              default:
  382. -                trap = NJS_TRAP_STRING_ARG;
  383. -                goto trap;
  384. +                ret = njs_value_to_string(vm, args, args);
  385. +                if (ret != NXT_OK) {
  386. +                    return ret;
  387. +                }
  388.              }
  389.  
  390.              break;
  391. @@ -716,8 +764,10 @@ njs_normalize_args(njs_vm_t *vm, njs_val
  392.                  break;
  393.  
  394.              default:
  395. -                trap = NJS_TRAP_STRING_ARG;
  396. -                goto trap;
  397. +                ret = njs_value_to_string(vm, args, args);
  398. +                if (ret != NXT_OK) {
  399. +                    return ret;
  400. +                }
  401.              }
  402.  
  403.              break;
  404. @@ -751,12 +801,6 @@ njs_normalize_args(njs_vm_t *vm, njs_val
  405.  
  406.      return NJS_OK;
  407.  
  408. -trap:
  409. -
  410. -    njs_vm_trap_value(vm, args);
  411. -
  412. -    return njs_trap(vm, trap);
  413. -
  414.  type_error:
  415.  
  416.      njs_type_error(vm, "cannot convert %s to %s", njs_type_string(args->type),
  417. diff --git a/njs/njs_function.h b/njs/njs_function.h
  418. --- a/njs/njs_function.h
  419. +++ b/njs/njs_function.h
  420. @@ -74,11 +74,6 @@ typedef struct {
  421.  #define NJS_CONTINUATION_SIZE      njs_continuation_size(njs_continuation_t)
  422.  
  423.  
  424. -#define njs_vm_trap_value(vm, val)                                            \
  425. -    (vm)->top_frame->trap_scratch.data.u.value = val
  426. -
  427. -
  428. -
  429.  typedef struct njs_exception_s     njs_exception_t;
  430.  
  431.  struct njs_exception_s {
  432. @@ -92,10 +87,6 @@ struct njs_exception_s {
  433.  
  434.  
  435.  struct njs_native_frame_s {
  436. -    njs_value_t                    trap_scratch;
  437. -    njs_value_t                    trap_values[2];
  438. -    u_char                         *trap_restart;
  439. -
  440.      u_char                         *free;
  441.  
  442.      njs_function_t                 *function;
  443. @@ -118,14 +109,7 @@ struct njs_native_frame_s {
  444.      /* Skip the Function.call() and Function.apply() methods frames. */
  445.      uint8_t                        skip;              /* 1 bit  */
  446.  
  447. -    /* A number of trap tries, it can be no more than three. */
  448. -    uint8_t                        trap_tries;        /* 2 bits */
  449. -
  450. -    /*
  451. -     * The first operand in trap is reference to original value,
  452. -     * it is used to increment or decrement this value.
  453. -     */
  454. -    uint8_t                        trap_reference;   /* 1 bit */
  455. +    uint8_t                        call; /* 1 bit */
  456.  };
  457.  
  458.  
  459. @@ -168,6 +152,8 @@ njs_ret_t njs_function_lambda_frame(njs_
  460.  njs_ret_t njs_function_activate(njs_vm_t *vm, njs_function_t *function,
  461.      const njs_value_t *this, const njs_value_t *args, nxt_uint_t nargs,
  462.      njs_index_t retval, size_t advance);
  463. +njs_ret_t njs_function_call(njs_vm_t *vm, njs_function_t *function,
  464. +    njs_value_t *args, nxt_uint_t nargs, njs_index_t retval);
  465.  njs_ret_t njs_function_lambda_call(njs_vm_t *vm, njs_index_t retval,
  466.      u_char *return_address);
  467.  njs_ret_t njs_function_native_call(njs_vm_t *vm, njs_function_native_t native,
  468. @@ -215,36 +201,6 @@ njs_function_apply(njs_vm_t *vm, njs_fun
  469.  }
  470.  
  471.  
  472. -/*
  473. - * Replaces the current function with a new one.
  474. - * Can only be used for continuation functions
  475. - * (data.u.function.continuation_size > 0).
  476. - */
  477. -nxt_inline njs_ret_t
  478. -njs_function_replace(njs_vm_t *vm, njs_function_t *function,
  479. -    const njs_value_t *args, nxt_uint_t nargs, njs_index_t retval)
  480. -{
  481. -    nxt_int_t  ret;
  482. -
  483. -    ret = njs_function_apply(vm, function, args, nargs, retval);
  484. -    if (nxt_slow_path(ret == NXT_ERROR)) {
  485. -        return ret;
  486. -    }
  487. -
  488. -    /*
  489. -     * 1) njs_function_apply() allocs a new function frame,
  490. -     *    in order to preserve the retval of a new function and ignore
  491. -     *    retval of the current function during stack unwinding
  492. -     *    skip flag is needed.
  493. -     * 2) it is also needed for correct callee arguments update in
  494. -     *    njs_function_native_call() see "Object((new Date(0)).toJSON())".
  495. -     */
  496. -    vm->top_frame->previous->skip = 1;
  497. -
  498. -    return NJS_APPLIED;
  499. -}
  500. -
  501. -
  502.  nxt_inline njs_native_frame_t *
  503.  njs_function_previous_frame(njs_native_frame_t *frame)
  504.  {
  505. diff --git a/njs/njs_math.c b/njs/njs_math.c
  506. --- a/njs/njs_math.c
  507. +++ b/njs/njs_math.c
  508. @@ -359,13 +359,15 @@ njs_object_math_hypot(njs_vm_t *vm, njs_
  509.      njs_index_t unused)
  510.  {
  511.      double      num;
  512. +    njs_ret_t   ret;
  513.      nxt_uint_t  i;
  514.  
  515.      for (i = 1; i < nargs; i++) {
  516.          if (!njs_is_numeric(&args[i])) {
  517. -            njs_vm_trap_value(vm, &args[i]);
  518. -
  519. -            return njs_trap(vm, NJS_TRAP_NUMBER_ARG);
  520. +            ret = njs_value_to_numeric(vm, &args[i], &args[i]);
  521. +            if (ret != NXT_OK) {
  522. +                return ret;
  523. +            }
  524.          }
  525.      }
  526.  
  527. @@ -498,6 +500,7 @@ njs_object_math_max(njs_vm_t *vm, njs_va
  528.      njs_index_t unused)
  529.  {
  530.      double      num;
  531. +    njs_ret_t   ret;
  532.      nxt_uint_t  i;
  533.  
  534.      if (nargs > 1) {
  535. @@ -507,9 +510,10 @@ njs_object_math_max(njs_vm_t *vm, njs_va
  536.                  goto done;
  537.  
  538.              } else if (!njs_is_numeric(&args[i])) {
  539. -                njs_vm_trap_value(vm, &args[i]);
  540. -
  541. -                return njs_trap(vm, NJS_TRAP_NUMBER_ARG);
  542. +                ret = njs_value_to_numeric(vm, &args[i], &args[i]);
  543. +                if (ret != NXT_OK) {
  544. +                    return ret;
  545. +                }
  546.              }
  547.          }
  548.  
  549. @@ -536,14 +540,16 @@ njs_object_math_min(njs_vm_t *vm, njs_va
  550.      njs_index_t unused)
  551.  {
  552.      double      num;
  553. +    njs_ret_t   ret;
  554.      nxt_uint_t  i;
  555.  
  556.      if (nargs > 1) {
  557.          for (i = 1; i < nargs; i++) {
  558.              if (!njs_is_numeric(&args[i])) {
  559. -                njs_vm_trap_value(vm, &args[i]);
  560. -
  561. -                return njs_trap(vm, NJS_TRAP_NUMBER_ARG);
  562. +                ret = njs_value_to_numeric(vm, &args[i], &args[i]);
  563. +                if (ret != NXT_OK) {
  564. +                    return ret;
  565. +                }
  566.              }
  567.          }
  568.  
  569. diff --git a/njs/njs_object.c b/njs/njs_object.c
  570. --- a/njs/njs_object.c
  571. +++ b/njs/njs_object.c
  572. @@ -2144,7 +2144,6 @@ njs_object_prototype_has_own_property(nj
  573.          vm->retval = njs_value_false;
  574.          return NXT_OK;
  575.  
  576. -    case NJS_TRAP:
  577.      case NXT_ERROR:
  578.      default:
  579.          return ret;
  580. @@ -2185,7 +2184,6 @@ njs_object_prototype_prop_is_enumerable(
  581.          retval = &njs_value_false;
  582.          break;
  583.  
  584. -    case NJS_TRAP:
  585.      case NXT_ERROR:
  586.      default:
  587.          return ret;
  588. diff --git a/njs/njs_object_property.c b/njs/njs_object_property.c
  589. --- a/njs/njs_object_property.c
  590. +++ b/njs/njs_object_property.c
  591. @@ -38,7 +38,6 @@ static njs_object_prop_t *njs_descriptor
  592.   *   NXT_DECLINED         property was not found in object,
  593.   *     if pq->lhq.value != NULL it contains retval of type
  594.   *     njs_object_prop_t * where prop->type is NJS_WHITEOUT
  595. - *   NJS_TRAP             the property trap must be called,
  596.   *   NXT_ERROR            exception has been thrown.
  597.   *
  598.   *   TODO:
  599. @@ -53,10 +52,16 @@ njs_property_query(njs_vm_t *vm, njs_pro
  600.      uint32_t        (*hash)(const void *, size_t);
  601.      njs_ret_t       ret;
  602.      njs_object_t    *obj;
  603. +    njs_value_t     prop;
  604.      njs_function_t  *function;
  605.  
  606.      if (nxt_slow_path(!njs_is_primitive(property))) {
  607. -        return njs_trap(vm, NJS_TRAP_PROPERTY);
  608. +        ret = njs_value_to_string(vm, &prop, (njs_value_t *) property);
  609. +        if (ret != NXT_OK) {
  610. +            return ret;
  611. +        }
  612. +
  613. +        property = &prop;
  614.      }
  615.  
  616.      hash = nxt_djb_hash;
  617. @@ -473,7 +478,6 @@ njs_external_property_delete(njs_vm_t *v
  618.   *      retval will contain the property's value
  619.   *
  620.   *   NXT_DECLINED         property was not found in object
  621. - *   NJS_TRAP             the property trap must be called
  622.   *   NJS_APPLIED          the property getter was applied
  623.   *   NXT_ERROR            exception has been thrown.
  624.   *      retval will contain undefined
  625. @@ -553,7 +557,6 @@ njs_value_property(njs_vm_t *vm, const n
  626.  
  627.          return NXT_DECLINED;
  628.  
  629. -    case NJS_TRAP:
  630.      case NXT_ERROR:
  631.      default:
  632.  
  633. @@ -566,7 +569,6 @@ njs_value_property(njs_vm_t *vm, const n
  634.  
  635.  /*
  636.   *   NXT_OK               property has been set successfully
  637. - *   NJS_TRAP             the property trap must be called
  638.   *   NJS_APPLIED          the property setter was applied
  639.   *   NXT_ERROR            exception has been thrown.
  640.   */
  641. @@ -669,7 +671,6 @@ njs_value_property_set(njs_vm_t *vm, njs
  642.  
  643.          break;
  644.  
  645. -    case NJS_TRAP:
  646.      case NXT_ERROR:
  647.      default:
  648.  
  649. @@ -1152,7 +1153,6 @@ njs_object_prop_descriptor(njs_vm_t *vm,
  650.          *dest = njs_value_undefined;
  651.          return NXT_OK;
  652.  
  653. -    case NJS_TRAP:
  654.      case NXT_ERROR:
  655.      default:
  656.          return ret;
  657. diff --git a/njs/njs_regexp.c b/njs/njs_regexp.c
  658. --- a/njs/njs_regexp.c
  659. +++ b/njs/njs_regexp.c
  660. @@ -112,17 +112,19 @@ njs_regexp_constructor(njs_vm_t *vm, njs
  661.      pattern = njs_arg(args, nargs, 1);
  662.  
  663.      if (!njs_is_regexp(pattern) && !njs_is_primitive(pattern)) {
  664. -        njs_vm_trap_value(vm, &args[1]);
  665. -
  666. -        return njs_trap(vm, NJS_TRAP_STRING_ARG);
  667. +        ret = njs_value_to_string(vm, &args[1], &args[1]);
  668. +        if (ret != NXT_OK) {
  669. +            return ret;
  670. +        }
  671.      }
  672.  
  673.      flags = njs_arg(args, nargs, 2);
  674.  
  675.      if (!njs_is_primitive(flags)) {
  676. -        njs_vm_trap_value(vm, &args[2]);
  677. -
  678. -        return njs_trap(vm, NJS_TRAP_STRING_ARG);
  679. +        ret = njs_value_to_string(vm, &args[2], &args[2]);
  680. +        if (ret != NXT_OK) {
  681. +            return ret;
  682. +        }
  683.      }
  684.  
  685.      re_flags = 0;
  686. diff --git a/njs/njs_string.c b/njs/njs_string.c
  687. --- a/njs/njs_string.c
  688. +++ b/njs/njs_string.c
  689. @@ -853,6 +853,7 @@ njs_string_prototype_concat(njs_vm_t *vm
  690.  {
  691.      u_char             *p, *start;
  692.      uint64_t           size, length, mask;
  693. +    njs_ret_t          ret;
  694.      nxt_uint_t         i;
  695.      njs_string_prop_t  string;
  696.  
  697. @@ -863,9 +864,10 @@ njs_string_prototype_concat(njs_vm_t *vm
  698.  
  699.      for (i = 0; i < nargs; i++) {
  700.          if (!njs_is_string(&args[i])) {
  701. -            njs_vm_trap_value(vm, &args[i]);
  702. -
  703. -            return njs_trap(vm, NJS_TRAP_STRING_ARG);
  704. +            ret = njs_value_to_string(vm, &args[i], &args[i]);
  705. +            if (ret != NXT_OK) {
  706. +                return ret;
  707. +            }
  708.          }
  709.      }
  710.  
  711. @@ -1222,16 +1224,12 @@ njs_string_prototype_char_at(njs_vm_t *v
  712.  
  713.      slice.string_length = njs_string_prop(&string, &args[0]);
  714.  
  715. -    start = 0;
  716. +    start = njs_primitive_value_to_integer(njs_arg(args, nargs, 1));
  717.      length = 1;
  718.  
  719. -    if (nargs > 1) {
  720. -        start = njs_number(&args[1]);
  721. -
  722. -        if (start < 0 || start >= (ssize_t) slice.string_length) {
  723. -            start = 0;
  724. -            length = 0;
  725. -        }
  726. +    if (start < 0 || start >= (ssize_t) slice.string_length) {
  727. +        start = 0;
  728. +        length = 0;
  729.      }
  730.  
  731.      slice.start = start;
  732. @@ -1448,6 +1446,7 @@ njs_string_bytes_from_array(njs_vm_t *vm
  733.  {
  734.      u_char       *p;
  735.      uint32_t     i, length;
  736. +    njs_ret_t    ret;
  737.      njs_array_t  *array;
  738.      njs_value_t  *octet;
  739.  
  740. @@ -1456,9 +1455,10 @@ njs_string_bytes_from_array(njs_vm_t *vm
  741.  
  742.      for (i = 0; i < length; i++) {
  743.          if (!njs_is_numeric(&array->start[i])) {
  744. -            njs_vm_trap_value(vm, &array->start[i]);
  745. -
  746. -            return njs_trap(vm, NJS_TRAP_NUMBER_ARG);
  747. +            ret = njs_value_to_numeric(vm, &array->start[i], &array->start[i]);
  748. +            if (ret != NXT_OK) {
  749. +                return ret;
  750. +            }
  751.          }
  752.      }
  753.  
  754. @@ -1684,13 +1684,15 @@ njs_string_from_char_code(njs_vm_t *vm,
  755.      double      num;
  756.      size_t      size;
  757.      int32_t     code;
  758. +    njs_ret_t   ret;
  759.      nxt_uint_t  i;
  760.  
  761.      for (i = 1; i < nargs; i++) {
  762.          if (!njs_is_numeric(&args[i])) {
  763. -            njs_vm_trap_value(vm, &args[i]);
  764. -
  765. -            return njs_trap(vm, NJS_TRAP_NUMBER_ARG);
  766. +            ret = njs_value_to_numeric(vm, &args[i], &args[i]);
  767. +            if (ret != NXT_OK) {
  768. +                return ret;
  769. +            }
  770.          }
  771.      }
  772.  
  773. @@ -2397,20 +2399,16 @@ njs_string_prototype_repeat(njs_vm_t *vm
  774.      uint32_t           size, length;
  775.      njs_string_prop_t  string;
  776.  
  777. -    n = 0;
  778. +    n = njs_primitive_value_to_integer(njs_arg(args, nargs, 1));
  779.  
  780.      (void) njs_string_prop(&string, &args[0]);
  781.  
  782. -    if (nargs > 1) {
  783. -        max = (string.size > 1) ? NJS_STRING_MAX_LENGTH / string.size
  784. -                                : NJS_STRING_MAX_LENGTH;
  785. -
  786. -        n = njs_number(&args[1]);
  787. -
  788. -        if (nxt_slow_path(n < 0 || n >= max)) {
  789. -            njs_range_error(vm, NULL);
  790. -            return NXT_ERROR;
  791. -        }
  792. +    max = (string.size > 1) ? NJS_STRING_MAX_LENGTH / string.size
  793. +                            : NJS_STRING_MAX_LENGTH;
  794. +
  795. +    if (nxt_slow_path(n < 0 || n >= max)) {
  796. +        njs_range_error(vm, NULL);
  797. +        return NXT_ERROR;
  798.      }
  799.  
  800.      if (string.size == 0) {
  801. @@ -3390,8 +3388,10 @@ njs_string_replace_search_continuation(n
  802.      r = njs_vm_continuation(vm);
  803.  
  804.      if (!njs_is_primitive(&r->retval)) {
  805. -        njs_vm_trap_value(vm, &r->retval);
  806. -        return njs_trap(vm, NJS_TRAP_STRING_ARG);
  807. +        ret = njs_value_to_string(vm, &r->retval, &r->retval);
  808. +        if (ret != NXT_OK) {
  809. +            return ret;
  810. +        }
  811.      }
  812.  
  813.      ret = njs_primitive_value_to_string(vm, &string, &r->retval);
  814. diff --git a/njs/njs_value.c b/njs/njs_value.c
  815. --- a/njs/njs_value.c
  816. +++ b/njs/njs_value.c
  817. @@ -169,11 +169,12 @@ njs_values_strict_equal(const njs_value_
  818.   */
  819.  
  820.  njs_ret_t
  821. -njs_value_to_primitive(njs_vm_t *vm, njs_value_t *value, nxt_uint_t hint)
  822. +njs_value_to_primitive(njs_vm_t *vm, njs_value_t *dst, njs_value_t *value,
  823. +   nxt_uint_t hint)
  824.  {
  825.      njs_ret_t           ret;
  826. -    njs_value_t         *retval;
  827. -    njs_function_t      *function;
  828. +    nxt_uint_t          trap_tries;
  829. +    njs_value_t         retval;
  830.      njs_object_prop_t   *prop;
  831.      nxt_lvlhsh_query_t  lhq;
  832.  
  833. @@ -187,76 +188,100 @@ njs_value_to_primitive(njs_vm_t *vm, njs
  834.          nxt_string("toString"),
  835.      };
  836.  
  837. -    if (!njs_is_primitive(value)) {
  838. -        retval = &vm->top_frame->trap_scratch;
  839.  
  840. -        if (!njs_is_primitive(retval)) {
  841. +    if (njs_is_primitive(value)) {
  842. +        /* GC */
  843. +        *dst = *value;
  844. +        return NXT_OK;
  845. +    }
  846.  
  847. -            for ( ;; ) {
  848. -                ret = NXT_ERROR;
  849. +    trap_tries = 0;
  850.  
  851. -                if (njs_is_object(value) && vm->top_frame->trap_tries < 2) {
  852. -                    hint ^= vm->top_frame->trap_tries++;
  853. +    for ( ;; ) {
  854. +        ret = NXT_ERROR;
  855.  
  856. -                    lhq.key_hash = hashes[hint];
  857. -                    lhq.key = names[hint];
  858. +        if (njs_is_object(value) && trap_tries < 2) {
  859. +            hint ^= trap_tries++;
  860.  
  861. -                    prop = njs_object_property(vm, njs_object(value), &lhq);
  862. +            lhq.key_hash = hashes[hint];
  863. +            lhq.key = names[hint];
  864.  
  865. -                    if (nxt_fast_path(prop != NULL)) {
  866. +            prop = njs_object_property(vm, njs_object(value), &lhq);
  867.  
  868. -                        if (!njs_is_function(&prop->value)) {
  869. -                            /* Try the second method. */
  870. -                            continue;
  871. -                        }
  872. +            if (prop == NULL || !njs_is_function(&prop->value)) {
  873. +                /* Try the second method. */
  874. +                continue;
  875. +            }
  876.  
  877. -                        function = njs_function(&prop->value);
  878. +            ret = njs_function_call(vm, njs_function(&prop->value), value, 1,
  879. +                                    (njs_index_t) &retval);
  880.  
  881. -                        ret = njs_function_apply(vm, function, value, 1,
  882. -                                                 (njs_index_t) retval);
  883. -                        /*
  884. -                         * njs_function_apply() can return
  885. -                         *   NXT_OK, NJS_APPLIED, NXT_ERROR, NXT_AGAIN.
  886. -                         */
  887. -                        if (nxt_fast_path(ret == NXT_OK)) {
  888. +            if (nxt_fast_path(ret == NXT_OK)) {
  889. +                if (njs_is_primitive(&retval)) {
  890. +                    break;
  891. +                 }
  892.  
  893. -                            if (njs_is_primitive(&vm->retval)) {
  894. -                                retval = &vm->retval;
  895. -                                break;
  896. -                            }
  897. +                /* Try the second method. */
  898. +                continue;
  899. +             }
  900.  
  901. -                            /* Try the second method. */
  902. -                            continue;
  903. -                        }
  904. +            /* NXT_ERROR */
  905.  
  906. -                        if (ret == NJS_APPLIED) {
  907. -                            /*
  908. -                             * A user-defined method or continuation have
  909. -                             * been prepared to run.  The method will return
  910. -                             * to the current instruction and will restart it.
  911. -                             */
  912. -                            ret = 0;
  913. -                        }
  914. -                    }
  915. -                }
  916. +            return ret;
  917. +         }
  918.  
  919. -                if (ret == NXT_ERROR) {
  920. -                    njs_type_error(vm,
  921. -                                   "Cannot convert object to primitive value");
  922. -                }
  923. +        njs_type_error(vm, "Cannot convert object to primitive value");
  924.  
  925. -                return ret;
  926. -            }
  927. +        return ret;
  928. +     }
  929. +
  930. +    *dst = retval;
  931. +
  932. +    return NXT_OK;
  933. +}
  934. +
  935. +
  936. +njs_ret_t
  937. +njs_value_to_numeric(njs_vm_t *vm, njs_value_t *dst, njs_value_t *value)
  938. +{
  939. +    double     num;
  940. +    njs_ret_t  ret;
  941. +
  942. +    ret = njs_value_to_primitive(vm, dst, value, 0);
  943. +    if (nxt_slow_path(ret != NXT_OK)) {
  944. +        return ret;
  945. +    }
  946. +
  947. +    if (!njs_is_numeric(dst)) {
  948. +        num = NAN;
  949. +
  950. +        if (njs_is_string(dst)) {
  951. +            num = njs_string_to_number(dst, 0);
  952.          }
  953.  
  954. -        *value = *retval;
  955. -
  956. -        njs_set_invalid(retval);
  957. +        njs_set_number(dst, num);
  958.      }
  959.  
  960. -    vm->top_frame->trap_tries = 0;
  961. +    return NXT_OK;
  962. +}
  963.  
  964. -    return 1;
  965. +
  966. +njs_ret_t
  967. +njs_value_to_string(njs_vm_t *vm, njs_value_t *dst, njs_value_t *value)
  968. +{
  969. +    njs_ret_t    ret;
  970. +    njs_value_t  primitive;
  971. +
  972. +    if (nxt_slow_path(!njs_is_primitive(value))) {
  973. +        ret = njs_value_to_primitive(vm, &primitive, value, 1);
  974. +        if (nxt_slow_path(ret != NXT_OK)) {
  975. +            return ret;
  976. +        }
  977. +
  978. +        value = &primitive;
  979. +    }
  980. +
  981. +    return njs_primitive_value_to_string(vm, dst, value);
  982.  }
  983.  
  984.  
  985. diff --git a/njs/njs_value.h b/njs/njs_value.h
  986. --- a/njs/njs_value.h
  987. +++ b/njs/njs_value.h
  988. @@ -561,7 +561,7 @@ typedef enum {
  989.  
  990.  
  991.  #define njs_set_boolean(value, yn)                                            \
  992. -    *(value) = yn ? njs_value_true : njs_value_false
  993. +    *(value) = (yn) ? njs_value_true : njs_value_false
  994.  
  995.  
  996.  #define njs_set_true(value)                                                   \
  997. @@ -687,8 +687,12 @@ void njs_value_retain(njs_value_t *value
  998.  void njs_value_release(njs_vm_t *vm, njs_value_t *value);
  999.  nxt_bool_t njs_values_strict_equal(const njs_value_t *val1,
  1000.      const njs_value_t *val2);
  1001. -njs_ret_t njs_value_to_primitive(njs_vm_t *vm, njs_value_t *value,
  1002. -    nxt_uint_t hint);
  1003. +njs_ret_t njs_value_to_primitive(njs_vm_t *vm, njs_value_t *dst,
  1004. +    njs_value_t *value, nxt_uint_t hint);
  1005. +njs_ret_t njs_value_to_numeric(njs_vm_t *vm, njs_value_t *dst,
  1006. +    njs_value_t *value);
  1007. +njs_ret_t njs_value_to_string(njs_vm_t *vm, njs_value_t *dst,
  1008. +    njs_value_t *value);
  1009.  njs_array_t *njs_value_enumerate(njs_vm_t *vm, const njs_value_t *value,
  1010.      njs_object_enum_t kind, nxt_bool_t all);
  1011.  njs_array_t *njs_value_own_enumerate(njs_vm_t *vm, const njs_value_t *value,
  1012. diff --git a/njs/njs_vm.c b/njs/njs_vm.c
  1013. --- a/njs/njs_vm.c
  1014. +++ b/njs/njs_vm.c
  1015. @@ -23,10 +23,10 @@ struct njs_property_next_s {
  1016.  
  1017.  static njs_ret_t njs_string_concat(njs_vm_t *vm, njs_value_t *val1,
  1018.      njs_value_t *val2);
  1019. -static njs_ret_t njs_values_equal(njs_vm_t *vm, const njs_value_t *val1,
  1020. -    const njs_value_t *val2);
  1021. -static njs_ret_t njs_values_compare(njs_vm_t *vm, const njs_value_t *val1,
  1022. -    const njs_value_t *val2);
  1023. +static njs_ret_t njs_values_equal(njs_vm_t *vm, njs_value_t *val1,
  1024. +    njs_value_t *val2);
  1025. +static njs_ret_t njs_values_compare(njs_vm_t *vm, njs_value_t *val1,
  1026. +    njs_value_t *val2);
  1027.  static njs_ret_t njs_function_frame_create(njs_vm_t *vm, njs_value_t *value,
  1028.      const njs_value_t *this, uintptr_t nargs, nxt_bool_t ctor);
  1029.  static njs_object_t *njs_function_new_object(njs_vm_t *vm, njs_value_t *value);
  1030. @@ -35,29 +35,6 @@ static void njs_vm_scopes_restore(njs_vm
  1031.  static njs_ret_t njs_vmcode_continuation(njs_vm_t *vm, njs_value_t *invld1,
  1032.      njs_value_t *invld2);
  1033.  
  1034. -static void njs_vm_trap(njs_vm_t *vm, njs_trap_t trap, njs_value_t *value1,
  1035. -    njs_value_t *value2);
  1036. -static void njs_vm_trap_argument(njs_vm_t *vm, njs_trap_t trap);
  1037. -static njs_ret_t njs_vmcode_number_primitive(njs_vm_t *vm, njs_value_t *invld,
  1038. -    njs_value_t *narg);
  1039. -static njs_ret_t njs_vmcode_string_primitive(njs_vm_t *vm, njs_value_t *invld,
  1040. -    njs_value_t *narg);
  1041. -static njs_ret_t njs_vmcode_addition_primitive(njs_vm_t *vm, njs_value_t *invld,
  1042. -    njs_value_t *narg);
  1043. -static njs_ret_t njs_vmcode_comparison_primitive(njs_vm_t *vm,
  1044. -    njs_value_t *invld, njs_value_t *narg);
  1045. -static njs_ret_t njs_vmcode_number_argument(njs_vm_t *vm, njs_value_t *invld1,
  1046. -    njs_value_t *inlvd2);
  1047. -static njs_ret_t njs_vmcode_string_argument(njs_vm_t *vm, njs_value_t *invld1,
  1048. -    njs_value_t *inlvd2);
  1049. -static njs_ret_t njs_vmcode_primitive_argument(njs_vm_t *vm,
  1050. -    njs_value_t *invld1, njs_value_t *inlvd2);
  1051. -static njs_ret_t njs_vmcode_restart(njs_vm_t *vm, njs_value_t *invld1,
  1052. -    njs_value_t *invld2);
  1053. -static njs_ret_t njs_object_value_to_string(njs_vm_t *vm, njs_value_t *value);
  1054. -static njs_ret_t njs_vmcode_value_to_string(njs_vm_t *vm, njs_value_t *invld1,
  1055. -    njs_value_t *invld2);
  1056. -
  1057.  static njs_ret_t njs_vm_add_backtrace_entry(njs_vm_t *vm, njs_frame_t *frame);
  1058.  
  1059.  void njs_debug(njs_index_t index, njs_value_t *value);
  1060. @@ -79,9 +56,8 @@ const nxt_str_t  njs_entry_anonymous =  
  1061.  nxt_int_t
  1062.  njs_vmcode_interpreter(njs_vm_t *vm)
  1063.  {
  1064. -    u_char                *catch;
  1065. +    u_char                *catch, call;
  1066.      njs_ret_t             ret;
  1067. -    njs_trap_t            trap;
  1068.      njs_value_t           *retval, *value1, *value2;
  1069.      njs_frame_t           *frame;
  1070.      njs_native_frame_t    *previous;
  1071. @@ -147,40 +123,6 @@ start:
  1072.          }
  1073.      }
  1074.  
  1075. -    if (ret == NJS_TRAP) {
  1076. -        trap = vm->trap;
  1077. -
  1078. -        switch (trap) {
  1079. -
  1080. -        case NJS_TRAP_NUMBER:
  1081. -            value2 = value1;
  1082. -
  1083. -            /* Fall through. */
  1084. -
  1085. -        case NJS_TRAP_NUMBERS:
  1086. -        case NJS_TRAP_ADDITION:
  1087. -        case NJS_TRAP_COMPARISON:
  1088. -        case NJS_TRAP_INCDEC:
  1089. -        case NJS_TRAP_PROPERTY:
  1090. -
  1091. -            njs_vm_trap(vm, trap, value1, value2);
  1092. -
  1093. -            goto start;
  1094. -
  1095. -        case NJS_TRAP_NUMBER_ARG:
  1096. -        case NJS_TRAP_STRING_ARG:
  1097. -        case NJS_TRAP_PRIMITIVE_ARG:
  1098. -
  1099. -            njs_vm_trap_argument(vm, trap);
  1100. -
  1101. -            goto start;
  1102. -
  1103. -        default:
  1104. -            ret = NXT_ERROR;
  1105. -            break;
  1106. -        }
  1107. -    }
  1108. -
  1109.      if (ret == NXT_ERROR) {
  1110.  
  1111.          for ( ;; ) {
  1112. @@ -210,14 +152,44 @@ start:
  1113.  
  1114.              njs_vm_scopes_restore(vm, frame, previous);
  1115.  
  1116. +            call = frame->native.call;
  1117. +
  1118.              if (frame->native.size != 0) {
  1119.                  vm->stack_size -= frame->native.size;
  1120.                  nxt_mp_free(vm->mem_pool, frame);
  1121.              }
  1122. +
  1123. +            if (call) {
  1124. +                return NXT_ERROR;
  1125. +            }
  1126. +
  1127.          }
  1128.      }
  1129.  
  1130. -    /* NXT_AGAIN, NJS_STOP. */
  1131. +    /* NXT_ERROR, NJS_STOP. */
  1132. +
  1133. +    return ret;
  1134. +}
  1135. +
  1136. +
  1137. +nxt_int_t
  1138. +njs_vmcode_run(njs_vm_t *vm)
  1139. +{
  1140. +    njs_ret_t  ret;
  1141. +
  1142. +    if (nxt_slow_path(vm->count > 128)) {
  1143. +        njs_internal_error(vm, "recursion limit reached");
  1144. +        return NXT_ERROR;
  1145. +    }
  1146. +
  1147. +    vm->count++;
  1148. +
  1149. +    ret = njs_vmcode_interpreter(vm);
  1150. +    if (ret == NJS_STOP) {
  1151. +        ret = NJS_OK;
  1152. +    }
  1153. +
  1154. +    vm->count--;
  1155.  
  1156.      return ret;
  1157.  }
  1158. @@ -620,7 +592,6 @@ njs_vmcode_property_in(njs_vm_t *vm, njs
  1159.  
  1160.          break;
  1161.  
  1162. -    case NJS_TRAP:
  1163.      case NXT_ERROR:
  1164.      default:
  1165.  
  1166. @@ -715,7 +686,6 @@ njs_vmcode_property_delete(njs_vm_t *vm,
  1167.      case NXT_DECLINED:
  1168.          break;
  1169.  
  1170. -    case NJS_TRAP:
  1171.      case NXT_ERROR:
  1172.      default:
  1173.  
  1174. @@ -892,40 +862,60 @@ njs_vmcode_instance_of(njs_vm_t *vm, njs
  1175.  njs_ret_t
  1176.  njs_vmcode_increment(njs_vm_t *vm, njs_value_t *reference, njs_value_t *value)
  1177.  {
  1178. -    double  num;
  1179. -
  1180. -    if (nxt_fast_path(njs_is_numeric(value))) {
  1181. -        num = njs_number(value) + 1.0;
  1182. -
  1183. -        njs_release(vm, reference);
  1184. -
  1185. -        njs_set_number(reference, num);
  1186. -        vm->retval = *reference;
  1187. -
  1188. -        return sizeof(njs_vmcode_3addr_t);
  1189. +    double       num;
  1190. +    njs_ret_t    ret;
  1191. +    njs_value_t  numeric;
  1192. +
  1193. +    if (nxt_slow_path(!njs_is_numeric(value))) {
  1194. +        ret = njs_value_to_numeric(vm, &numeric, value);
  1195. +        if (nxt_slow_path(ret != NXT_OK)) {
  1196. +            return ret;
  1197. +        }
  1198. +
  1199. +        num = njs_number(&numeric);
  1200. +
  1201. +    } else {
  1202. +        num = njs_number(value);
  1203.      }
  1204.  
  1205. -    return njs_trap(vm, NJS_TRAP_INCDEC);
  1206. +    num += 1.0;
  1207. +
  1208. +    njs_release(vm, reference);
  1209. +
  1210. +    njs_set_number(reference, num);
  1211. +    vm->retval = *reference;
  1212. +
  1213. +    return sizeof(njs_vmcode_3addr_t);
  1214.  }
  1215.  
  1216.  
  1217.  njs_ret_t
  1218.  njs_vmcode_decrement(njs_vm_t *vm, njs_value_t *reference, njs_value_t *value)
  1219.  {
  1220. -    double  num;
  1221. -
  1222. -    if (nxt_fast_path(njs_is_numeric(value))) {
  1223. -        num = njs_number(value) - 1.0;
  1224. -
  1225. -        njs_release(vm, reference);
  1226. -
  1227. -        njs_set_number(reference, num);
  1228. -        vm->retval = *reference;
  1229. -
  1230. -        return sizeof(njs_vmcode_3addr_t);
  1231. +    double       num;
  1232. +    njs_ret_t    ret;
  1233. +    njs_value_t  numeric;
  1234. +
  1235. +    if (nxt_slow_path(!njs_is_numeric(value))) {
  1236. +        ret = njs_value_to_numeric(vm, &numeric, value);
  1237. +        if (nxt_slow_path(ret != NXT_OK)) {
  1238. +            return ret;
  1239. +        }
  1240. +
  1241. +        num = njs_number(&numeric);
  1242. +
  1243. +    } else {
  1244. +        num = njs_number(value);
  1245.      }
  1246.  
  1247. -    return njs_trap(vm, NJS_TRAP_INCDEC);
  1248. +    num -= 1.0;
  1249. +
  1250. +    njs_release(vm, reference);
  1251. +
  1252. +    njs_set_number(reference, num);
  1253. +    vm->retval = *reference;
  1254. +
  1255. +    return sizeof(njs_vmcode_3addr_t);
  1256.  }
  1257.  
  1258.  
  1259. @@ -934,19 +924,27 @@ njs_vmcode_post_increment(njs_vm_t *vm,
  1260.      njs_value_t *value)
  1261.  {
  1262.      double  num;
  1263. -
  1264. -    if (nxt_fast_path(njs_is_numeric(value))) {
  1265. +    njs_ret_t    ret;
  1266. +    njs_value_t  numeric;
  1267. +
  1268. +    if (nxt_slow_path(!njs_is_numeric(value))) {
  1269. +        ret = njs_value_to_numeric(vm, &numeric, value);
  1270. +        if (nxt_slow_path(ret != NXT_OK)) {
  1271. +            return ret;
  1272. +        }
  1273. +
  1274. +        num = njs_number(&numeric);
  1275. +
  1276. +    } else {
  1277.          num = njs_number(value);
  1278. -
  1279. -        njs_release(vm, reference);
  1280. -
  1281. -        njs_set_number(reference, num + 1.0);
  1282. -        njs_set_number(&vm->retval, num);
  1283. -
  1284. -        return sizeof(njs_vmcode_3addr_t);
  1285.      }
  1286.  
  1287. -    return njs_trap(vm, NJS_TRAP_INCDEC);
  1288. +    njs_release(vm, reference);
  1289. +
  1290. +    njs_set_number(reference, num + 1.0);
  1291. +    njs_set_number(&vm->retval, num);
  1292. +
  1293. +    return sizeof(njs_vmcode_3addr_t);
  1294.  }
  1295.  
  1296.  
  1297. @@ -954,20 +952,28 @@ njs_ret_t
  1298.  njs_vmcode_post_decrement(njs_vm_t *vm, njs_value_t *reference,
  1299.      njs_value_t *value)
  1300.  {
  1301. -    double  num;
  1302. -
  1303. -    if (nxt_fast_path(njs_is_numeric(value))) {
  1304. +    double       num;
  1305. +    njs_ret_t    ret;
  1306. +    njs_value_t  numeric;
  1307. +
  1308. +    if (nxt_slow_path(!njs_is_numeric(value))) {
  1309. +        ret = njs_value_to_numeric(vm, &numeric, value);
  1310. +        if (nxt_slow_path(ret != NXT_OK)) {
  1311. +            return ret;
  1312. +        }
  1313. +
  1314. +        num = njs_number(&numeric);
  1315. +
  1316. +    } else {
  1317.          num = njs_number(value);
  1318. -
  1319. -        njs_release(vm, reference);
  1320. -
  1321. -        njs_set_number(reference, num - 1.0);
  1322. -        njs_set_number(&vm->retval, num);
  1323. -
  1324. -        return sizeof(njs_vmcode_3addr_t);
  1325.      }
  1326.  
  1327. -    return njs_trap(vm, NJS_TRAP_INCDEC);
  1328. +    njs_release(vm, reference);
  1329. +
  1330. +    njs_set_number(reference, num - 1.0);
  1331. +    njs_set_number(&vm->retval, num);
  1332. +
  1333. +    return sizeof(njs_vmcode_3addr_t);
  1334.  }
  1335.  
  1336.  
  1337. @@ -1042,69 +1048,105 @@ njs_vmcode_delete(njs_vm_t *vm, njs_valu
  1338.  njs_ret_t
  1339.  njs_vmcode_unary_plus(njs_vm_t *vm, njs_value_t *value, njs_value_t *invld)
  1340.  {
  1341. -    if (nxt_fast_path(njs_is_numeric(value))) {
  1342. -        njs_set_number(&vm->retval, njs_number(value));
  1343. -        return sizeof(njs_vmcode_2addr_t);
  1344. +    njs_ret_t    ret;
  1345. +    njs_value_t  numeric;
  1346. +
  1347. +    if (nxt_slow_path(!njs_is_numeric(value))) {
  1348. +        ret = njs_value_to_numeric(vm, &numeric, value);
  1349. +        if (ret != NXT_OK) {
  1350. +            return ret;
  1351. +        }
  1352. +
  1353. +        value = &numeric;
  1354.      }
  1355.  
  1356. -    return njs_trap(vm, NJS_TRAP_NUMBER);
  1357. +    njs_set_number(&vm->retval, njs_number(value));
  1358. +
  1359. +    return sizeof(njs_vmcode_2addr_t);
  1360.  }
  1361.  
  1362.  
  1363.  njs_ret_t
  1364.  njs_vmcode_unary_negation(njs_vm_t *vm, njs_value_t *value, njs_value_t *invld)
  1365.  {
  1366. -    if (nxt_fast_path(njs_is_numeric(value))) {
  1367. -        njs_set_number(&vm->retval, - njs_number(value));
  1368. -        return sizeof(njs_vmcode_2addr_t);
  1369. +    njs_ret_t    ret;
  1370. +    njs_value_t  numeric;
  1371. +
  1372. +    if (nxt_slow_path(!njs_is_numeric(value))) {
  1373. +        ret = njs_value_to_numeric(vm, &numeric, value);
  1374. +        if (ret != NXT_OK) {
  1375. +            return ret;
  1376. +        }
  1377. +
  1378. +        value = &numeric;
  1379.      }
  1380.  
  1381. -    return njs_trap(vm, NJS_TRAP_NUMBER);
  1382. +    njs_set_number(&vm->retval, -njs_number(value));
  1383. +
  1384. +    return sizeof(njs_vmcode_2addr_t);
  1385.  }
  1386.  
  1387.  
  1388.  njs_ret_t
  1389.  njs_vmcode_addition(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
  1390.  {
  1391. -    double       num;
  1392.      njs_ret_t    ret;
  1393. -    njs_value_t  *s1, *s2, *src, dst;
  1394. +
  1395. +    njs_value_t  primitive1, primitive2, dst, *s1, *s2, *src;
  1396. +
  1397. +    if (nxt_slow_path(!njs_is_primitive(val1))) {
  1398. +
  1399. +        /*
  1400. +         * ECMAScript 5.1:
  1401. +         *   Date should return String, other types sould return Number.
  1402. +         */
  1403. +
  1404. +        ret = njs_value_to_primitive(vm, &primitive1, val1, njs_is_date(val1));
  1405. +        if (ret != NXT_OK) {
  1406. +            return ret;
  1407. +        }
  1408. +
  1409. +        val1 = &primitive1;
  1410. +    }
  1411. +
  1412. +    if (nxt_slow_path(!njs_is_primitive(val2))) {
  1413. +
  1414. +        /*
  1415. +         * ECMAScript 5.1:
  1416. +         *   Date should return String, other types sould return Number.
  1417. +         */
  1418. +
  1419. +        ret = njs_value_to_primitive(vm, &primitive2, val2, njs_is_date(val2));
  1420. +        if (ret != NXT_OK) {
  1421. +            return ret;
  1422. +        }
  1423. +
  1424. +        val2 = &primitive2;
  1425. +    }
  1426.  
  1427.      if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) {
  1428. -
  1429. -        num = njs_number(val1) + njs_number(val2);
  1430. -        njs_set_number(&vm->retval, num);
  1431. -
  1432. +        njs_set_number(&vm->retval, njs_number(val1) + njs_number(val2));
  1433.          return sizeof(njs_vmcode_3addr_t);
  1434.      }
  1435.  
  1436. -    if (nxt_fast_path(njs_is_string(val1) && njs_is_string(val2))) {
  1437. -        return njs_string_concat(vm, val1, val2);
  1438. +    if (njs_is_string(val1)) {
  1439. +        s1 = val1;
  1440. +        s2 = &dst;
  1441. +        src = val2;
  1442. +
  1443. +    } else {
  1444. +        s1 = &dst;
  1445. +        s2 = val2;
  1446. +        src = val1;
  1447.      }
  1448.  
  1449. -    if (nxt_fast_path(njs_is_primitive(val1) && njs_is_primitive(val2))) {
  1450. -
  1451. -        if (njs_is_string(val1)) {
  1452. -            s1 = val1;
  1453. -            s2 = &dst;
  1454. -            src = val2;
  1455. -
  1456. -        } else {
  1457. -            s1 = &dst;
  1458. -            s2 = val2;
  1459. -            src = val1;
  1460. -        }
  1461. -
  1462. -        ret = njs_primitive_value_to_string(vm, &dst, src);
  1463. -
  1464. -        if (nxt_fast_path(ret == NXT_OK)) {
  1465. -            return njs_string_concat(vm, s1, s2);
  1466. -        }
  1467. -
  1468. -        return ret;
  1469. +    ret = njs_primitive_value_to_string(vm, &dst, src);
  1470. +
  1471. +    if (nxt_fast_path(ret == NXT_OK)) {
  1472. +        return njs_string_concat(vm, s1, s2);
  1473.      }
  1474.  
  1475. -    return njs_trap(vm, NJS_TRAP_ADDITION);
  1476. +    return ret;
  1477.  }
  1478.  
  1479.  
  1480. @@ -1149,140 +1191,238 @@ njs_string_concat(njs_vm_t *vm, njs_valu
  1481.  njs_ret_t
  1482.  njs_vmcode_substraction(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
  1483.  {
  1484. -    double  num;
  1485. -
  1486. -    if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) {
  1487. -
  1488. -        num = njs_number(val1) - njs_number(val2);
  1489. -        njs_set_number(&vm->retval, num);
  1490. -
  1491. -        return sizeof(njs_vmcode_3addr_t);
  1492. +    njs_ret_t    ret;
  1493. +    njs_value_t  numeric1, numeric2;
  1494. +
  1495. +    if (nxt_slow_path(!njs_is_numeric(val1))) {
  1496. +        ret = njs_value_to_numeric(vm, &numeric1, val1);
  1497. +        if (ret != NXT_OK) {
  1498. +            return ret;
  1499. +        }
  1500. +
  1501. +        val1 = &numeric1;
  1502.      }
  1503.  
  1504. -    return njs_trap(vm, NJS_TRAP_NUMBERS);
  1505. +    if (nxt_slow_path(!njs_is_numeric(val2))) {
  1506. +        ret = njs_value_to_numeric(vm, &numeric2, val2);
  1507. +        if (ret != NXT_OK) {
  1508. +            return ret;
  1509. +        }
  1510. +
  1511. +        val2 = &numeric2;
  1512. +    }
  1513. +
  1514. +    njs_set_number(&vm->retval, njs_number(val1) - njs_number(val2));
  1515. +
  1516. +    return sizeof(njs_vmcode_3addr_t);
  1517.  }
  1518.  
  1519.  
  1520.  njs_ret_t
  1521.  njs_vmcode_multiplication(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
  1522.  {
  1523. -    double  num;
  1524. -
  1525. -    if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) {
  1526. -
  1527. -        num = njs_number(val1) * njs_number(val2);
  1528. -        njs_set_number(&vm->retval, num);
  1529. -
  1530. -        return sizeof(njs_vmcode_3addr_t);
  1531. +    njs_ret_t    ret;
  1532. +    njs_value_t  numeric1, numeric2;
  1533. +
  1534. +    if (nxt_slow_path(!njs_is_numeric(val1))) {
  1535. +        ret = njs_value_to_numeric(vm, &numeric1, val1);
  1536. +        if (ret != NXT_OK) {
  1537. +            return ret;
  1538. +        }
  1539. +
  1540. +        val1 = &numeric1;
  1541.      }
  1542.  
  1543. -    return njs_trap(vm, NJS_TRAP_NUMBERS);
  1544. +    if (nxt_slow_path(!njs_is_numeric(val2))) {
  1545. +        ret = njs_value_to_numeric(vm, &numeric2, val2);
  1546. +        if (ret != NXT_OK) {
  1547. +            return ret;
  1548. +        }
  1549. +
  1550. +        val2 = &numeric2;
  1551. +    }
  1552. +
  1553. +    njs_set_number(&vm->retval, njs_number(val1) * njs_number(val2));
  1554. +
  1555. +    return sizeof(njs_vmcode_3addr_t);
  1556.  }
  1557.  
  1558.  
  1559.  njs_ret_t
  1560.  njs_vmcode_exponentiation(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
  1561.  {
  1562. -    double      num, base, exponent;
  1563. -    nxt_bool_t  valid;
  1564. -
  1565. -    if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) {
  1566. -        base = njs_number(val1);
  1567. -        exponent = njs_number(val2);
  1568. -
  1569. -        /*
  1570. -         * According to ES7:
  1571. -         *  1. If exponent is NaN, the result should be NaN;
  1572. -         *  2. The result of +/-1 ** +/-Infinity should be NaN.
  1573. -         */
  1574. -        valid = nxt_expect(1, fabs(base) != 1
  1575. -                              || (!isnan(exponent) && !isinf(exponent)));
  1576. -
  1577. -        if (valid) {
  1578. -            num = pow(base, exponent);
  1579. -
  1580. -        } else {
  1581. -            num = NAN;
  1582. +    double       num, base, exponent;
  1583. +    njs_ret_t    ret;
  1584. +    nxt_bool_t   valid;
  1585. +    njs_value_t  numeric1, numeric2;
  1586. +
  1587. +    if (nxt_slow_path(!njs_is_numeric(val1))) {
  1588. +        ret = njs_value_to_numeric(vm, &numeric1, val1);
  1589. +        if (ret != NXT_OK) {
  1590. +            return ret;
  1591.          }
  1592.  
  1593. -        njs_set_number(&vm->retval, num);
  1594. -
  1595. -        return sizeof(njs_vmcode_3addr_t);
  1596. +        val1 = &numeric1;
  1597.      }
  1598.  
  1599. -    return njs_trap(vm, NJS_TRAP_NUMBERS);
  1600. +    if (nxt_slow_path(!njs_is_numeric(val2))) {
  1601. +        ret = njs_value_to_numeric(vm, &numeric2, val2);
  1602. +        if (ret != NXT_OK) {
  1603. +            return ret;
  1604. +        }
  1605. +
  1606. +        val2 = &numeric2;
  1607. +    }
  1608. +
  1609. +    base = njs_number(val1);
  1610. +    exponent = njs_number(val2);
  1611. +
  1612. +    /*
  1613. +     * According to ES7:
  1614. +     *  1. If exponent is NaN, the result should be NaN;
  1615. +     *  2. The result of +/-1 ** +/-Infinity should be NaN.
  1616. +     */
  1617. +    valid = nxt_expect(1, fabs(base) != 1
  1618. +                          || (!isnan(exponent) && !isinf(exponent)));
  1619. +
  1620. +    if (valid) {
  1621. +        num = pow(base, exponent);
  1622. +
  1623. +    } else {
  1624. +        num = NAN;
  1625. +    }
  1626. +
  1627. +    njs_set_number(&vm->retval, num);
  1628. +
  1629. +    return sizeof(njs_vmcode_3addr_t);
  1630.  }
  1631.  
  1632.  
  1633.  njs_ret_t
  1634.  njs_vmcode_division(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
  1635.  {
  1636. -    double  num;
  1637. -
  1638. -    if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) {
  1639. -
  1640. -        num = njs_number(val1) / njs_number(val2);
  1641. -        njs_set_number(&vm->retval, num);
  1642. -
  1643. -        return sizeof(njs_vmcode_3addr_t);
  1644. +    njs_ret_t    ret;
  1645. +    njs_value_t  numeric1, numeric2;
  1646. +
  1647. +    if (nxt_slow_path(!njs_is_numeric(val1))) {
  1648. +        ret = njs_value_to_numeric(vm, &numeric1, val1);
  1649. +        if (ret != NXT_OK) {
  1650. +            return ret;
  1651. +        }
  1652. +
  1653. +        val1 = &numeric1;
  1654.      }
  1655.  
  1656. -    return njs_trap(vm, NJS_TRAP_NUMBERS);
  1657. +    if (nxt_slow_path(!njs_is_numeric(val2))) {
  1658. +        ret = njs_value_to_numeric(vm, &numeric2, val2);
  1659. +        if (ret != NXT_OK) {
  1660. +            return ret;
  1661. +        }
  1662. +
  1663. +        val2 = &numeric2;
  1664. +    }
  1665. +
  1666. +    njs_set_number(&vm->retval, njs_number(val1) / njs_number(val2));
  1667. +
  1668. +    return sizeof(njs_vmcode_3addr_t);
  1669.  }
  1670.  
  1671.  
  1672.  njs_ret_t
  1673.  njs_vmcode_remainder(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
  1674.  {
  1675. -    double  num;
  1676. -
  1677. -    if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) {
  1678. -
  1679. -        num = fmod(njs_number(val1), njs_number(val2));
  1680. -        njs_set_number(&vm->retval, num);
  1681. -
  1682. -        return sizeof(njs_vmcode_3addr_t);
  1683. +    njs_ret_t    ret;
  1684. +    njs_value_t  numeric1, numeric2;
  1685. +
  1686. +    if (nxt_slow_path(!njs_is_numeric(val1))) {
  1687. +        ret = njs_value_to_numeric(vm, &numeric1, val1);
  1688. +        if (ret != NXT_OK) {
  1689. +            return ret;
  1690. +        }
  1691. +
  1692. +        val1 = &numeric1;
  1693.      }
  1694.  
  1695. -    return njs_trap(vm, NJS_TRAP_NUMBERS);
  1696. +    if (nxt_slow_path(!njs_is_numeric(val2))) {
  1697. +        ret = njs_value_to_numeric(vm, &numeric2, val2);
  1698. +        if (ret != NXT_OK) {
  1699. +            return ret;
  1700. +        }
  1701. +
  1702. +        val2 = &numeric2;
  1703. +    }
  1704. +
  1705. +    njs_set_number(&vm->retval, fmod(njs_number(val1), njs_number(val2)));
  1706. +
  1707. +    return sizeof(njs_vmcode_3addr_t);
  1708.  }
  1709.  
  1710.  
  1711.  njs_ret_t
  1712.  njs_vmcode_left_shift(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
  1713.  {
  1714. -    int32_t   num1;
  1715. -    uint32_t  num2;
  1716. -
  1717. -    if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) {
  1718. -
  1719. -        num1 = njs_number_to_int32(njs_number(val1));
  1720. -        num2 = njs_number_to_uint32(njs_number(val2));
  1721. -        njs_set_number(&vm->retval, num1 << (num2 & 0x1f));
  1722. -
  1723. -        return sizeof(njs_vmcode_3addr_t);
  1724. +    int32_t      num1;
  1725. +    uint32_t     num2;
  1726. +    njs_ret_t    ret;
  1727. +    njs_value_t  numeric1, numeric2;
  1728. +
  1729. +    if (nxt_slow_path(!njs_is_numeric(val1))) {
  1730. +        ret = njs_value_to_numeric(vm, &numeric1, val1);
  1731. +        if (ret != NXT_OK) {
  1732. +            return ret;
  1733. +        }
  1734. +
  1735. +        val1 = &numeric1;
  1736.      }
  1737.  
  1738. -    return njs_trap(vm, NJS_TRAP_NUMBERS);
  1739. +    if (nxt_slow_path(!njs_is_numeric(val2))) {
  1740. +        ret = njs_value_to_numeric(vm, &numeric2, val2);
  1741. +        if (ret != NXT_OK) {
  1742. +            return ret;
  1743. +        }
  1744. +
  1745. +        val2 = &numeric2;
  1746. +    }
  1747. +
  1748. +    num1 = njs_number_to_int32(njs_number(val1));
  1749. +    num2 = njs_number_to_uint32(njs_number(val2));
  1750. +    njs_set_number(&vm->retval, num1 << (num2 & 0x1f));
  1751. +
  1752. +    return sizeof(njs_vmcode_3addr_t);
  1753.  }
  1754.  
  1755.  
  1756.  njs_ret_t
  1757.  njs_vmcode_right_shift(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
  1758.  {
  1759. -    int32_t   num1;
  1760. -    uint32_t  num2;
  1761. -
  1762. -    if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) {
  1763. -
  1764. -        num1 = njs_number_to_int32(njs_number(val1));
  1765. -        num2 = njs_number_to_uint32(njs_number(val2));
  1766. -        njs_set_number(&vm->retval, num1 >> (num2 & 0x1f));
  1767. -
  1768. -        return sizeof(njs_vmcode_3addr_t);
  1769. +    int32_t      num1;
  1770. +    uint32_t     num2;
  1771. +    njs_ret_t    ret;
  1772. +    njs_value_t  numeric1, numeric2;
  1773. +
  1774. +    if (nxt_slow_path(!njs_is_numeric(val1))) {
  1775. +        ret = njs_value_to_numeric(vm, &numeric1, val1);
  1776. +        if (ret != NXT_OK) {
  1777. +            return ret;
  1778. +        }
  1779. +
  1780. +        val1 = &numeric1;
  1781.      }
  1782.  
  1783. -    return njs_trap(vm, NJS_TRAP_NUMBERS);
  1784. +    if (nxt_slow_path(!njs_is_numeric(val2))) {
  1785. +        ret = njs_value_to_numeric(vm, &numeric2, val2);
  1786. +        if (ret != NXT_OK) {
  1787. +            return ret;
  1788. +        }
  1789. +
  1790. +        val2 = &numeric2;
  1791. +    }
  1792. +
  1793. +    num1 = njs_number_to_int32(njs_number(val1));
  1794. +    num2 = njs_number_to_uint32(njs_number(val2));
  1795. +    njs_set_number(&vm->retval, num1 >> (num2 & 0x1f));
  1796. +
  1797. +    return sizeof(njs_vmcode_3addr_t);
  1798.  }
  1799.  
  1800.  
  1801. @@ -1290,34 +1430,40 @@ njs_ret_t
  1802.  njs_vmcode_unsigned_right_shift(njs_vm_t *vm, njs_value_t *val1,
  1803.      njs_value_t *val2)
  1804.  {
  1805. -    uint32_t  num1, num2;
  1806. -
  1807. -    if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) {
  1808. -
  1809. -        num1 = njs_number_to_uint32(njs_number(val1));
  1810. -        num2 = njs_number_to_uint32(njs_number(val2));
  1811. -        njs_set_number(&vm->retval, num1 >> (num2 & 0x1f));
  1812. -
  1813. -        return sizeof(njs_vmcode_3addr_t);
  1814. +    uint32_t     num1, num2;
  1815. +    njs_ret_t    ret;
  1816. +    njs_value_t  numeric1, numeric2;
  1817. +
  1818. +    if (nxt_slow_path(!njs_is_numeric(val1))) {
  1819. +        ret = njs_value_to_numeric(vm, &numeric1, val1);
  1820. +        if (ret != NXT_OK) {
  1821. +            return ret;
  1822. +        }
  1823. +
  1824. +        val1 = &numeric1;
  1825.      }
  1826.  
  1827. -    return njs_trap(vm, NJS_TRAP_NUMBERS);
  1828. +    if (nxt_slow_path(!njs_is_numeric(val2))) {
  1829. +        ret = njs_value_to_numeric(vm, &numeric2, val2);
  1830. +        if (ret != NXT_OK) {
  1831. +            return ret;
  1832. +        }
  1833. +
  1834. +        val2 = &numeric2;
  1835. +    }
  1836. +
  1837. +    num1 = njs_number_to_uint32(njs_number(val1));
  1838. +    num2 = njs_number_to_uint32(njs_number(val2));
  1839. +    njs_set_number(&vm->retval, num1 >> (num2 & 0x1f));
  1840. +
  1841. +    return sizeof(njs_vmcode_3addr_t);
  1842.  }
  1843.  
  1844.  
  1845.  njs_ret_t
  1846.  njs_vmcode_logical_not(njs_vm_t *vm, njs_value_t *value, njs_value_t *inlvd)
  1847.  {
  1848. -    const njs_value_t  *retval;
  1849. -
  1850. -    if (njs_is_true(value)) {
  1851. -        retval = &njs_value_false;
  1852. -
  1853. -    } else {
  1854. -        retval = &njs_value_true;
  1855. -    }
  1856. -
  1857. -    vm->retval = *retval;
  1858. +    njs_set_boolean(&vm->retval, !njs_is_true(value));
  1859.  
  1860.      return sizeof(njs_vmcode_2addr_t);
  1861.  }
  1862. @@ -1358,85 +1504,133 @@ njs_vmcode_test_if_false(njs_vm_t *vm, n
  1863.  njs_ret_t
  1864.  njs_vmcode_bitwise_not(njs_vm_t *vm, njs_value_t *value, njs_value_t *invld)
  1865.  {
  1866. -    int32_t  num;
  1867. -
  1868. -    if (nxt_fast_path(njs_is_numeric(value))) {
  1869. -        num = njs_number_to_integer(njs_number(value));
  1870. -        njs_set_number(&vm->retval, ~num);
  1871. -
  1872. -        return sizeof(njs_vmcode_2addr_t);
  1873. +    njs_ret_t    ret;
  1874. +    njs_value_t  numeric;
  1875. +
  1876. +    if (nxt_slow_path(!njs_is_numeric(value))) {
  1877. +        ret = njs_value_to_numeric(vm, &numeric, value);
  1878. +        if (ret != NXT_OK) {
  1879. +            return ret;
  1880. +        }
  1881. +
  1882. +        value = &numeric;
  1883.      }
  1884.  
  1885. -    return njs_trap(vm, NJS_TRAP_NUMBER);
  1886. +    njs_set_number(&vm->retval, ~njs_number_to_integer(njs_number(value)));
  1887. +
  1888. +    return sizeof(njs_vmcode_2addr_t);
  1889.  }
  1890.  
  1891.  
  1892.  njs_ret_t
  1893.  njs_vmcode_bitwise_and(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
  1894.  {
  1895. -    int32_t  num1, num2;
  1896. -
  1897. -    if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) {
  1898. -
  1899. -        num1 = njs_number_to_integer(njs_number(val1));
  1900. -        num2 = njs_number_to_integer(njs_number(val2));
  1901. -        njs_set_number(&vm->retval, num1 & num2);
  1902. -
  1903. -        return sizeof(njs_vmcode_3addr_t);
  1904. +    int32_t      num1, num2;
  1905. +    njs_ret_t    ret;
  1906. +    njs_value_t  numeric1, numeric2;
  1907. +
  1908. +    if (nxt_slow_path(!njs_is_numeric(val1))) {
  1909. +        ret = njs_value_to_numeric(vm, &numeric1, val1);
  1910. +        if (ret != NXT_OK) {
  1911. +            return ret;
  1912. +        }
  1913. +
  1914. +        val1 = &numeric1;
  1915.      }
  1916.  
  1917. -    return njs_trap(vm, NJS_TRAP_NUMBERS);
  1918. +    if (nxt_slow_path(!njs_is_numeric(val2))) {
  1919. +        ret = njs_value_to_numeric(vm, &numeric2, val2);
  1920. +        if (ret != NXT_OK) {
  1921. +            return ret;
  1922. +        }
  1923. +
  1924. +        val2 = &numeric2;
  1925. +    }
  1926. +
  1927. +    num1 = njs_number_to_integer(njs_number(val1));
  1928. +    num2 = njs_number_to_integer(njs_number(val2));
  1929. +    njs_set_number(&vm->retval, num1 & num2);
  1930. +
  1931. +    return sizeof(njs_vmcode_3addr_t);
  1932.  }
  1933.  
  1934.  
  1935.  njs_ret_t
  1936.  njs_vmcode_bitwise_xor(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
  1937.  {
  1938. -    int32_t  num1, num2;
  1939. -
  1940. -    if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) {
  1941. -
  1942. -        num1 = njs_number_to_integer(njs_number(val1));
  1943. -        num2 = njs_number_to_integer(njs_number(val2));
  1944. -        njs_set_number(&vm->retval, num1 ^ num2);
  1945. -
  1946. -        return sizeof(njs_vmcode_3addr_t);
  1947. +    int32_t      num1, num2;
  1948. +    njs_ret_t    ret;
  1949. +    njs_value_t  numeric1, numeric2;
  1950. +
  1951. +    if (nxt_slow_path(!njs_is_numeric(val1))) {
  1952. +        ret = njs_value_to_numeric(vm, &numeric1, val1);
  1953. +        if (ret != NXT_OK) {
  1954. +            return ret;
  1955. +        }
  1956. +
  1957. +        val1 = &numeric1;
  1958.      }
  1959.  
  1960. -    return njs_trap(vm, NJS_TRAP_NUMBERS);
  1961. +    if (nxt_slow_path(!njs_is_numeric(val2))) {
  1962. +        ret = njs_value_to_numeric(vm, &numeric2, val2);
  1963. +        if (ret != NXT_OK) {
  1964. +            return ret;
  1965. +        }
  1966. +
  1967. +        val2 = &numeric2;
  1968. +    }
  1969. +
  1970. +    num1 = njs_number_to_integer(njs_number(val1));
  1971. +    num2 = njs_number_to_integer(njs_number(val2));
  1972. +    njs_set_number(&vm->retval, num1 ^ num2);
  1973. +
  1974. +    return sizeof(njs_vmcode_3addr_t);
  1975.  }
  1976.  
  1977.  
  1978.  njs_ret_t
  1979.  njs_vmcode_bitwise_or(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
  1980.  {
  1981. -    int32_t  num1, num2;
  1982. -
  1983. -    if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) {
  1984. -
  1985. -        num1 = njs_number_to_uint32(njs_number(val1));
  1986. -        num2 = njs_number_to_uint32(njs_number(val2));
  1987. -        njs_set_number(&vm->retval, num1 | num2);
  1988. -
  1989. -        return sizeof(njs_vmcode_3addr_t);
  1990. +    int32_t      num1, num2;
  1991. +    njs_ret_t    ret;
  1992. +    njs_value_t  numeric1, numeric2;
  1993. +
  1994. +    if (nxt_slow_path(!njs_is_numeric(val1))) {
  1995. +        ret = njs_value_to_numeric(vm, &numeric1, val1);
  1996. +        if (ret != NXT_OK) {
  1997. +            return ret;
  1998. +        }
  1999. +
  2000. +        val1 = &numeric1;
  2001.      }
  2002.  
  2003. -    return njs_trap(vm, NJS_TRAP_NUMBERS);
  2004. +    if (nxt_slow_path(!njs_is_numeric(val2))) {
  2005. +        ret = njs_value_to_numeric(vm, &numeric2, val2);
  2006. +        if (ret != NXT_OK) {
  2007. +            return ret;
  2008. +        }
  2009. +
  2010. +        val2 = &numeric2;
  2011. +    }
  2012. +
  2013. +    num1 = njs_number_to_integer(njs_number(val1));
  2014. +    num2 = njs_number_to_integer(njs_number(val2));
  2015. +    njs_set_number(&vm->retval, num1 | num2);
  2016. +
  2017. +    return sizeof(njs_vmcode_3addr_t);
  2018.  }
  2019.  
  2020.  
  2021.  njs_ret_t
  2022.  njs_vmcode_equal(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
  2023.  {
  2024. -    njs_ret_t          ret;
  2025. -    const njs_value_t  *retval;
  2026. +    njs_ret_t  ret;
  2027.  
  2028.      ret = njs_values_equal(vm, val1, val2);
  2029.  
  2030.      if (nxt_fast_path(ret >= 0)) {
  2031.  
  2032. -        retval = (ret != 0) ? &njs_value_true : &njs_value_false;
  2033. -        vm->retval = *retval;
  2034. +        njs_set_boolean(&vm->retval, ret != 0);
  2035.  
  2036.          return sizeof(njs_vmcode_3addr_t);
  2037.      }
  2038. @@ -1466,10 +1660,14 @@ njs_vmcode_not_equal(njs_vm_t *vm, njs_v
  2039.  
  2040.  
  2041.  static njs_ret_t
  2042. -njs_values_equal(njs_vm_t *vm, const njs_value_t *val1, const njs_value_t *val2)
  2043. +njs_values_equal(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
  2044.  {
  2045. -    nxt_bool_t         nv1, nv2;
  2046. -    const njs_value_t  *hv, *lv;
  2047. +    njs_ret_t    ret;
  2048. +    nxt_bool_t   nv1, nv2;
  2049. +    njs_value_t  primitive;
  2050. +    njs_value_t  *hv, *lv;
  2051. +
  2052. +again:
  2053.  
  2054.      nv1 = njs_is_null_or_undefined(val1);
  2055.      nv2 = njs_is_null_or_undefined(val2);
  2056. @@ -1515,22 +1713,29 @@ njs_values_equal(njs_vm_t *vm, const njs
  2057.      }
  2058.  
  2059.      /* "hv" is an object and "lv" is either a string or a numeric. */
  2060. -    return njs_trap(vm, NJS_TRAP_COMPARISON);
  2061. +
  2062. +    ret = njs_value_to_primitive(vm, &primitive, hv, 0);
  2063. +    if (ret != NXT_OK) {
  2064. +        return ret;
  2065. +    }
  2066. +
  2067. +    val1 = &primitive;
  2068. +    val2 = lv;
  2069. +
  2070. +    goto again;
  2071.  }
  2072.  
  2073.  
  2074.  njs_ret_t
  2075.  njs_vmcode_less(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
  2076.  {
  2077. -    njs_ret_t          ret;
  2078. -    const njs_value_t  *retval;
  2079. +    njs_ret_t  ret;
  2080.  
  2081.      ret = njs_values_compare(vm, val1, val2);
  2082.  
  2083.      if (nxt_fast_path(ret >= -1)) {
  2084.  
  2085. -        retval = (ret > 0) ? &njs_value_true : &njs_value_false;
  2086. -        vm->retval = *retval;
  2087. +        njs_set_boolean(&vm->retval, ret > 0);
  2088.  
  2089.          return sizeof(njs_vmcode_3addr_t);
  2090.      }
  2091. @@ -1556,15 +1761,13 @@ njs_vmcode_less_or_equal(njs_vm_t *vm, n
  2092.  njs_ret_t
  2093.  njs_vmcode_greater_or_equal(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
  2094.  {
  2095. -    njs_ret_t          ret;
  2096. -    const njs_value_t  *retval;
  2097. +    njs_ret_t  ret;
  2098.  
  2099.      ret = njs_values_compare(vm, val1, val2);
  2100.  
  2101.      if (nxt_fast_path(ret >= -1)) {
  2102.  
  2103. -        retval = (ret == 0) ? &njs_value_true : &njs_value_false;
  2104. -        vm->retval = *retval;
  2105. +        njs_set_boolean(&vm->retval, ret == 0);
  2106.  
  2107.          return sizeof(njs_vmcode_3addr_t);
  2108.      }
  2109. @@ -1578,62 +1781,66 @@ njs_vmcode_greater_or_equal(njs_vm_t *vm
  2110.   * njs_values_compare() returns
  2111.   *   1 if val1 is less than val2,
  2112.   *   0 if val1 is greater than or equal to val2,
  2113. - *  -1 if the values are not comparable,
  2114. - *  or negative trap number if convertion to primitive is required.
  2115. + *  -1 if the values are not comparable.
  2116.   */
  2117.  
  2118.  static njs_ret_t
  2119. -njs_values_compare(njs_vm_t *vm, const njs_value_t *val1,
  2120. -    const njs_value_t *val2)
  2121. +njs_values_compare(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
  2122.  {
  2123. -    double  num1, num2;
  2124. -
  2125. -    if (nxt_fast_path(njs_is_primitive(val1) && njs_is_primitive(val2))) {
  2126. -
  2127. -        if (nxt_fast_path(njs_is_numeric(val1))) {
  2128. -            num1 = njs_number(val1);
  2129. -
  2130. -            if (nxt_fast_path(njs_is_numeric(val2))) {
  2131. -                num2 = njs_number(val2);
  2132. -
  2133. -            } else {
  2134. -                num2 = njs_string_to_number(val2, 0);
  2135. -            }
  2136. -
  2137. -        } else if (njs_is_numeric(val2)) {
  2138. -            num1 = njs_string_to_number(val1, 0);
  2139. +    double       num1, num2;
  2140. +    njs_ret_t    ret;
  2141. +    njs_value_t  primitive1, primitive2;
  2142. +
  2143. +    if (nxt_slow_path(!njs_is_primitive(val1))) {
  2144. +        ret = njs_value_to_primitive(vm, &primitive1, val1, 0);
  2145. +        if (ret != NXT_OK) {
  2146. +            return ret;
  2147. +        }
  2148. +
  2149. +        val1 = &primitive1;
  2150. +    }
  2151. +
  2152. +    if (nxt_slow_path(!njs_is_primitive(val2))) {
  2153. +        ret = njs_value_to_primitive(vm, &primitive2, val2, 0);
  2154. +        if (ret != NXT_OK) {
  2155. +            return ret;
  2156. +        }
  2157. +
  2158. +        val2 = &primitive2;
  2159. +    }
  2160. +
  2161. +    if (nxt_fast_path(njs_is_numeric(val1))) {
  2162. +        num1 = njs_number(val1);
  2163. +
  2164. +        if (nxt_fast_path(njs_is_numeric(val2))) {
  2165.              num2 = njs_number(val2);
  2166.  
  2167.          } else {
  2168. -            return (njs_string_cmp(val1, val2) < 0) ? 1 : 0;
  2169. +            num2 = njs_string_to_number(val2, 0);
  2170.          }
  2171.  
  2172. -        /* NaN and void values are not comparable with anything. */
  2173. -        if (isnan(num1) || isnan(num2)) {
  2174. -            return -1;
  2175. -        }
  2176. -
  2177. -        /* Infinities are handled correctly by comparision. */
  2178. -        return (num1 < num2);
  2179. +    } else if (njs_is_numeric(val2)) {
  2180. +        num1 = njs_string_to_number(val1, 0);
  2181. +        num2 = njs_number(val2);
  2182. +
  2183. +    } else {
  2184. +        return (njs_string_cmp(val1, val2) < 0) ? 1 : 0;
  2185.      }
  2186.  
  2187. -    return njs_trap(vm, NJS_TRAP_COMPARISON);
  2188. +    /* NaN and void values are not comparable with anything. */
  2189. +    if (isnan(num1) || isnan(num2)) {
  2190. +        return -1;
  2191. +    }
  2192. +
  2193. +    /* Infinities are handled correctly by comparision. */
  2194. +    return (num1 < num2);
  2195.  }
  2196.  
  2197.  
  2198.  njs_ret_t
  2199.  njs_vmcode_strict_equal(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
  2200.  {
  2201. -    const njs_value_t  *retval;
  2202. -
  2203. -    if (njs_values_strict_equal(val1, val2)) {
  2204. -        retval = &njs_value_true;
  2205. -
  2206. -    } else {
  2207. -        retval = &njs_value_false;
  2208. -    }
  2209. -
  2210. -    vm->retval = *retval;
  2211. +    njs_set_boolean(&vm->retval, njs_values_strict_equal(val1, val2));
  2212.  
  2213.      return sizeof(njs_vmcode_3addr_t);
  2214.  }
  2215. @@ -1642,16 +1849,7 @@ njs_vmcode_strict_equal(njs_vm_t *vm, nj
  2216.  njs_ret_t
  2217.  njs_vmcode_strict_not_equal(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
  2218.  {
  2219. -    const njs_value_t  *retval;
  2220. -
  2221. -    if (njs_values_strict_equal(val1, val2)) {
  2222. -        retval = &njs_value_false;
  2223. -
  2224. -    } else {
  2225. -        retval = &njs_value_true;
  2226. -    }
  2227. -
  2228. -    vm->retval = *retval;
  2229. +    njs_set_boolean(&vm->retval, !njs_values_strict_equal(val1, val2));
  2230.  
  2231.      return sizeof(njs_vmcode_3addr_t);
  2232.  }
  2233. @@ -1863,7 +2061,6 @@ njs_vmcode_method_frame(njs_vm_t *vm, nj
  2234.      case NXT_DECLINED:
  2235.          break;
  2236.  
  2237. -    case NJS_TRAP:
  2238.      case NXT_ERROR:
  2239.      default:
  2240.  
  2241. @@ -1871,6 +2068,11 @@ njs_vmcode_method_frame(njs_vm_t *vm, nj
  2242.      }
  2243.  
  2244.      if (value == NULL || !njs_is_function(value)) {
  2245. +        ret = njs_value_to_string(vm, name, name);
  2246. +        if (nxt_slow_path(ret != NXT_OK)) {
  2247. +            return NXT_ERROR;
  2248. +        }
  2249. +
  2250.          njs_string_get(name, &string);
  2251.          njs_type_error(vm, "(intermediate value)[\"%V\"] is not a function",
  2252.                         &string);
  2253. @@ -1935,6 +2137,7 @@ njs_vmcode_function_call(njs_vm_t *vm, n
  2254.  njs_ret_t
  2255.  njs_vmcode_return(njs_vm_t *vm, njs_value_t *invld, njs_value_t *retval)
  2256.  {
  2257. +    uint8_t             call;
  2258.      njs_value_t         *value;
  2259.      njs_frame_t         *frame;
  2260.      njs_native_frame_t  *previous;
  2261. @@ -1967,9 +2170,11 @@ njs_vmcode_return(njs_vm_t *vm, njs_valu
  2262.  
  2263.      vm->current = frame->return_address;
  2264.  
  2265. +    call = frame->native.call;
  2266. +
  2267.      njs_function_frame_free(vm, &frame->native);
  2268.  
  2269. -    return 0;
  2270. +    return call ? NJS_STOP : 0;
  2271.  }
  2272.  
  2273.  
  2274. @@ -2037,6 +2242,14 @@ const njs_vmcode_generic_t  njs_continua
  2275.  };
  2276.  
  2277.  
  2278. +const njs_vmcode_generic_t  njs_stop[] = {
  2279. +    { .code = { .operation = njs_vmcode_stop,
  2280. +                .operands =  NJS_VMCODE_1OPERAND,
  2281. +                .retval = NJS_VMCODE_NO_RETVAL },
  2282. +      .operand1 = NJS_INDEX_GLOBAL_RETVAL },
  2283. +};
  2284. +
  2285. +
  2286.  static njs_ret_t
  2287.  njs_vmcode_continuation(njs_vm_t *vm, njs_value_t *invld1, njs_value_t *invld2)
  2288.  {
  2289. @@ -2289,384 +2502,6 @@ njs_vmcode_reference_error(njs_vm_t *vm,
  2290.  }
  2291.  
  2292.  
  2293. -static const njs_vmcode_1addr_t  njs_trap_number[] = {
  2294. -    { .code = { .operation = njs_vmcode_number_primitive,
  2295. -                .operands =  NJS_VMCODE_1OPERAND,
  2296. -                .retval = NJS_VMCODE_NO_RETVAL },
  2297. -      .index = 0 },
  2298. -    { .code = { .operation = njs_vmcode_restart,
  2299. -                .operands =  NJS_VMCODE_NO_OPERAND,
  2300. -                .retval = NJS_VMCODE_NO_RETVAL } },
  2301. -};
  2302. -
  2303. -
  2304. -static const njs_vmcode_1addr_t  njs_trap_numbers[] = {
  2305. -    { .code = { .operation = njs_vmcode_number_primitive,
  2306. -                .operands =  NJS_VMCODE_1OPERAND,
  2307. -                .retval = NJS_VMCODE_NO_RETVAL },
  2308. -      .index = 0 },
  2309. -    { .code = { .operation = njs_vmcode_number_primitive,
  2310. -                .operands =  NJS_VMCODE_1OPERAND,
  2311. -                .retval = NJS_VMCODE_NO_RETVAL },
  2312. -      .index = 1 },
  2313. -    { .code = { .operation = njs_vmcode_restart,
  2314. -                .operands =  NJS_VMCODE_NO_OPERAND,
  2315. -                .retval = NJS_VMCODE_NO_RETVAL } },
  2316. -};
  2317. -
  2318. -
  2319. -static const njs_vmcode_1addr_t  njs_trap_addition[] = {
  2320. -    { .code = { .operation = njs_vmcode_addition_primitive,
  2321. -                .operands =  NJS_VMCODE_1OPERAND,
  2322. -                .retval = NJS_VMCODE_NO_RETVAL },
  2323. -      .index = 0 },
  2324. -    { .code = { .operation = njs_vmcode_addition_primitive,
  2325. -                .operands =  NJS_VMCODE_1OPERAND,
  2326. -                .retval = NJS_VMCODE_NO_RETVAL },
  2327. -      .index = 1 },
  2328. -    { .code = { .operation = njs_vmcode_restart,
  2329. -                .operands =  NJS_VMCODE_NO_OPERAND,
  2330. -                .retval = NJS_VMCODE_NO_RETVAL } },
  2331. -};
  2332. -
  2333. -
  2334. -static const njs_vmcode_1addr_t  njs_trap_comparison[] = {
  2335. -    { .code = { .operation = njs_vmcode_comparison_primitive,
  2336. -                .operands =  NJS_VMCODE_1OPERAND,
  2337. -                .retval = NJS_VMCODE_NO_RETVAL },
  2338. -      .index = 0 },
  2339. -    { .code = { .operation = njs_vmcode_comparison_primitive,
  2340. -                .operands =  NJS_VMCODE_1OPERAND,
  2341. -                .retval = NJS_VMCODE_NO_RETVAL },
  2342. -      .index = 1 },
  2343. -    { .code = { .operation = njs_vmcode_restart,
  2344. -                .operands =  NJS_VMCODE_NO_OPERAND,
  2345. -                .retval = NJS_VMCODE_NO_RETVAL } },
  2346. -};
  2347. -
  2348. -
  2349. -static const njs_vmcode_1addr_t  njs_trap_property[] = {
  2350. -    { .code = { .operation = njs_vmcode_string_primitive,
  2351. -                .operands =  NJS_VMCODE_1OPERAND,
  2352. -                .retval = NJS_VMCODE_NO_RETVAL },
  2353. -      .index = 1 },
  2354. -    { .code = { .operation = njs_vmcode_restart,
  2355. -                .operands =  NJS_VMCODE_NO_OPERAND,
  2356. -                .retval = NJS_VMCODE_NO_RETVAL } },
  2357. -};
  2358. -
  2359. -
  2360. -static const njs_vmcode_1addr_t  njs_trap_number_argument = {
  2361. -    .code = { .operation = njs_vmcode_number_argument,
  2362. -              .operands =  NJS_VMCODE_NO_OPERAND,
  2363. -              .retval = NJS_VMCODE_NO_RETVAL }
  2364. -};
  2365. -
  2366. -
  2367. -static const njs_vmcode_1addr_t  njs_trap_string_argument = {
  2368. -    .code = { .operation = njs_vmcode_string_argument,
  2369. -              .operands =  NJS_VMCODE_NO_OPERAND,
  2370. -              .retval = NJS_VMCODE_NO_RETVAL }
  2371. -};
  2372. -
  2373. -
  2374. -static const njs_vmcode_1addr_t  njs_trap_primitive_argument = {
  2375. -    .code = { .operation = njs_vmcode_primitive_argument,
  2376. -              .operands =  NJS_VMCODE_NO_OPERAND,
  2377. -              .retval = NJS_VMCODE_NO_RETVAL }
  2378. -};
  2379. -
  2380. -
  2381. -static const njs_vm_trap_t  njs_vm_traps[] = {
  2382. -    /* NJS_TRAP_NUMBER     */     { .code = &njs_trap_number[0]       },
  2383. -    /* NJS_TRAP_NUMBERS    */     { .code = &njs_trap_numbers[0]      },
  2384. -    /* NJS_TRAP_ADDITION   */     { .code = &njs_trap_addition[0]     },
  2385. -    /* NJS_TRAP_COMPARISON */     { .code = &njs_trap_comparison[0]   },
  2386. -    /* NJS_TRAP_INCDEC     */     { .code = &njs_trap_numbers[1],
  2387. -                                    .reference = 1                    },
  2388. -    /* NJS_TRAP_PROPERTY   */     { .code = &njs_trap_property[0]     },
  2389. -    /* NJS_TRAP_NUMBER_ARG */     { .code = &njs_trap_number_argument },
  2390. -    /* NJS_TRAP_STRING_ARG */     { .code = &njs_trap_string_argument },
  2391. -    /* NJS_TRAP_PRIMITIVE_ARG */  { .code = &njs_trap_primitive_argument },
  2392. -};
  2393. -
  2394. -
  2395. -static void
  2396. -njs_vm_trap(njs_vm_t *vm, njs_trap_t trap, njs_value_t *value1,
  2397. -    njs_value_t *value2)
  2398. -{
  2399. -    njs_native_frame_t  *frame;
  2400. -
  2401. -    frame = vm->top_frame;
  2402. -
  2403. -    /*
  2404. -     * The trap_scratch value is for results of "valueOf" and "toString"
  2405. -     * methods.  The trap_values[] are original operand values which will
  2406. -     * be replaced with primitive values returned by "valueOf" or "toString"
  2407. -     * methods.  The scratch value is stored separately to preserve the
  2408. -     * original operand values for the second method call if the first
  2409. -     * method call will return non-primitive value.
  2410. -     */
  2411. -    njs_set_invalid(&frame->trap_scratch);
  2412. -    frame->trap_values[1] = *value2;
  2413. -    frame->trap_reference = njs_vm_traps[trap].reference;
  2414. -
  2415. -    if (njs_vm_traps[trap].reference) {
  2416. -        frame->trap_values[0].data.u.value = value1;
  2417. -
  2418. -    } else {
  2419. -        frame->trap_values[0] = *value1;
  2420. -    }
  2421. -
  2422. -    frame->trap_restart = vm->current;
  2423. -    vm->current = (u_char *) njs_vm_traps[trap].code;
  2424. -}
  2425. -
  2426. -
  2427. -static void
  2428. -njs_vm_trap_argument(njs_vm_t *vm, njs_trap_t trap)
  2429. -{
  2430. -    njs_value_t         *value;
  2431. -    njs_native_frame_t  *frame;
  2432. -
  2433. -    frame = vm->top_frame;
  2434. -    value = frame->trap_scratch.data.u.value;
  2435. -    njs_set_invalid(&frame->trap_scratch);
  2436. -
  2437. -    frame->trap_values[1].data.u.value = value;
  2438. -    frame->trap_values[0] = *value;
  2439. -
  2440. -    frame->trap_restart = vm->current;
  2441. -    vm->current = (u_char *) njs_vm_traps[trap].code;
  2442. -}
  2443. -
  2444. -
  2445. -static njs_ret_t
  2446. -njs_vmcode_number_primitive(njs_vm_t *vm, njs_value_t *invld, njs_value_t *narg)
  2447. -{
  2448. -    double       num;
  2449. -    njs_ret_t    ret;
  2450. -    njs_value_t  *value;
  2451. -
  2452. -    value = &vm->top_frame->trap_values[(uintptr_t) narg];
  2453. -
  2454. -    ret = njs_value_to_primitive(vm, value, 0);
  2455. -
  2456. -    if (nxt_fast_path(ret > 0)) {
  2457. -
  2458. -        if (!njs_is_numeric(value)) {
  2459. -            num = NAN;
  2460. -
  2461. -            if (njs_is_string(value)) {
  2462. -                num = njs_string_to_number(value, 0);
  2463. -            }
  2464. -
  2465. -            njs_set_number(value, num);
  2466. -        }
  2467. -
  2468. -        ret = sizeof(njs_vmcode_1addr_t);
  2469. -    }
  2470. -
  2471. -    return ret;
  2472. -}
  2473. -
  2474. -
  2475. -static njs_ret_t
  2476. -njs_vmcode_string_primitive(njs_vm_t *vm, njs_value_t *invld, njs_value_t *narg)
  2477. -{
  2478. -    njs_ret_t    ret;
  2479. -    njs_value_t  *value;
  2480. -
  2481. -    value = &vm->top_frame->trap_values[(uintptr_t) narg];
  2482. -
  2483. -    ret = njs_value_to_primitive(vm, value, 1);
  2484. -
  2485. -    if (nxt_fast_path(ret > 0)) {
  2486. -        ret = njs_primitive_value_to_string(vm, value, value);
  2487. -
  2488. -        if (nxt_fast_path(ret == NXT_OK)) {
  2489. -            return sizeof(njs_vmcode_1addr_t);
  2490. -        }
  2491. -    }
  2492. -
  2493. -    return ret;
  2494. -}
  2495. -
  2496. -
  2497. -static njs_ret_t
  2498. -njs_vmcode_addition_primitive(njs_vm_t *vm, njs_value_t *invld,
  2499. -    njs_value_t *narg)
  2500. -{
  2501. -    njs_ret_t    ret;
  2502. -    nxt_uint_t   hint;
  2503. -    njs_value_t  *value;
  2504. -
  2505. -    value = &vm->top_frame->trap_values[(uintptr_t) narg];
  2506. -
  2507. -    /*
  2508. -     * ECMAScript 5.1:
  2509. -     *   Date should return String, other types sould return Number.
  2510. -     */
  2511. -    hint = njs_is_date(value);
  2512. -
  2513. -    ret = njs_value_to_primitive(vm, value, hint);
  2514. -
  2515. -    if (nxt_fast_path(ret > 0)) {
  2516. -        return sizeof(njs_vmcode_1addr_t);
  2517. -    }
  2518. -
  2519. -    return ret;
  2520. -}
  2521. -
  2522. -
  2523. -static njs_ret_t
  2524. -njs_vmcode_comparison_primitive(njs_vm_t *vm, njs_value_t *invld,
  2525. -    njs_value_t *narg)
  2526. -{
  2527. -    njs_ret_t    ret;
  2528. -    njs_value_t  *value;
  2529. -
  2530. -    value = &vm->top_frame->trap_values[(uintptr_t) narg];
  2531. -
  2532. -    ret = njs_value_to_primitive(vm, value, 0);
  2533. -
  2534. -    if (nxt_fast_path(ret > 0)) {
  2535. -        return sizeof(njs_vmcode_1addr_t);
  2536. -    }
  2537. -
  2538. -    return ret;
  2539. -}
  2540. -
  2541. -
  2542. -static njs_ret_t
  2543. -njs_vmcode_number_argument(njs_vm_t *vm, njs_value_t *invld1,
  2544. -    njs_value_t *inlvd2)
  2545. -{
  2546. -    double       num;
  2547. -    njs_ret_t    ret;
  2548. -    njs_value_t  *value;
  2549. -
  2550. -    value = &vm->top_frame->trap_values[0];
  2551. -
  2552. -    ret = njs_value_to_primitive(vm, value, 0);
  2553. -
  2554. -    if (nxt_fast_path(ret > 0)) {
  2555. -
  2556. -        if (!njs_is_numeric(value)) {
  2557. -            num = NAN;
  2558. -
  2559. -            if (njs_is_string(value)) {
  2560. -                num = njs_string_to_number(value, 0);
  2561. -            }
  2562. -
  2563. -            njs_set_number(value, num);
  2564. -        }
  2565. -
  2566. -        *vm->top_frame->trap_values[1].data.u.value = *value;
  2567. -
  2568. -        vm->current = vm->top_frame->trap_restart;
  2569. -        vm->top_frame->trap_restart = NULL;
  2570. -
  2571. -        return 0;
  2572. -    }
  2573. -
  2574. -    return ret;
  2575. -}
  2576. -
  2577. -
  2578. -static njs_ret_t
  2579. -njs_vmcode_string_argument(njs_vm_t *vm, njs_value_t *invld1,
  2580. -    njs_value_t *inlvd2)
  2581. -{
  2582. -    njs_ret_t    ret;
  2583. -    njs_value_t  *value;
  2584. -
  2585. -    value = &vm->top_frame->trap_values[0];
  2586. -
  2587. -    ret = njs_value_to_primitive(vm, value, 1);
  2588. -
  2589. -    if (nxt_fast_path(ret > 0)) {
  2590. -        ret = njs_primitive_value_to_string(vm, value, value);
  2591. -
  2592. -        if (nxt_fast_path(ret == NXT_OK)) {
  2593. -            *vm->top_frame->trap_values[1].data.u.value = *value;
  2594. -
  2595. -            vm->current = vm->top_frame->trap_restart;
  2596. -            vm->top_frame->trap_restart = NULL;
  2597. -        }
  2598. -    }
  2599. -
  2600. -    return ret;
  2601. -}
  2602. -
  2603. -
  2604. -static njs_ret_t
  2605. -njs_vmcode_primitive_argument(njs_vm_t *vm, njs_value_t *invld1,
  2606. -    njs_value_t *inlvd2)
  2607. -{
  2608. -    njs_ret_t    ret;
  2609. -    njs_value_t  *value;
  2610. -
  2611. -    value = &vm->top_frame->trap_values[0];
  2612. -
  2613. -    ret = njs_value_to_primitive(vm, value, 0);
  2614. -
  2615. -    if (nxt_fast_path(ret > 0)) {
  2616. -        *vm->top_frame->trap_values[1].data.u.value = *value;
  2617. -
  2618. -        vm->current = vm->top_frame->trap_restart;
  2619. -        vm->top_frame->trap_restart = NULL;
  2620. -
  2621. -        return 0;
  2622. -    }
  2623. -
  2624. -    return ret;
  2625. -}
  2626. -
  2627. -
  2628. -static njs_ret_t
  2629. -njs_vmcode_restart(njs_vm_t *vm, njs_value_t *invld1, njs_value_t *invld2)
  2630. -{
  2631. -    u_char                *restart;
  2632. -    njs_ret_t             ret;
  2633. -    njs_value_t           *retval, *value1;
  2634. -    njs_native_frame_t    *frame;
  2635. -    njs_vmcode_generic_t  *vmcode;
  2636. -
  2637. -    frame = vm->top_frame;
  2638. -    restart = frame->trap_restart;
  2639. -    frame->trap_restart = NULL;
  2640. -    vm->current = restart;
  2641. -    vmcode = (njs_vmcode_generic_t *) restart;
  2642. -
  2643. -    value1 = &frame->trap_values[0];
  2644. -
  2645. -    if (frame->trap_reference) {
  2646. -        value1 = value1->data.u.value;
  2647. -    }
  2648. -
  2649. -    ret = vmcode->code.operation(vm, value1, &frame->trap_values[1]);
  2650. -
  2651. -    if (nxt_slow_path(ret == NJS_ERROR)) {
  2652. -        return ret;
  2653. -    }
  2654. -
  2655. -    if (nxt_slow_path(ret == NJS_TRAP)) {
  2656. -        /* Trap handlers are not reentrant. */
  2657. -        njs_internal_error(vm, "trap inside restart instruction");
  2658. -        return NXT_ERROR;
  2659. -    }
  2660. -
  2661. -    if (vmcode->code.retval) {
  2662. -        retval = njs_vmcode_operand(vm, vmcode->operand1);
  2663. -        njs_release(vm, retval);
  2664. -        *retval = vm->retval;
  2665. -    }
  2666. -
  2667. -    return ret;
  2668. -}
  2669. -
  2670. -
  2671.  njs_ret_t
  2672.  njs_vm_value_to_string(njs_vm_t *vm, nxt_str_t *dst, const njs_value_t *src)
  2673.  {
  2674. @@ -2689,14 +2524,7 @@ njs_vm_value_to_string(njs_vm_t *vm, nxt
  2675.  
  2676.      value = *src;
  2677.  
  2678. -    if (nxt_slow_path(!njs_is_primitive(&value))) {
  2679. -        ret = njs_object_value_to_string(vm, &value);
  2680. -        if (nxt_slow_path(ret != NXT_OK)) {
  2681. -            return ret;
  2682. -        }
  2683. -    }
  2684. -
  2685. -    ret = njs_primitive_value_to_string(vm, &value, &value);
  2686. +    ret = njs_value_to_string(vm, &value, &value);
  2687.  
  2688.      if (nxt_fast_path(ret == NXT_OK)) {
  2689.          size = value.short_string.size;
  2690. @@ -2723,73 +2551,6 @@ njs_vm_value_to_string(njs_vm_t *vm, nxt
  2691.  }
  2692.  
  2693.  
  2694. -static njs_ret_t
  2695. -njs_object_value_to_string(njs_vm_t *vm, njs_value_t *value)
  2696. -{
  2697. -    u_char              *current;
  2698. -    njs_ret_t           ret;
  2699. -    njs_native_frame_t  *previous;
  2700. -
  2701. -    static const njs_vmcode_1addr_t  value_to_string[] = {
  2702. -        { .code = { .operation = njs_vmcode_value_to_string,
  2703. -                    .operands =  NJS_VMCODE_NO_OPERAND,
  2704. -                    .retval = NJS_VMCODE_NO_RETVAL } },
  2705. -    };
  2706. -
  2707. -    /*
  2708. -     * Execute the single njs_vmcode_value_to_string() instruction.
  2709. -     * The trap_scratch value is for results of "toString" or "valueOf"
  2710. -     * methods.  The trap_values[0] is an original object value which will
  2711. -     * be replaced with primitive value returned by "toString" or "valueOf"
  2712. -     * methods.  The scratch value is stored separately to preserve the
  2713. -     * original object value for the second "valueOf" method call if the
  2714. -     * first "toString" method call will return non-primitive value.
  2715. -     */
  2716. -
  2717. -    current = vm->current;
  2718. -    vm->current = (u_char *) value_to_string;
  2719. -
  2720. -    njs_set_invalid(&vm->top_frame->trap_scratch);
  2721. -    vm->top_frame->trap_values[0] = *value;
  2722. -
  2723. -    /*
  2724. -     * Prevent njs_vmcode_interpreter() to unwind the current frame if
  2725. -     * an exception happens.  It preserves the current frame state if
  2726. -     * njs_vm_value_string() is called from within njs_vm_run().
  2727. -     */
  2728. -    previous = vm->top_frame->previous;
  2729. -    vm->top_frame->previous = NULL;
  2730. -
  2731. -    ret = njs_vmcode_interpreter(vm);
  2732. -
  2733. -    if (ret == NJS_STOP) {
  2734. -        ret = NXT_OK;
  2735. -        *value = vm->top_frame->trap_values[0];
  2736. -    }
  2737. -
  2738. -    vm->current = current;
  2739. -    vm->top_frame->previous = previous;
  2740. -
  2741. -    return ret;
  2742. -}
  2743. -
  2744. -
  2745. -static njs_ret_t
  2746. -njs_vmcode_value_to_string(njs_vm_t *vm, njs_value_t *invld1,
  2747. -    njs_value_t *invld2)
  2748. -{
  2749. -    njs_ret_t  ret;
  2750. -
  2751. -    ret = njs_value_to_primitive(vm, &vm->top_frame->trap_values[0], 1);
  2752. -
  2753. -    if (nxt_fast_path(ret > 0)) {
  2754. -        return NJS_STOP;
  2755. -    }
  2756. -
  2757. -    return ret;
  2758. -}
  2759. -
  2760. -
  2761.  nxt_int_t
  2762.  njs_vm_value_string_copy(njs_vm_t *vm, nxt_str_t *retval,
  2763.      const njs_value_t *value, uintptr_t *next)
  2764. diff --git a/njs/njs_vm.h b/njs/njs_vm.h
  2765. --- a/njs/njs_vm.h
  2766. +++ b/njs/njs_vm.h
  2767. @@ -19,33 +19,14 @@
  2768.   *    -3:                        not used;
  2769.   *    -4 (NJS_STOP/NXT_DONE):    njs_vmcode_stop() has stopped execution,
  2770.   *                               execution has completed successfully;
  2771. - *    -5 (NJS_TRAP)              trap to convert objects to primitive values;
  2772. - *    -6 .. -11:                 not used.
  2773. + *    -5 .. -11:                 not used.
  2774.   */
  2775.  
  2776.  #define NJS_STOP                 NXT_DONE
  2777. -#define NJS_TRAP                 (-5)
  2778.  
  2779.  /* The last return value which preempts execution. */
  2780.  #define NJS_PREEMPT              (-11)
  2781.  
  2782. -/*  Traps events. */
  2783. -typedef enum {
  2784. -    NJS_TRAP_NUMBER = 0,
  2785. -    NJS_TRAP_NUMBERS,
  2786. -    NJS_TRAP_ADDITION,
  2787. -    NJS_TRAP_COMPARISON,
  2788. -    NJS_TRAP_INCDEC,
  2789. -    NJS_TRAP_PROPERTY,
  2790. -    NJS_TRAP_NUMBER_ARG,
  2791. -    NJS_TRAP_STRING_ARG,
  2792. -    NJS_TRAP_PRIMITIVE_ARG,
  2793. -} njs_trap_t;
  2794. -
  2795. -
  2796. -#define njs_trap(vm, code)                                                    \
  2797. -    vm->trap = code, NJS_TRAP;
  2798. -
  2799.  
  2800.  /*
  2801.   * A user-defined function is prepared to run.  This code is never
  2802. @@ -532,12 +513,6 @@ enum njs_function_e {
  2803.  
  2804.  
  2805.  typedef struct {
  2806. -    const njs_vmcode_1addr_t  *code;
  2807. -    nxt_bool_t                reference;
  2808. -} njs_vm_trap_t;
  2809. -
  2810. -
  2811. -typedef struct {
  2812.      uint32_t                  line;
  2813.      nxt_str_t                 file;
  2814.      nxt_str_t                 name;
  2815. @@ -549,6 +524,8 @@ struct njs_vm_s {
  2816.      /* njs_vm_t must be aligned to njs_value_t due to scratch value. */
  2817.      njs_value_t              retval;
  2818.  
  2819. +    nxt_uint_t               count;
  2820. +
  2821.      nxt_array_t              *paths;
  2822.  
  2823.      u_char                   *current;
  2824. @@ -613,8 +590,6 @@ struct njs_vm_s {
  2825.      nxt_array_t              *debug;
  2826.      nxt_array_t              *backtrace;
  2827.  
  2828. -    njs_trap_t               trap:8;
  2829. -
  2830.      /*
  2831.       * njs_property_query() uses it to store reference to a temporary
  2832.       * PROPERTY_HANDLERs for NJS_EXTERNAL values in NJS_PROPERTY_QUERY_SET
  2833. @@ -659,6 +634,7 @@ struct njs_vm_shared_s {
  2834.  
  2835.  
  2836.  nxt_int_t njs_vmcode_interpreter(njs_vm_t *vm);
  2837. +nxt_int_t njs_vmcode_run(njs_vm_t *vm);
  2838.  
  2839.  njs_ret_t njs_vmcode_object(njs_vm_t *vm, njs_value_t *inlvd1,
  2840.      njs_value_t *inlvd2);
  2841. @@ -821,6 +797,7 @@ extern const nxt_mem_proto_t     njs_arr
  2842.  extern const nxt_lvlhsh_proto_t  njs_object_hash_proto;
  2843.  
  2844.  extern const njs_vmcode_generic_t  njs_continuation_nexus[];
  2845. +extern const njs_vmcode_generic_t  njs_stop[];
  2846.  
  2847.  
  2848.  #endif /* _NJS_VM_H_INCLUDED_ */
  2849. diff --git a/njs/test/njs_interactive_test.c b/njs/test/njs_interactive_test.c
  2850. --- a/njs/test/njs_interactive_test.c
  2851. +++ b/njs/test/njs_interactive_test.c
  2852. @@ -230,8 +230,7 @@ static njs_interactive_test_t  njs_test[
  2853.  
  2854.      { nxt_string("var o = { toString: function() { return [1] } }" ENTER
  2855.                   "o" ENTER),
  2856. -      nxt_string("TypeError: Cannot convert object to primitive value\n"
  2857. -                 "    at main (native)\n") },
  2858. +      nxt_string("TypeError: Cannot convert object to primitive value") },
  2859.  
  2860.      /* line numbers */
  2861.  
  2862. diff --git a/njs/test/njs_unit_test.c b/njs/test/njs_unit_test.c
  2863. --- a/njs/test/njs_unit_test.c
  2864. +++ b/njs/test/njs_unit_test.c
  2865. @@ -450,6 +450,49 @@ static njs_unit_test_t  njs_test[] =
  2866.                   "var b = { toString: function() { return a+'b' } }; '0'+b"),
  2867.        nxt_string("0ab") },
  2868.  
  2869. +    { nxt_string("({valueOf:()=>'4'}) / ({valueOf:()=>2})"),
  2870. +      nxt_string("2") },
  2871. +
  2872. +    { nxt_string("({valueOf:()=>{throw 'x'}}) / ({valueOf:()=>{throw 'y'}});"
  2873. +                 "var e; try { x/y } catch(ex) {e = ex}; ex"),
  2874. +      nxt_string("x") },
  2875. +
  2876. +    { nxt_string("({valueOf:()=>2}) / ({valueOf:()=>{throw 'y'}});"
  2877. +                 "var e; try { x/y } catch(ex) {e = ex}; ex"),
  2878. +      nxt_string("y") },
  2879. +
  2880. +    { nxt_string("({valueOf:()=>'4'}) % ({valueOf:()=>3})"),
  2881. +      nxt_string("1") },
  2882. +
  2883. +    { nxt_string("({valueOf:()=>9}) >>> ({valueOf:()=>2})"),
  2884. +      nxt_string("2") },
  2885. +
  2886. +    { nxt_string("({valueOf:()=>0x1f}) & ({valueOf:()=>0xf})"),
  2887. +      nxt_string("15") },
  2888. +
  2889. +    { nxt_string("({valueOf:()=>0x1f}) ^ ({valueOf:()=>0xf})"),
  2890. +      nxt_string("16") },
  2891. +
  2892. +    { nxt_string("({valueOf:()=>0xf}) == ({valueOf:()=>0xf})"),
  2893. +      nxt_string("false") },
  2894. +
  2895. +    { nxt_string("({valueOf:()=>0xf}) == 0xf"),
  2896. +      nxt_string("true") },
  2897. +
  2898. +    { nxt_string("0xf == ({valueOf:()=>0xf})"),
  2899. +      nxt_string("true") },
  2900. +
  2901. +    { nxt_string("({valueOf:()=>'0xf'}) == 0xf"),
  2902. +      nxt_string("true") },
  2903. +
  2904. +    { nxt_string("0xf == ({valueOf:()=>'0xf'})"),
  2905. +      nxt_string("true") },
  2906. +
  2907. +    { nxt_string("({valueOf:()=>0xf}) == '0xf'"),
  2908. +      nxt_string("true") },
  2909. +
  2910. +    { nxt_string("'0xf' == ({valueOf:()=>0xf})"),
  2911. +      nxt_string("true") },
  2912.      /**/
  2913.  
  2914.      { nxt_string("1 + undefined"),
  2915. @@ -1648,6 +1691,9 @@ static njs_unit_test_t  njs_test[] =
  2916.      { nxt_string("new 0[isNaN]"),
  2917.        nxt_string("TypeError: (intermediate value)[\"[object Function]\"] is not a function") },
  2918.  
  2919. +    { nxt_string("new 0[undefined]"),
  2920. +      nxt_string("TypeError: (intermediate value)[\"undefined\"] is not a function") },
  2921. +
  2922.      /**/
  2923.  
  2924.      { nxt_string("var a; a = 1 ? 2 : 3"),
  2925. @@ -4766,6 +4812,9 @@ static njs_unit_test_t  njs_test[] =
  2926.      { nxt_string("String.prototype.substring(1, 5)"),
  2927.        nxt_string("") },
  2928.  
  2929. +    { nxt_string("String.prototype.substr.call({toString:()=>{throw new Error('Oops')}})"),
  2930. +      nxt_string("Error: Oops") },
  2931. +
  2932.      { nxt_string("String.prototype.slice(1, 5)"),
  2933.        nxt_string("") },
  2934.  
  2935. @@ -6418,6 +6467,9 @@ static njs_unit_test_t  njs_test[] =
  2936.      { nxt_string("(function(){ function f() {return f}; return f()})()"),
  2937.        nxt_string("[object Function]") },
  2938.  
  2939. +    { nxt_string("function  f() {}; f.toString = ()=> 'F'; ({'F':1})[f]"),
  2940. +      nxt_string("1") },
  2941. +
  2942.      { nxt_string("var a = ''; "
  2943.                   "function f(list) {"
  2944.                   "    function add(v) {a+=v};"
  2945. @@ -10324,6 +10376,9 @@ static njs_unit_test_t  njs_test[] =
  2946.      { nxt_string("Date.UTC(2011, 5, 24, 6, 0)"),
  2947.        nxt_string("1308895200000") },
  2948.  
  2949. +    { nxt_string("Date.UTC({valueOf:()=>2011}, 5, 24, 6, 0)"),
  2950. +      nxt_string("1308895200000") },
  2951. +
  2952.      { nxt_string("Date.parse()"),
  2953.        nxt_string("NaN") },
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top