@@ -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 */
0 commit comments