• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright JS Foundation and other contributors, http://js.foundation
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "jerryscript.h"
17 #include "jerryscript-port.h"
18 #include "jerryscript-port-default.h"
19 #include "test-common.h"
20 #include <gtest/gtest.h>
21 
22 static bool
count_objects(jerry_value_t object,void * user_arg)23 count_objects (jerry_value_t object, void *user_arg)
24 {
25   (void) object;
26   TEST_ASSERT (user_arg != NULL);
27 
28   int *counter = (int *) user_arg;
29 
30   (*counter)++;
31   return true;
32 } /* count_objects */
33 
34 static void
test_container(void)35 test_container (void)
36 {
37   jerry_value_t global = jerry_get_global_object ();
38   jerry_value_t map_str = jerry_create_string ((const jerry_char_t *) "Map");
39   jerry_value_t map_result = jerry_get_property (global, map_str);
40   jerry_type_t type = jerry_value_get_type (map_result);
41 
42   jerry_release_value (map_result);
43   jerry_release_value (map_str);
44   jerry_release_value (global);
45 
46   /* If there is no Map function this is not an es2015 profile build, skip this test case. */
47   if (type != JERRY_TYPE_FUNCTION)
48   {
49     jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Container based test is disabled!\n");
50     return;
51   }
52 
53   {
54     /* Create a "DEMO" array which will be used for the Map below. */
55     const char array_str[] = "var DEMO = [[1, 2], [3, 4]]; DEMO";
56     jerry_value_t array = jerry_eval ((const jerry_char_t *) array_str, sizeof (array_str) - 1, 0);
57     TEST_ASSERT (jerry_value_is_object (array));
58     TEST_ASSERT (!jerry_value_is_error (array));
59     jerry_release_value (array);
60   }
61 
62   const char eval_str[] = "new Map (DEMO)";
63   {
64     /* Make sure that the Map and it's prototype object/function is initialized. */
65     jerry_value_t result = jerry_eval ((const jerry_char_t *) eval_str, sizeof (eval_str) - 1, 0);
66     TEST_ASSERT (jerry_value_is_object (result));
67     TEST_ASSERT (!jerry_value_is_error (result));
68     jerry_release_value (result);
69   }
70 
71   /* Do a bit of cleaning to clear up old objects. */
72   jerry_gc (JERRY_GC_PRESSURE_LOW);
73 
74   /* Get the number of iterable objects. */
75   int start_count = 0;
76   jerry_objects_foreach (count_objects, &start_count);
77 
78   /* Create another map. */
79   jerry_value_t result = jerry_eval ((const jerry_char_t *) eval_str, sizeof (eval_str) - 1, 0);
80 
81   /* Remove any old/unused objects. */
82   jerry_gc (JERRY_GC_PRESSURE_LOW);
83 
84   /* Get the current number of objects. */
85   int end_count = 0;
86   jerry_objects_foreach (count_objects, &end_count);
87 
88   /* As only one Map was created the number of available iterable objects should be incremented only by one. */
89   ASSERT_TRUE (!(end_count > start_count));
90   ASSERT_TRUE (!((end_count - start_count) == 1));
91 
92   jerry_release_value (result);
93 } /* test_container */
94 
95 static void
test_internal_prop(void)96 test_internal_prop (void)
97 {
98   /* Make sure that the object is initialized in the engine. */
99   {
100     jerry_value_t object = jerry_create_object ();
101     jerry_release_value (object);
102   }
103 
104   /* Get the number of iterable objects. */
105   int before_object_count = 0;
106   jerry_objects_foreach (count_objects, &before_object_count);
107 
108   jerry_value_t object = jerry_create_object ();
109 
110   /* After creating the object, the number of objects is incremented by one. */
111   int after_object_count = 0;
112   {
113     jerry_objects_foreach (count_objects, &after_object_count);
114 
115     TEST_ASSERT (after_object_count > before_object_count);
116     TEST_ASSERT ((after_object_count - before_object_count) == 1);
117   }
118 
119   jerry_value_t internal_prop_name = jerry_create_string ((const jerry_char_t *) "hidden_foo");
120   jerry_value_t internal_prop_object = jerry_create_object ();
121   bool internal_result = jerry_set_internal_property (object, internal_prop_name, internal_prop_object);
122   TEST_ASSERT (internal_result == true);
123   jerry_release_value (internal_prop_name);
124   jerry_release_value (internal_prop_object);
125 
126   /* After adding an internal property object, the number of object is incremented by one. */
127   {
128     int after_internal_count = 0;
129     jerry_objects_foreach (count_objects, &after_internal_count);
130 
131     TEST_ASSERT (after_internal_count > after_object_count);
132     TEST_ASSERT ((after_internal_count - after_object_count) == 1);
133   }
134 
135   jerry_release_value (object);
136 } /* test_internal_prop */
137 
138 static int test_data = 1;
139 
free_test_data(void * data_p)140 static void free_test_data (void *data_p)
141 {
142   TEST_ASSERT ((int *) data_p == &test_data);
143 } /* free_test_data */
144 
145 static const jerry_object_native_info_t test_info =
146 {
147   .free_cb = free_test_data
148 };
149 
150 static const jerry_char_t strict_equal_source[] = "var x = function(a, b) {return a === b;}; x";
151 
152 static bool
find_test_object_by_data(const jerry_value_t candidate,void * object_data_p,void * context_p)153 find_test_object_by_data (const jerry_value_t candidate,
154                           void *object_data_p,
155                           void *context_p)
156 {
157   if (object_data_p == &test_data)
158   {
159     *((jerry_value_t *) context_p) = jerry_acquire_value (candidate);
160     return false;
161   }
162   return true;
163 } /* find_test_object_by_data */
164 
165 static bool
find_test_object_by_property(const jerry_value_t candidate,void * context_p)166 find_test_object_by_property (const jerry_value_t candidate,
167                               void *context_p)
168 {
169   jerry_value_t *args_p = (jerry_value_t *) context_p;
170   jerry_value_t result = jerry_has_property (candidate, args_p[0]);
171 
172   bool has_property = (!jerry_value_is_error (result) && jerry_get_boolean_value (result));
173 
174   /* If the object has the desired property, store a new reference to it in args_p[1]. */
175   if (has_property)
176   {
177     args_p[1] = jerry_acquire_value (candidate);
178   }
179 
180   jerry_release_value (result);
181 
182   /* Stop iterating if we've found our object. */
183   return !has_property;
184 } /* find_test_object_by_property */
185 class ObjectsForeachTest : public testing::Test{
186 public:
SetUpTestCase()187     static void SetUpTestCase()
188     {
189         GTEST_LOG_(INFO) << "ObjectsForeachTest SetUpTestCase";
190     }
191 
TearDownTestCase()192     static void TearDownTestCase()
193     {
194         GTEST_LOG_(INFO) << "ObjectsForeachTest TearDownTestCase";
195     }
196 
SetUp()197     void SetUp() override {}
TearDown()198     void TearDown() override {}
199 
200 };
201 static constexpr size_t JERRY_SCRIPT_MEM_SIZE = 50 * 1024 * 1024;
context_alloc_fn(size_t size,void * cb_data)202 static void* context_alloc_fn(size_t size, void* cb_data)
203 {
204     (void)cb_data;
205     size_t newSize = size > JERRY_SCRIPT_MEM_SIZE ? JERRY_SCRIPT_MEM_SIZE : size;
206     return malloc(newSize);
207 }
208 HWTEST_F(ObjectsForeachTest, Test001, testing::ext::TestSize.Level1)
209 {
210   jerry_context_t *ctx_p = jerry_create_context (1024, context_alloc_fn, NULL);
211   jerry_port_default_set_current_context (ctx_p);
212   jerry_init (JERRY_INIT_EMPTY);
213 
214   /* Render strict-equal as a function. */
215   jerry_value_t parse_result = jerry_parse (NULL,
216                                             0,
217                                             strict_equal_source,
218                                             sizeof (strict_equal_source) - 1,
219                                             JERRY_PARSE_STRICT_MODE);
220   TEST_ASSERT (!jerry_value_is_error (parse_result));
221   jerry_value_t strict_equal = jerry_run (parse_result);
222   TEST_ASSERT (!jerry_value_is_error (strict_equal));
223   jerry_release_value (parse_result);
224 
225   /* Create an object and associate some native data with it. */
226   jerry_value_t object = jerry_create_object ();
227   jerry_set_object_native_pointer (object, &test_data, &test_info);
228 
229   /* Retrieve the object by its native pointer. */
230 
231   jerry_value_t found_object;
232   TEST_ASSERT (jerry_objects_foreach_by_native_info (&test_info, find_test_object_by_data, &found_object));
233   jerry_value_t args[2] = {object, found_object};
234 
235   /* Assert that the correct object was retrieved. */
236   jerry_value_t undefined = jerry_create_undefined ();
237   jerry_value_t strict_equal_result = jerry_call_function (strict_equal, undefined, args, 2);
238   TEST_ASSERT (jerry_value_is_boolean (strict_equal_result) && jerry_get_boolean_value (strict_equal_result));
239   jerry_release_value (strict_equal_result);
240   jerry_release_value (found_object);
241   jerry_release_value (object);
242 
243   /* Collect garbage. */
244   jerry_gc (JERRY_GC_PRESSURE_LOW);
245 
246   /* Attempt to retrieve the object by its native pointer again. */
247   TEST_ASSERT (!jerry_objects_foreach_by_native_info (&test_info, find_test_object_by_data, &found_object));
248 
249   /* Create an object and set a property on it. */
250   object = jerry_create_object ();
251   jerry_value_t property_name = jerry_create_string ((jerry_char_t *) "xyzzy");
252   jerry_value_t property_value = jerry_create_number (42);
253   jerry_release_value (jerry_set_property (object, property_name, property_value));
254   jerry_release_value (property_value);
255 
256   /* Retrieve the object by the presence of its property, placing it at args[1]. */
257   args[0] = property_name;
258   TEST_ASSERT (jerry_objects_foreach (find_test_object_by_property, args));
259 
260   /* Assert that the right object was retrieved and release both the original reference to it and the retrieved one. */
261   args[0] = object;
262   strict_equal_result = jerry_call_function (strict_equal, undefined, args, 2);
263   TEST_ASSERT (jerry_value_is_boolean (strict_equal_result) && jerry_get_boolean_value (strict_equal_result));
264   jerry_release_value (strict_equal_result);
265   jerry_release_value (args[0]);
266   jerry_release_value (args[1]);
267 
268   /* Collect garbage. */
269   jerry_gc (JERRY_GC_PRESSURE_LOW);
270 
271   /* Attempt to retrieve the object by the presence of its property again. */
272   args[0] = property_name;
273   TEST_ASSERT (!jerry_objects_foreach (find_test_object_by_property, args));
274 
275   jerry_release_value (property_name);
276   jerry_release_value (undefined);
277   jerry_release_value (strict_equal);
278 
279   test_container ();
280   test_internal_prop ();
281 
282   jerry_cleanup ();
283   free (ctx_p);
284 }
285