Skip to content

Commit 3664d9d

Browse files
Gabriel "_|Nix|_" SchulhofLaszloLango
Gabriel "_|Nix|_" Schulhof
authored andcommitted
Add an API to traverse objects by their associated native data (#2236)
JerryScript-DCO-1.0-Signed-off-by: Gabriel Schulhof [email protected]
1 parent bb84466 commit 3664d9d

File tree

4 files changed

+422
-0
lines changed

4 files changed

+422
-0
lines changed

docs/02.API-REFERENCE.md

+208
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,33 @@ typedef bool (*jerry_object_property_foreach_t) (const jerry_value_t property_na
291291
void *user_data_p);
292292
```
293293

294+
## jerry_objects_foreach_t
295+
296+
**Summary**
297+
298+
Function type applied for each object in the engine
299+
300+
**Prototype**
301+
302+
```c
303+
typedef bool (*jerry_objects_foreach_t) (const jerry_value_t object,
304+
void *user_data_p);
305+
```
306+
307+
## jerry_objects_foreach_by_native_info_t
308+
309+
**Summary**
310+
311+
Function type applied for each matching object in the engine
312+
313+
**Prototype**
314+
315+
```c
316+
typedef bool (*jerry_objects_foreach_by_native_info_t) (const jerry_value_t object,
317+
void *object_data_p,
318+
void *user_data_p);
319+
```
320+
294321
## jerry_vm_exec_stop_callback_t
295322

296323
**Summary**
@@ -4564,6 +4591,187 @@ bool foreach_function (const jerry_value_t prop_name,
45644591

45654592
- [jerry_object_property_foreach_t](#jerry_object_property_foreach_t)
45664593

4594+
## jerry_objects_foreach
4595+
4596+
**Summary**
4597+
4598+
Iterate over objects.
4599+
4600+
*Note*: Values obtained in `foreach_p` must be retained using [jerry_acquire_value](#jerry_acquire_value).
4601+
4602+
**Prototype**
4603+
4604+
```c
4605+
bool jerry_objects_foreach (jerry_objects_foreach_t foreach_p,
4606+
void *user_data_p);
4607+
```
4608+
4609+
- `foreach_p` - function that will be invoked for each object.
4610+
- `user_data_p` - User data to pass to the function.
4611+
- return value
4612+
- `true`, if the search function terminated the traversal by returning `false`
4613+
- `false`, if the end of the list of objects was reached
4614+
4615+
**Example**
4616+
4617+
```c
4618+
typedef struct
4619+
{
4620+
jerry_value_t property_name;
4621+
jerry_value_t result;
4622+
} find_my_object_info_t;
4623+
4624+
/*
4625+
* Find the first object with the given property.
4626+
*/
4627+
static bool
4628+
find_my_object(const jerry_value_t candidate,
4629+
void *user_data_p)
4630+
{
4631+
find_my_object_info_t *info_p = (find_my_object_info_t *) user_data_p;
4632+
jerry_value_t has_property = jerry_object_has_property (candidate, info_p->property_name);
4633+
bool keep_searching = (jerry_value_has_error_flag (has_property) || !jerry_get_boolean_value ());
4634+
if (!keep_searching)
4635+
{
4636+
/* We found it, so we acquire the value and record it. */
4637+
info_p->result = jerry_acquire_value (candidate);
4638+
}
4639+
jerry_release_value (has_property);
4640+
return keep_searching;
4641+
} /* find_my_object */
4642+
4643+
{
4644+
find_my_object_info_t search_info =
4645+
{
4646+
.property_name = jerry_create_string ("desired_property")
4647+
};
4648+
4649+
if (jerry_object_foreach (find_my_object, &search_info))
4650+
{
4651+
/* The search was successful. Do something useful with search_info.result. */
4652+
...
4653+
4654+
/* Release the found object after we're done using it. */
4655+
jerry_release_value (search_info.result);
4656+
}
4657+
else
4658+
{
4659+
/* The search has failed. */
4660+
}
4661+
4662+
jerry_release_value (search_info.desired_property);
4663+
}
4664+
```
4665+
**See also**
4666+
4667+
- [jerry_objects_foreach_t](#jerry_objects_foreach_t)
4668+
4669+
## jerry_objects_foreach_by_native_info
4670+
4671+
**Summary**
4672+
4673+
Iterate over objects matching a certain native data type.
4674+
4675+
*Note*: Values obtained in `foreach_p` must be retained using [jerry_acquire_value](#jerry_acquire_value).
4676+
4677+
**Prototype**
4678+
4679+
```c
4680+
bool jerry_objects_foreach_by_native_info (const jerry_object_native_info_t *native_info_p,
4681+
jerry_objects_foreach_by_native_info_t foreach_p,
4682+
void *user_data_p);
4683+
```
4684+
4685+
- `native_info_p` - native pointer's type infomation.
4686+
- return value
4687+
- `true`, if the search function terminated the traversal by returning `false`
4688+
- `false`, if the end of the list of objects was reached
4689+
4690+
**Example**
4691+
4692+
```c
4693+
typedef struct
4694+
{
4695+
int foo;
4696+
bool bar;
4697+
} native_obj_t;
4698+
4699+
typedef struct
4700+
{
4701+
jerry_value_t found_object;
4702+
void *match_data_p;
4703+
} find_object_data_t;
4704+
4705+
static void native_freecb (void *native_p)
4706+
{
4707+
... // free the native pointer
4708+
} /* native_freecb */
4709+
4710+
// NOTE: The address (!) of type_info acts as a way to uniquely "identify" the
4711+
// C type `native_obj_t *`.
4712+
static const jerry_object_native_info_t native_obj_type_info =
4713+
{
4714+
.free_cb = native_freecb
4715+
};
4716+
4717+
// Function creating JS object that is "backed" by a native_obj_t *:
4718+
{
4719+
...
4720+
4721+
// construct object and native_set value:
4722+
jerry_value_t object = ...;
4723+
native_obj_t *native_obj_p = malloc (sizeof (*native_obj_p));
4724+
jerry_set_object_native_pointer (object, native_obj_p, &native_obj_type_info);
4725+
4726+
...
4727+
}
4728+
4729+
// Native method that retrieves the JavaScript object by way of its native data:
4730+
static bool find_object (const jerry_value_t candidate, void *data_p, void *user_data_p)
4731+
{
4732+
find_object_data_t *find_data_p = (find_object_data_t *) user_data_p;
4733+
4734+
if (find_data_p->match_data_p == data_p)
4735+
{
4736+
// If the object was found, acquire it and store it in the user data.
4737+
find_data_p->found_object = jerry_acquire_value (candidate);
4738+
4739+
// Stop traversing over the objects.
4740+
return false;
4741+
}
4742+
4743+
// Indicate that the object was not found, so traversal must continue.
4744+
return true;
4745+
} /* find_object */
4746+
...
4747+
{
4748+
find_object_data_t find_data =
4749+
{
4750+
.match_data = native_obj
4751+
};
4752+
4753+
if (jerry_objects_foreach_by_native_info (&native_obj_type_info, find_object, &find_data))
4754+
{
4755+
// The object was found and is now stored in find_data.found_object. After using it, it must be released.
4756+
...
4757+
jerry_release_value (find_data.found_object);
4758+
}
4759+
else
4760+
{
4761+
// The object was not found.
4762+
}
4763+
...
4764+
}
4765+
```
4766+
4767+
**See also**
4768+
4769+
- [jerry_create_object](#jerry_create_object)
4770+
- [jerry_set_object_native_pointer](#jerry_set_object_native_pointer)
4771+
- [jerry_get_object_native_pointer](#jerry_get_object_native_pointer)
4772+
- [jerry_object_native_info_t](#jerry_object_native_info_t)
4773+
- [jerry_objects_foreach](#jerry_objects_foreach)
4774+
45674775

45684776
# Input validator functions
45694777

jerry-core/api/jerry.c

+64
Original file line numberDiff line numberDiff line change
@@ -2462,6 +2462,70 @@ jerry_set_object_native_handle (const jerry_value_t obj_val, /**< object to set
24622462
}
24632463
} /* jerry_set_object_native_handle */
24642464

2465+
/**
2466+
* Traverse objects.
2467+
*
2468+
* @return true - traversal was interrupted by the callback.
2469+
* false - otherwise - traversal visited all objects.
2470+
*/
2471+
bool jerry_objects_foreach (jerry_objects_foreach_t foreach_p,
2472+
void *user_data_p)
2473+
{
2474+
jerry_assert_api_available ();
2475+
2476+
JERRY_ASSERT (foreach_p != NULL);
2477+
2478+
for (ecma_object_t *iter_p = JERRY_CONTEXT (ecma_gc_objects_p);
2479+
iter_p != NULL;
2480+
iter_p = ECMA_GET_POINTER (ecma_object_t, iter_p->gc_next_cp))
2481+
{
2482+
if (!ecma_is_lexical_environment (iter_p)
2483+
&& !foreach_p (ecma_make_object_value (iter_p), user_data_p))
2484+
{
2485+
return true;
2486+
}
2487+
}
2488+
2489+
return false;
2490+
} /* jerry_objects_foreach */
2491+
2492+
/**
2493+
* Traverse objects having a given native type info.
2494+
*
2495+
* @return true - traversal was interrupted by the callback.
2496+
* false - otherwise - traversal visited all objects.
2497+
*/
2498+
bool
2499+
jerry_objects_foreach_by_native_info (const jerry_object_native_info_t *native_info_p,
2500+
jerry_objects_foreach_by_native_info_t foreach_p,
2501+
void *user_data_p)
2502+
{
2503+
jerry_assert_api_available ();
2504+
2505+
JERRY_ASSERT (native_info_p != NULL);
2506+
JERRY_ASSERT (foreach_p != NULL);
2507+
2508+
ecma_native_pointer_t *native_pointer_p;
2509+
2510+
for (ecma_object_t *iter_p = JERRY_CONTEXT (ecma_gc_objects_p);
2511+
iter_p != NULL;
2512+
iter_p = ECMA_GET_POINTER (ecma_object_t, iter_p->gc_next_cp))
2513+
{
2514+
if (!ecma_is_lexical_environment (iter_p))
2515+
{
2516+
native_pointer_p = ecma_get_native_pointer_value (iter_p, LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER);
2517+
if (native_pointer_p
2518+
&& ((const jerry_object_native_info_t *) native_pointer_p->u.info_p) == native_info_p
2519+
&& !foreach_p (ecma_make_object_value (iter_p), native_pointer_p->data_p, user_data_p))
2520+
{
2521+
return true;
2522+
}
2523+
}
2524+
}
2525+
2526+
return false;
2527+
} /* jerry_objects_foreach_by_native_info */
2528+
24652529
/**
24662530
* Get native pointer and its type information, associated with specified object.
24672531
*

jerry-core/include/jerryscript-core.h

+17
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,18 @@ typedef jerry_value_t (*jerry_vm_exec_stop_callback_t) (void *user_p);
210210
typedef bool (*jerry_object_property_foreach_t) (const jerry_value_t property_name,
211211
const jerry_value_t property_value,
212212
void *user_data_p);
213+
/**
214+
* Function type applied for each object in the engine.
215+
*/
216+
typedef bool (*jerry_objects_foreach_t) (const jerry_value_t object,
217+
void *user_data_p);
218+
219+
/**
220+
* Function type applied for each matching object in the engine.
221+
*/
222+
typedef bool (*jerry_objects_foreach_by_native_info_t) (const jerry_value_t object,
223+
void *object_data_p,
224+
void *user_data_p);
213225

214226
/**
215227
* User context item manager
@@ -439,6 +451,11 @@ void jerry_set_object_native_handle (const jerry_value_t obj_val, uintptr_t hand
439451
bool jerry_get_object_native_pointer (const jerry_value_t obj_val,
440452
void **out_native_pointer_p,
441453
const jerry_object_native_info_t **out_pointer_info_p);
454+
bool jerry_objects_foreach (jerry_objects_foreach_t foreach_p,
455+
void *user_data);
456+
bool jerry_objects_foreach_by_native_info (const jerry_object_native_info_t *native_info_p,
457+
jerry_objects_foreach_by_native_info_t foreach_p,
458+
void *user_data_p);
442459
void jerry_set_object_native_pointer (const jerry_value_t obj_val,
443460
void *native_pointer_p,
444461
const jerry_object_native_info_t *native_info_p);

0 commit comments

Comments
 (0)