mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Implementing 'typeof' opcode handler.
This commit is contained in:
parent
704c26ff80
commit
dc3f529307
@ -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);
|
||||
|
||||
|
||||
@ -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 ];
|
||||
|
||||
|
||||
@ -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) \
|
||||
{ \
|
||||
|
||||
@ -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";
|
||||
|
||||
@ -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
29
tests/jerry/typeof.js
Normal 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");
|
||||
Loading…
x
Reference in New Issue
Block a user