From 309280675a52cf5f27613b1bcee9136faec485c5 Mon Sep 17 00:00:00 2001 From: Oldes Date: Thu, 2 Apr 2020 13:17:41 +0200 Subject: [PATCH] FEAT: PROTECT/words supported for an object! value PROTECT object! now protects the object and its words, but not their values. PRODUCT/deep object! protects the object, its words, and their values. PROTECT/words object! only protects the words of the object!, but not the object itself or the values of the words. PROTECT/words/deep object! also protects any values assigned to the words, but still not protects the object itself. Implements: https://github.com/Oldes/Rebol-issues/issues/1014 Related to: https://github.com/Oldes/Rebol-issues/issues/1170 --- src/core/n-control.c | 22 ++++++++-------- src/tests/units/object-test.r3 | 47 ++++++++++++++++++++++++++++++---- 2 files changed, 54 insertions(+), 15 deletions(-) diff --git a/src/core/n-control.c b/src/core/n-control.c index ebea515ab6..1a74bad697 100644 --- a/src/core/n-control.c +++ b/src/core/n-control.c @@ -37,6 +37,7 @@ enum { PROT_DEEP, PROT_HIDE, PROT_WORD, + PROT_WORDS, PROT_PERMANENTLY }; @@ -135,16 +136,17 @@ enum { { REBSER *series = VAL_OBJ_FRAME(value); - if (IS_MARK_SERIES(series)) return; // avoid loop - - if (GET_FLAG(flags, PROT_SET)) { - PROTECT_SERIES(series); - if (GET_FLAG(flags, PROT_PERMANENTLY)) LOCK_SERIES(series); + if (!GET_FLAG(flags, PROT_WORDS)) { + if (IS_MARK_SERIES(series)) return; // avoid loop + if (GET_FLAG(flags, PROT_SET)) { + PROTECT_SERIES(series); + if (GET_FLAG(flags, PROT_PERMANENTLY)) LOCK_SERIES(series); + } + else + //unprotect series only when not locked (using protect/permanently) + if (!IS_LOCK_SERIES(series)) + UNPROTECT_SERIES(series); } - else - //unprotect series only when not locked (using protect/permanently) - if (!IS_LOCK_SERIES(series)) - UNPROTECT_SERIES(series); for (value = FRM_WORDS(series)+1; NOT_END(value); value++) { Protect_Word(value, flags); @@ -213,7 +215,7 @@ enum { Check_Security(SYM_PROTECT, POL_WRITE, val); if (D_REF(2)) SET_FLAG(flags, PROT_DEEP); - //if (D_REF(3)) SET_FLAG(flags, PROT_WORD); + if (D_REF(3)) SET_FLAG(flags, PROT_WORDS); if (D_REF(5)) SET_FLAG(flags, PROT_HIDE); else SET_FLAG(flags, PROT_WORD); // there is no unhide diff --git a/src/tests/units/object-test.r3 b/src/tests/units/object-test.r3 index 5f7d0bad51..80c0cba3ad 100644 --- a/src/tests/units/object-test.r3 +++ b/src/tests/units/object-test.r3 @@ -39,6 +39,13 @@ Rebol [ ===end-group=== +===start-group=== "EXTEND object" + --test-- "extend object" + obj: object [] + --assert 1 = extend obj 'a 1 + --assert 1 = obj/a +===end-group=== + ===start-group=== "APPEND on OBJECT" ;@@ https://github.com/rebol/rebol-issues/issues/708 --test-- "issue-708" @@ -58,11 +65,41 @@ Rebol [ --assert err/id = 'protected unprotect o - --test-- "issue-1170" - ;@@ https://github.com/Oldes/Rebol-issues/issues/1170 - obj: protect object [a: object [b: 10]] - --assert error? try [obj/a: 0] - --assert not error? try [obj/a/b: 0] +===end-group=== + +===start-group=== "PROTECT object!" + ;@@ https://github.com/Oldes/Rebol-issues/issues/1014 + --test-- "protect object" + ; To prevent adding words to o, and prevent modification of words already in o: + o: protect object [a: object [b: 10]] + --assert error? try [extend o 'c 3] + --assert error? try [append o 'd] + --assert error? try [o/a: 0] + --assert not error? try [o/a/b: 0] ;;@@ https://github.com/Oldes/Rebol-issues/issues/1170 + + --test-- "protect/words object!" + ; To allow adding words to o, but prevent modification to words already in o: + o: protect/words object [a: object [b: 10]] + --assert not error? try [extend o 'c 3] + --assert not error? try [append o 'd] + --assert error? try [o/a: 0] + --assert not error? try [o/a/b: 0] + + --test-- "protect/deep object!" + ; To prevent adding words to o, modification of words already in o, or their contents: + o: protect/deep object [a: object [b: 10]] + --assert error? try [extend o 'c 3] + --assert error? try [append o 'd] + --assert error? try [o/a: 0] + --assert error? try [o/a/b: 0] + + --test-- "protect/words/deep object!" + ; To allow adding words to o, but prevent modification of words already in o or their contents: + o: protect/words/deep object [a: object [b: 10]] + --assert not error? try [extend o 'c 3] + --assert not error? try [append o 'd] + --assert error? try [o/a: 0] + --assert error? try [o/a/b: 0] ===end-group===