Implementing 'typeof' opcode handler.

This commit is contained in:
Ruben Ayrapetyan 2014-08-26 12:43:13 +04:00
parent 704c26ff80
commit dc3f529307
6 changed files with 204 additions and 9 deletions

View File

@ -29,6 +29,7 @@
#include "ecma-try-catch-macro.h"
#include "ecma-objects.h"
bool is_reg_variable (int_data_t *int_data, idx_t var_idx);
ecma_completion_value_t get_variable_value (int_data_t *, idx_t, bool);
ecma_completion_value_t set_variable_value (int_data_t *, idx_t, ecma_value_t);

View File

@ -54,6 +54,19 @@ do_strict_eval_arguments_check (ecma_reference_t ref) /**< ECMA-reference */
return ret;
} /* do_strict_eval_arguments_check */
/**
* Check if the variable is register variable.
*
* @return true - if var_idx is register variable in current interpreter context,
* false - otherwise.
*/
bool
is_reg_variable (int_data_t *int_data, /**< interpreter context */
idx_t var_idx) /**< variable identifier */
{
return (var_idx >= int_data->min_reg_num && var_idx <= int_data->max_reg_num);
} /* is_reg_variable */
/**
* Get variable's value.
*
@ -68,8 +81,7 @@ get_variable_value (int_data_t *int_data, /**< interpreter context */
{
ecma_completion_value_t ret_value;
if (var_idx >= int_data->min_reg_num
&& var_idx <= int_data->max_reg_num)
if (is_reg_variable (int_data, var_idx))
{
ecma_value_t reg_value = int_data->regs_p[ var_idx - int_data->min_reg_num ];
@ -119,8 +131,7 @@ set_variable_value (int_data_t *int_data, /**< interpreter context */
{
ecma_completion_value_t ret_value;
if (var_idx >= int_data->min_reg_num
&& var_idx <= int_data->max_reg_num)
if (is_reg_variable (int_data, var_idx))
{
ecma_value_t reg_value = int_data->regs_p[ var_idx - int_data->min_reg_num ];

View File

@ -128,7 +128,6 @@ free_string_literal_copy (string_literal_copy *str_lit_descr_p) /**< string lite
op (prop_set_decl) \
op (obj_decl) \
op (delete) \
op (typeof) \
op (with) \
op (end_with) \
op (meta) \
@ -1092,6 +1091,153 @@ opfunc_this (opcode_t opdata, /**< operation data */
return ret_value;
} /* opfunc_this */
/**
* Evaluate argument of typeof.
*
* See also: ECMA-262 v5, 11.4.3
*
* @return completion value
* Returned value must be freed with ecma_free_completion_value
*/
static ecma_completion_value_t
evaluate_arg_for_typeof (int_data_t *int_data, /**< interpreter context */
idx_t var_idx) /**< arg variable identifier */
{
ecma_completion_value_t ret_value;
if (is_reg_variable (int_data, var_idx))
{
// 2.b
ret_value = get_variable_value (int_data,
var_idx,
false);
JERRY_ASSERT (ecma_is_completion_value_normal (ret_value));
}
else
{
ecma_string_t *var_name_string_p = ecma_new_ecma_string_from_lit_index (var_idx);
ecma_reference_t ref = ecma_op_get_identifier_reference (int_data->lex_env_p,
var_name_string_p,
int_data->is_strict);
ecma_deref_ecma_string (var_name_string_p);
const bool is_unresolvable_reference = ecma_is_value_undefined (ref.base);
if (is_unresolvable_reference)
{
ret_value = ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_UNDEFINED);
}
else
{
ret_value = ecma_op_get_value (ref);
}
ecma_free_reference (ref);
}
return ret_value;
} /* evaluate_arg_for_typeof */
/**
* 'typeof' opcode handler.
*
* See also: ECMA-262 v5, 11.4.3
*
* @return completion value
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
opfunc_typeof (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
const idx_t dst_var_idx = opdata.data.typeof.lhs;
const idx_t obj_var_idx = opdata.data.typeof.obj;
int_data->pos++;
ecma_completion_value_t ret_value;
ECMA_TRY_CATCH (typeof_evaluate_arg_completion,
evaluate_arg_for_typeof (int_data,
obj_var_idx),
ret_value);
ecma_value_t typeof_arg = typeof_evaluate_arg_completion.value;
ecma_string_t *type_str_p = NULL;
switch ((ecma_type_t)typeof_arg.value_type)
{
case ECMA_TYPE_SIMPLE:
{
switch ((ecma_simple_value_t)typeof_arg.value)
{
case ECMA_SIMPLE_VALUE_UNDEFINED:
{
type_str_p = ecma_get_magic_string (ECMA_MAGIC_STRING_UNDEFINED);
break;
}
case ECMA_SIMPLE_VALUE_NULL:
{
type_str_p = ecma_get_magic_string (ECMA_MAGIC_STRING_NULL);
break;
}
case ECMA_SIMPLE_VALUE_FALSE:
{
type_str_p = ecma_get_magic_string (ECMA_MAGIC_STRING_FALSE);
break;
}
case ECMA_SIMPLE_VALUE_TRUE:
{
type_str_p = ecma_get_magic_string (ECMA_MAGIC_STRING_TRUE);
break;
}
case ECMA_SIMPLE_VALUE_EMPTY:
case ECMA_SIMPLE_VALUE_ARRAY_REDIRECT:
case ECMA_SIMPLE_VALUE__COUNT:
{
JERRY_UNREACHABLE ();
}
}
break;
}
case ECMA_TYPE_NUMBER:
{
type_str_p = ecma_get_magic_string (ECMA_MAGIC_STRING_NUMBER);
break;
}
case ECMA_TYPE_STRING:
{
type_str_p = ecma_get_magic_string (ECMA_MAGIC_STRING_STRING);
break;
}
case ECMA_TYPE_OBJECT:
{
if (ecma_op_is_callable (typeof_arg))
{
type_str_p = ecma_get_magic_string (ECMA_MAGIC_STRING_FUNCTION);
}
else
{
type_str_p = ecma_get_magic_string (ECMA_MAGIC_STRING_OBJECT);
}
break;
}
}
ret_value = set_variable_value (int_data,
dst_var_idx,
ecma_make_string_value (type_str_p));
ecma_deref_ecma_string (type_str_p);
ECMA_FINALIZE (typeof_evaluate_arg_completion);
return ret_value;
} /* opfunc_typeof */
#define GETOP_DEF_1(a, name, field1) \
inline opcode_t getop_##name (idx_t arg1) \
{ \

View File

@ -46,6 +46,10 @@ ecma_get_magic_string_zt (ecma_magic_string_id_t id) /**< magic string id */
case ECMA_MAGIC_STRING_NULL: return (ecma_char_t*) "null";
case ECMA_MAGIC_STRING_FALSE: return (ecma_char_t*) "false";
case ECMA_MAGIC_STRING_TRUE: return (ecma_char_t*) "true";
case ECMA_MAGIC_STRING_NUMBER: return (ecma_char_t*) "number";
case ECMA_MAGIC_STRING_STRING: return (ecma_char_t*) "string";
case ECMA_MAGIC_STRING_OBJECT: return (ecma_char_t*) "object";
case ECMA_MAGIC_STRING_FUNCTION: return (ecma_char_t*) "function";
case ECMA_MAGIC_STRING_LENGTH: return (ecma_char_t*) "length";
case ECMA_MAGIC_STRING_NAN: return (ecma_char_t*) "NaN";
case ECMA_MAGIC_STRING_INFINITY: return (ecma_char_t*) "Infinity";

View File

@ -36,10 +36,14 @@ typedef enum
ECMA_MAGIC_STRING_CONSTRUCTOR, /**< "constructor" */
ECMA_MAGIC_STRING_CALLER, /**< "caller" */
ECMA_MAGIC_STRING_CALLEE, /**< "callee" */
ECMA_MAGIC_STRING_UNDEFINED,/**< "undefined" */
ECMA_MAGIC_STRING_NULL,/**< "null" */
ECMA_MAGIC_STRING_FALSE,/**< "false" */
ECMA_MAGIC_STRING_TRUE,/**< "true" */
ECMA_MAGIC_STRING_UNDEFINED, /**< "undefined" */
ECMA_MAGIC_STRING_NULL, /**< "null" */
ECMA_MAGIC_STRING_FALSE, /**< "false" */
ECMA_MAGIC_STRING_TRUE, /**< "true" */
ECMA_MAGIC_STRING_NUMBER, /**< "number" */
ECMA_MAGIC_STRING_STRING, /**< "string" */
ECMA_MAGIC_STRING_OBJECT, /**< "object" */
ECMA_MAGIC_STRING_FUNCTION, /**< "function" */
ECMA_MAGIC_STRING_LENGTH, /**< "length" */
ECMA_MAGIC_STRING_NAN, /**< "NaN" */
ECMA_MAGIC_STRING_INFINITY /**< "Infinity" */

29
tests/jerry/typeof.js Normal file
View File

@ -0,0 +1,29 @@
// Copyright 2014 Samsung Electronics Co., Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
function f()
{
return 1;
}
assert(typeof(a) === "undefined");
assert(typeof(null) === "null");
assert(typeof(false) === "false");
assert(typeof(true) === "true");
assert(typeof(1) === "number");
assert(typeof(1.1) === "number");
assert(typeof('abcd') === "string");
assert(typeof("1.1") === "string");
assert(typeof(this) === "object");
assert(typeof(f) === "function");