* inside closures, however, only work if CvOUTSIDE == find_runcv.
*/
- outside = CvOUTSIDE(proto);
- if (!outside || (CvCLONE(outside) && ! CvCLONED(outside)))
+ if (SvTYPE(proto) == SVt_PVCV)
outside = find_runcv(NULL);
- if (SvTYPE(proto) == SVt_PVFM
- && CvROOT(outside) != CvROOT(CvOUTSIDE(proto)))
+ else {
outside = CvOUTSIDE(proto);
+ if (CvCLONE(outside) && ! CvCLONED(outside)) {
+ CV * const runcv = find_runcv(NULL);
+ if (CvROOT(runcv) == CvROOT(outside))
+ outside = runcv;
+ }
+ }
depth = CvDEPTH(outside);
assert(depth || SvTYPE(proto) == SVt_PVFM);
if (!depth)
is $closure_test::s2->()(), '10 cubes',
'cloning closure proto with no CvOUTSIDE';
+# Also brought up in #113812: Even when being cloned, a closure prototype
+# might have its CvOUTSIDE pointing to the wrong thing.
+{
+ package main::113812;
+ $s1 = sub {
+ my $x = 3;
+ $s2 = sub {
+ $x;
+ $s3 = sub { $x };
+ };
+ };
+ $s1->();
+ undef &$s1; # frees $s2’s prototype, causing the $s3 proto to have its
+ # CvOUTSIDE point to $s1
+ ::is $s2->()(), 3, 'cloning closure proto whose CvOUTSIDE has changed';
+}
+
done_testing();