]> git.proxmox.com Git - ceph.git/blame - ceph/src/civetweb/src/third_party/duktape-1.5.2/src-separate/duk_api_object.c
buildsys: switch source download to quincy
[ceph.git] / ceph / src / civetweb / src / third_party / duktape-1.5.2 / src-separate / duk_api_object.c
CommitLineData
7c673cae
FG
1/*
2 * Object handling: property access and other support functions.
3 */
4
5#include "duk_internal.h"
6
7/*
8 * Property handling
9 *
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).
13 */
14
15DUK_EXTERNAL duk_bool_t duk_get_prop(duk_context *ctx, duk_idx_t obj_index) {
16 duk_hthread *thr = (duk_hthread *) ctx;
17 duk_tval *tv_obj;
18 duk_tval *tv_key;
19 duk_bool_t rc;
20
21 DUK_ASSERT_CTX_VALID(ctx);
22
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.
25 */
26
27 tv_obj = duk_require_tval(ctx, obj_index);
28 tv_key = duk_require_tval(ctx, -1);
29
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 */
33
34 duk_remove(ctx, -2); /* remove key */
35 return rc; /* 1 if property found, 0 otherwise */
36}
37
38DUK_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);
41
42 obj_index = duk_require_normalize_index(ctx, obj_index);
43 duk_push_string(ctx, key);
44 return duk_get_prop(ctx, obj_index);
45}
46
47DUK_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);
49
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);
53}
54
55DUK_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;
57
58 DUK_ASSERT_CTX_VALID(ctx);
59 DUK_ASSERT_DISABLE(stridx >= 0);
60 DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS);
11fdf7f2 61 DUK_UNREF(thr);
7c673cae
FG
62
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);
66}
67
68DUK_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) {
69 duk_bool_t rc;
70
71 DUK_ASSERT_CTX_VALID(ctx);
72 DUK_ASSERT_DISABLE(stridx >= 0);
73 DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS);
74
75 rc = duk_get_prop_stridx(ctx, obj_index, stridx);
76 if (out_has_prop) {
77 *out_has_prop = rc;
78 }
79 rc = duk_to_boolean(ctx, -1);
80 DUK_ASSERT(rc == 0 || rc == 1);
81 duk_pop(ctx);
82 return rc;
83}
84
11fdf7f2 85DUK_LOCAL duk_bool_t duk__put_prop_shared(duk_context *ctx, duk_idx_t obj_idx, duk_idx_t idx_key) {
7c673cae
FG
86 duk_hthread *thr = (duk_hthread *) ctx;
87 duk_tval *tv_obj;
88 duk_tval *tv_key;
89 duk_tval *tv_val;
90 duk_small_int_t throw_flag;
91 duk_bool_t rc;
92
7c673cae
FG
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).
96 */
97
11fdf7f2
TL
98 /* Key and value indices are either (-2, -1) or (-1, -2). Given idx_key,
99 * idx_val is always (idx_key ^ 0x01).
100 */
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);
7c673cae
FG
106 throw_flag = duk_is_strict_call(ctx);
107
108 rc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, throw_flag);
109 DUK_ASSERT(rc == 0 || rc == 1);
110
111 duk_pop_2(ctx); /* remove key and value */
112 return rc; /* 1 if property found, 0 otherwise */
113}
114
11fdf7f2
TL
115DUK_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);
118}
119
120DUK_EXTERNAL duk_bool_t duk_put_prop_string(duk_context *ctx, duk_idx_t obj_idx, const char *key) {
7c673cae
FG
121 DUK_ASSERT_CTX_VALID(ctx);
122 DUK_ASSERT(key != NULL);
123
11fdf7f2
TL
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).
127 */
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);
7c673cae
FG
131}
132
11fdf7f2 133DUK_EXTERNAL duk_bool_t duk_put_prop_index(duk_context *ctx, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {
7c673cae
FG
134 DUK_ASSERT_CTX_VALID(ctx);
135
11fdf7f2
TL
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);
7c673cae
FG
139}
140
11fdf7f2 141DUK_INTERNAL duk_bool_t duk_put_prop_stridx(duk_context *ctx, duk_idx_t obj_idx, duk_small_int_t stridx) {
7c673cae
FG
142 duk_hthread *thr = (duk_hthread *) ctx;
143
144 DUK_ASSERT_CTX_VALID(ctx);
145 DUK_ASSERT_DISABLE(stridx >= 0);
146 DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS);
11fdf7f2 147 DUK_UNREF(thr);
7c673cae 148
11fdf7f2 149 obj_idx = duk_require_normalize_index(ctx, obj_idx);
7c673cae 150 duk_push_hstring(ctx, DUK_HTHREAD_GET_STRING(thr, stridx));
11fdf7f2 151 return duk__put_prop_shared(ctx, obj_idx, -1);
7c673cae
FG
152}
153
154DUK_EXTERNAL duk_bool_t duk_del_prop(duk_context *ctx, duk_idx_t obj_index) {
155 duk_hthread *thr = (duk_hthread *) ctx;
156 duk_tval *tv_obj;
157 duk_tval *tv_key;
158 duk_small_int_t throw_flag;
159 duk_bool_t rc;
160
161 DUK_ASSERT_CTX_VALID(ctx);
162
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.
165 */
166
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);
170
171 rc = duk_hobject_delprop(thr, tv_obj, tv_key, throw_flag);
172 DUK_ASSERT(rc == 0 || rc == 1);
173
174 duk_pop(ctx); /* remove key */
175 return rc;
176}
177
178DUK_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);
181
182 obj_index = duk_require_normalize_index(ctx, obj_index);
183 duk_push_string(ctx, key);
184 return duk_del_prop(ctx, obj_index);
185}
186
187DUK_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);
189
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);
193}
194
195DUK_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;
197
198 DUK_ASSERT_CTX_VALID(ctx);
199 DUK_ASSERT_DISABLE(stridx >= 0);
200 DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS);
11fdf7f2 201 DUK_UNREF(thr);
7c673cae
FG
202
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);
206}
207
208DUK_EXTERNAL duk_bool_t duk_has_prop(duk_context *ctx, duk_idx_t obj_index) {
209 duk_hthread *thr = (duk_hthread *) ctx;
210 duk_tval *tv_obj;
211 duk_tval *tv_key;
212 duk_bool_t rc;
213
214 DUK_ASSERT_CTX_VALID(ctx);
215
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.
218 */
219
220 tv_obj = duk_require_tval(ctx, obj_index);
221 tv_key = duk_require_tval(ctx, -1);
222
223 rc = duk_hobject_hasprop(thr, tv_obj, tv_key);
224 DUK_ASSERT(rc == 0 || rc == 1);
225
226 duk_pop(ctx); /* remove key */
227 return rc; /* 1 if property found, 0 otherwise */
228}
229
230DUK_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);
233
234 obj_index = duk_require_normalize_index(ctx, obj_index);
235 duk_push_string(ctx, key);
236 return duk_has_prop(ctx, obj_index);
237}
238
239DUK_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);
241
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);
245}
246
247DUK_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;
249
250 DUK_ASSERT_CTX_VALID(ctx);
251 DUK_ASSERT_DISABLE(stridx >= 0);
252 DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS);
11fdf7f2 253 DUK_UNREF(thr);
7c673cae
FG
254
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);
258}
259
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.
264 */
265DUK_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;
267 duk_hobject *obj;
268 duk_hstring *key;
269
270 DUK_ASSERT_CTX_VALID(ctx);
271
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);
277
278 duk_hobject_define_property_internal(thr, obj, key, desc_flags);
279
280 duk_pop(ctx); /* pop key */
281}
282
283DUK_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;
285 duk_hobject *obj;
286
287 DUK_ASSERT_CTX_VALID(ctx);
288
289 obj = duk_require_hobject(ctx, obj_index);
290 DUK_ASSERT(obj != NULL);
291
292 duk_hobject_define_property_internal_arridx(thr, obj, arr_index, desc_flags);
293 /* value popped by call */
294}
295
296DUK_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;
298 duk_hobject *obj;
299 duk_hstring *key;
300
301 DUK_ASSERT_CTX_VALID(ctx);
302 DUK_ASSERT_DISABLE(stridx >= 0);
303 DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS);
304
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);
310
311 duk_hobject_define_property_internal(thr, obj, key, desc_flags);
312 /* value popped by call */
313}
314
315DUK_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;
317 duk_hobject *obj;
318 duk_hstring *key;
319
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);
325
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);
330
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 */
334}
335
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().
339 */
340
341DUK_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);
346}
347
348/* Object.defineProperty() equivalent C binding. */
349DUK_EXTERNAL void duk_def_prop(duk_context *ctx, duk_idx_t obj_index, duk_uint_t flags) {
350 duk_hthread *thr = (duk_hthread *) ctx;
351 duk_idx_t idx_base;
352 duk_hobject *obj;
353 duk_hstring *key;
354 duk_idx_t idx_value;
355 duk_hobject *get;
356 duk_hobject *set;
357 duk_uint_t is_data_desc;
358 duk_uint_t is_acc_desc;
359
360 DUK_ASSERT_CTX_VALID(ctx);
361
362 obj = duk_require_hobject(ctx, obj_index);
363
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
369 * time.
370 */
371 goto fail_invalid_desc;
372 }
373
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;
382 }
383 idx_base--;
384 } else {
385 set = NULL;
386 }
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;
394 }
395 idx_base--;
396 } else {
397 get = NULL;
398 }
399 if (flags & DUK_DEFPROP_HAVE_VALUE) {
400 idx_value = idx_base;
401 idx_base--;
402 } else {
403 idx_value = (duk_idx_t) -1;
404 }
405 key = duk_require_hstring(ctx, idx_base);
406
407 duk_require_valid_index(ctx, idx_base);
408
409 duk_hobject_define_property_helper(ctx,
410 flags /*defprop_flags*/,
411 obj,
412 key,
413 idx_value,
414 get,
415 set);
416
417 /* Clean up stack */
418
419 duk_set_top(ctx, idx_base);
420
421 /* [ ... obj ... ] */
422
423 return;
424
425 fail_invalid_desc:
11fdf7f2 426 DUK_ERROR_TYPE(thr, DUK_STR_INVALID_DESCRIPTOR);
7c673cae
FG
427 return;
428
429 fail_not_callable:
11fdf7f2 430 DUK_ERROR_TYPE(thr, DUK_STR_NOT_CALLABLE);
7c673cae
FG
431 return;
432}
433
434/*
435 * Object related
436 *
437 * Note: seal() and freeze() are accessible through Ecmascript bindings,
438 * and are not exposed through the API.
439 */
440
441DUK_EXTERNAL void duk_compact(duk_context *ctx, duk_idx_t obj_index) {
442 duk_hthread *thr = (duk_hthread *) ctx;
443 duk_hobject *obj;
444
445 DUK_ASSERT_CTX_VALID(ctx);
446
447 obj = duk_get_hobject(ctx, obj_index);
448 if (obj) {
449 /* Note: this may fail, caller should protect the call if necessary */
450 duk_hobject_compact_props(thr, obj);
451 }
452}
453
454/* XXX: the duk_hobject_enum.c stack APIs should be reworked */
455
456DUK_EXTERNAL void duk_enum(duk_context *ctx, duk_idx_t obj_index, duk_uint_t enum_flags) {
457 DUK_ASSERT_CTX_VALID(ctx);
458
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] */
462}
463
464DUK_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);
466
467 duk_require_hobject(ctx, enum_index);
468 duk_dup(ctx, enum_index);
469 return duk_hobject_enumerator_next(ctx, get_value);
470}
471
472/*
473 * Helpers for writing multiple properties
474 */
475
476DUK_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;
478
479 DUK_ASSERT_CTX_VALID(ctx);
480
481 obj_index = duk_require_normalize_index(ctx, obj_index);
482 if (ent != NULL) {
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);
486 ent++;
487 }
488 }
489}
490
491DUK_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;
493
494 DUK_ASSERT_CTX_VALID(ctx);
495
496 obj_index = duk_require_normalize_index(ctx, obj_index);
497 if (ent != NULL) {
498 while (ent->key != NULL) {
499 duk_push_number(ctx, ent->value);
500 duk_put_prop_string(ctx, obj_index, ent->key);
501 ent++;
502 }
503 }
504}
505
506/*
507 * Shortcut for accessing global object properties
508 */
509
510DUK_EXTERNAL duk_bool_t duk_get_global_string(duk_context *ctx, const char *key) {
511 duk_hthread *thr = (duk_hthread *) ctx;
512 duk_bool_t ret;
513
514 DUK_ASSERT_CTX_VALID(ctx);
515 DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
516
517 /* XXX: direct implementation */
518
519 duk_push_hobject(ctx, thr->builtins[DUK_BIDX_GLOBAL]);
520 ret = duk_get_prop_string(ctx, -1, key);
521 duk_remove(ctx, -2);
522 return ret;
523}
524
525DUK_EXTERNAL duk_bool_t duk_put_global_string(duk_context *ctx, const char *key) {
526 duk_hthread *thr = (duk_hthread *) ctx;
527 duk_bool_t ret;
528
529 DUK_ASSERT_CTX_VALID(ctx);
530 DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
531
532 /* XXX: direct implementation */
533
534 duk_push_hobject(ctx, thr->builtins[DUK_BIDX_GLOBAL]);
535 duk_insert(ctx, -2);
536 ret = duk_put_prop_string(ctx, -2, key); /* [ ... global val ] -> [ ... global ] */
537 duk_pop(ctx);
538 return ret;
539}
540
541/*
542 * Object prototype
543 */
544
545DUK_EXTERNAL void duk_get_prototype(duk_context *ctx, duk_idx_t index) {
546 duk_hthread *thr = (duk_hthread *) ctx;
547 duk_hobject *obj;
548 duk_hobject *proto;
549
550 DUK_ASSERT_CTX_VALID(ctx);
551 DUK_UNREF(thr);
552
553 obj = duk_require_hobject(ctx, index);
554 DUK_ASSERT(obj != NULL);
555
556 /* XXX: shared helper for duk_push_hobject_or_undefined()? */
557 proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, obj);
558 if (proto) {
559 duk_push_hobject(ctx, proto);
560 } else {
561 duk_push_undefined(ctx);
562 }
563}
564
565DUK_EXTERNAL void duk_set_prototype(duk_context *ctx, duk_idx_t index) {
566 duk_hthread *thr = (duk_hthread *) ctx;
567 duk_hobject *obj;
568 duk_hobject *proto;
569
570 DUK_ASSERT_CTX_VALID(ctx);
571
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) */
578
11fdf7f2
TL
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"? */
582 return;
583 }
584#endif
585
7c673cae
FG
586 DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, obj, proto);
587
588 duk_pop(ctx);
589}
590
591/*
592 * Object finalizer
593 */
594
595/* XXX: these could be implemented as macros calling an internal function
596 * directly.
597 * XXX: same issue as with Duktape.fin: there's no way to delete the property
598 * now (just set it to undefined).
599 */
600DUK_EXTERNAL void duk_get_finalizer(duk_context *ctx, duk_idx_t index) {
601 DUK_ASSERT_CTX_VALID(ctx);
602
603 duk_get_prop_stridx(ctx, index, DUK_STRIDX_INT_FINALIZER);
604}
605
606DUK_EXTERNAL void duk_set_finalizer(duk_context *ctx, duk_idx_t index) {
607 DUK_ASSERT_CTX_VALID(ctx);
608
609 duk_put_prop_stridx(ctx, index, DUK_STRIDX_INT_FINALIZER);
610}