]> git.proxmox.com Git - ceph.git/blame - ceph/src/civetweb/src/third_party/duktape-1.3.0/src-separate/duk_hobject_finalizer.c
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / civetweb / src / third_party / duktape-1.3.0 / src-separate / duk_hobject_finalizer.c
CommitLineData
7c673cae
FG
1/*
2 * Run an duk_hobject finalizer. Used for both reference counting
3 * and mark-and-sweep algorithms. Must never throw an error.
4 *
5 * There is no return value. Any return value or error thrown by
6 * the finalizer is ignored (although errors are debug logged).
7 *
8 * Notes:
9 *
10 * - The thread used for calling the finalizer is the same as the
11 * 'thr' argument. This may need to change later.
12 *
13 * - The finalizer thread 'top' assertions are there because it is
14 * critical that strict stack policy is observed (i.e. no cruft
15 * left on the finalizer stack).
16 */
17
18#include "duk_internal.h"
19
20DUK_LOCAL duk_ret_t duk__finalize_helper(duk_context *ctx) {
21 DUK_ASSERT(ctx != NULL);
22
23 DUK_DDD(DUK_DDDPRINT("protected finalization helper running"));
24
25 /* [... obj] */
26
27 /* XXX: Finalizer lookup should traverse the prototype chain (to allow
28 * inherited finalizers) but should not invoke accessors or proxy object
29 * behavior. At the moment this lookup will invoke proxy behavior, so
30 * caller must ensure that this function is not called if the target is
31 * a Proxy.
32 */
33
34 duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_FINALIZER); /* -> [... obj finalizer] */
35 if (!duk_is_callable(ctx, -1)) {
36 DUK_DDD(DUK_DDDPRINT("-> no finalizer or finalizer not callable"));
37 return 0;
38 }
39 duk_dup(ctx, -2); /* -> [... obj finalizer obj] */
40 DUK_DDD(DUK_DDDPRINT("-> finalizer found, calling finalizer"));
41 duk_call(ctx, 1); /* -> [... obj retval] */
42 DUK_DDD(DUK_DDDPRINT("finalizer finished successfully"));
43 return 0;
44
45 /* Note: we rely on duk_safe_call() to fix up the stack for the caller,
46 * so we don't need to pop stuff here. There is no return value;
47 * caller determines rescued status based on object refcount.
48 */
49}
50
51DUK_INTERNAL void duk_hobject_run_finalizer(duk_hthread *thr, duk_hobject *obj) {
52 duk_context *ctx = (duk_context *) thr;
53 duk_ret_t rc;
54#ifdef DUK_USE_ASSERTIONS
55 duk_idx_t entry_top;
56#endif
57
58 DUK_DDD(DUK_DDDPRINT("running object finalizer for object: %p", (void *) obj));
59
60 DUK_ASSERT(thr != NULL);
61 DUK_ASSERT(ctx != NULL);
62 DUK_ASSERT(obj != NULL);
63 DUK_ASSERT_VALSTACK_SPACE(thr, 1);
64
65#ifdef DUK_USE_ASSERTIONS
66 entry_top = duk_get_top(ctx);
67#endif
68 /*
69 * Get and call the finalizer. All of this must be wrapped
70 * in a protected call, because even getting the finalizer
71 * may trigger an error (getter may throw one, for instance).
72 */
73
74 /* XXX: use a NULL error handler for the finalizer call? */
75
76 DUK_DDD(DUK_DDDPRINT("-> finalizer found, calling wrapped finalize helper"));
77 duk_push_hobject(ctx, obj); /* this also increases refcount by one */
78 rc = duk_safe_call(ctx, duk__finalize_helper, 0 /*nargs*/, 1 /*nrets*/); /* -> [... obj retval/error] */
79 DUK_ASSERT_TOP(ctx, entry_top + 2); /* duk_safe_call discipline */
80
81 if (rc != DUK_EXEC_SUCCESS) {
82 /* Note: we ask for one return value from duk_safe_call to get this
83 * error debugging here.
84 */
85 DUK_D(DUK_DPRINT("wrapped finalizer call failed for object %p (ignored); error: %!T",
86 (void *) obj, (duk_tval *) duk_get_tval(ctx, -1)));
87 }
88 duk_pop_2(ctx); /* -> [...] */
89
90 DUK_ASSERT_TOP(ctx, entry_top);
91}