Esempio n. 1
0
/**
 * ImplicitThisValue operation.
 *
 * See also: ECMA-262 v5, 10.2.1
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value.
 */
ecma_value_t
ecma_op_implicit_this_value (ecma_object_t *lex_env_p) /**< lexical environment */
{
  JERRY_ASSERT (lex_env_p != NULL
                && ecma_is_lexical_environment (lex_env_p));

  if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
  {
    return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
  }
  else
  {
    JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_OBJECTBOUND);

    if (ecma_get_lex_env_provide_this (lex_env_p))
    {
      ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p);
      ecma_ref_object (binding_obj_p);

      return ecma_make_object_value (binding_obj_p);
    }
    else
    {
      return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
    }
  }
} /* ecma_op_implicit_this_value */
Esempio n. 2
0
/**
 * Get reference to Global lexical environment
 *
 * @return pointer to the object's instance
 */
ecma_object_t *
ecma_get_global_environment (void)
{
  ecma_ref_object (ecma_global_lex_env_p);

  return ecma_global_lex_env_p;
} /* ecma_get_global_environment */
/**
 * The Object object's 'getPrototypeOf' routine
 *
 * See also:
 *          ECMA-262 v5, 15.2.3.2
 *
 * @return completion value
 *         Returned value must be freed with ecma_free_completion_value.
 */
static ecma_completion_value_t
ecma_builtin_object_object_get_prototype_of (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_object_t *prototype_p = ecma_get_object_prototype (obj_p);

    if (prototype_p)
    {
      ret_value = ecma_make_normal_completion_value (ecma_make_object_value (prototype_p));
      ecma_ref_object (prototype_p);
    }
    else
    {
      ret_value = ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_NULL);
    }
  }

  return ret_value;
} /* ecma_builtin_object_object_get_prototype_of */
Esempio n. 4
0
/**
 * Get top lexical environment (variable environment) of current execution context
 *
 * @return lexical environment
 */
ecma_object_t*
vm_get_lex_env (void)
{
  JERRY_ASSERT (vm_top_context_p != NULL);

  ecma_ref_object (vm_top_context_p->lex_env_p);

  return vm_top_context_p->lex_env_p;
} /* vm_get_lex_env */
Esempio n. 5
0
/**
 * Copy ecma value.
 *
 * Note:
 *  Operation algorithm.
 *   switch (valuetype)
 *    case simple:
 *      simply return the value as it was passed;
 *    case number:
 *      copy the number
 *      and return new ecma value
 *      pointing to copy of the number;
 *    case string:
 *      increase reference counter of the string
 *      and return the value as it was passed.
 *    case object;
 *      increase reference counter of the object if do_ref_if_object is true
 *      and return the value as it was passed.
 *
 * @return See note.
 */
ecma_value_t
ecma_copy_value (ecma_value_t value, /**< ecma value */
                 bool do_ref_if_object) /**< if the value is object value,
                                             increment reference counter of the object */
{
  ecma_value_t value_copy = 0;

  switch (ecma_get_value_type_field (value))
  {
    case ECMA_TYPE_SIMPLE:
    {
      value_copy = value;

      break;
    }
    case ECMA_TYPE_NUMBER:
    {
      ecma_number_t *num_p = ecma_get_number_from_value (value);

      ecma_number_t *number_copy_p = ecma_alloc_number ();
      *number_copy_p = *num_p;

      value_copy = ecma_make_number_value (number_copy_p);

      break;
    }
    case ECMA_TYPE_STRING:
    {
      ecma_string_t *string_p = ecma_get_string_from_value (value);

      string_p = ecma_copy_or_ref_ecma_string (string_p);

      value_copy = ecma_make_string_value (string_p);

      break;
    }
    case ECMA_TYPE_OBJECT:
    {
      ecma_object_t *obj_p = ecma_get_object_from_value (value);

      if (do_ref_if_object)
      {
        ecma_ref_object (obj_p);
      }

      value_copy = value;

      break;
    }
  }

  return value_copy;
} /* ecma_copy_value */
Esempio n. 6
0
/**
 * Get reference to specified built-in object
 *
 * @return pointer to the object's instance
 */
ecma_object_t *
ecma_builtin_get (ecma_builtin_id_t builtin_id) /**< id of built-in to check on */
{
  JERRY_ASSERT (builtin_id < ECMA_BUILTIN_ID__COUNT);

  if (unlikely (ecma_builtin_objects[builtin_id] == NULL))
  {
    ecma_instantiate_builtin (builtin_id);
  }

  ecma_ref_object (ecma_builtin_objects[builtin_id]);

  return ecma_builtin_objects[builtin_id];
} /* ecma_builtin_get */
Esempio n. 7
0
/**
 * Construct property descriptor from specified property
 *
 * @return property descriptor, corresponding to type and content of the specified property, i.e.:
 *                  - for named data properties: { [Value], [Writable], [Enumerable], [Configurable] };
 *                  - for named accessor properties: { [Get] - if defined,
 *                                                     [Set] - if defined,
 *                                                     [Enumerable], [Configurable]
 *                                                   }.
 */
ecma_property_descriptor_t
ecma_get_property_descriptor_from_property (ecma_property_t *prop_p) /**< property */
{
  ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor ();

  prop_desc.is_enumerable = ecma_is_property_enumerable (prop_p);
  prop_desc.is_enumerable_defined = true;
  prop_desc.is_configurable = ecma_is_property_configurable (prop_p);
  prop_desc.is_configurable_defined = true;

  if (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA)
  {
    prop_desc.value = ecma_copy_value (ecma_get_named_data_property_value (prop_p));
    prop_desc.is_value_defined = true;
    prop_desc.is_writable = ecma_is_property_writable (prop_p);
    prop_desc.is_writable_defined = true;
  }
  else
  {
    JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR);
    prop_desc.get_p = ecma_get_named_accessor_property_getter (prop_p);
    prop_desc.is_get_defined = true;
    if (prop_desc.get_p != NULL)
    {
      ecma_ref_object (prop_desc.get_p);
    }

    prop_desc.set_p = ecma_get_named_accessor_property_setter (prop_p);
    prop_desc.is_set_defined = true;
    if (prop_desc.set_p != NULL)
    {
      ecma_ref_object (prop_desc.set_p);
    }
  }

  return prop_desc;
} /* ecma_get_property_descriptor_from_property */
Esempio n. 8
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 */
Esempio n. 9
0
/**
 * Insert an entry into LCache
 */
void
ecma_lcache_insert (ecma_object_t *object_p, /**< object */
                    ecma_string_t *prop_name_p, /**< property's name */
                    ecma_property_t *prop_p) /**< pointer to associated property or NULL
                                              *   (NULL indicates that the object doesn't have property
                                              *   with the name specified) */
{
  JERRY_ASSERT (object_p != NULL);
  JERRY_ASSERT (prop_name_p != NULL);

#ifndef CONFIG_ECMA_LCACHE_DISABLE
  prop_name_p = ecma_copy_or_ref_ecma_string (prop_name_p);

  lit_string_hash_t hash_key = ecma_string_hash (prop_name_p);

  if (prop_p != NULL)
  {
    if (unlikely (ecma_is_property_lcached (prop_p)))
    {
      int32_t entry_index;
      for (entry_index = 0; entry_index < ECMA_LCACHE_HASH_ROW_LENGTH; entry_index++)
      {
        if (ecma_lcache_hash_table[hash_key][entry_index].object_cp != ECMA_NULL_POINTER
            && ecma_lcache_hash_table[hash_key][entry_index].prop_p == prop_p)
        {
#ifndef JERRY_NDEBUG
          ecma_object_t *obj_in_entry_p;
          obj_in_entry_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t,
                                                      ecma_lcache_hash_table[hash_key][entry_index].object_cp);
          JERRY_ASSERT (obj_in_entry_p == object_p);
#endif /* !JERRY_NDEBUG */
          break;
        }
      }

      JERRY_ASSERT (entry_index != ECMA_LCACHE_HASH_ROW_LENGTH);
      ecma_lcache_invalidate_entry (&ecma_lcache_hash_table[hash_key][entry_index]);
    }

    JERRY_ASSERT (!ecma_is_property_lcached (prop_p));
    ecma_set_property_lcached (prop_p, true);
  }

  int32_t entry_index;
  for (entry_index = 0; entry_index < ECMA_LCACHE_HASH_ROW_LENGTH; entry_index++)
  {
    if (ecma_lcache_hash_table[hash_key][entry_index].object_cp == ECMA_NULL_POINTER)
    {
      break;
    }
  }

  if (entry_index == ECMA_LCACHE_HASH_ROW_LENGTH)
  {
    /* No empty entry was found, invalidating the whole row */
    for (uint32_t i = 0; i < ECMA_LCACHE_HASH_ROW_LENGTH; i++)
    {
      ecma_lcache_invalidate_entry (&ecma_lcache_hash_table[hash_key][i]);
    }

    entry_index = 0;
  }

  ecma_ref_object (object_p);
  ECMA_SET_NON_NULL_POINTER (ecma_lcache_hash_table[ hash_key ][ entry_index ].object_cp, object_p);
  ECMA_SET_NON_NULL_POINTER (ecma_lcache_hash_table[ hash_key ][ entry_index ].prop_name_cp, prop_name_p);
  ecma_lcache_hash_table[ hash_key ][ entry_index ].prop_p = prop_p;
#else /* CONFIG_ECMA_LCACHE_DISABLE */
  (void) prop_p;
#endif /* !CONFIG_ECMA_LCACHE_DISABLE */
} /* ecma_lcache_insert */
Esempio n. 10
0
/**
 * ToPropertyDescriptor operation.
 *
 * See also:
 *          ECMA-262 v5, 8.10.5
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value
 */
ecma_value_t
ecma_op_to_property_descriptor (ecma_value_t obj_value, /**< object value */
                                ecma_property_descriptor_t *out_prop_desc_p) /**< [out] filled property descriptor
                                                                                  if return value is normal
                                                                                  empty completion value */
{
  ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);

  // 1.
  if (!ecma_is_value_object (obj_value))
  {
    ret_value = ecma_raise_type_error (ECMA_ERR_MSG (""));
  }
  else
  {
    ecma_object_t *obj_p = ecma_get_object_from_value (obj_value);

    // 2.
    ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor ();

    // 3.
    ecma_string_t *enumerable_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_ENUMERABLE);

    if (ecma_op_object_get_property (obj_p, enumerable_magic_string_p) != NULL)
    {
      ECMA_TRY_CATCH (enumerable_prop_value,
                      ecma_op_object_get (obj_p, enumerable_magic_string_p),
                      ret_value);

      prop_desc.is_enumerable_defined = true;
      prop_desc.is_enumerable = ecma_op_to_boolean (enumerable_prop_value);

      ECMA_FINALIZE (enumerable_prop_value);
    }

    ecma_deref_ecma_string (enumerable_magic_string_p);

    if (!ecma_is_value_error (ret_value))
    {
      JERRY_ASSERT (ecma_is_value_empty (ret_value));

      // 4.
      ecma_string_t *configurable_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_CONFIGURABLE);

      if (ecma_op_object_get_property (obj_p, configurable_magic_string_p) != NULL)
      {
        ECMA_TRY_CATCH (configurable_prop_value,
                        ecma_op_object_get (obj_p, configurable_magic_string_p),
                        ret_value);

        prop_desc.is_configurable_defined = true;
        prop_desc.is_configurable = ecma_op_to_boolean (configurable_prop_value);

        ECMA_FINALIZE (configurable_prop_value);
      }

      ecma_deref_ecma_string (configurable_magic_string_p);
    }

    if (!ecma_is_value_error (ret_value))
    {
      JERRY_ASSERT (ecma_is_value_empty (ret_value));

      // 5.
      ecma_string_t *value_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_VALUE);

      if (ecma_op_object_get_property (obj_p, value_magic_string_p) != NULL)
      {
        ECMA_TRY_CATCH (value_prop_value,
                        ecma_op_object_get (obj_p, value_magic_string_p),
                        ret_value);

        prop_desc.is_value_defined = true;
        prop_desc.value = ecma_copy_value (value_prop_value);

        ECMA_FINALIZE (value_prop_value);
      }

      ecma_deref_ecma_string (value_magic_string_p);
    }

    if (!ecma_is_value_error (ret_value))
    {
      JERRY_ASSERT (ecma_is_value_empty (ret_value));

      // 6.
      ecma_string_t *writable_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_WRITABLE);

      if (ecma_op_object_get_property (obj_p, writable_magic_string_p) != NULL)
      {
        ECMA_TRY_CATCH (writable_prop_value,
                        ecma_op_object_get (obj_p, writable_magic_string_p),
                        ret_value);

        prop_desc.is_writable_defined = true;
        prop_desc.is_writable = ecma_op_to_boolean (writable_prop_value);

        ECMA_FINALIZE (writable_prop_value);
      }

      ecma_deref_ecma_string (writable_magic_string_p);
    }

    if (!ecma_is_value_error (ret_value))
    {
      JERRY_ASSERT (ecma_is_value_empty (ret_value));

      // 7.
      ecma_string_t *get_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_GET);

      if (ecma_op_object_get_property (obj_p, get_magic_string_p) != NULL)
      {
        ECMA_TRY_CATCH (get_prop_value,
                        ecma_op_object_get (obj_p, get_magic_string_p),
                        ret_value);

        if (!ecma_op_is_callable (get_prop_value)
            && !ecma_is_value_undefined (get_prop_value))
        {
          ret_value = ecma_raise_type_error (ECMA_ERR_MSG (""));
        }
        else
        {
          prop_desc.is_get_defined = true;

          if (ecma_is_value_undefined (get_prop_value))
          {
            prop_desc.get_p = NULL;
          }
          else
          {
            JERRY_ASSERT (ecma_is_value_object (get_prop_value));

            ecma_object_t *get_p = ecma_get_object_from_value (get_prop_value);
            ecma_ref_object (get_p);

            prop_desc.get_p = get_p;
          }
        }

        ECMA_FINALIZE (get_prop_value);
      }

      ecma_deref_ecma_string (get_magic_string_p);
    }

    if (!ecma_is_value_error (ret_value))
    {
      JERRY_ASSERT (ecma_is_value_empty (ret_value));

      // 8.

      ecma_string_t *set_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_SET);

      if (ecma_op_object_get_property (obj_p, set_magic_string_p) != NULL)
      {
        ECMA_TRY_CATCH (set_prop_value,
                        ecma_op_object_get (obj_p, set_magic_string_p),
                        ret_value);

        if (!ecma_op_is_callable (set_prop_value)
            && !ecma_is_value_undefined (set_prop_value))
        {
          ret_value = ecma_raise_type_error (ECMA_ERR_MSG (""));
        }
        else
        {
          prop_desc.is_set_defined = true;

          if (ecma_is_value_undefined (set_prop_value))
          {
            prop_desc.set_p = NULL;
          }
          else
          {
            JERRY_ASSERT (ecma_is_value_object (set_prop_value));

            ecma_object_t *set_p = ecma_get_object_from_value (set_prop_value);
            ecma_ref_object (set_p);

            prop_desc.set_p = set_p;
          }
        }

        ECMA_FINALIZE (set_prop_value);
      }

      ecma_deref_ecma_string (set_magic_string_p);
    }

    if (!ecma_is_value_error (ret_value))
    {
      JERRY_ASSERT (ecma_is_value_empty (ret_value));

      // 9.
      if (prop_desc.is_get_defined
          || prop_desc.is_set_defined)
      {
        if (prop_desc.is_value_defined
            || prop_desc.is_writable_defined)
        {
          ret_value = ecma_raise_type_error (ECMA_ERR_MSG (""));
        }
      }
    }

    if (!ecma_is_value_error (ret_value))
    {
      JERRY_ASSERT (ecma_is_value_empty (ret_value));
    }
    else
    {
      ecma_free_property_descriptor (&prop_desc);
    }

    *out_prop_desc_p = prop_desc;
  }

  return ret_value;
} /* ecma_op_to_property_descriptor */