Skip to content

Commit f34219c

Browse files
author
Gabriel Schulhof
committed
Support a user context void * pointer in jerry_context_t (#1717)
This modification makes it possible to initialize a context in such a way that a `void *` pointer is stored inside the context and is made available via a new `jerry_get_user_context()` API. The pointer is initialized via a new `jerry_init_with_user_context()` API, which calls the existing `jerry_init()`, after which it sets the value of the new `user_context` element in the `jerry_context_t` structure using the context allocation callback provided as the second parameter to the new `jerry_init_with_user_context()` API. The location of the cleanup function responsible for deallocating the pointer created by the context allocation callback is provided as the third parameter. This location is stored in the context along with the pointer itself. When a context is discarded via `jerry_cleanup()`, the user context cleanup function is called to dispose of the pointer stored within the context. The semantics behind the API are such that it is now possible to choose for each context an agent which manages arbitrary user data keyed to the given context. The agent must be chosen at context instantiation time and cannot be changed afterwards, remaining in effect for the lifetime of the context. Fixes #1717 JerryScript-DCO-1.0-Signed-off-by: Gabriel Schulhof gabriel.schulhof@intel.com
1 parent a83319c commit f34219c

File tree

5 files changed

+215
-3
lines changed

5 files changed

+215
-3
lines changed

docs/02.API-REFERENCE.md

Lines changed: 114 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -225,8 +225,10 @@ typedef bool (*jerry_object_property_foreach_t) (const jerry_value_t property_na
225225

226226
**Summary**
227227

228-
Initializes the JerryScript engine, making possible to run JavaScript code and perform operations on
229-
JavaScript values.
228+
Initializes the JerryScript engine, making it possible to run JavaScript code and perform operations
229+
on JavaScript values. See also [jerry_init_with_user_context](#jerry_init_with_user_context) if you
230+
wish to initialize the JerryScript engine in such a way that its context contains a custom pointer
231+
which you can later retrieve using [jerry_get_user_context](#jerry_get_user_context).
230232

231233
**Prototype**
232234

@@ -259,13 +261,91 @@ jerry_init (jerry_init_flag_t flags)
259261
**See also**
260262

261263
- [jerry_cleanup](#jerry_cleanup)
264+
- [jerry_init_with_user_context](#jerry_init_with_user_context)
265+
266+
267+
## jerry_init_with_user_context
268+
269+
**Summary**
270+
271+
Calls [jerry_init](#jerry_init) to initialize the JerryScript engine, thereby making it possible
272+
to run JavaScript code and perform operations on JavaScript values. In addition to the first
273+
parameter this function accepts two more parameters with which it allows the caller to store a
274+
`void *` pointer inside the context being initialized with `jerry_init ()`. The function calls the
275+
callback given in its `init_cb` parameter to allocate the memory for the pointer and it stores the
276+
function pointer given in the `deinit_cb` parameter along with the pointer so that it may be called
277+
to free the stored pointer when `jerry_cleanup ()` is later called to dispose of the context.
278+
279+
**Prototype**
280+
281+
```c
282+
void
283+
jerry_init_with_user_context (jerry_init_flag_t flags,
284+
jerry_user_context_init_cb init_cb,
285+
jerry_user_context_deinit_cb deinit_cb);
286+
```
287+
288+
`flags` - combination of various engine configuration flags:
289+
290+
- `JERRY_INIT_EMPTY` - no flags, just initialize in default configuration.
291+
- `JERRY_INIT_SHOW_OPCODES` - print compiled byte-code.
292+
- `JERRY_INIT_SHOW_REGEXP_OPCODES` - print compiled regexp byte-code.
293+
- `JERRY_INIT_MEM_STATS` - dump memory statistics.
294+
- `JERRY_INIT_MEM_STATS_SEPARATE` - dump memory statistics and reset peak values after parse.
295+
- `JERRY_INIT_DEBUGGER` - enable all features required by debugging.
296+
297+
`init_cb` - a function pointer that will be called to allocate the custom pointer.
298+
299+
`deinit_cb` - a function pointer that will be called when the custom pointer must be freed.
300+
301+
**Example**
302+
303+
```c
304+
void *
305+
init_user_context (void)
306+
{
307+
void *return_value;
308+
309+
/* allocate and initialize return_value */
310+
311+
return return_value;
312+
} /* init_user_context */
313+
314+
void
315+
free_user_context (void *context)
316+
{
317+
318+
/* free the value allocated above */
319+
320+
} /* free_user_context */
321+
322+
{
323+
/* init_user_context () will be called before the call below returns */
324+
jerry_init_with_user_context (JERRY_INIT_SHOW_OPCODES | JERRY_INIT_SHOW_REGEXP_OPCODES,
325+
init_user_context,
326+
free_user_context);
327+
328+
/* ... */
329+
330+
/* free_user_context () will be called before the call below returns */
331+
jerry_cleanup ();
332+
}
333+
```
334+
335+
**See also**
336+
337+
- [jerry_cleanup](#jerry_cleanup)
338+
- [jerry_get_user_context](#jerry_get_user_context)
262339

263340

264341
## jerry_cleanup
265342

266343
**Summary**
267344

268-
Finish JavaScript engine execution, freeing memory and JavaScript values.
345+
Finish JavaScript engine execution, freeing memory and JavaScript values. If the context was
346+
initialized with `jerry_init_with_user_context ()` and a `deinit_cb` was provided, then it will
347+
be called to free the memory at the custom pointer which was associated with the context being
348+
cleaned up.
269349

270350
*Note*: JavaScript values, received from engine, will be inaccessible after the cleanup.
271351

@@ -279,6 +359,37 @@ jerry_cleanup (void);
279359
**See also**
280360

281361
- [jerry_init](#jerry_init)
362+
- [jerry_init_with_user_context](#jerry_init_with_user_context)
363+
364+
365+
## jerry_get_user_context
366+
367+
**Summary**
368+
369+
Retrieve the pointer stored within the current context.
370+
371+
**Prototype**
372+
373+
```c
374+
void *
375+
jerry_get_user_context (void);
376+
```
377+
378+
- return value: the pointer that was assigned during `jerry_init_with_user_context ()`
379+
380+
**Example**
381+
382+
```c
383+
{
384+
/* ... */
385+
my_context *custom_data = (my_context *) jerry_get_user_context ();
386+
/* ... */
387+
}
388+
```
389+
390+
**See also**
391+
- [jerry_init_with_user_context](#jerry_init_with_user_context)
392+
- [jerry_cleanup](#jerry_cleanup)
282393

283394

284395
## jerry_register_magic_strings

jerry-core/jcontext/jcontext.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ typedef struct
6161
ecma_lit_storage_item_t *number_list_first_p; /**< first item of the literal number list */
6262
ecma_object_t *ecma_global_lex_env_p; /**< global lexical environment */
6363
vm_frame_ctx_t *vm_top_context_p; /**< top (current) interpreter context */
64+
void *user_context_p; /**< user-provided context-specific pointer */
65+
jerry_user_context_deinit_cb user_context_deinit_cb; /**< user-provided deleter for context-specific pointer */
6466
size_t ecma_gc_objects_number; /**< number of currently allocated objects */
6567
size_t ecma_gc_new_objects; /**< number of newly allocated objects since last GC session */
6668
size_t jmem_heap_allocated_size; /**< size of allocated regions */

jerry-core/jerry.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,22 @@ jerry_init (jerry_init_flag_t flags) /**< combination of Jerry flags */
166166
#endif /* JERRY_DEBUGGER */
167167
} /* jerry_init */
168168

169+
/**
170+
* Initialize Jerry engine with custom user context.
171+
*/
172+
void
173+
jerry_init_with_user_context (jerry_init_flag_t flags, /**< combination of Jerry flags */
174+
jerry_user_context_init_cb init_cb, /**< callback to call to create the user context or
175+
* NULL, in which case no user context will be
176+
* created */
177+
jerry_user_context_deinit_cb deinit_cb) /**< callback to call to free the user context or
178+
* NULL if it does not need to be freed */
179+
{
180+
jerry_init (flags);
181+
JERRY_CONTEXT (user_context_p) = (init_cb ? init_cb () : NULL);
182+
JERRY_CONTEXT (user_context_deinit_cb) = deinit_cb;
183+
} /* jerry_init_with_user_context */
184+
169185
/**
170186
* Terminate Jerry engine
171187
*/
@@ -185,8 +201,24 @@ jerry_cleanup (void)
185201

186202
jmem_finalize ();
187203
jerry_make_api_unavailable ();
204+
205+
if (JERRY_CONTEXT (user_context_deinit_cb))
206+
{
207+
JERRY_CONTEXT (user_context_deinit_cb) (JERRY_CONTEXT (user_context_p));
208+
}
188209
} /* jerry_cleanup */
189210

211+
/**
212+
* Retrieve user context.
213+
*
214+
* @return the user-provided context-specific pointer
215+
*/
216+
void *
217+
jerry_get_user_context (void)
218+
{
219+
return JERRY_CONTEXT (user_context_p);
220+
} /* jerry_get_user_context */
221+
190222
/**
191223
* Register external magic string array
192224
*/

jerry-core/jerryscript.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,16 @@ typedef void (*jerry_object_native_free_callback_t) (void *native_p);
177177
typedef bool (*jerry_object_property_foreach_t) (const jerry_value_t property_name,
178178
const jerry_value_t property_value,
179179
void *user_data_p);
180+
/**
181+
* Function type for user context allocation
182+
*/
183+
typedef void *(*jerry_user_context_init_cb) (void);
184+
185+
/**
186+
* Function type for user context deallocation
187+
*/
188+
typedef void (*jerry_user_context_deinit_cb) (void *user_context_p);
189+
180190
/**
181191
* Type information of a native pointer.
182192
*/
@@ -189,11 +199,15 @@ typedef struct
189199
* General engine functions
190200
*/
191201
void jerry_init (jerry_init_flag_t flags);
202+
void jerry_init_with_user_context (jerry_init_flag_t flags,
203+
jerry_user_context_init_cb init_cb,
204+
jerry_user_context_deinit_cb deinit_cb);
192205
void jerry_cleanup (void);
193206
void jerry_register_magic_strings (const jerry_char_ptr_t *ex_str_items_p, uint32_t count,
194207
const jerry_length_t *str_lengths_p);
195208
void jerry_get_memory_limits (size_t *out_data_bss_brk_limit_p, size_t *out_stack_limit_p);
196209
void jerry_gc (void);
210+
void *jerry_get_user_context (void);
197211

198212
/**
199213
* Parser and executor functions

tests/unit/test-user-context.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
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 "config.h"
17+
#include "jerryscript.h"
18+
#include "test-common.h"
19+
20+
static const char *identifying_string = "identifying string";
21+
static bool user_context_new_was_called = false;
22+
static bool user_context_free_was_called = false;
23+
24+
static void *
25+
user_context_new (void)
26+
{
27+
user_context_new_was_called = true;
28+
return (void *) identifying_string;
29+
} /* user_context_new */
30+
31+
static void
32+
user_context_free (void *user_context_p)
33+
{
34+
user_context_free_was_called = true;
35+
TEST_ASSERT (((const char *) user_context_p) == identifying_string);
36+
} /* user_context_free */
37+
38+
int
39+
main (void)
40+
{
41+
TEST_INIT ();
42+
43+
jerry_init_with_user_context (JERRY_INIT_EMPTY, user_context_new, user_context_free);
44+
45+
TEST_ASSERT ((((const char *)(jerry_get_user_context ()))) == identifying_string);
46+
47+
jerry_cleanup ();
48+
49+
TEST_ASSERT (user_context_new_was_called);
50+
TEST_ASSERT (user_context_free_was_called);
51+
52+
return 0;
53+
} /* main */

0 commit comments

Comments
 (0)