On Fri, Jul 25, 2008 at 11:45:43AM -0400, Frédéric Brière wrote:
> I'd probably do more harm than good by putting my greasy hands in there.

Actually, once I managed to wrap my head around some of the inner
workings, the fix was quite simple.  It's basically an extension of
r3752.

(It's just that it took me an obscene amount of time to realize that the
default out_method was only set for subrequests.  Until then, I couldn't
figure out why there wasn't an infinite loop between flush_buffer and
out_method.  Silly me.)

Anyway, here it is.  Notice that scomp() was also affected by this bug,
so -- nyah!  :)


If I'm not mistaken (and I very well could be), this doesn't fix the
issue for subrequests, or at least those called with out_method.
(Without out_method, they will merely pile up their output over the
parent's STACK_BUFFER, right?)

IOW, if you set out_method, and then scomp() a component that makes a
subrequest that happens to call flush_buffer(), things will get screwy.
I think.


-- 
I knew I'd hate COBOL the moment I saw they'd used "perform" instead of
"do".
                -- Larry Wall on a not-so-popular programming language
commit 9b0321290c6aa92a0f5e0413c1e49c301a94c671
Author: Frédéric Brière <[EMAIL PROTECTED]>
Date:   Fri Jul 25 11:04:10 2008 -0400

    Fixed the bad interaction between flush_buffer() and the store modifier
    
    This marks as non-flushable by default all components called with the
    store modifier, as well as any other component they themselves call.

diff --git a/lib/HTML/Mason/Request.pm b/lib/HTML/Mason/Request.pm
index 2ea78c6..3adf2e0 100644
--- a/lib/HTML/Mason/Request.pm
+++ b/lib/HTML/Mason/Request.pm
@@ -450,7 +450,7 @@ sub exec {
             tie *SELECTED, 'Tie::Handle::Mason';
 
             my $old = select SELECTED;
-            my $mods = {base_comp => $request_comp, store => \($self->{request_buffer})};
+            my $mods = {base_comp => $request_comp, store => \($self->{request_buffer}), flushable => 1};
 
             if ($self->{has_plugins}) {
                 my $context = bless
@@ -1239,7 +1239,7 @@ sub comp {
     my $filter_buffer = '';
     my $top_buffer = defined($mods{store}) ? $mods{store} : $self->{top_stack}->[STACK_BUFFER];
     my $stack_buffer = $comp->{has_filter} ? \$filter_buffer : $top_buffer;
-    my $flushable = exists $mods{flushable} ? $mods{flushable} : 1;
+    my $flushable = exists $mods{flushable} ? $mods{flushable} : ($self->{top_stack}->[STACK_BUFFER_IS_FLUSHABLE] && ! defined($mods{store})) ;
 
     # Add new stack frame and point dynamically scoped $self->{top_stack} at it.
     push @{ $self->{stack} },
@@ -1329,7 +1329,7 @@ sub comp {
 sub scomp {
     my $self = shift;
     my $buf;
-    $self->comp({store => \$buf, flushable => 0},@_);
+    $self->comp({store => \$buf},@_);
     return $buf;
 }
 
diff --git a/t/05-request.t b/t/05-request.t
index 5698aa4..7c8b0c6 100644
--- a/t/05-request.t
+++ b/t/05-request.t
@@ -935,5 +935,54 @@ EOF
 
 #------------------------------------------------------------
 
+    $group->add_test( name => 'flush_and_store',
+                      description => 'Test that $m->flush_buffer is ignored in a store\'d component',
+                      interp_params => { autoflush => 1 },
+                      component => <<'EOF',
+<%def .world>\
+World\
+</%def>
+
+% my $world;
+% $m->comp( { store => \$world }, '.world');
+Hello, <% $world %>!
+
+% $world = $m->scomp('.world');
+Hello, <% $world %>!
+EOF
+                      expect => <<'EOF',
+
+Hello, World!
+
+Hello, World!
+EOF
+                    );
+
+#------------------------------------------------------------
+
+    $group->add_test( name => 'flush_and_scomp_recursive',
+                      description => 'Test that $m->flush_buffer is ignored in a recursive scomp() call',
+                      interp_params => { autoflush => 1 },
+                      component => <<'EOF',
+<%def .orld>\
+orld\
+</%def>
+
+<%def .world>\
+W<& .orld &>\
+</%def>
+
+% my $world = $m->scomp('.world');
+Hello, <% $world %>!
+EOF
+                      expect => <<'EOF',
+
+
+Hello, World!
+EOF
+                    );
+
+#------------------------------------------------------------
+
     return $group;
 }

Reply via email to