/**
 * The Object object's 'isSealed' routine
 *
 * See also:
 *          ECMA-262 v5, 15.2.3.11
 *
 * @return completion value
 *         Returned value must be freed with ecma_free_completion_value.
 */
static ecma_completion_value_t
ecma_builtin_object_object_is_sealed (ecma_value_t this_arg __attr_unused___, /**< 'this' argument */
                                      ecma_value_t arg) /**< routine's argument */
{
  ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();

  // 1.
  if (!ecma_is_value_object (arg))
  {
    ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE));
  }
  else
  {
    ecma_object_t *obj_p = ecma_get_object_from_value (arg);

    bool is_sealed;

    // 3.
    if (ecma_get_object_extensible (obj_p))
    {
      is_sealed = false;
    }
    else
    {
      /* the value can be updated in the loop below */
      is_sealed = true;

      // 2.
      ecma_collection_header_t *props_p = ecma_op_object_get_property_names (obj_p, false, false, false);

      ecma_collection_iterator_t iter;
      ecma_collection_iterator_init (&iter, props_p);

      while (ecma_collection_iterator_next (&iter))
      {
        ecma_string_t *property_name_p = ecma_get_string_from_value (*iter.current_value_p);

        // 2.a
        ecma_property_t *property_p = ecma_op_object_get_own_property (obj_p, property_name_p);

        // 2.b
        if (ecma_is_property_configurable (property_p))
        {
          is_sealed = false;
          break;
        }
      }

      ecma_free_values_collection (props_p, true);
    }

    // 4.
    ret_value = ecma_make_simple_completion_value (is_sealed
                                                   ? ECMA_SIMPLE_VALUE_TRUE
                                                   : ECMA_SIMPLE_VALUE_FALSE);
  }

  return ret_value;
} /* ecma_builtin_object_object_is_sealed */
/**
 * The Object.keys and Object.getOwnPropertyNames routine's common part.
 *
 * See also:
 *          ECMA-262 v5, 15.2.3.4 steps 2-5
 *          ECMA-262 v5, 15.2.3.14 steps 3-6
 *
 * @return ecma value - Array of property names.
 *         Returned value must be freed with ecma_free_value.
 */
ecma_value_t
ecma_builtin_helper_object_get_properties (ecma_object_t *obj_p, /**< object */
                                           bool only_enumerable_properties) /**< list enumerable properties? */
{
  JERRY_ASSERT (obj_p != NULL);

  ecma_value_t new_array = ecma_op_create_array_object (NULL, 0, false);
  JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (new_array));
  ecma_object_t *new_array_p = ecma_get_object_from_value (new_array);

  uint32_t index = 0;

  ecma_collection_header_t *props_p = ecma_op_object_get_property_names (obj_p,
                                                                         false,
                                                                         only_enumerable_properties,
                                                                         false);

  ecma_collection_iterator_t iter;
  ecma_collection_iterator_init (&iter, props_p);

  while (ecma_collection_iterator_next (&iter))
  {
    ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index);

    ecma_value_t completion = ecma_builtin_helper_def_prop (new_array_p,
                                                            index_string_p,
                                                            *iter.current_value_p,
                                                            true, /* Writable */
                                                            true, /* Enumerable */
                                                            true, /* Configurable */
                                                            false); /* Failure handling */

    JERRY_ASSERT (ecma_is_value_true (completion));

    ecma_deref_ecma_string (index_string_p);

    index++;
  }

  ecma_free_values_collection (props_p, true);

  return new_array;
} /* ecma_builtin_helper_object_get_properties */
示例#3
0
/**
 * 'for-in' opcode handler
 *
 * See also:
 *          ECMA-262 v5, 12.6.4
 *
 * @return completion value
 *         Returned value must be freed with ecma_free_value
 */
ecma_collection_header_t *
opfunc_for_in (ecma_value_t left_value, /**< left value */
               ecma_value_t *result_obj_p) /**< expression object */
{
  ecma_value_t compl_val = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
  ecma_collection_header_t *prop_names_p = NULL;

  /* 3. */
  if (!ecma_is_value_undefined (left_value)
      && !ecma_is_value_null (left_value))
  {
    /* 4. */
    ECMA_TRY_CATCH (obj_expr_value,
                    ecma_op_to_object (left_value),
                    compl_val);

    ecma_object_t *obj_p = ecma_get_object_from_value (obj_expr_value);
    prop_names_p = ecma_op_object_get_property_names (obj_p, false, true, true);

    if (prop_names_p->unit_number != 0)
    {
      ecma_ref_object (obj_p);
      *result_obj_p = ecma_make_object_value (obj_p);
    }
    else
    {
      ecma_dealloc_collection_header (prop_names_p);
      prop_names_p = NULL;
    }

    ECMA_FINALIZE (obj_expr_value);
  }

  JERRY_ASSERT (ecma_is_value_empty (compl_val));

  return prop_names_p;
} /* opfunc_for_in */
示例#4
0
/**
 * [[DefineOwnProperty]] ecma array object's operation
 *
 * See also:
 *          ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8
 *          ECMA-262 v5, 15.4.5.1
 *
 * @return completion value
 *         Returned value must be freed with ecma_free_completion_value
 */
ecma_completion_value_t
ecma_op_array_object_define_own_property (ecma_object_t *obj_p, /**< the array object */
                                          ecma_string_t *property_name_p, /**< property name */
                                          const ecma_property_descriptor_t *property_desc_p, /**< property descriptor */
                                          bool is_throw) /**< flag that controls failure handling */
{
  JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_ARRAY);


  // 1.
  ecma_string_t *magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH);
  ecma_property_t *len_prop_p = ecma_op_object_get_own_property (obj_p, magic_string_length_p);
  JERRY_ASSERT (len_prop_p != NULL && len_prop_p->type == ECMA_PROPERTY_NAMEDDATA);

  // 2.
  ecma_value_t old_len_value = ecma_get_named_data_property_value (len_prop_p);

  ecma_number_t *num_p = ecma_get_number_from_value (old_len_value);
  uint32_t old_len_uint32 = ecma_number_to_uint32 (*num_p);

  // 3.
  bool is_property_name_equal_length = ecma_compare_ecma_strings (property_name_p,
                                                                  magic_string_length_p);

  ecma_deref_ecma_string (magic_string_length_p);

  if (is_property_name_equal_length)
  {
    // a.
    if (!property_desc_p->is_value_defined)
    {
      // i.
      return ecma_op_general_object_define_own_property (obj_p, property_name_p, property_desc_p, is_throw);
    }

    ecma_number_t new_len_num;

    // c.
    ecma_completion_value_t completion = ecma_op_to_number (property_desc_p->value);
    if (ecma_is_completion_value_throw (completion))
    {
      return completion;
    }

    JERRY_ASSERT (ecma_is_completion_value_normal (completion)
                  && ecma_is_value_number (ecma_get_completion_value_value (completion)));

    new_len_num = *ecma_get_number_from_completion_value (completion);

    ecma_free_completion_value (completion);

    uint32_t new_len_uint32 = ecma_number_to_uint32 (new_len_num);

    // d.
    if (ecma_uint32_to_number (new_len_uint32) != new_len_num)
    {
      return ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_RANGE));
    }
    else
    {
      // b., e.
      ecma_number_t *new_len_num_p = ecma_alloc_number ();
      *new_len_num_p = new_len_num;

      ecma_property_descriptor_t new_len_property_desc = *property_desc_p;
      new_len_property_desc.value = ecma_make_number_value (new_len_num_p);

      ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();

      // f.
      if (new_len_uint32 >= old_len_uint32)
      {
        // i.
        magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH);
        ret_value = ecma_op_general_object_define_own_property (obj_p,
                                                                magic_string_length_p,
                                                                &new_len_property_desc,
                                                                is_throw);
        ecma_deref_ecma_string (magic_string_length_p);
      }
      else
      {
        // g.
        if (!ecma_is_property_writable (len_prop_p))
        {
          ret_value = ecma_reject (is_throw);
        }
        else
        {
          // h.
          bool new_writable;
          if (!new_len_property_desc.is_writable_defined
              || new_len_property_desc.is_writable)
          {
            new_writable = true;
          }
          else
          {
            // ii.
            new_writable = false;

            // iii.
            new_len_property_desc.is_writable_defined = true;
            new_len_property_desc.is_writable = true;
          }

          // j.
          magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH);
          ecma_completion_value_t succeeded = ecma_op_general_object_define_own_property (obj_p,
                                                                                          magic_string_length_p,
                                                                                          &new_len_property_desc,
                                                                                          is_throw);
          ecma_deref_ecma_string (magic_string_length_p);

          /* Handling normal false and throw values */
          if (!ecma_is_completion_value_normal_true (succeeded))
          {
            JERRY_ASSERT (ecma_is_completion_value_normal_false (succeeded)
                          || ecma_is_completion_value_throw (succeeded));

            // k.
            ret_value = succeeded;
          }
          else
          {
            // l
            JERRY_ASSERT (new_len_uint32 < old_len_uint32);

            /*
             * Item i. is replaced with faster iteration: only indices that actually exist in the array, are iterated
             */
            bool is_reduce_succeeded = true;

            ecma_collection_header_t *array_index_props_p = ecma_op_object_get_property_names (obj_p,
                                                                                               true,
                                                                                               false,
                                                                                               false);

            ecma_length_t array_index_props_num = array_index_props_p->unit_number;

            MEM_DEFINE_LOCAL_ARRAY (array_index_values_p, array_index_props_num, uint32_t);

            ecma_collection_iterator_t iter;
            ecma_collection_iterator_init (&iter, array_index_props_p);

            uint32_t array_index_values_pos = 0;

            while (ecma_collection_iterator_next (&iter))
            {
              ecma_string_t *property_name_p = ecma_get_string_from_value (*iter.current_value_p);

              uint32_t index;
              bool is_index = ecma_string_get_array_index (property_name_p, &index);
              JERRY_ASSERT (is_index);
              JERRY_ASSERT (index < old_len_uint32);

              array_index_values_p[array_index_values_pos++] = index;
            }

            JERRY_ASSERT (array_index_values_pos == array_index_props_num);

            while (array_index_values_pos != 0
                   && array_index_values_p[--array_index_values_pos] >= new_len_uint32)
            {
              uint32_t index = array_index_values_p[array_index_values_pos];

              // ii.
              ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index);
              ecma_completion_value_t delete_succeeded = ecma_op_object_delete (obj_p,
                                                                                index_string_p,
                                                                                false);
              ecma_deref_ecma_string (index_string_p);

              if (ecma_is_completion_value_normal_false (delete_succeeded))
              {
                // iii.
                new_len_uint32 = (index + 1u);

                ecma_number_t *new_len_num_p = ecma_get_number_from_value (new_len_property_desc.value);

                // 1.
                *new_len_num_p = ecma_uint32_to_number (index + 1u);

                // 2.
                if (!new_writable)
                {
                  new_len_property_desc.is_writable_defined = true;
                  new_len_property_desc.is_writable = false;
                }

                // 3.
                ecma_string_t *magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH);
                ecma_completion_value_t completion = ecma_op_general_object_define_own_property (obj_p,
                                                                                                 magic_string_length_p,
                                                                                                 &new_len_property_desc,
                                                                                                 false);
                ecma_deref_ecma_string (magic_string_length_p);

                JERRY_ASSERT (ecma_is_completion_value_normal_true (completion)
                              || ecma_is_completion_value_normal_false (completion));

                is_reduce_succeeded = false;

                break;
              }
            }

            MEM_FINALIZE_LOCAL_ARRAY (array_index_values_p);

            ecma_free_values_collection (array_index_props_p, true);

            if (!is_reduce_succeeded)
            {
              ret_value = ecma_reject (is_throw);
            }
            else
            {
              // m.
              if (!new_writable)
              {
                ecma_property_descriptor_t prop_desc_not_writable = ecma_make_empty_property_descriptor ();

                prop_desc_not_writable.is_writable_defined = true;
                prop_desc_not_writable.is_writable = false;

                ecma_completion_value_t completion_set_not_writable;
                magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH);
                completion_set_not_writable = ecma_op_general_object_define_own_property (obj_p,
                                                                                          magic_string_length_p,
                                                                                          &prop_desc_not_writable,
                                                                                          false);
                ecma_deref_ecma_string (magic_string_length_p);
                JERRY_ASSERT (ecma_is_completion_value_normal_true (completion_set_not_writable));
              }

              ret_value = ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_TRUE);
            }
          }
        }
      }

      ecma_dealloc_number (new_len_num_p);

      return ret_value;
    }

    JERRY_UNREACHABLE ();
  }
  else
  {
    // 4.a.
    uint32_t index;

    if (!ecma_string_get_array_index (property_name_p, &index))
    {
      // 5.
      return ecma_op_general_object_define_own_property (obj_p,
                                                         property_name_p,
                                                         property_desc_p,
                                                         is_throw);
    }

    // 4.

    // b.
    if (index >= old_len_uint32
        && !ecma_is_property_writable (len_prop_p))
    {
      return ecma_reject (is_throw);
    }

    // c.
    ecma_completion_value_t succeeded = ecma_op_general_object_define_own_property (obj_p,
                                                                                    property_name_p,
                                                                                    property_desc_p,
                                                                                    false);
    // d.
    JERRY_ASSERT (ecma_is_completion_value_normal_true (succeeded)
                  || ecma_is_completion_value_normal_false (succeeded));

    if (ecma_is_completion_value_normal_false (succeeded))
    {
      return ecma_reject (is_throw);
    }

    // e.
    if (index >= old_len_uint32)
    {
      // i., ii.
      ecma_number_t *num_p = ecma_alloc_number ();
      *num_p = ecma_number_add (ecma_uint32_to_number (index), ECMA_NUMBER_ONE);

      ecma_named_data_property_assign_value (obj_p, len_prop_p, ecma_make_number_value (num_p));

      ecma_dealloc_number (num_p);
    }

    // f.
    return ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_TRUE);
  }

  JERRY_UNREACHABLE ();
} /* ecma_op_array_object_define_own_property */
示例#5
0
/**
 * 'for-in' opcode handler
 *
 * See also:
 *          ECMA-262 v5, 12.6.4
 *
 * @return completion value
 *         Returned value must be freed with ecma_free_completion_value
 */
ecma_completion_value_t
opfunc_for_in (vm_instr_t instr, /**< instruction */
               vm_frame_ctx_t *int_data_p) /**< interpreter context */
{
  const vm_idx_t expr_idx = instr.data.for_in.expr;
  const vm_idx_t block_end_oc_idx_1 = instr.data.for_in.oc_idx_1;
  const vm_idx_t block_end_oc_idx_2 = instr.data.for_in.oc_idx_2;
  const vm_instr_counter_t for_in_end_oc = (vm_instr_counter_t) (
    vm_calc_instr_counter_from_idx_idx (block_end_oc_idx_1,
                                        block_end_oc_idx_2) + int_data_p->pos);

  ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();

  /* 1., 2. */
  ECMA_TRY_CATCH (expr_value,
                  get_variable_value (int_data_p,
                                      expr_idx,
                                      false),
                  ret_value);

  int_data_p->pos++;

  vm_instr_t meta_instr = vm_get_instr (int_data_p->bytecode_header_p->instrs_p, for_in_end_oc);
  JERRY_ASSERT (meta_instr.op_idx == VM_OP_META);
  JERRY_ASSERT (meta_instr.data.meta.type == OPCODE_META_TYPE_END_FOR_IN);

  /* 3. */
  if (!ecma_is_value_undefined (expr_value)
      && !ecma_is_value_null (expr_value))
  {
    /* 4. */
    ECMA_TRY_CATCH (obj_expr_value,
                    ecma_op_to_object (expr_value),
                    ret_value);

    ecma_object_t *obj_p = ecma_get_object_from_value (obj_expr_value);

    ecma_collection_iterator_t names_iterator;
    ecma_collection_header_t *names_p = ecma_op_object_get_property_names (obj_p, false, true, true);

    if (names_p != NULL)
    {
      ecma_collection_iterator_init (&names_iterator, names_p);

      const vm_instr_counter_t for_in_body_begin_oc = int_data_p->pos;
      const vm_instr_counter_t for_in_body_end_oc = for_in_end_oc;

      while (ecma_collection_iterator_next (&names_iterator))
      {
        ecma_value_t name_value = *names_iterator.current_value_p;

        ecma_string_t *name_p = ecma_get_string_from_value (name_value);

        if (ecma_op_object_get_property (obj_p, name_p) != NULL)
        {
          ecma_completion_value_t completion = set_variable_value (int_data_p,
                                                                   int_data_p->pos,
                                                                   VM_REG_SPECIAL_FOR_IN_PROPERTY_NAME,
                                                                   name_value);
          JERRY_ASSERT (ecma_is_completion_value_empty (completion));

          vm_run_scope_t run_scope_for_in = { for_in_body_begin_oc, for_in_body_end_oc };

          ecma_completion_value_t for_in_body_completion = vm_loop (int_data_p, &run_scope_for_in);
          if (ecma_is_completion_value_empty (for_in_body_completion))
          {
            JERRY_ASSERT (int_data_p->pos == for_in_body_end_oc);

            int_data_p->pos = for_in_body_begin_oc;
          }
          else
          {
            JERRY_ASSERT (ecma_is_completion_value_throw (for_in_body_completion)
                          || ecma_is_completion_value_return (for_in_body_completion)
                          || ecma_is_completion_value_jump (for_in_body_completion));
            JERRY_ASSERT (int_data_p->pos <= for_in_body_end_oc);

            ret_value = for_in_body_completion;
            break;
          }
        }
      }

      ecma_free_values_collection (names_p, true);
    }

    ECMA_FINALIZE (obj_expr_value);
  }

  int_data_p->pos = (vm_instr_counter_t) (for_in_end_oc + 1u);

  ECMA_FINALIZE (expr_value);

  return ret_value;
} /* opfunc_for_in */
/**
 * The Object object's 'defineProperties' routine
 *
 * See also:
 *          ECMA-262 v5, 15.2.3.7
 *
 * @return completion value
 *         Returned value must be freed with ecma_free_completion_value.
 */
static ecma_completion_value_t
ecma_builtin_object_object_define_properties (ecma_value_t this_arg __attr_unused___, /**< 'this' argument */
                                              ecma_value_t arg1, /**< routine's first argument */
                                              ecma_value_t arg2) /**< routine's second argument */
{
  ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();

  // 1.
  if (!ecma_is_value_object (arg1))
  {
    ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE));
  }
  else
  {
    ecma_object_t *obj_p = ecma_get_object_from_value (arg1);

    // 2.
    ECMA_TRY_CATCH (props,
                    ecma_op_to_object (arg2),
                    ret_value);

    ecma_object_t *props_p = ecma_get_object_from_value (props);
    // 3.
    ecma_collection_header_t *prop_names_p = ecma_op_object_get_property_names (props_p, false, true, false);
    uint32_t property_number = prop_names_p->unit_number;

    ecma_collection_iterator_t iter;
    ecma_collection_iterator_init (&iter, prop_names_p);

    // 4.
    MEM_DEFINE_LOCAL_ARRAY (property_descriptors, property_number, ecma_property_descriptor_t);

    uint32_t property_descriptor_number = 0;

    while (ecma_collection_iterator_next (&iter)
           && ecma_is_completion_value_empty (ret_value))
    {
      // 5.a
      ECMA_TRY_CATCH (desc_obj,
                      ecma_op_object_get (props_p, ecma_get_string_from_value (*iter.current_value_p)),
                      ret_value);

      // 5.b
      ECMA_TRY_CATCH (conv_result,
                      ecma_op_to_property_descriptor (desc_obj,
                                                      &property_descriptors[property_descriptor_number]),
                      ret_value);

      property_descriptor_number++;

      ECMA_FINALIZE (conv_result);
      ECMA_FINALIZE (desc_obj);
    }

    // 6.
    ecma_collection_iterator_init (&iter, prop_names_p);
    for (uint32_t index = 0;
         index < property_number && ecma_is_completion_value_empty (ret_value);
         index++)
    {
      bool is_next = ecma_collection_iterator_next (&iter);
      JERRY_ASSERT (is_next);

      ECMA_TRY_CATCH (define_own_prop_ret,
                      ecma_op_object_define_own_property (obj_p,
                                                          ecma_get_string_from_value (*iter.current_value_p),
                                                          &property_descriptors[index],
                                                          true),
                      ret_value);

      ECMA_FINALIZE (define_own_prop_ret);
    }

    // Clean up
    for (uint32_t index = 0;
         index < property_descriptor_number;
         index++)
    {
      ecma_free_property_descriptor (&property_descriptors[index]);
    }

    MEM_FINALIZE_LOCAL_ARRAY (property_descriptors);

    ecma_free_values_collection (prop_names_p, true);

    // 7.
    if (ecma_is_completion_value_empty (ret_value))
    {
      ret_value = ecma_make_normal_completion_value (ecma_copy_value (arg1, true));
    }

    ECMA_FINALIZE (props);
  }

  return ret_value;
} /* ecma_builtin_object_object_define_properties */
/**
 * The Object object's 'isFrozen' routine
 *
 * See also:
 *          ECMA-262 v5, 15.2.3.12
 *
 * @return completion value
 *         Returned value must be freed with ecma_free_completion_value.
 */
static ecma_completion_value_t
ecma_builtin_object_object_is_frozen (ecma_value_t this_arg __attr_unused___, /**< 'this' argument */
                                      ecma_value_t arg) /**< routine's argument */
{
  ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();

  // 1.
  if (!ecma_is_value_object (arg))
  {
    ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE));
  }
  else
  {
    ecma_object_t *obj_p = ecma_get_object_from_value (arg);

    bool is_frozen;

    // 3.
    if (ecma_get_object_extensible (obj_p))
    {
      is_frozen = false;
    }
    else
    {
      is_frozen = true;

      // 2.
      ecma_collection_header_t *props_p = ecma_op_object_get_property_names (obj_p, false, false, false);

      ecma_collection_iterator_t iter;
      ecma_collection_iterator_init (&iter, props_p);

      while (ecma_collection_iterator_next (&iter))
      {
        ecma_string_t *property_name_p = ecma_get_string_from_value (*iter.current_value_p);

        // 2.a
        ecma_property_t *property_p = ecma_op_object_get_own_property (obj_p, property_name_p);

        JERRY_ASSERT (property_p->type == ECMA_PROPERTY_NAMEDDATA || property_p->type == ECMA_PROPERTY_NAMEDACCESSOR);

        // 2.b
        if (property_p->type == ECMA_PROPERTY_NAMEDDATA && ecma_is_property_writable (property_p))
        {
          is_frozen = false;
          break;
        }

        // 2.c
        if (ecma_is_property_configurable (property_p))
        {
          is_frozen = false;
          break;
        }
      }

      ecma_free_values_collection (props_p, true);
    }

    // 4.
    ret_value = ecma_make_simple_completion_value (is_frozen
                                                   ? ECMA_SIMPLE_VALUE_TRUE
                                                   : ECMA_SIMPLE_VALUE_FALSE);
  }

  return ret_value;
} /* ecma_builtin_object_object_is_frozen */
/**
 * The Object object's 'freeze' routine
 *
 * See also:
 *          ECMA-262 v5, 15.2.3.9
 *
 * @return completion value
 *         Returned value must be freed with ecma_free_completion_value.
 */
static ecma_completion_value_t
ecma_builtin_object_object_freeze (ecma_value_t this_arg __attr_unused___, /**< 'this' argument */
                                   ecma_value_t arg) /**< routine's argument */
{
  ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();

  // 1.
  if (!ecma_is_value_object (arg))
  {
    ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE));
  }
  else
  {
    // 2.
    ecma_object_t *obj_p = ecma_get_object_from_value (arg);

    ecma_collection_header_t *props_p = ecma_op_object_get_property_names (obj_p, false, false, false);


    ecma_collection_iterator_t iter;
    ecma_collection_iterator_init (&iter, props_p);

    while (ecma_collection_iterator_next (&iter)
           && ecma_is_completion_value_empty (ret_value))
    {
      ecma_string_t *property_name_p = ecma_get_string_from_value (*iter.current_value_p);
      ecma_property_t *property_p = ecma_op_object_get_own_property (obj_p, property_name_p);

      // 2.a
      ecma_property_descriptor_t prop_desc = ecma_get_property_descriptor_from_property (property_p);

      // 2.b
      if (property_p->type == ECMA_PROPERTY_NAMEDDATA && ecma_is_property_writable (property_p))
      {
        prop_desc.is_writable = false;
      }

      // 2.c
      if (ecma_is_property_configurable (property_p))
      {
        prop_desc.is_configurable = false;
      }

      // 2.d
      ECMA_TRY_CATCH (define_own_prop_ret,
                      ecma_op_object_define_own_property (obj_p,
                                                          property_name_p,
                                                          &prop_desc,
                                                          true),
                      ret_value);
      ECMA_FINALIZE (define_own_prop_ret);

      ecma_free_property_descriptor (&prop_desc);
    }

    ecma_free_values_collection (props_p, true);

    if (ecma_is_completion_value_empty (ret_value))
    {
      // 3.
      ecma_set_object_extensible (obj_p, false);

      // 4.
      ret_value = ecma_make_normal_completion_value (ecma_copy_value (arg, true));
    }
  }

  return ret_value;
} /* ecma_builtin_object_object_freeze */
示例#9
0
/**
 * Abstract operation Walk defined in 15.12.2
 *
 * See also:
 *          ECMA-262 v5, 15.12.2
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value.
 */
static ecma_value_t
ecma_builtin_json_walk (ecma_object_t *reviver_p, /**< reviver function */
                        ecma_object_t *holder_p, /**< holder object */
                        ecma_string_t *name_p) /**< property name */
{
  JERRY_ASSERT (reviver_p);
  JERRY_ASSERT (holder_p);
  JERRY_ASSERT (name_p);

  ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);

  ECMA_TRY_CATCH (value_get,
                  ecma_op_object_get (holder_p, name_p),
                  ret_value);

  if (ecma_is_value_object (value_get))
  {
    ecma_object_t *object_p = ecma_get_object_from_value (value_get);

    ecma_collection_header_t *props_p = ecma_op_object_get_property_names (object_p, false, true, false);

    ecma_collection_iterator_t iter;
    ecma_collection_iterator_init (&iter, props_p);

    while (ecma_collection_iterator_next (&iter)
           && ecma_is_value_empty (ret_value))
    {
      ecma_string_t *property_name_p = ecma_get_string_from_value (*iter.current_value_p);

      ECMA_TRY_CATCH (value_walk,
                      ecma_builtin_json_walk (reviver_p,
                                              object_p,
                                              property_name_p),
                      ret_value);

      /*
       * We cannot optimize this function since any members
       * can be changed (deleted) by the reviver function.
       */
      if (ecma_is_value_undefined (value_walk))
      {
        ecma_value_t delete_val = ecma_op_general_object_delete (object_p,
                                                                 property_name_p,
                                                                 false);
        JERRY_ASSERT (ecma_is_value_boolean (delete_val));
      }
      else
      {
        ecma_builtin_json_define_value_property (object_p,
                                                 property_name_p,
                                                 value_walk);
      }

      ECMA_FINALIZE (value_walk);
    }

    ecma_free_values_collection (props_p, true);
  }

  if (ecma_is_value_empty (ret_value))
  {
    ecma_value_t arguments_list[2];

    arguments_list[0] = ecma_make_string_value (name_p);
    arguments_list[1] = value_get;

   /*
    * The completion value can be anything including exceptions.
    */
    ret_value = ecma_op_function_call (reviver_p,
                                       ecma_make_object_value (holder_p),
                                       arguments_list,
                                       2);
  }
  else
  {
    JERRY_ASSERT (ecma_is_value_error (ret_value));
  }

  ECMA_FINALIZE (value_get);

  return ret_value;
} /* ecma_builtin_json_walk */
示例#10
0
/**
 * Abstract operation 'JO' defined in 15.12.3
 *
 * See also:
 *          ECMA-262 v5, 15.12.3
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value.
 */
static ecma_value_t
ecma_builtin_json_object (ecma_object_t *obj_p, /**< the object*/
                          ecma_json_stringify_context_t *context_p) /**< context*/
{
  ecma_value_t obj_value = ecma_make_object_value (obj_p);

  /* 1. */
  if (ecma_has_object_value_in_collection (context_p->occurence_stack_p, obj_value))
  {
    return ecma_raise_type_error ("");
  }

  ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);

  /* 2. */
  ecma_append_to_values_collection (context_p->occurence_stack_p, obj_value, true);

  /* 3. */
  ecma_string_t *stepback_p = context_p->indent_str_p;

  /* 4. */
  context_p->indent_str_p = ecma_concat_ecma_strings (context_p->indent_str_p, context_p->gap_str_p);

  ecma_collection_header_t *property_keys_p;

  /* 5. */
  if (context_p->property_list_p->unit_number > 0)
  {
    property_keys_p = context_p->property_list_p;
  }
  /* 6. */
  else
  {
    property_keys_p = ecma_new_values_collection (NULL, 0, true);

    ecma_collection_header_t *props_p = ecma_op_object_get_property_names (obj_p, false, true, false);

    ecma_collection_iterator_t iter;
    ecma_collection_iterator_init (&iter, props_p);

    while (ecma_collection_iterator_next (&iter))
    {
      ecma_string_t *property_name_p = ecma_get_string_from_value (*iter.current_value_p);
      ecma_property_t *property_p = ecma_op_object_get_own_property (obj_p, property_name_p);

      JERRY_ASSERT (ecma_is_property_enumerable (property_p));

      if (property_p->type == ECMA_PROPERTY_NAMEDDATA)
      {
        ecma_append_to_values_collection (property_keys_p, *iter.current_value_p, true);
      }
    }

    ecma_free_values_collection (props_p, true);
  }

  /* 7. */
  ecma_collection_header_t *partial_p = ecma_new_values_collection (NULL, 0, true);

  /* 8. */
  ecma_collection_iterator_t iterator;
  ecma_collection_iterator_init (&iterator, property_keys_p);

  while (ecma_collection_iterator_next (&iterator) && ecma_is_value_empty (ret_value))
  {
    ecma_value_t value = *iterator.current_value_p;
    ecma_string_t *key_p = ecma_get_string_from_value (value);

    /* 8.a */
    ECMA_TRY_CATCH (str_val,
                    ecma_builtin_json_str (key_p, obj_p, context_p),
                    ret_value);

    /* 8.b */
    if (!ecma_is_value_undefined (str_val))
    {
      ecma_string_t *colon_p = ecma_get_magic_string (LIT_MAGIC_STRING_COLON_CHAR);
      ecma_string_t *value_str_p = ecma_get_string_from_value (str_val);
      ecma_string_t *tmp_str_p;

      /* 8.b.i */
      ecma_value_t str_comp_val = ecma_builtin_json_quote (key_p);
      JERRY_ASSERT (!ecma_is_value_error (str_comp_val));

      ecma_string_t *member_str_p = ecma_get_string_from_value (str_comp_val);

      /* 8.b.ii */
      tmp_str_p = ecma_concat_ecma_strings (member_str_p, colon_p);
      ecma_free_value (str_comp_val);
      ecma_deref_ecma_string (colon_p);
      member_str_p = tmp_str_p;

      /* 8.b.iii */
      bool is_gap_empty = (ecma_string_get_length (context_p->gap_str_p) == 0);

      if (!is_gap_empty)
      {
        ecma_string_t *space_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_SPACE_CHAR);

        tmp_str_p = ecma_concat_ecma_strings (member_str_p, space_str_p);
        ecma_deref_ecma_string (member_str_p);
        ecma_deref_ecma_string (space_str_p);
        member_str_p = tmp_str_p;
      }

      /* 8.b.iv */
      tmp_str_p = ecma_concat_ecma_strings (member_str_p, value_str_p);
      ecma_deref_ecma_string (member_str_p);
      member_str_p = tmp_str_p;

      /* 8.b.v */
      ecma_value_t member_value = ecma_make_string_value (member_str_p);
      ecma_append_to_values_collection (partial_p, member_value, true);
      ecma_deref_ecma_string (member_str_p);
    }

    ECMA_FINALIZE (str_val);
  }

  if (context_p->property_list_p->unit_number == 0)
  {
    ecma_free_values_collection (property_keys_p, true);
  }

  if (!ecma_is_value_empty (ret_value))
  {
    ecma_free_values_collection (partial_p, true);
    ecma_deref_ecma_string (stepback_p);
    return ret_value;
  }

  /* 9. */
  if (partial_p->unit_number == 0)
  {
    ecma_string_t *left_brace_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LEFT_BRACE_CHAR);
    ecma_string_t *right_brace_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_RIGHT_BRACE_CHAR);

    ecma_string_t *final_str_p = ecma_concat_ecma_strings (left_brace_str_p, right_brace_str_p);
    ret_value = ecma_make_string_value (final_str_p);

    ecma_deref_ecma_string (left_brace_str_p);
    ecma_deref_ecma_string (right_brace_str_p);
  }
  /* 10. */
  else
  {
    bool is_gap_empty = (ecma_string_get_length (context_p->gap_str_p) == 0);

    /* 10.a */
    if (is_gap_empty)
    {
      ecma_string_t *left_brace_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LEFT_BRACE_CHAR);
      ecma_string_t *right_brace_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_RIGHT_BRACE_CHAR);

      ret_value = ecma_builtin_helper_json_create_non_formatted_json (left_brace_str_p,
                                                                      right_brace_str_p,
                                                                      partial_p);

      ecma_deref_ecma_string (left_brace_str_p);
      ecma_deref_ecma_string (right_brace_str_p);
    }
    /* 10.b */
    else
    {
      ecma_string_t *left_brace_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LEFT_BRACE_CHAR);
      ecma_string_t *right_brace_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_RIGHT_BRACE_CHAR);

      ret_value = ecma_builtin_helper_json_create_formatted_json (left_brace_str_p,
                                                                  right_brace_str_p,
                                                                  stepback_p,
                                                                  partial_p,
                                                                  context_p);

      ecma_deref_ecma_string (left_brace_str_p);
      ecma_deref_ecma_string (right_brace_str_p);
    }
  }

  ecma_free_values_collection (partial_p, true);

  /* 11. */
  ecma_remove_last_value_from_values_collection (context_p->occurence_stack_p);

  /* 12. */
  ecma_deref_ecma_string (context_p->indent_str_p);
  context_p->indent_str_p = stepback_p;

  /* 13. */
  return ret_value;
} /* ecma_builtin_json_object */