diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype-unscopables.c b/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype-unscopables.c new file mode 100644 index 000000000..12d826e1a --- /dev/null +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype-unscopables.c @@ -0,0 +1,28 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * 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. + */ + +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" + +#if ENABLED (JERRY_ES2015) + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-array-prototype-unscopables.inc.h" +#define BUILTIN_UNDERSCORED_ID array_prototype_unscopables +#include "ecma-builtin-internal-routines-template.inc.h" + +#endif /* ENABLED (JERRY_ES2015) */ diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype-unscopables.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype-unscopables.inc.h new file mode 100644 index 000000000..287635fa8 --- /dev/null +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype-unscopables.inc.h @@ -0,0 +1,55 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * 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. + */ + +/* + * Array.prototype[@@unscopables] built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + + +#if ENABLED (JERRY_ES2015) + +SIMPLE_VALUE (LIT_MAGIC_STRING_COPY_WITHIN, + ECMA_VALUE_TRUE, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE) + +SIMPLE_VALUE (LIT_MAGIC_STRING_ENTRIES, + ECMA_VALUE_TRUE, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE) + +SIMPLE_VALUE (LIT_MAGIC_STRING_FILL, + ECMA_VALUE_TRUE, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE) + +SIMPLE_VALUE (LIT_MAGIC_STRING_FIND, + ECMA_VALUE_TRUE, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE) + +SIMPLE_VALUE (LIT_MAGIC_STRING_FIND_INDEX, + ECMA_VALUE_TRUE, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE) + +SIMPLE_VALUE (LIT_MAGIC_STRING_KEYS, + ECMA_VALUE_TRUE, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE) + +SIMPLE_VALUE (LIT_MAGIC_STRING_VALUES, + ECMA_VALUE_TRUE, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE) + +#endif /* ENABLED (JERRY_ES2015) */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.inc.h index 99ec75143..59ba8d323 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.inc.h @@ -29,6 +29,13 @@ OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, ECMA_BUILTIN_ID_ARRAY, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#if ENABLED (JERRY_ES2015) +/* ECMA-262 v6, 22.1.3.31 */ +OBJECT_VALUE (LIT_GLOBAL_SYMBOL_UNSCOPABLES, + ECMA_BUILTIN_ID_ARRAY_PROTOTYPE_UNSCOPABLES, + ECMA_PROPERTY_FLAG_CONFIGURABLE) +#endif /* ENABLED (JERRY_ES2015) */ + /* Number properties: * (property name, object pointer getter) */ diff --git a/jerry-core/ecma/builtin-objects/ecma-builtins.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtins.inc.h index efd69fd09..2fd2faba4 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtins.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtins.inc.h @@ -510,6 +510,13 @@ BUILTIN_ROUTINE (ECMA_BUILTIN_ID_WEAKSET, #if ENABLED (JERRY_ES2015) +/* The Array.prototype[@@unscopables] object */ +BUILTIN (ECMA_BUILTIN_ID_ARRAY_PROTOTYPE_UNSCOPABLES, + ECMA_OBJECT_TYPE_GENERAL, + ECMA_BUILTIN_ID__COUNT, + true, + array_prototype_unscopables) + /* The Symbol prototype object (ECMA-262 v6, 19.4.2.7) */ BUILTIN (ECMA_BUILTIN_ID_SYMBOL_PROTOTYPE, ECMA_OBJECT_TYPE_GENERAL, diff --git a/jerry-core/ecma/operations/ecma-reference.c b/jerry-core/ecma/operations/ecma-reference.c index 26cc15ff6..5da480603 100644 --- a/jerry-core/ecma/operations/ecma-reference.c +++ b/jerry-core/ecma/operations/ecma-reference.c @@ -91,6 +91,57 @@ ecma_op_resolve_super_reference_value (ecma_object_t *lex_env_p) /**< starting l lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); } } /* ecma_op_resolve_super_reference_value */ + +/** + * Helper method for HasBindig operation + * + * See also: + * ECMA-262 v6, 8.1.1.2.1 steps 7-9; + * + * @return ECMA_VALUE_TRUE - if the property is unscopable + * ECMA_VALUE_FALSE - if a the property is not unscopable + * ECMA_VALUE_ERROR - otherwise + */ +static ecma_value_t +ecma_op_is_prop_unscopable (ecma_object_t *lex_env_p, /**< lexical environment */ + ecma_string_t *prop_name_p) /**< property's name */ +{ + if (lex_env_p == ecma_get_global_environment ()) + { + return ECMA_VALUE_FALSE; + } + + ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); + + ecma_value_t unscopables = ecma_op_object_get_by_symbol_id (binding_obj_p, LIT_MAGIC_STRING_UNSCOPABLES); + + if (ECMA_IS_VALUE_ERROR (unscopables)) + { + return unscopables; + } + + if (ecma_is_value_object (unscopables)) + { + ecma_object_t *unscopables_obj_p = ecma_get_object_from_value (unscopables); + ecma_value_t get_unscopables_value = ecma_op_object_get (unscopables_obj_p, prop_name_p); + ecma_deref_object (unscopables_obj_p); + + if (ECMA_IS_VALUE_ERROR (get_unscopables_value)) + { + return get_unscopables_value; + } + + bool is_blocked = ecma_op_to_boolean (get_unscopables_value); + + ecma_free_value (get_unscopables_value); + + return ecma_make_boolean_value (is_blocked); + } + + ecma_free_value (unscopables); + + return ECMA_VALUE_FALSE; +} /* ecma_op_is_prop_unscopable */ #endif /* ENABLED (JERRY_ES2015) */ /** @@ -131,39 +182,67 @@ ecma_op_resolve_reference_value (ecma_object_t *lex_env_p, /**< starting lexical { ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); -#if ENABLED (JERRY_LCACHE) - ecma_property_t *property_p = ecma_lcache_lookup (binding_obj_p, name_p); +#if ENABLED (JERRY_ES2015) + bool lcache_lookup_allowed = (lex_env_p == ecma_get_global_environment ()); +#else /* !ENABLED (JERRY_ES2015)*/ + bool lcache_lookup_allowed = true; +#endif /* ENABLED (JERRY_ES2015) */ - if (property_p != NULL) + if (lcache_lookup_allowed) { - ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); +#if ENABLED (JERRY_LCACHE) + ecma_property_t *property_p = ecma_lcache_lookup (binding_obj_p, name_p); - if (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA) + if (property_p != NULL) { - return ecma_fast_copy_value (prop_value_p->value); + ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + if (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA) + { + return ecma_fast_copy_value (prop_value_p->value); + } + + JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR); + + ecma_getter_setter_pointers_t *get_set_pair_p = ecma_get_named_accessor_property (prop_value_p); + + if (get_set_pair_p->getter_cp == JMEM_CP_NULL) + { + return ECMA_VALUE_UNDEFINED; + } + + ecma_object_t *getter_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->getter_cp); + + ecma_value_t base_value = ecma_make_object_value (binding_obj_p); + return ecma_op_function_call (getter_p, base_value, NULL, 0); } - - JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR); - - ecma_getter_setter_pointers_t *get_set_pair_p = ecma_get_named_accessor_property (prop_value_p); - - if (get_set_pair_p->getter_cp == JMEM_CP_NULL) - { - return ECMA_VALUE_UNDEFINED; - } - - ecma_object_t *getter_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->getter_cp); - - ecma_value_t base_value = ecma_make_object_value (binding_obj_p); - return ecma_op_function_call (getter_p, base_value, NULL, 0); - } #endif /* ENABLED (JERRY_LCACHE) */ + } ecma_value_t prop_value = ecma_op_object_find (binding_obj_p, name_p); if (ecma_is_value_found (prop_value)) { +#if ENABLED (JERRY_ES2015) + ecma_value_t blocked = ecma_op_is_prop_unscopable (lex_env_p, name_p); + + if (ECMA_IS_VALUE_ERROR (blocked)) + { + ecma_free_value (prop_value); + return blocked; + } + + if (ecma_is_value_true (blocked)) + { + ecma_free_value (prop_value); + } + else + { + return prop_value; + } +#else /* !ENABLED (JERRY_ES2015) */ return prop_value; +#endif /* ENABLED (JERRY_ES2015) */ } } else diff --git a/jerry-core/lit/lit-magic-strings.inc.h b/jerry-core/lit/lit-magic-strings.inc.h index 265f9b8bb..d06939f24 100644 --- a/jerry-core/lit/lit-magic-strings.inc.h +++ b/jerry-core/lit/lit-magic-strings.inc.h @@ -136,10 +136,13 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_EVAL, "eval") #if ENABLED (JERRY_BUILTIN_REGEXP) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_EXEC, "exec") #endif -#if ENABLED (JERRY_BUILTIN_ARRAY) && ENABLED (JERRY_ES2015) \ +#if ENABLED (JERRY_ES2015) \ || ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FILL, "fill") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FIND, "find") +#endif +#if ENABLED (JERRY_BUILTIN_ARRAY) && ENABLED (JERRY_ES2015) \ +|| ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FROM, "from") #endif #if ENABLED (JERRY_BUILTIN_ARRAY) \ @@ -353,10 +356,7 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SYMBOL, "symbol") || ENABLED (JERRY_BUILTIN_JSON) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_JSON_UL, "toJSON") #endif -#if ENABLED (JERRY_BUILTIN_ARRAY) && ENABLED (JERRY_ES2015) \ -|| ENABLED (JERRY_ES2015) && ENABLED (JERRY_ES2015_BUILTIN_MAP) \ -|| ENABLED (JERRY_ES2015) && ENABLED (JERRY_ES2015_BUILTIN_SET) \ -|| ENABLED (JERRY_ES2015) && ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) +#if ENABLED (JERRY_ES2015) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_VALUES, "values") #endif LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BOOLEAN_UL, "Boolean") @@ -392,10 +392,7 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_COMPILE, "compile") || ENABLED (JERRY_ES2015_MODULE_SYSTEM) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DEFAULT, "default") #endif -#if ENABLED (JERRY_BUILTIN_ARRAY) && ENABLED (JERRY_ES2015) \ -|| ENABLED (JERRY_ES2015) && ENABLED (JERRY_ES2015_BUILTIN_MAP) \ -|| ENABLED (JERRY_ES2015) && ENABLED (JERRY_ES2015_BUILTIN_SET) \ -|| ENABLED (JERRY_ES2015) && ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) +#if ENABLED (JERRY_ES2015) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ENTRIES, "entries") #endif #if ENABLED (JERRY_BUILTIN_ARRAY) \ @@ -539,7 +536,7 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_UNDEFINED_UL, "Undefined") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ARGUMENTS, "arguments") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DECODE_URI, "decodeURI") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ENCODE_URI, "encodeURI") -#if ENABLED (JERRY_BUILTIN_ARRAY) && ENABLED (JERRY_ES2015) \ +#if ENABLED (JERRY_ES2015) \ || ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FIND_INDEX, "findIndex") #endif @@ -592,7 +589,7 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BYTE_OFFSET_UL, "byteOffset") #if ENABLED (JERRY_BUILTIN_STRING) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CHAR_CODE_AT_UL, "charCodeAt") #endif -#if ENABLED (JERRY_BUILTIN_ARRAY) && ENABLED (JERRY_ES2015) \ +#if ENABLED (JERRY_ES2015) \ || ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_COPY_WITHIN, "copyWithin") #endif @@ -865,7 +862,7 @@ LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (10, LIT_MAGIC_STRING_TYPED_ARRAY_UL) LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (10, LIT_MAGIC_STRING_BYTE_LENGTH_UL) #elif ENABLED (JERRY_BUILTIN_STRING) LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (10, LIT_MAGIC_STRING_CHAR_CODE_AT_UL) -#elif ENABLED (JERRY_BUILTIN_ARRAY) && ENABLED (JERRY_ES2015) \ +#elif ENABLED (JERRY_ES2015) \ || ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (10, LIT_MAGIC_STRING_COPY_WITHIN) #else diff --git a/tests/jerry/es2015/symbol-unscopables.js b/tests/jerry/es2015/symbol-unscopables.js new file mode 100644 index 000000000..8fc7076af --- /dev/null +++ b/tests/jerry/es2015/symbol-unscopables.js @@ -0,0 +1,88 @@ +// Copyright JS Foundation and other contributors, http://js.foundation +// +// 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. + +var obj = { + prop1: 42, + prop2: 13, + prop3: "foo", + prop4: 1 +}; + +var obj2 = { + foo: "foo" +}; + +obj[Symbol.unscopables] = { + prop1: false, + prop2: true, + prop3: undefined, + prop4: obj2 +}; + +with (obj) +{ + assert(prop1 === 42); + + try { + prop2; + assert(false); + } catch (e) { + assert(e instanceof ReferenceError); + } + + assert (prop3 === "foo"); + + try { + prop4; + assert(false); + } catch (e) { + assert(e instanceof ReferenceError); + } + + try { + prop5; + assert(false); + } catch (e) { + assert(e instanceof ReferenceError); + } +} + +var obj2 = {}; +Object.defineProperty(obj2, Symbol.unscopables, { get: function () { throw 42; } }); + +with (obj2) { + try { + prop; + assert(false); + } catch (e) { + assert(e instanceof ReferenceError); + } +} + +var symbol_obj = Array.prototype[Symbol.unscopables]; +assert(symbol_obj.copyWithin === true); +assert(symbol_obj.entries === true); +assert(symbol_obj.fill === true); +assert(symbol_obj.find === true); +assert(symbol_obj.findIndex === true); +assert(symbol_obj.keys === true); +assert(symbol_obj.values === true); + +assert(Object.getPrototypeOf(Array.prototype[Symbol.unscopables]) === null); + +var obj3 = Object.getOwnPropertyDescriptor(Array.prototype[Symbol.unscopables], "find"); +assert(obj3.value === true); +assert(obj3.writable === true); +assert(obj3.enumerable == true); +assert(obj3.configurable == true);