# HG changeset patch # User cin # Date 1361312730 -14400 # Node ID 85572f512abc16593facde007087cb1d18a1d788 # Parent 3a9cfea098ddaf50eb1c9a03cb97a85e573ef897 *TTView refactoring diff -r 3a9cfea098dd -r 85572f512abc Lib/IMPL/Web/View/TTDocument.pm --- a/Lib/IMPL/Web/View/TTDocument.pm Tue Feb 19 19:58:27 2013 +0400 +++ b/Lib/IMPL/Web/View/TTDocument.pm Wed Feb 20 02:25:30 2013 +0400 @@ -23,7 +23,6 @@ props => [ layout => PROP_RW, loader => PROP_RW, - controls => PROP_RO, ] }; @@ -41,59 +40,14 @@ $this->InitInstance(); } -sub templateVars { - my $this = shift; - my $name = shift; - if (@_) { - return $this->context->stash->set($name, shift); - } else { - return $this->context->stash->get($name); - } -} - -sub RequireControl { - my ($this, $control, $ctx) = @_; - - $ctx ||= $this->context; - - if (my $factory = $this->controls->{$control}) { - return $factory; - } else { - my $path = $control; - - if ( my $template = $this->loader->template($path) ) { - - $factory = new IMPL::Web::View::TTFactory( - $template->class || TTControl, - $template, - $ctx, - join( '/', splice( @{[split(/\//,$path)]}, 0, -1 ) ) - ); - - if ($template->class) { - Loader->safe->Require($template->class); - } - - $this->controls->{$control} = $factory; - - return $factory; - - } else { - die new IMPL::KeyNotFoundException($control); - } - } -} - sub Render { my ($this,$args) = @_; $args ||= {}; - $this->context->localise(); - - my $documentContext; my %controls; my $require; + my $documentContext; $require = sub { my $control = shift; if (my $factory = $controls{$control}) { @@ -125,9 +79,13 @@ } }; + $this->context->localise(); + $documentContext = _clone_context( $this->context ); + my $self = $this; + weaken($self); $this->context->stash->set(require => $require); - $this->context->stash->set(document => $this); - $documentContext = Template::Context->new( { %{$this->context} } ); + #$this->context->stash->set(document => sub { $self }); + my $text = eval { @@ -158,8 +116,12 @@ return $this->next::method($args); } }; + + undef $require; + undef $documentContext; + undef %controls; + $this->context->delocalise(); - $this->context->delocalise(); my $e = $@; if ($e) { @@ -171,6 +133,13 @@ } +sub _clone_context { + my $args = { %{shift || {}} }; + delete $args->{CONFIG}; + + return Template::Context->new($args); +} + 1; __END__ diff -r 3a9cfea098dd -r 85572f512abc Lib/IMPL/Web/View/TTFactory.pm --- a/Lib/IMPL/Web/View/TTFactory.pm Tue Feb 19 19:58:27 2013 +0400 +++ b/Lib/IMPL/Web/View/TTFactory.pm Wed Feb 20 02:25:30 2013 +0400 @@ -49,13 +49,13 @@ $this->context->localise(); - my $ctx = new Template::Context({ %{$this->context} }); + my $ctx = _clone_context($this->context); $this->context->delocalise(); my $stash = $ctx->stash; my $require = $this->require; - + $stash->update({ require => sub { my ($module) = @_; @@ -65,7 +65,7 @@ } }); - return ($name, $this->template, $ctx, hashApply({ factory => $this },$refProps)); + return ($name, $this->template, $ctx, $refProps); } sub CreateObject { @@ -90,6 +90,13 @@ return $instance; } +sub _clone_context { + my $args = { %{shift || {}} }; + delete $args->{CONFIG}; + + return Template::Context->new($args); +} + sub save { die new IMPL::NotImplementedException("This class doesn't support serialization"); } diff -r 3a9cfea098dd -r 85572f512abc Lib/IMPL/Web/View/TTLoader.pm --- a/Lib/IMPL/Web/View/TTLoader.pm Tue Feb 19 19:58:27 2013 +0400 +++ b/Lib/IMPL/Web/View/TTLoader.pm Wed Feb 20 02:25:30 2013 +0400 @@ -78,7 +78,7 @@ my $opts = { %{ $this->options } }; $this->context->localise(); - my $ctx = Template::Context->new( %{$this->context} ); + my $ctx = _clone_context($this->context); $this->context->delocalise(); return TTDocument->new( $tt, $ctx, $this, $vars ); @@ -146,6 +146,13 @@ } } +sub _clone_context { + my $args = { %{shift || {}} }; + delete $args->{CONFIG}; + + return Template::Context->new($args); +} + 1; __END__ diff -r 3a9cfea098dd -r 85572f512abc _test/Test/Web/View.pm --- a/_test/Test/Web/View.pm Tue Feb 19 19:58:27 2013 +0400 +++ b/_test/Test/Web/View.pm Wed Feb 20 02:25:30 2013 +0400 @@ -87,7 +87,6 @@ assert( $doc->context->stash->get('user') eq 'test_user'); # document should not have 'this' template variable - assert( not $doc->templateVars('this') ); assert( $doc->context != $loader->context); # document should have an own context }; @@ -108,14 +107,7 @@ assert(not $doc->can('notexists')); # autoloaded property should be ignored assert(not defined $doc->notexists); # nonexisting property assert($doc->template->version == 10); # static metadata - assert($doc->templateVars('notexists') eq ''); #nonexisting template variable - assert($doc->templateVars('user') eq 'test_user'); # global data - assert($doc->templateVars('templateVar') eq ''); # defined in CTOR block, should be local - assert($doc->templateVars('dynamic') eq 'this is a dynamic value'); assert($doc->context->stash->get('user') eq 'test_user' ); # runtime context should be derived from documentContext - $doc->context->stash->set('user', 'nobody'); - assert($doc->templateVars('user') eq 'test_user'); # isolated - $doc->context->stash->set('user', 'test_user'); my $text = $doc->Render(); my $expected = read_file($this->GetResourceFile('Resources','TTView.Output','simple.txt'), binmode => ':utf8'); @@ -124,55 +116,6 @@ }; -test TTControlTests => sub { - my ($this) = @_; - - my $loader = $this->CreateLoader(); - - my $doc = $loader->document('simple'); - - assert(defined $doc); - - my $factory = $doc->RequireControl('My/Org/Panel'); - - assert(defined $factory); - - # control factory shares document scope to perform an initialization on demand - assert($factory->context->stash == $doc->context->stash); - - assert($factory == $doc->RequireControl('My/Org/Panel'), "Control should be loaded only once"); - - my $ctl = $factory->new('information', { visualClass => 'simple', data => ['one','two','hello world'] } ); - - assert(defined $ctl); - - assert($ctl->name eq 'information', "Created control should have a name", "Got: ".$ctl->name, "Expected: information"); - - assert($ctl->GetAttribute('visualClass') eq 'simple'); - - assert($factory->instances == 1); - - $doc->childNodes([$ctl]); - - assert($doc->templateVars('dojo.require')); - assert(ref $doc->templateVars('dojo.require') eq 'ARRAY'); - assert($doc->templateVars('dojo.require')->[0] eq 'dijit.form.Input' ); - - my $text = $ctl->Render(); - - my $expected = read_file($this->GetResourceFile('Resources', 'TTView.Output', 'Panel.txt'), binmode => ':utf8'); - assert($text eq $expected, '$ctl->Render(): Bad output', "Got: $text", "Expected: $expected"); - - - my $doc2 = $loader->document('simple'); - - assert( $doc2->documentContext->stash->get( ['require',['My/Org/Panel'] ] ) ); - print Dumper($doc2->context->stash); - assert( $doc2->context->stash->get( ['require',['My/Org/Panel'] ] ) ); - - -}; - test TestDocumentLayout => sub { my ($this) = @_; @@ -208,8 +151,6 @@ assert(ref $loader->context->stash->get([ 'dojo', 0, 'require', 0]) eq 'ARRAY'); assertarray($loader->context->stash->get([ 'dojo', 0, 'require', 0]),[]); assert($loader->context->stash != $doc->context->stash); - assert($loader->context->stash != $doc->documentContext->stash); - assert($doc->context->stash != $doc->documentContext->stash); assert(defined $doc); @@ -251,21 +192,16 @@ AssertMemoryLeak(sub { my $doc = $loader->document('simple'); - }); + },'dump'); AssertMemoryLeak(sub { my $doc = $loader->document('simple'); $doc->Render( { self => $doc } ); - }); + },'dump'); $loader->template('Layout/default'); $loader->template('My/Org/Panel'); $loader->template('My/Org/TextPreview'); - AssertMemoryLeak(sub { - my $doc = $loader->document('simple'); - my $factory = $doc->RequireControl('My/Org/Panel'); - my $ctl = $doc->childNodes($factory->new('information', { visualClass => 'complex' }) ); - },'dump'); $loader->template('complex'); AssertMemoryLeak(sub {