@@ -58,7 +58,7 @@ public void RenderTagHelper(TagHelperChunk chunk)
58
58
{
59
59
var tagHelperDescriptors = chunk . Descriptors ;
60
60
61
- RenderBeginTagHelperScope ( chunk . TagName ) ;
61
+ RenderBeginTagHelperScope ( chunk . TagName , chunk . Children ) ;
62
62
63
63
RenderTagHelpersCreation ( chunk ) ;
64
64
@@ -71,11 +71,15 @@ public void RenderTagHelper(TagHelperChunk chunk)
71
71
72
72
RenderUnboundHTMLAttributes ( unboundHTMLAttributes ) ;
73
73
74
- // TODO: Modify code generation to handle all content modes
75
- //RenderRunTagHelpers(bufferedBody: false);
76
- //RenderTagOutput(_tagHelperContext.OutputGenerateStartTagMethodName);
77
- //RenderTagHelperBody(chunk.Children, bufferBody: false);
78
- //RenderTagOutput(_tagHelperContext.OutputGenerateEndTagMethodName);
74
+ RenderRunTagHelpers ( ) ;
75
+
76
+ RenderTagOutput ( _tagHelperContext . OutputGenerateStartTagMethodName ) ;
77
+ RenderTagOutput ( _tagHelperContext . OutputGeneratePreContentMethodName ) ;
78
+
79
+ RenderTagHelperContent ( ) ;
80
+
81
+ RenderTagOutput ( _tagHelperContext . OutputGeneratePostContentMethodName ) ;
82
+ RenderTagOutput ( _tagHelperContext . OutputGenerateEndTagMethodName ) ;
79
83
80
84
RenderEndTagHelpersScope ( ) ;
81
85
}
@@ -85,11 +89,13 @@ internal static string GetVariableName(TagHelperDescriptor descriptor)
85
89
return "__" + descriptor . TypeName . Replace ( '.' , '_' ) ;
86
90
}
87
91
88
- private void RenderBeginTagHelperScope ( string tagName )
92
+ private void RenderBeginTagHelperScope ( string tagName , IList < Chunk > children )
89
93
{
90
94
// Scopes/execution contexts are a runtime feature.
91
95
if ( _designTimeMode )
92
96
{
97
+ // Render all of the tag helper children inline for intellisense.
98
+ _bodyVisitor . Accept ( children ) ;
93
99
return ;
94
100
}
95
101
@@ -104,6 +110,30 @@ private void RenderBeginTagHelperScope(string tagName)
104
110
_writer . WriteStringLiteral ( tagName )
105
111
. WriteParameterSeparator ( )
106
112
. WriteStringLiteral ( GenerateUniqueId ( ) )
113
+ . WriteParameterSeparator ( ) ;
114
+
115
+ // We remove the target writer so TagHelper authors can retrieve content.
116
+ var oldWriter = _context . TargetWriterName ;
117
+ _context . TargetWriterName = null ;
118
+
119
+ // Disabling instrumentation inside TagHelper bodies since we never know if it's accurate
120
+ var oldInstrumentation = _context . Host . EnableInstrumentation ;
121
+ _context . Host . EnableInstrumentation = false ;
122
+
123
+ using ( _writer . BuildAsyncLambda ( endLine : false ) )
124
+ {
125
+ // Render all of the tag helper children.
126
+ _bodyVisitor . Accept ( children ) ;
127
+ }
128
+
129
+ _context . Host . EnableInstrumentation = oldInstrumentation ;
130
+
131
+ _context . TargetWriterName = oldWriter ;
132
+
133
+ _writer . WriteParameterSeparator ( )
134
+ . Write ( _tagHelperContext . StartWritingScopeMethodName )
135
+ . WriteParameterSeparator ( )
136
+ . Write ( _tagHelperContext . EndWritingScopeMethodName )
107
137
. WriteEndMethodInvocation ( ) ;
108
138
}
109
139
@@ -302,18 +332,72 @@ private void RenderUnboundHTMLAttributes(IEnumerable<KeyValuePair<string, Chunk>
302
332
}
303
333
}
304
334
305
- private void RenderTagHelperBody ( IList < Chunk > children , bool bufferBody )
335
+ private void RenderTagHelperContent ( )
306
336
{
307
- // If we want to buffer the body we need to create a writing scope to capture the body content .
308
- if ( bufferBody )
337
+ // Rendering output is a runtime feature .
338
+ if ( _designTimeMode )
309
339
{
310
- // Render all of the tag helper children in a buffered writing scope.
311
- BuildBufferedWritingScope ( children ) ;
340
+ return ;
312
341
}
313
- else
342
+
343
+ _writer . Write ( "if (" )
344
+ . Write ( ExecutionContextVariableName )
345
+ . Write ( "." )
346
+ . Write ( _tagHelperContext . ExecutionContextOutputPropertyName )
347
+ . Write ( "." )
348
+ . Write ( _tagHelperContext . OutputContentSetPropertyName )
349
+ . WriteLine ( ")" ) ;
350
+
351
+ // Render the body of the if statement, at this point in the codegen the TagHelperOutput's Content was set
352
+ // so we should just render its Content, no need to forcefully execute the child content.
353
+ using ( _writer . BuildScope ( ) )
314
354
{
315
- // Render all of the tag helper children.
316
- _bodyVisitor . Accept ( children ) ;
355
+ RenderTagOutput ( _tagHelperContext . OutputGenerateContentMethodName ) ;
356
+ }
357
+
358
+ _writer . Write ( "else if (" )
359
+ . Write ( ExecutionContextVariableName )
360
+ . Write ( "." )
361
+ . Write ( _tagHelperContext . ExecutionContextChildContentRetrievedPropertyName )
362
+ . WriteLine ( ")" ) ;
363
+
364
+ // Render the body of the else if statement, at this point in the codegen the GetChildContentAsync method
365
+ // was invoked but the TagHelperOutput's Content was not set. Call into GetChildContentAsync to retrieve
366
+ // the cached value of the content so we don't execute the child content twice.
367
+ using ( _writer . BuildScope ( ) )
368
+ {
369
+ CSharpCodeVisitor . RenderPreWriteStart ( _writer , _context ) ;
370
+
371
+ _writer . WriteInstanceMethodInvocation ( ExecutionContextVariableName ,
372
+ _tagHelperContext . ExecutionContextGetChildContentAsyncMethodName ,
373
+ endLine : false ) ;
374
+
375
+ _writer . Write ( ".Result" )
376
+ . WriteEndMethodInvocation ( ) ;
377
+ }
378
+
379
+ _writer . WriteLine ( "else" ) ;
380
+
381
+ // Render the body of the else statement, at this point in the codegen the GetChildContentAsync method
382
+ // was not invoked and the TagHelperOutput's Content was not set. Call into ExecuteChildContentAsync to
383
+ // to execute and render child content.
384
+ using ( _writer . BuildScope ( ) )
385
+ {
386
+ if ( ! string . IsNullOrEmpty ( _context . TargetWriterName ) )
387
+ {
388
+ _writer . WriteMethodInvocation ( _tagHelperContext . StartWritingScopeMethodName , _context . TargetWriterName ) ;
389
+ }
390
+
391
+ _writer . WriteInstanceMethodInvocation (
392
+ ExecutionContextVariableName ,
393
+ _tagHelperContext . ExecutionContextExecuteChildContentAsyncMethodName ,
394
+ endLine : false ) ;
395
+ _writer . WriteLine ( ".Wait();" ) ;
396
+
397
+ if ( ! string . IsNullOrEmpty ( _context . TargetWriterName ) )
398
+ {
399
+ _writer . WriteMethodInvocation ( _tagHelperContext . EndWritingScopeMethodName ) ;
400
+ }
317
401
}
318
402
}
319
403
@@ -348,7 +432,7 @@ private void RenderTagOutput(string tagOutputMethodName)
348
432
. WriteEndMethodInvocation ( ) ;
349
433
}
350
434
351
- private void RenderRunTagHelpers ( bool bufferedBody )
435
+ private void RenderRunTagHelpers ( )
352
436
{
353
437
// No need to run anything in design time mode.
354
438
if ( _designTimeMode )
@@ -362,15 +446,9 @@ private void RenderRunTagHelpers(bool bufferedBody)
362
446
. Write ( " = " )
363
447
. WriteStartInstanceMethodInvocation ( RunnerVariableName ,
364
448
_tagHelperContext . RunnerRunAsyncMethodName ) ;
365
- _writer . Write ( ExecutionContextVariableName ) ;
366
-
367
- if ( bufferedBody )
368
- {
369
- _writer . WriteParameterSeparator ( )
370
- . Write ( StringValueBufferVariableName ) ;
371
- }
372
449
373
- _writer . WriteEndMethodInvocation ( endLine : false )
450
+ _writer . Write ( ExecutionContextVariableName )
451
+ . WriteEndMethodInvocation ( endLine : false )
374
452
. WriteLine ( ".Result;" ) ;
375
453
}
376
454
0 commit comments