changeset 189:08015e2803f1

IMPL::Vew::Web - fixed memory leaks, more tests
author cin
date Wed, 04 Apr 2012 02:49:45 +0400
parents 029c9610528c
children cd1ff7029a63
files Lib/IMPL/Profiler/Memory.pm Lib/IMPL/Web/View/TTControl.pm Lib/IMPL/Web/View/TTDocument.pm _test/Resources/TTView.Output/Panel.txt _test/Resources/TTView/My/Org/Panel.tt _test/Resources/TTView/My/Org/TextPreview.tt _test/Resources/TTView/complex.tt _test/Test/Web/View.pm
diffstat 8 files changed, 82 insertions(+), 34 deletions(-) [+]
line wrap: on
line diff
--- a/Lib/IMPL/Profiler/Memory.pm	Tue Apr 03 20:08:42 2012 +0400
+++ b/Lib/IMPL/Profiler/Memory.pm	Wed Apr 04 02:49:45 2012 +0400
@@ -78,7 +78,7 @@
 
 sub Dump {
 	my $this = shift;
-	return Data::Dumper->Dump($this->{objects});
+	return Data::Dumper->Dump([$this->{objects}]);
 }
 
 sub isLeak {
--- a/Lib/IMPL/Web/View/TTControl.pm	Tue Apr 03 20:08:42 2012 +0400
+++ b/Lib/IMPL/Web/View/TTControl.pm	Wed Apr 04 02:49:45 2012 +0400
@@ -36,7 +36,7 @@
 	
 	if ( my $ctor = $template->blocks->{CTOR} ) {
 		$context->process($ctor, { this => $this } );
-		$this->templateVars('this',undef);
+		$context->stash->set('this',undef);
 	}
 	
 	$this->id($name . "-" . _GetNextId()) unless $this->id;
@@ -50,17 +50,6 @@
 	}
 );
 
-sub templateVars {
-	my $this = shift;
-	my $name = shift;
-	
-	if (@_) {
-		return $this->context->stash->set($name, shift);		
-	} else {
-		return $this->context->stash->get($name);
-	}
-}
-
 sub renderBlock {
 	$_[0]->template->blocks->{RENDER};
 }
@@ -71,7 +60,7 @@
 	$args = {} unless ref $args eq 'HASH';
 	
 	if(my $body = $this->renderBlock ) {
-		return $this->context->include( $body, { %$args, this => $this, template => $this->template } );
+		return $this->context->include( $body, { %$args, this => $this, template => $this->template, document => $this->document } );
 	} else {
 		return "";
 	}	
--- a/Lib/IMPL/Web/View/TTDocument.pm	Tue Apr 03 20:08:42 2012 +0400
+++ b/Lib/IMPL/Web/View/TTDocument.pm	Wed Apr 04 02:49:45 2012 +0400
@@ -17,6 +17,10 @@
 	public property opts => PROP_GET | PROP_OWNERSET;
 	public property loader => PROP_GET | PROP_OWNERSET;
 	public property controls => PROP_GET | PROP_OWNERSET;
+	
+	# store the stash separately to make require() method to work correctly
+	# even when a stash of the context is modified during the processing 
+	public property stash => PROP_GET | PROP_OWNERSET; 
 }
 
 sub CTOR {
@@ -28,6 +32,7 @@
 	$this->layout( $template->layout ) unless $this->layout;
 	
 	$this->opts($refOpts);
+	$this->stash($this->context->stash);
 }
 
 our %CTOR = (
@@ -41,38 +46,48 @@
 	}
 );
 
+sub templateVars {
+	my $this = shift;
+	my $name = shift;
+	
+	if (@_) {
+		return $this->stash->set($name, shift);		
+	} else {
+		return $this->stash->get($name);
+	}
+}
+
 sub require {
 	my ($this, $control) = @_;
 	
 	if (my $factory = $this->controls->{$control}) {
 		return $factory;
 	} else {
-=pod		
+	
 		my $path = $control;
 		if ( my $template = $this->loader->template($path) ) {
-			#my $opts = { %{$this->opts} };
-			#$opts->{STASH} = $this->context->stash->clone();
+
+			my $opts = { %{$this->opts} };
+			$opts->{STASH} = $this->stash->clone();
  
-			my $ctx = new Template::Context();#$opts);
+			my $ctx = new Template::Context($opts);
 			
 			$factory = new IMPL::Web::View::TTFactory(
 				typeof IMPL::Web::View::TTControl,
 				$template,
 				$ctx,
-				{} #$opts
+				$opts
 			);
 			
 			my @parts = split(/\/+/,$control);
 			
 			$this->controls->{$control} = $factory;
-			$this->context->stash->set([map { $_, 0 } @parts], $factory);
 						
 			return $factory;
 
 		} else {
 			die new IMPL::KeyNotFoundException($control);
 		}
-=cut		
 	}
 }
 
@@ -134,7 +149,7 @@
 
 Скприт шаблона формирует структуру документа, затем сформированная структура форматируется в готовый документ.
 Процесс преобразования объектной модели в готовый документ может быть выполнена как вручную, так и при помощи
-вспомогательного шаблона - обертки. Если у шаблона документа указан C<wrapper> в метаданных, то он будет
+вспомогательного шаблона - обертки. Если у шаблона документа указан C<layout> в метаданных, то он будет
 использован как шаблон для форматирования объектной модели, вывод самого шаблона будет проигнорирован. Если
 обертка не задана, то результатом будет вывод самого скрипта шаблона.
 
@@ -161,11 +176,9 @@
 
 =item 1 Загружает шаблон C<my/org/input.tt>
 
-=item 1 Создает фабрику элементов управления с собственным контекстом, вложенным в контекст документа.
+=item 1 Создает фабрику элементов управления с собственным контекстом, унаследованным от контекст документа.
 
-=item 1 Выполняет шаблон в пространстве имен фабрики 
-
-=item 1 Регистритует фабрику в контексте документа по пути C<my.org.input>
+=item 1 Выполняет шаблон в пространстве имен фабрики
 
 =back
 
--- a/_test/Resources/TTView.Output/Panel.txt	Tue Apr 03 20:08:42 2012 +0400
+++ b/_test/Resources/TTView.Output/Panel.txt	Wed Apr 04 02:49:45 2012 +0400
@@ -1,1 +1,8 @@
-<div class="simple" data-dojo-type="dijit.form.Input"></div>
+<div class="simple" data-dojo-type="dijit.form.Input">
+				<div data-dojo-type="dijit.layout.ContentPane">one</div>
+		<hr />
+				<div data-dojo-type="dijit.layout.ContentPane">two</div>
+		<hr />
+				<div data-dojo-type="dijit.layout.ContentPane">hello world</div>
+		<hr />
+	</div>
--- a/_test/Resources/TTView/My/Org/Panel.tt	Tue Apr 03 20:08:42 2012 +0400
+++ b/_test/Resources/TTView/My/Org/Panel.tt	Wed Apr 04 02:49:45 2012 +0400
@@ -10,5 +10,16 @@
 	END;
 %]
 [% BLOCK RENDER %]
-<div class="$visualClass" data-dojo-type="$dojoClass">$this.nodeValue</div>
+[%
+	TPreview = document.require('My/Org/TextPreview');
+	FOREACH text IN data;
+		CALL this.appendChild(TPreview.new('preview', nodeValue = text ));
+	END;
+%]
+<div class="$visualClass" data-dojo-type="$dojoClass">
+	[% FOREACH node IN this.selectNodes('preview') %]
+		[% node.Render() %]
+		<hr />
+	[% END %]
+</div>
 [% END %]
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_test/Resources/TTView/My/Org/TextPreview.tt	Wed Apr 04 02:49:45 2012 +0400
@@ -0,0 +1,8 @@
+[%
+	BLOCK INIT;
+		dojo.require.push("dijit.layout.ContentPane");
+	END;
+%]
+[% BLOCK RENDER %]
+	<div data-dojo-type="dijit.layout.ContentPane">$this.nodeValue</div>
+[% END %]
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_test/Resources/TTView/complex.tt	Wed Apr 04 02:49:45 2012 +0400
@@ -0,0 +1,9 @@
+[%
+	META version = 1, title = "my document 2";
+
+	TPanel = document.require('My/Org/Panel');
+		
+	this.appendChild(TPanel.new('information'));
+	
+	this.selectSingleNode('information').Render();
+%]
\ No newline at end of file
--- a/_test/Test/Web/View.pm	Tue Apr 03 20:08:42 2012 +0400
+++ b/_test/Test/Web/View.pm	Wed Apr 04 02:49:45 2012 +0400
@@ -24,7 +24,11 @@
 	
 	my $data = MProfiler->Monitor($code, sub { $_ =~ m/^IMPL::/} );
 	
-	assert( not($data->isLeak), "Memory leak detected", GetCallerSourceLine()  , @{$data->{objects}}, $dump ? $data->Dump : () );
+	if ($data->isLeak and $dump) {
+		write_file("dump.out", { binmode => ':utf8' }, $data->Dump() );
+	}
+	
+	assert( not($data->isLeak), "Memory leak detected", GetCallerSourceLine()  , @{$data->{objects}} );	
 }
 
 sub templatesDir {
@@ -111,7 +115,6 @@
 	
 	assert(defined $factory);
 	
-	assert(not $loader->context->stash->get('My.Org.Panel'));
 	
 	assert($factory->context->stash != $doc->context->stash);
 	
@@ -127,9 +130,9 @@
 	
 	assert($factory->instances == 1);
 	
-	assert($doc->templateVars('My.Org.Panel') == $factory);
+	$doc->appendChild($ctl);
 	
-	my $text = $ctl->Render();
+	my $text = $ctl->Render({ data => ['one','two','hello world']});
 	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");
@@ -151,12 +154,20 @@
 		$doc->Render( { self => $doc } );
 	});
 	
-	AssertMemoryLeak(sub{
+	$loader->template('My/Org/Panel');
+	$loader->template('My/Org/TextPreview');
+	AssertMemoryLeak(sub {
 		my $doc = $loader->document('simple');
 		my $factory = $doc->require('My/Org/Panel');
-		#my $ctl = $doc->AppendChild($factory->new('information', { visualClass => 'complex' }) );		
+		my $ctl = $doc->AppendChild($factory->new('information', { visualClass => 'complex' }) );		
 	});
 	
+	$loader->template('complex');
+	AssertMemoryLeak(sub {
+		my $doc = $loader->document('complex');
+		$doc->Render();
+	},'dump');
+	
 };
 
 1;
\ No newline at end of file