Rework Element
/...attributes
/modifier checking
#138
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Background
Support for checking
...attributes
and modifiers against a component'sElement
was something that landed at the last minute before we went into beta, and it ended up being somewhat bolted-on (as passed attribute values were from the start) in the emitted code. This meant that we resolved component elements in a different way than we resolved their block params, and also that we were explicitly passing type parameters in certain places in emitted output, which opened the door to bugs like #133 and complicates the JS interop story.This PR reworks how we emit TS code for elements and components in a template. Examples of the transformation before and after this PR follow.
(funny symbol details for the unfamiliar)
𝚪
is a template-wide context value responsible for representing the available@arg
s andthis
value as well as the declaredElement
type and block parameters for the component the template belongs toχ
is the environment-provided library of primitives used to express template constructs as TypeScript𝛄
is newly introduced in this PR and is a local context value for the element or component we're in the process of emitting, containing the type of its DOM element and, for components, the available block parametersElements
Before
After
Components
Before
After
Notes
This change fixes #133, and eliminates the possibility of us running into similar issues in the future, as it gets us out of the "emitting paths in type-space" game entirely. You may also have noticed that the code we emit for elements and components is now 100% valid JS, which should make integration with JS backing classes for editor support more tenable in the future (though the top-level template boilerplate still includes type annotations).
This change also means that the type of
Element
a component has could depend on the types of its args. While that's not a pattern I love (and in many cases it would probably still require{{! @glint-ignore }}
for...attributes
in the implementing template), there are some potential use cases that could be compelling, and either way it seems like a nice property for resolution ofYields
andElement
types to work the same way.