* Test namespace cleanup
* Add recognication for RenderFragment in tag helpers
* Remove dead code from node writers
* refactor type check
* Continue to treat child content as a delegate in codegen
* Add extension to enumerate child content
* Reorganize code generation tests
These were growing a bit disorganized, and weren't really result in good
code reuse.
* fix test base class
* Add some child-content tests
* Add an explicit node for ChildContent
Adds a strongly typed node to represent a 'ChildContent' and what it
contains. This allows us to simplify the code generation path,
detect/processes more issues in IR passes, and will be essential for
supporting multiple child content.
* Ignore ChildContent in components when it's just whitespace
* Add diagnostic for duplicate child content
* Add support for explicit child content elements
Precursor to support for multiple child content items
* Add support for multiple child-content elements
* Change delegate signature for RenderFragment<T>
* Clean up Tag Helper constants
* Allow RenderFragment<T> as a child content
* Allow renaming the template parameter
* Improve error message for invalid child content
* Add diagnostic for repeated child content parameter names
Adds support for Razor templates and RenderFragment<T>.
Razor templates are a little-known Razor feature that looks like:
```
@<tag>....<tag>
```
It's so little known that it's not even covered in our docs, but it's
been around for many many years. This features hasn't been implemented
until now for Blazor, and this feature brings it back as a build
building block for templated components (more to come).
In Blazor land a template like:
```
@{ RenderFragment<Person> template = @<div>@item.Name</div>; }
```
complies to code like:
```
RenderFragment<Person> template = (__builder, item) =>
{
__builder.OpenElement(...);
...
__builder.CloseElement(...);
}
```
Since the declaration always has a generic type parameter inside, it
needs to be in a context where the type is known.. ie: not with `var`.
See tests for ways to consume templates.
NOTE: There are the following caveats for templates
- Templates require a single root element.
- Templates don't work in the `@functions { }` block
These limitations are baked into the core of Razor and will take a while
for us to address (v3.0).
This change adds the ability to merge sibling nodes when possible during
markup block rewriting. We retain that invariant that each markup block
is a valid chunk of markup containing properly nested tags.
We still haven't done any work to remove whitespace yet, so most of the
cases where this comes into play right now will merge an element with
its surrounding whitespace.
* Reenable HtmlBlock unit tests
* Add E2E tests for HTML Block cases
* Remove harded GenerateBaselines=true
* Fix#1193
This commit addresses the root cause of #1193. When we merge HTML
text nodes into HTML blocks we need to re-encode any HTML entities that
were encoded eariler.
I did a bit of a deep dive on how HTML encoding is handled in Blazor and
I think this is the best strategy. I think it's valuable that the
BrowserRenderer uses document.createTextNode, which will always encode
the text - this handles dynamic content. We want to keep this in place
to avoid HTML injection attacks.
* Fix#1265 Reenable MarkupBlock
* test cleanup
This change will cause the compiler to ignore <!DOCTYPE ...>
declarations in Blazor components. We don't think there's much useful
Blazor can do with doctype, since we don't generate textual output for
the browser the parse. The sanest thing to do for now is just to skip
over it.
* Add HTML Block rewriter
* Baseline updates
* test gaps
* Update some unit tests to represent same behavior as before
* Define Markup frame type. Tests for rendering markup frames into render tree.
* Support markup frames during diffing (retain, insert, update, delete)
* Support markup blocks on WebAssembly
* Support rendering markup frames with server-side execution too
* Support markup blocks with multiple top-level nodes. Support updating markup dynamically.
* Define MarkupString type as a way to insert dynamic markup without needing custom RenderFragment code
* Remove comment
* CR: Better null value handling
* Add build command for generating the new boot JSON file
* Remove build command for generating index.html
* Update build targets to generate blazor.boot.json
* Change SPA fallback routing to look for index.html in regular wwwroot. Will need to update setup for published apps later.
* Stop autorebuild when index.html changes, since we no longer 'build' that file
* Update Boot.WebAssembly.ts logic to use boot JSON info on startup
* Restore support for loading CSS/JS from Blazor library projects
* Use new startup script tag in all samples and templates
* Fix MonoSanity sample - it must now be an exe because we use that as the trigger to generate the boot json (not the presence of index.html any more)
* Fix SPA fallback routing for published apps
Because in a previous commit, I changed it to look for index.html inside "wwwroot" instead of "dist" (because we no longer build it). But "wwwroot" doesn't exist for published apps, because static file servers wouldn't understand it.
* CR: Fix path normalization
- Prepare for building multiple entrypoint variants of the .js library
- Use async interop more consistently for rendering and event handling
- Add binary serializer for RenderBatch with tests
Updates ASP.NET package versions to 2.1
Tweaks TFMs
- libraries = netstandard2.0
- exes/apps/tools = netcoreapp2.1
- unit tests = netcoreapp2.0
- e2e tests = netcoreapp2.1 (dependency on apps)
The exception to this is the Browser.JS project which depends on our
tool for its build. however this project just builds the js code so its
TFM doesn't really matter.
This change introduces a mechanism for bypassing type checking and then
uses for the 'event handlers'. The event handler tag helpers have some
ideosyncratic behaviors and rely on overloading at the render tree
builder level.
Introduces a new primitive used by the compiler for type checking. Type
checking applies to component parameters when setting the value directly
and when using bind. This is nice because it also adds error checking
for bind.
The logic that binds event handlers was interfering with the code that
prevents component properties from receiving complex content.
This check was a little overzealous.
The problem is that the new HTML rewrite pass was traversing into
attributes of all kinds and would turn any HTML content inside those
attributes into elements where possible. The solution is to not do
that.
We weren't handling a few cases that can occur during typing correctly.
Our passes that look at the content of attributes need to be prepared
for it to be empty in cases where the attribute has been partially
typed in the editor.
I added a smoke test for this that attempts to simulate typing and found
another issue to fix.
The end result of this is that the design for this kind of code is
simpler and takes a more 'brute-force' approach to understanding
attributes. I think this is a good change based on the problems with how
this code has been written today, there are too many possible cases to
try and have the code express and document them all.
* In Blazor cshtml files, auto-import Microsoft.AspNetCore.Blazor and Microsoft.AspNetCore.Blazor.Components. Fixes#749
* Remove redundant @using directives from tests
* Update assertion in test
* Update all affected baselines
This change replaces the parsing of HTML that we perform during the code
generation phase, which parsing of HTML during the IR lowering phase.
The main benefit of this change is that the structure of the HTML is
reflected in the IR tree, allowing us to do more more advance
transformations.
As an example, see how the the handling of `<script>` tags is now a
separate pass.
As an aside from this I also redesigned the structure of component IR
nodes to match the new HTML element nodes. Passes are now more easily
aware of the nodes they are expected to handle and are more easily aware
of the difference between a component and element. This still isn't as
clean as I would like, but I think it's a reasonable improvement.
Another benefit of this is that the code generation is much simpler and
requires much less bookkeeping and statefulness.
* Stop the value<-->checked conversions for checkboxes. Just use native 'checked' property. Fixes#703
* Properly handle removal of 'checked' and 'value' attributes
* E2E coverage for removing 'value'
* Before refactoring ParameterCollection assignment logic, add more test coverage
* Begin caching parameter assignment info
* Factor out some reflection code to a reusable location
* Use IPropertySetter to avoid all per-property-assignment reflection
* More error cases and tests for parameter assignment
* Enable binding to nonpublic properties
* Add analyzer to warn and provide fix for public component parameters
* Unit test for analyzer
* Component tag helper now includes private properties if they have [Parameter]
* CR feedback: Remove garbage from csproj
* CR feedback: Rename .Build.Analyzers to .Analyzers
* CR feedback: Move BlazorApi.cs to shared; use it from Analyzers test
* Fix incorrect test name
* Make as many parameters private as possible. Replace ILayoutComponent with BlazorLayoutComponent.
* In component tag helper discovery, consider private members too
* Reduce the work in component parameter discovery by not inspecting the BlazorComponent base class (or System.Object)
This change introduces ParameterAttribute to specify a bindable
component parameter. As of the 0.3 release of Blazor we plan to make
[Parameter] required to make a property bindable by callers.
This also applies to parameters when their value is set by the
infrastructure, such as `Body` for layouts, and route paramters.
The rationale behind this change is that we think there is a need to
separate the definition of properties from their suitability for a
caller to set them through markup. We plan to introduce more features in
this area in the future such as marking parameters as required. This is
first step, and we think that this approach will scale nicely as we add
more functionaly.
The 0.3 release seems like the right time to change this behavior since
we're also introducing `ref` for captures in this release.
* In Razor compilation, trim leading and trailing whitespace
* Update all unit tests to account for whitespace trimming
* Recognize that TagHelperIntermediateNode produces output too
* Skip TrimWhitespacePass during first phase of two-phase compile
* Skip TrimWhitespacePass during design-time builds
* Update baselines after rebase
The issue here is that we were missing tests for the design time code
path. We have tests that the bind-... cases work at runtime but were
missing coverage for the editor.
I took the most relevant set of the tests for running bind-... code and
added them to the tests for codegen.
This change makes our baseline system use CRLF for line endings end to
end. This isn't needed for correctness, but it helps with quality of
life when developing on OSX.
This will avoid churn to the baseline files related to line endings when
updating.
This might only take effect if you nuke the TestFiles directory and
check it out again.
This change adds `Action` to the set of types that have an overload on
RenderTreeBuilder. Additionally, we special case `Action` in the runtime
because passing the event args via DynamicInvoke() would throw.
Finally, reverted some of the clutter introduced by the first pass of
the event handler feature.
* Update Mono to 078d5147836
* Update driver.c to match updated Mono version
* Rebuild Mono binaries
* Update dependency resolution baseline to match updated Mono BCL
* Add E2E test for new RuntimeInformation values
This change removes support for the old syntax used for event handlers
and two-way binding.
See the relevant issues for details on the new features and
improvements:
bind https://github.com/aspnet/Blazor/issues/409
event handlers https://github.com/aspnet/Blazor/issues/503
Along with this change we've removed a few additional things Blazor
could do that aren't part of Razor's usual syntax.
----
The features that was used to make something like:
```
<button @onclick(...) />
```
is an expression that's embedded in a an element's attribute. This
feature might be useful in the future if we want to support 'splatting'
arbitrary attributes into a tag, but the runtime support for this isn't
accessible outside the Blazor core.
----
The features that implement:
```
<button onclick=@{ } />
```
have been removed in favor of a better design for lambdas, method group
conversions and other things for event handler attributes.
use `<button onclick=@(x => ...} />` instead.
We think is a better approach in general, because we want the app
developer to write and see the parameter list.
----
Both syntactic features that have been removed have dedicated error
messages in the compiler. If you're porting old code it should help you
figure out what to do.
* Improve support for more types of event handlers
Improves support for for other types of event handlers with eventargs
types derived from UIEventArgs. Additionally fleshes out the set of
event handler types.
This change improves support for using more specific event handler types
like:
```
<button onclick="@Clicked" />
@functions {
public void Clicked(UIMouseEventArgs e) { ... }
}
```
And:
```
builder.AddAttribute(12, "onkeypressed", KeyPressed);
...
void KeyPressed(UIKeyboardEventArgs e) { ... }
```
In particular what got better is:
- overload resolution for the AddAttribute method
- performance of different cases for AddAttribute
-----
The runtime now treats delegates as one of three types:
- arbitrary delegate: not attached to DOM events, not tracked by
renderer
- UIEventHandler: can attach to DOM events, tracked by renderer, first
class in IHandleEvents
- UIEventHandler-like: can attach to DOM events, tracked by renderer,
requires some special runtime support.
The set of overloads on AddAttribute has been tuned with a few specific
cases in mind.
Lambda expressions in an attribute will be inferred as UIEventHandler
unless the compiler does something more specific. So for instance,
passing a lambda as an attribute value for a component, where the
component doesn't define a matching attribute, will always be inferred
as UIEventHandler.
We now support method-group to delegate conversion for methods that
accept a derived UIEventArgs type. This means you can use a signature
like `void KeyPressed(UIKeyboardEventArgs e)` without any compiler
magic, and this will work in the runtime as long as the event type
produced by the runtime matches.
We also allow user-defined UIEventArgs-derived types. There's a pattern
for this and it requires defining an extension method and delegate type.
The method-group to delegate conversion part required some doing. It
doesn't play well with generics (Action<T> where T : UIEventArgs)
doesn't work at all. Adding more actual overloads (as opposed to
extensions) would cause lambda cases we want to work to be ambiguous.
----
The performance win here is to remove the need for a 'wrapper' delegate
created by the event handler tag helper code. This wrapper is now
created by the runtime, but only *after* we have checked the frame for
changes. This requires more heavy lifting in the runtime, but has the
advantage of producing no-op diffs as often as possible.
You will still get some inefficient behavior if your component uses a
capturing lambda in an event handler, so don't do that.
* Add selenium logs to test output
* Minor feedback
* WIP
This change adds support for mapping DOM event handlers as tag helpers
that function in a bi-modal way.
This is a new first-class feature for DOM events, and replaces a few
workarounds like using `@onclick(...)` or `click=@{ ... }`. I haven't
removed those things yet, this is a first pass to get the new support
in, we'll remove those things when we're totally satisfied.
When used with a string like `<button onclick="foo" />` the result is
a simple HTML attribute .
But when used with an implicit expression like
`<button onclick="@Foo" />` or
`<button onclick="@(x => Clicked = true)" />` a C# function is bound to
the click event from the DOM.