diff --git a/lib/ReadonlyX.pm b/lib/ReadonlyX.pm index 13e5d1b..eb8dba8 100644 --- a/lib/ReadonlyX.pm +++ b/lib/ReadonlyX.pm @@ -43,8 +43,8 @@ sub Scalar($;$) { my $var = $#_ == 0 && defined $_[0] ? $_[0] : $_[1]; my $ref = ref $var; $ref eq 'ARRAY' ? $_[0] = $var : $ref eq 'HASH' ? $_[0] - = $var : $ref eq 'SCALAR' - or $ref eq '' ? $_[0] = $var : $ref eq 'REF' ? $_[0] = \$_[1] : 1; + = $var : $ref eq 'SCALAR' || $ref eq 'Regexp' + || $ref eq '' ? $_[0] = $var : $ref eq 'REF' ? $_[0] = \$_[1] : 1; _readonly($_[0]); Internals::SvREADONLY($_[0], 1); } @@ -52,7 +52,7 @@ sub Scalar($;$) { sub Readonly(\[%@$]$) { my $type = ref $_[0]; return Scalar(${$_[0]}, defined $_[1] ? $_[1] : ()) - if $type eq 'SCALAR' or $type eq ''; + if $type eq 'SCALAR' or $type eq '' or $type eq 'Regexp'; return Hash(%{$_[0]}, defined $_[1] ? $_[1] : ()) if $type eq 'HASH'; return Array(@{$_[0]}, defined $_[1] ? $_[1] : []) if $type eq 'ARRAY'; } @@ -60,7 +60,7 @@ sub Readonly(\[%@$]$) { sub _readonly { my $type = ref $_[0]; my ($onoff) = $#_ ? $_[1] : 1; - if ($type eq '') { + if ($type eq '' or $type eq 'Regexp') { return Internals::SvREADONLY($_[0], $onoff); } elsif ($type eq 'SCALAR') { @@ -97,7 +97,7 @@ sub Clone(\[$@%]) { my $retval = Storable::dclone($_[0]); $retval = $$retval if ref $retval eq 'REF'; my $type = ref $retval; - _readonly(( $type eq 'SCALAR' || $type eq '' ? $$retval + _readonly(( $type eq 'SCALAR' or $type eq '' or $type eq 'Regexp' ? $$retval : $type eq 'HASH' ? $retval : $type eq 'ARRAY' ? @$retval : $retval diff --git a/t/general/clone.t b/t/general/clone.t index 9ff87de..5477960 100644 --- a/t/general/clone.t +++ b/t/general/clone.t @@ -11,6 +11,7 @@ use ReadonlyX; Readonly::Hash my %hash => (foo => 'bar'); Readonly::Array my @deep_array => (1, \@array); Readonly::Hash my %deep_hash => (foo => \@array); + Readonly::Scalar my $regexp => qr/regexp/; # my $scalar_clone = Readonly::Clone $scalar; $scalar_clone++; @@ -31,6 +32,10 @@ use ReadonlyX; my %deep_hash_clone = Readonly::Clone %deep_hash; $deep_hash_clone{foo}->[1] = 4; is $deep_hash_clone{foo}->[1], 4, 'deep hash clone is mutable'; + # + my $regexp_clone = Readonly::Clone $regexp; + $regexp_clone = qr/match/; + is $regexp_clone, qr/match/, 'regexp clone is mutable'; # } { Readonly::Scalar my $scalar => ['string']; diff --git a/t/general/regexp.t b/t/general/regexp.t new file mode 100644 index 0000000..9ff9c90 --- /dev/null +++ b/t/general/regexp.t @@ -0,0 +1,34 @@ +#!perl -I../../lib + +# Readonly regexp tests + +use strict; +use Test::More; +use ReadonlyX; + +sub expected +{ + my $line = shift; + $@ =~ s/\.$//; # difference between croak and die + return "Modification of a read-only value attempted at " . __FILE__ . " line $line\n"; +} + +use vars qw/$s1/; +my $ms1; + +# creation (2 tests) +eval {Readonly::Scalar $s1 => qr/13/}; +is $@ => '', 'Create a global regexp'; +eval {Readonly::Scalar $ms1 => qr/31/}; +is $@ => '', 'Create a lexical regexp'; + +# fetching (2 tests) +is $s1 => qr/13/, 'Fetch global'; +is $ms1 => qr/31/, 'Fetch lexical'; + +# storing (2 tests) +eval {$s1 = qr/7/}; +is $@ => expected(__LINE__-1), 'Error setting global'; +is $s1 => qr/13/, 'Readonly global value unchanged'; +# +done_testing;