2 * Object handling: property access and other support functions.
5 #include "duk_internal.h"
10 * The API exposes only the most common property handling functions.
11 * The caller can invoke Ecmascript built-ins for full control (e.g.
12 * defineProperty, getOwnPropertyDescriptor).
15 DUK_EXTERNAL duk_bool_t
duk_get_prop(duk_context
*ctx
, duk_idx_t obj_index
) {
16 duk_hthread
*thr
= (duk_hthread
*) ctx
;
21 DUK_ASSERT_CTX_VALID(ctx
);
23 /* Note: copying tv_obj and tv_key to locals to shield against a valstack
24 * resize is not necessary for a property get right now.
27 tv_obj
= duk_require_tval(ctx
, obj_index
);
28 tv_key
= duk_require_tval(ctx
, -1);
30 rc
= duk_hobject_getprop(thr
, tv_obj
, tv_key
);
31 DUK_ASSERT(rc
== 0 || rc
== 1);
32 /* a value is left on stack regardless of rc */
34 duk_remove(ctx
, -2); /* remove key */
35 return rc
; /* 1 if property found, 0 otherwise */
38 DUK_EXTERNAL duk_bool_t
duk_get_prop_string(duk_context
*ctx
, duk_idx_t obj_index
, const char *key
) {
39 DUK_ASSERT_CTX_VALID(ctx
);
40 DUK_ASSERT(key
!= NULL
);
42 obj_index
= duk_require_normalize_index(ctx
, obj_index
);
43 duk_push_string(ctx
, key
);
44 return duk_get_prop(ctx
, obj_index
);
47 DUK_EXTERNAL duk_bool_t
duk_get_prop_index(duk_context
*ctx
, duk_idx_t obj_index
, duk_uarridx_t arr_index
) {
48 DUK_ASSERT_CTX_VALID(ctx
);
50 obj_index
= duk_require_normalize_index(ctx
, obj_index
);
51 duk_push_uarridx(ctx
, arr_index
);
52 return duk_get_prop(ctx
, obj_index
);
55 DUK_INTERNAL duk_bool_t
duk_get_prop_stridx(duk_context
*ctx
, duk_idx_t obj_index
, duk_small_int_t stridx
) {
56 duk_hthread
*thr
= (duk_hthread
*) ctx
;
58 DUK_ASSERT_CTX_VALID(ctx
);
59 DUK_ASSERT_DISABLE(stridx
>= 0);
60 DUK_ASSERT(stridx
< DUK_HEAP_NUM_STRINGS
);
63 obj_index
= duk_require_normalize_index(ctx
, obj_index
);
64 duk_push_hstring(ctx
, DUK_HTHREAD_GET_STRING(thr
, stridx
));
65 return duk_get_prop(ctx
, obj_index
);
68 DUK_INTERNAL duk_bool_t
duk_get_prop_stridx_boolean(duk_context
*ctx
, duk_idx_t obj_index
, duk_small_int_t stridx
, duk_bool_t
*out_has_prop
) {
71 DUK_ASSERT_CTX_VALID(ctx
);
72 DUK_ASSERT_DISABLE(stridx
>= 0);
73 DUK_ASSERT(stridx
< DUK_HEAP_NUM_STRINGS
);
75 rc
= duk_get_prop_stridx(ctx
, obj_index
, stridx
);
79 rc
= duk_to_boolean(ctx
, -1);
80 DUK_ASSERT(rc
== 0 || rc
== 1);
85 DUK_LOCAL duk_bool_t
duk__put_prop_shared(duk_context
*ctx
, duk_idx_t obj_idx
, duk_idx_t idx_key
) {
86 duk_hthread
*thr
= (duk_hthread
*) ctx
;
90 duk_small_int_t throw_flag
;
93 /* Note: copying tv_obj and tv_key to locals to shield against a valstack
94 * resize is not necessary for a property put right now (putprop protects
95 * against it internally).
98 /* Key and value indices are either (-2, -1) or (-1, -2). Given idx_key,
99 * idx_val is always (idx_key ^ 0x01).
101 DUK_ASSERT((idx_key
== -2 && (idx_key
^ 1) == -1) ||
102 (idx_key
== -1 && (idx_key
^ 1) == -2));
103 tv_obj
= duk_require_tval(ctx
, obj_idx
);
104 tv_key
= duk_require_tval(ctx
, idx_key
);
105 tv_val
= duk_require_tval(ctx
, idx_key
^ 1);
106 throw_flag
= duk_is_strict_call(ctx
);
108 rc
= duk_hobject_putprop(thr
, tv_obj
, tv_key
, tv_val
, throw_flag
);
109 DUK_ASSERT(rc
== 0 || rc
== 1);
111 duk_pop_2(ctx
); /* remove key and value */
112 return rc
; /* 1 if property found, 0 otherwise */
115 DUK_EXTERNAL duk_bool_t
duk_put_prop(duk_context
*ctx
, duk_idx_t obj_idx
) {
116 DUK_ASSERT_CTX_VALID(ctx
);
117 return duk__put_prop_shared(ctx
, obj_idx
, -2);
120 DUK_EXTERNAL duk_bool_t
duk_put_prop_string(duk_context
*ctx
, duk_idx_t obj_idx
, const char *key
) {
121 DUK_ASSERT_CTX_VALID(ctx
);
122 DUK_ASSERT(key
!= NULL
);
124 /* Careful here and with other duk_put_prop_xxx() helpers: the
125 * target object and the property value may be in the same value
126 * stack slot (unusual, but still conceptually clear).
128 obj_idx
= duk_normalize_index(ctx
, obj_idx
);
129 (void) duk_push_string(ctx
, key
);
130 return duk__put_prop_shared(ctx
, obj_idx
, -1);
133 DUK_EXTERNAL duk_bool_t
duk_put_prop_index(duk_context
*ctx
, duk_idx_t obj_idx
, duk_uarridx_t arr_idx
) {
134 DUK_ASSERT_CTX_VALID(ctx
);
136 obj_idx
= duk_require_normalize_index(ctx
, obj_idx
);
137 duk_push_uarridx(ctx
, arr_idx
);
138 return duk__put_prop_shared(ctx
, obj_idx
, -1);
141 DUK_INTERNAL duk_bool_t
duk_put_prop_stridx(duk_context
*ctx
, duk_idx_t obj_idx
, duk_small_int_t stridx
) {
142 duk_hthread
*thr
= (duk_hthread
*) ctx
;
144 DUK_ASSERT_CTX_VALID(ctx
);
145 DUK_ASSERT_DISABLE(stridx
>= 0);
146 DUK_ASSERT(stridx
< DUK_HEAP_NUM_STRINGS
);
149 obj_idx
= duk_require_normalize_index(ctx
, obj_idx
);
150 duk_push_hstring(ctx
, DUK_HTHREAD_GET_STRING(thr
, stridx
));
151 return duk__put_prop_shared(ctx
, obj_idx
, -1);
154 DUK_EXTERNAL duk_bool_t
duk_del_prop(duk_context
*ctx
, duk_idx_t obj_index
) {
155 duk_hthread
*thr
= (duk_hthread
*) ctx
;
158 duk_small_int_t throw_flag
;
161 DUK_ASSERT_CTX_VALID(ctx
);
163 /* Note: copying tv_obj and tv_key to locals to shield against a valstack
164 * resize is not necessary for a property delete right now.
167 tv_obj
= duk_require_tval(ctx
, obj_index
);
168 tv_key
= duk_require_tval(ctx
, -1);
169 throw_flag
= duk_is_strict_call(ctx
);
171 rc
= duk_hobject_delprop(thr
, tv_obj
, tv_key
, throw_flag
);
172 DUK_ASSERT(rc
== 0 || rc
== 1);
174 duk_pop(ctx
); /* remove key */
178 DUK_EXTERNAL duk_bool_t
duk_del_prop_string(duk_context
*ctx
, duk_idx_t obj_index
, const char *key
) {
179 DUK_ASSERT_CTX_VALID(ctx
);
180 DUK_ASSERT(key
!= NULL
);
182 obj_index
= duk_require_normalize_index(ctx
, obj_index
);
183 duk_push_string(ctx
, key
);
184 return duk_del_prop(ctx
, obj_index
);
187 DUK_EXTERNAL duk_bool_t
duk_del_prop_index(duk_context
*ctx
, duk_idx_t obj_index
, duk_uarridx_t arr_index
) {
188 DUK_ASSERT_CTX_VALID(ctx
);
190 obj_index
= duk_require_normalize_index(ctx
, obj_index
);
191 duk_push_uarridx(ctx
, arr_index
);
192 return duk_del_prop(ctx
, obj_index
);
195 DUK_INTERNAL duk_bool_t
duk_del_prop_stridx(duk_context
*ctx
, duk_idx_t obj_index
, duk_small_int_t stridx
) {
196 duk_hthread
*thr
= (duk_hthread
*) ctx
;
198 DUK_ASSERT_CTX_VALID(ctx
);
199 DUK_ASSERT_DISABLE(stridx
>= 0);
200 DUK_ASSERT(stridx
< DUK_HEAP_NUM_STRINGS
);
203 obj_index
= duk_require_normalize_index(ctx
, obj_index
);
204 duk_push_hstring(ctx
, DUK_HTHREAD_GET_STRING(thr
, stridx
));
205 return duk_del_prop(ctx
, obj_index
);
208 DUK_EXTERNAL duk_bool_t
duk_has_prop(duk_context
*ctx
, duk_idx_t obj_index
) {
209 duk_hthread
*thr
= (duk_hthread
*) ctx
;
214 DUK_ASSERT_CTX_VALID(ctx
);
216 /* Note: copying tv_obj and tv_key to locals to shield against a valstack
217 * resize is not necessary for a property existence check right now.
220 tv_obj
= duk_require_tval(ctx
, obj_index
);
221 tv_key
= duk_require_tval(ctx
, -1);
223 rc
= duk_hobject_hasprop(thr
, tv_obj
, tv_key
);
224 DUK_ASSERT(rc
== 0 || rc
== 1);
226 duk_pop(ctx
); /* remove key */
227 return rc
; /* 1 if property found, 0 otherwise */
230 DUK_EXTERNAL duk_bool_t
duk_has_prop_string(duk_context
*ctx
, duk_idx_t obj_index
, const char *key
) {
231 DUK_ASSERT_CTX_VALID(ctx
);
232 DUK_ASSERT(key
!= NULL
);
234 obj_index
= duk_require_normalize_index(ctx
, obj_index
);
235 duk_push_string(ctx
, key
);
236 return duk_has_prop(ctx
, obj_index
);
239 DUK_EXTERNAL duk_bool_t
duk_has_prop_index(duk_context
*ctx
, duk_idx_t obj_index
, duk_uarridx_t arr_index
) {
240 DUK_ASSERT_CTX_VALID(ctx
);
242 obj_index
= duk_require_normalize_index(ctx
, obj_index
);
243 duk_push_uarridx(ctx
, arr_index
);
244 return duk_has_prop(ctx
, obj_index
);
247 DUK_INTERNAL duk_bool_t
duk_has_prop_stridx(duk_context
*ctx
, duk_idx_t obj_index
, duk_small_int_t stridx
) {
248 duk_hthread
*thr
= (duk_hthread
*) ctx
;
250 DUK_ASSERT_CTX_VALID(ctx
);
251 DUK_ASSERT_DISABLE(stridx
>= 0);
252 DUK_ASSERT(stridx
< DUK_HEAP_NUM_STRINGS
);
255 obj_index
= duk_require_normalize_index(ctx
, obj_index
);
256 duk_push_hstring(ctx
, DUK_HTHREAD_GET_STRING(thr
, stridx
));
257 return duk_has_prop(ctx
, obj_index
);
260 /* Define own property without inheritance looks and such. This differs from
261 * [[DefineOwnProperty]] because special behaviors (like Array 'length') are
262 * not invoked by this method. The caller must be careful to invoke any such
263 * behaviors if necessary.
265 DUK_INTERNAL
void duk_xdef_prop(duk_context
*ctx
, duk_idx_t obj_index
, duk_small_uint_t desc_flags
) {
266 duk_hthread
*thr
= (duk_hthread
*) ctx
;
270 DUK_ASSERT_CTX_VALID(ctx
);
272 obj
= duk_require_hobject(ctx
, obj_index
);
273 DUK_ASSERT(obj
!= NULL
);
274 key
= duk_to_hstring(ctx
, -2);
275 DUK_ASSERT(key
!= NULL
);
276 DUK_ASSERT(duk_require_tval(ctx
, -1) != NULL
);
278 duk_hobject_define_property_internal(thr
, obj
, key
, desc_flags
);
280 duk_pop(ctx
); /* pop key */
283 DUK_INTERNAL
void duk_xdef_prop_index(duk_context
*ctx
, duk_idx_t obj_index
, duk_uarridx_t arr_index
, duk_small_uint_t desc_flags
) {
284 duk_hthread
*thr
= (duk_hthread
*) ctx
;
287 DUK_ASSERT_CTX_VALID(ctx
);
289 obj
= duk_require_hobject(ctx
, obj_index
);
290 DUK_ASSERT(obj
!= NULL
);
292 duk_hobject_define_property_internal_arridx(thr
, obj
, arr_index
, desc_flags
);
293 /* value popped by call */
296 DUK_INTERNAL
void duk_xdef_prop_stridx(duk_context
*ctx
, duk_idx_t obj_index
, duk_small_int_t stridx
, duk_small_uint_t desc_flags
) {
297 duk_hthread
*thr
= (duk_hthread
*) ctx
;
301 DUK_ASSERT_CTX_VALID(ctx
);
302 DUK_ASSERT_DISABLE(stridx
>= 0);
303 DUK_ASSERT(stridx
< DUK_HEAP_NUM_STRINGS
);
305 obj
= duk_require_hobject(ctx
, obj_index
);
306 DUK_ASSERT(obj
!= NULL
);
307 key
= DUK_HTHREAD_GET_STRING(thr
, stridx
);
308 DUK_ASSERT(key
!= NULL
);
309 DUK_ASSERT(duk_require_tval(ctx
, -1) != NULL
);
311 duk_hobject_define_property_internal(thr
, obj
, key
, desc_flags
);
312 /* value popped by call */
315 DUK_INTERNAL
void duk_xdef_prop_stridx_builtin(duk_context
*ctx
, duk_idx_t obj_index
, duk_small_int_t stridx
, duk_small_int_t builtin_idx
, duk_small_uint_t desc_flags
) {
316 duk_hthread
*thr
= (duk_hthread
*) ctx
;
320 DUK_ASSERT_CTX_VALID(ctx
);
321 DUK_ASSERT_DISABLE(stridx
>= 0);
322 DUK_ASSERT(stridx
< DUK_HEAP_NUM_STRINGS
);
323 DUK_ASSERT_DISABLE(builtin_idx
>= 0);
324 DUK_ASSERT(builtin_idx
< DUK_NUM_BUILTINS
);
326 obj
= duk_require_hobject(ctx
, obj_index
);
327 DUK_ASSERT(obj
!= NULL
);
328 key
= DUK_HTHREAD_GET_STRING(thr
, stridx
);
329 DUK_ASSERT(key
!= NULL
);
331 duk_push_hobject(ctx
, thr
->builtins
[builtin_idx
]);
332 duk_hobject_define_property_internal(thr
, obj
, key
, desc_flags
);
333 /* value popped by call */
336 /* This is a rare property helper; it sets the global thrower (E5 Section 13.2.3)
337 * setter/getter into an object property. This is needed by the 'arguments'
338 * object creation code, function instance creation code, and Function.prototype.bind().
341 DUK_INTERNAL
void duk_xdef_prop_stridx_thrower(duk_context
*ctx
, duk_idx_t obj_index
, duk_small_int_t stridx
, duk_small_uint_t desc_flags
) {
342 duk_hthread
*thr
= (duk_hthread
*) ctx
;
343 duk_hobject
*obj
= duk_require_hobject(ctx
, obj_index
);
344 duk_hobject
*thrower
= thr
->builtins
[DUK_BIDX_TYPE_ERROR_THROWER
];
345 duk_hobject_define_accessor_internal(thr
, obj
, DUK_HTHREAD_GET_STRING(thr
, stridx
), thrower
, thrower
, desc_flags
);
348 /* Object.defineProperty() equivalent C binding. */
349 DUK_EXTERNAL
void duk_def_prop(duk_context
*ctx
, duk_idx_t obj_index
, duk_uint_t flags
) {
350 duk_hthread
*thr
= (duk_hthread
*) ctx
;
357 duk_uint_t is_data_desc
;
358 duk_uint_t is_acc_desc
;
360 DUK_ASSERT_CTX_VALID(ctx
);
362 obj
= duk_require_hobject(ctx
, obj_index
);
364 is_data_desc
= flags
& (DUK_DEFPROP_HAVE_VALUE
| DUK_DEFPROP_HAVE_WRITABLE
);
365 is_acc_desc
= flags
& (DUK_DEFPROP_HAVE_GETTER
| DUK_DEFPROP_HAVE_SETTER
);
366 if (is_data_desc
&& is_acc_desc
) {
367 /* "Have" flags must not be conflicting so that they would
368 * apply to both a plain property and an accessor at the same
371 goto fail_invalid_desc
;
374 idx_base
= duk_get_top_index(ctx
);
375 if (flags
& DUK_DEFPROP_HAVE_SETTER
) {
376 duk_require_type_mask(ctx
, idx_base
, DUK_TYPE_MASK_UNDEFINED
|
377 DUK_TYPE_MASK_OBJECT
|
378 DUK_TYPE_MASK_LIGHTFUNC
);
379 set
= duk_get_hobject_or_lfunc_coerce(ctx
, idx_base
);
380 if (set
!= NULL
&& !DUK_HOBJECT_IS_CALLABLE(set
)) {
381 goto fail_not_callable
;
387 if (flags
& DUK_DEFPROP_HAVE_GETTER
) {
388 duk_require_type_mask(ctx
, idx_base
, DUK_TYPE_MASK_UNDEFINED
|
389 DUK_TYPE_MASK_OBJECT
|
390 DUK_TYPE_MASK_LIGHTFUNC
);
391 get
= duk_get_hobject_or_lfunc_coerce(ctx
, idx_base
);
392 if (get
!= NULL
&& !DUK_HOBJECT_IS_CALLABLE(get
)) {
393 goto fail_not_callable
;
399 if (flags
& DUK_DEFPROP_HAVE_VALUE
) {
400 idx_value
= idx_base
;
403 idx_value
= (duk_idx_t
) -1;
405 key
= duk_require_hstring(ctx
, idx_base
);
407 duk_require_valid_index(ctx
, idx_base
);
409 duk_hobject_define_property_helper(ctx
,
410 flags
/*defprop_flags*/,
419 duk_set_top(ctx
, idx_base
);
421 /* [ ... obj ... ] */
426 DUK_ERROR_TYPE(thr
, DUK_STR_INVALID_DESCRIPTOR
);
430 DUK_ERROR_TYPE(thr
, DUK_STR_NOT_CALLABLE
);
437 * Note: seal() and freeze() are accessible through Ecmascript bindings,
438 * and are not exposed through the API.
441 DUK_EXTERNAL
void duk_compact(duk_context
*ctx
, duk_idx_t obj_index
) {
442 duk_hthread
*thr
= (duk_hthread
*) ctx
;
445 DUK_ASSERT_CTX_VALID(ctx
);
447 obj
= duk_get_hobject(ctx
, obj_index
);
449 /* Note: this may fail, caller should protect the call if necessary */
450 duk_hobject_compact_props(thr
, obj
);
454 /* XXX: the duk_hobject_enum.c stack APIs should be reworked */
456 DUK_EXTERNAL
void duk_enum(duk_context
*ctx
, duk_idx_t obj_index
, duk_uint_t enum_flags
) {
457 DUK_ASSERT_CTX_VALID(ctx
);
459 duk_dup(ctx
, obj_index
);
460 duk_require_hobject_or_lfunc_coerce(ctx
, -1);
461 duk_hobject_enumerator_create(ctx
, enum_flags
); /* [target] -> [enum] */
464 DUK_EXTERNAL duk_bool_t
duk_next(duk_context
*ctx
, duk_idx_t enum_index
, duk_bool_t get_value
) {
465 DUK_ASSERT_CTX_VALID(ctx
);
467 duk_require_hobject(ctx
, enum_index
);
468 duk_dup(ctx
, enum_index
);
469 return duk_hobject_enumerator_next(ctx
, get_value
);
473 * Helpers for writing multiple properties
476 DUK_EXTERNAL
void duk_put_function_list(duk_context
*ctx
, duk_idx_t obj_index
, const duk_function_list_entry
*funcs
) {
477 const duk_function_list_entry
*ent
= funcs
;
479 DUK_ASSERT_CTX_VALID(ctx
);
481 obj_index
= duk_require_normalize_index(ctx
, obj_index
);
483 while (ent
->key
!= NULL
) {
484 duk_push_c_function(ctx
, ent
->value
, ent
->nargs
);
485 duk_put_prop_string(ctx
, obj_index
, ent
->key
);
491 DUK_EXTERNAL
void duk_put_number_list(duk_context
*ctx
, duk_idx_t obj_index
, const duk_number_list_entry
*numbers
) {
492 const duk_number_list_entry
*ent
= numbers
;
494 DUK_ASSERT_CTX_VALID(ctx
);
496 obj_index
= duk_require_normalize_index(ctx
, obj_index
);
498 while (ent
->key
!= NULL
) {
499 duk_push_number(ctx
, ent
->value
);
500 duk_put_prop_string(ctx
, obj_index
, ent
->key
);
507 * Shortcut for accessing global object properties
510 DUK_EXTERNAL duk_bool_t
duk_get_global_string(duk_context
*ctx
, const char *key
) {
511 duk_hthread
*thr
= (duk_hthread
*) ctx
;
514 DUK_ASSERT_CTX_VALID(ctx
);
515 DUK_ASSERT(thr
->builtins
[DUK_BIDX_GLOBAL
] != NULL
);
517 /* XXX: direct implementation */
519 duk_push_hobject(ctx
, thr
->builtins
[DUK_BIDX_GLOBAL
]);
520 ret
= duk_get_prop_string(ctx
, -1, key
);
525 DUK_EXTERNAL duk_bool_t
duk_put_global_string(duk_context
*ctx
, const char *key
) {
526 duk_hthread
*thr
= (duk_hthread
*) ctx
;
529 DUK_ASSERT_CTX_VALID(ctx
);
530 DUK_ASSERT(thr
->builtins
[DUK_BIDX_GLOBAL
] != NULL
);
532 /* XXX: direct implementation */
534 duk_push_hobject(ctx
, thr
->builtins
[DUK_BIDX_GLOBAL
]);
536 ret
= duk_put_prop_string(ctx
, -2, key
); /* [ ... global val ] -> [ ... global ] */
545 DUK_EXTERNAL
void duk_get_prototype(duk_context
*ctx
, duk_idx_t index
) {
546 duk_hthread
*thr
= (duk_hthread
*) ctx
;
550 DUK_ASSERT_CTX_VALID(ctx
);
553 obj
= duk_require_hobject(ctx
, index
);
554 DUK_ASSERT(obj
!= NULL
);
556 /* XXX: shared helper for duk_push_hobject_or_undefined()? */
557 proto
= DUK_HOBJECT_GET_PROTOTYPE(thr
->heap
, obj
);
559 duk_push_hobject(ctx
, proto
);
561 duk_push_undefined(ctx
);
565 DUK_EXTERNAL
void duk_set_prototype(duk_context
*ctx
, duk_idx_t index
) {
566 duk_hthread
*thr
= (duk_hthread
*) ctx
;
570 DUK_ASSERT_CTX_VALID(ctx
);
572 obj
= duk_require_hobject(ctx
, index
);
573 DUK_ASSERT(obj
!= NULL
);
574 duk_require_type_mask(ctx
, -1, DUK_TYPE_MASK_UNDEFINED
|
575 DUK_TYPE_MASK_OBJECT
);
576 proto
= duk_get_hobject(ctx
, -1);
577 /* proto can also be NULL here (allowed explicitly) */
579 #if defined(DUK_USE_ROM_OBJECTS)
580 if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr
*) obj
)) {
581 DUK_ERROR_TYPE(thr
, DUK_STR_NOT_CONFIGURABLE
); /* XXX: "read only object"? */
586 DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr
, obj
, proto
);
595 /* XXX: these could be implemented as macros calling an internal function
597 * XXX: same issue as with Duktape.fin: there's no way to delete the property
598 * now (just set it to undefined).
600 DUK_EXTERNAL
void duk_get_finalizer(duk_context
*ctx
, duk_idx_t index
) {
601 DUK_ASSERT_CTX_VALID(ctx
);
603 duk_get_prop_stridx(ctx
, index
, DUK_STRIDX_INT_FINALIZER
);
606 DUK_EXTERNAL
void duk_set_finalizer(duk_context
*ctx
, duk_idx_t index
) {
607 DUK_ASSERT_CTX_VALID(ctx
);
609 duk_put_prop_stridx(ctx
, index
, DUK_STRIDX_INT_FINALIZER
);