Skip to content

Commit eb795ff

Browse files
committed
Add duk_seal(), duk_freeze()
1 parent 16e03e1 commit eb795ff

4 files changed

Lines changed: 66 additions & 49 deletions

File tree

src-input/duk_api_internal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,8 @@ DUK_INTERNAL_DECL void duk_pop_undefined(duk_context *ctx);
303303

304304
DUK_INTERNAL_DECL void duk_compact_m1(duk_context *ctx);
305305

306+
DUK_INTERNAL_DECL void duk_seal_freeze_raw(duk_context *ctx, duk_idx_t obj_idx, duk_bool_t is_freeze);
307+
306308
DUK_INTERNAL_DECL void duk_insert_undefined(duk_context *ctx, duk_idx_t idx);
307309
DUK_INTERNAL_DECL void duk_insert_undefined_n(duk_context *ctx, duk_idx_t idx, duk_idx_t count);
308310

src-input/duk_api_object.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,67 @@ DUK_EXTERNAL duk_bool_t duk_next(duk_context *ctx, duk_idx_t enum_index, duk_boo
543543
return duk_hobject_enumerator_next(ctx, get_value);
544544
}
545545

546+
DUK_INTERNAL void duk_seal_freeze_raw(duk_context *ctx, duk_idx_t obj_idx, duk_bool_t is_freeze) {
547+
duk_hthread *thr = (duk_hthread *) ctx;
548+
duk_tval *tv;
549+
duk_hobject *h;
550+
551+
tv = duk_require_tval(ctx, obj_idx);
552+
DUK_ASSERT(tv != NULL);
553+
554+
/* Seal/freeze are quite rare in practice so it'd be nice to get the
555+
* correct behavior simply via automatic promotion (at the cost of some
556+
* memory churn). However, the promoted objects don't behave the same,
557+
* e.g. promoted lightfuncs are extensible.
558+
*/
559+
560+
switch (DUK_TVAL_GET_TAG(tv)) {
561+
case DUK_TAG_BUFFER:
562+
/* Plain buffer: already sealed, but not frozen (and can't be frozen
563+
* because index properties can't be made non-writable.
564+
*/
565+
if (is_freeze) {
566+
goto fail_cannot_freeze;
567+
}
568+
break;
569+
case DUK_TAG_LIGHTFUNC:
570+
/* Lightfunc: already sealed and frozen, success. */
571+
break;
572+
case DUK_TAG_OBJECT:
573+
h = DUK_TVAL_GET_OBJECT(tv);
574+
DUK_ASSERT(h != NULL);
575+
if (is_freeze && DUK_HOBJECT_IS_BUFOBJ(h)) {
576+
/* Buffer objects cannot be frozen because there's no internal
577+
* support for making virtual array indices non-writable.
578+
*/
579+
DUK_DD(DUK_DDPRINT("cannot freeze a buffer object"));
580+
goto fail_cannot_freeze;
581+
}
582+
duk_hobject_object_seal_freeze_helper(thr, h, is_freeze);
583+
584+
/* Sealed and frozen objects cannot gain any more properties,
585+
* so this is a good time to compact them.
586+
*/
587+
duk_hobject_compact_props(thr, h);
588+
break;
589+
default:
590+
/* ES2015 Sections 19.1.2.5, 19.1.2.17 */
591+
break;
592+
}
593+
return;
594+
595+
fail_cannot_freeze:
596+
DUK_ERROR_TYPE_INVALID_ARGS(thr); /* XXX: proper error message */
597+
}
598+
599+
DUK_EXTERNAL void duk_seal(duk_context *ctx, duk_idx_t obj_idx) {
600+
duk_seal_freeze_raw(ctx, obj_idx, 0 /*is_freeze*/);
601+
}
602+
603+
DUK_EXTERNAL void duk_freeze(duk_context *ctx, duk_idx_t obj_idx) {
604+
duk_seal_freeze_raw(ctx, obj_idx, 1 /*is_freeze*/);
605+
}
606+
546607
/*
547608
* Helpers for writing multiple properties
548609
*/

src-input/duk_bi_object.c

Lines changed: 1 addition & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -226,58 +226,10 @@ DUK_INTERNAL duk_ret_t duk_bi_object_constructor_define_properties(duk_context *
226226

227227
#if defined(DUK_USE_OBJECT_BUILTIN)
228228
DUK_INTERNAL duk_ret_t duk_bi_object_constructor_seal_freeze_shared(duk_context *ctx) {
229-
duk_hthread *thr = (duk_hthread *) ctx;
230-
duk_hobject *h;
231-
duk_bool_t is_freeze;
232-
233229
DUK_ASSERT_TOP(ctx, 1);
234230

235-
is_freeze = (duk_bool_t) duk_get_current_magic(ctx);
236-
if (duk_is_buffer(ctx, 0)) {
237-
/* Plain buffer: already sealed, but not frozen (and can't be frozen
238-
* because index properties can't be made non-writable.
239-
*/
240-
if (is_freeze) {
241-
goto fail_cannot_freeze;
242-
}
243-
return 1;
244-
} else if (duk_is_lightfunc(ctx, 0)) {
245-
/* Lightfunc: already sealed and frozen, success. */
246-
return 1;
247-
}
248-
#if 0
249-
/* Seal/freeze are quite rare in practice so it'd be nice to get the
250-
* correct behavior simply via automatic promotion (at the cost of some
251-
* memory churn). However, the promoted objects don't behave the same,
252-
* e.g. promoted lightfuncs are extensible.
253-
*/
254-
h = duk_require_hobject_promote_mask(ctx, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
255-
#endif
256-
257-
h = duk_get_hobject(ctx, 0);
258-
if (h == NULL) {
259-
/* ES2015 Sections 19.1.2.5, 19.1.2.17 */
260-
return 1;
261-
}
262-
263-
if (is_freeze && DUK_HOBJECT_IS_BUFOBJ(h)) {
264-
/* Buffer objects cannot be frozen because there's no internal
265-
* support for making virtual array indices non-writable.
266-
*/
267-
DUK_DD(DUK_DDPRINT("cannot freeze a buffer object"));
268-
goto fail_cannot_freeze;
269-
}
270-
271-
duk_hobject_object_seal_freeze_helper(thr, h, is_freeze);
272-
273-
/* Sealed and frozen objects cannot gain any more properties,
274-
* so this is a good time to compact them.
275-
*/
276-
duk_hobject_compact_props(thr, h);
231+
duk_seal_freeze_raw(ctx, 0, (duk_bool_t) duk_get_current_magic(ctx) /*is_freeze*/);
277232
return 1;
278-
279-
fail_cannot_freeze:
280-
DUK_DCERROR_TYPE_INVALID_ARGS(thr); /* XXX: proper error message */
281233
}
282234
#endif /* DUK_USE_OBJECT_BUILTIN */
283235

src-input/duktape.h.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -914,6 +914,8 @@ DUK_EXTERNAL_DECL void duk_put_number_list(duk_context *ctx, duk_idx_t obj_idx,
914914
DUK_EXTERNAL_DECL void duk_compact(duk_context *ctx, duk_idx_t obj_idx);
915915
DUK_EXTERNAL_DECL void duk_enum(duk_context *ctx, duk_idx_t obj_idx, duk_uint_t enum_flags);
916916
DUK_EXTERNAL_DECL duk_bool_t duk_next(duk_context *ctx, duk_idx_t enum_idx, duk_bool_t get_value);
917+
DUK_EXTERNAL_DECL void duk_seal(duk_context *ctx, duk_idx_t obj_idx);
918+
DUK_EXTERNAL_DECL void duk_freeze(duk_context *ctx, duk_idx_t obj_idx);
917919

918920
/*
919921
* String manipulation

0 commit comments

Comments
 (0)