-
Notifications
You must be signed in to change notification settings - Fork 190
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cleanup v1 AST #1568
Cleanup v1 AST #1568
Conversation
330baf9
to
05d8bdc
Compare
05d8bdc
to
69a11b1
Compare
// v2 new nodes | ||
NamedBlock: ['attributes', 'modifiers', 'children', 'comments'], | ||
SimpleElement: ['attributes', 'modifiers', 'children', 'comments'], | ||
Component: ['head', 'attributes', 'modifiers', 'children', 'comments'], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I "ensured these stays in sync with typing" as instructed by the comment on line 3
I don't think these are meant to be here, v2 nodes won't appear in the v1 AST and defining visitors for them doesn't do anything, and in any case, these aren't even in sync with what is currently in the "v2" AST
584ef8a
to
eee6eea
Compare
0cfb213
to
342810c
Compare
@@ -320,7 +320,7 @@ export default class Printer { | |||
return; | |||
} | |||
|
|||
this.buffer += mustache.escaped ? '{{' : '{{{'; | |||
this.buffer += mustache.trusting ? '{{{' : '{{'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good change
} | ||
|
||
if (options && options.plugins && options.plugins.ast) { | ||
if (options.plugins && options.plugins.ast) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (options.plugins && options.plugins.ast) { | |
if (options.plugins?.ast) { |
🤷
case 'ElementNode': | ||
return visitors.ElementNode(this, node, callback); | ||
walkBody(this, node.children, callback); | ||
return; | ||
case 'BlockStatement': |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -285,47 +343,36 @@ test('Element modifiers', () => { | |||
); | |||
}); | |||
|
|||
test('Element paths', (assert) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't see a replacement test for this scenario -- why was the test removed? (or did I miss an equiv test?)
test('html elements with paths', () => { | ||
let ast = parse(` | ||
<Foo as |bar|> | ||
<bar.x.y class='bar'/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't see a replacement test for this scenario -- why was the test removed? (or did I miss an equiv test?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because I only pushed the part one of two (the block statement part) not the element one so far
`{ type: "Program" }` isn't a real AST node you actually encounter, it was inherited from the Handlebars AST, but it has been split into AST.Template and AST.Block in Glimmer for a long time now. More throughly deprecate the `Program` visitor and builders. Also rename `blockParams` on `Template` to `locals`, and make both the array and the property immutable. We are only providing this information so that AST consumers can make decisions on what names are referring to outer local variables, but the compiler does not refer to it at all, and always use the original `options.locals` as the source of truth, so if any AST plugin tried to mutate this, it would not have worked. Keeping `blockParams` around as a deprecated alias for the time being. Consumers that need to support older versions should be able to feature detect this (such as with `"locals" in node`, or even just short-circuiting `node.locals ?? node.blockParams` to avoid triggering the deprecation warning.
These were marked as `@deprecated` in the code for a long time, but we never actaully issued deprecation warnings at runtime. These features were available for a very long time, so consumers shouldn't have a problem switching to the recommended properties at this point.
Note that this is referring to the Handlebars `{{> ... }}` syntax, not the (also defunct) Ember `{{partial ...}}` feature. This had never worked in any modern versions of Ember (maybe v1+) and the compiler doesn't do anything with it.
`PathHead` is not a real AST node, its visitor will never be called
Other than mustache, none of the other "callable" nodes allow a literal in the "callee" (node.path) position: {{log ("hi")}} ~~~~ illegal <div {{"hi"}} /> ~~~~ illegal {{#"hi"}}...{{/"hi"}} ~~~~ illegal Further more, in mustache positions this is only allowed if there are no other arguments: {{"hi" 1 2 3}} ~~~~ illlegal Most of these syntaxes already generate syntax errors in the parser but is allowed in the v1 AST, so it's possible for a AST plugin to force these illegal conditions in a transform but should ultimately get caught and rejected elsewhere. This commit fixes the type to reflect that these conditions are illegal/impossible and make sure we catch all of these edge cases in the v2 normalization step.
These probably once existed to normalize across all the possible nodes that call go into a `mustache.path` position, such that you can always do `node.path.original` on a mustache. In my opinion, this is of dubious utility in the first place – the `original` property on these can have a variety of different types, it's unclear what you would do with the generic value you acquired in this manner. Code like `if (node.path.original === "component")` will likely misclassify `{{"component"}}` as `{{component}}`. Further more, with the introduction of the `{{(sexp)}}` syntax, the original assumption no longer holds anyway, as sub-expression nodes do not have an `original` property. Deprecating this property and turning it into a getter/setter for `value`, ensuring they stay in sync. In the future, we may want to reclaim this original property to store the _actual_ original syntax in the form of a string. For example, today, if you had `{{1.0}}` in the source code, it gets parsed into the JavaScript number/value `1` and the original "raw" format is irrecoverably lost, which is a problem for printer and codemods type use cases.
The parser builders are the defacto constructors for the v1 AST nodes. As the nodes get increasingly more eloborate for backwards compatibility and such, it's important that we share the logic for constructing these nodes as much as possible so we don't miss any cases. Also standardize the signatures to use the object argument style, you should be able to clone a node by passing it back into the same builder method which it originated from.
This makes printing-esq tasks easier when working with `path.head` and restores feature parity with `path.original` which is a very common way to work with PathExpression nodes
The original commit has a few issues: - Type safety - Added a new AST node, which is unnecessary since we already have `VarHead`, but is also a breaking change and is kind of breakage we have been careful to avoid in this area thus far - The parsing is robust against a few classes of edge cases This rework the same feature (on the `Block`/`BlockStatement` side) and adds more test coverage for the feature. Also renamed the field to `block.params`.
342810c
to
3104daf
Compare
The previous/existing "parsing" code tries to piggy back on letting the HTML tokenizer/parser parse out the block params syntax into attribute nodes and tries to recover the information after the fact This is fundamentally broken and suffers from some wild edge cases like: ``` <div as="" |foo="bar|>...</div> // => <div as |foo|>...</div> ``` This is especially problematic in light of wanting to retain the source spans of the block params nodes. This commit rework the block params parsing and integrate it into the normal parsing pass in the appropiate time.
78d98b6
to
13aeaa0
Compare
Provide source spans for the open and close tags without adding new AST nodes, also parse the element's tag name into a path which has the required source span.
I'm liking the changes. Much better to do it at tokenizer/parser level |
It turns out to be important that AST plugins can mutate the list of local variables in the root `Template` node. Instead, use *that* list of local variables as the ultimate source of truth after AST plugin ran.
The rename is motivated by: 1. It's confusing for the root node to have "block params" 2. All other AST nodes that has `blockParams` also has a `params` field that exposes the source location as `VarHead`s There is some uncertainty in: 1. Whether there are a lot of existing AST consumers that uses it (shouldn't be a big deal in itself, as it's just a deprecation) 2. Whether the direction of using `Template.locals` as the source of truth for outside local variables will ultimately prevail When we have more certainty on those and if this rename is still desired, it should be possible to revert this commit
The refactor in #1568 slightly changed the semantics of `path.parts` in that it didn't previously include `this` or the leading `@`. This commit restores the previous semantics.
The refactor in #1568 slightly changed the semantics of `path.parts` in that it didn't previously include `this` or the leading `@`. This commit restores the previous semantics.
The refactor in #1568 slightly changed the semantics of `path.parts` in that it didn't previously include `this` or the leading `@`. This commit restores the previous semantics.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The deprecation warnings introduced here seems to be triggered A LOT In Ember projects when templates are compiled. I get thousands of lines like the following when building:
DEPRECATION: The original property on literal nodes is deprecated, use value instead
DEPRECATION: The original property on literal nodes is deprecated, use value instead
DEPRECATION: The original property on literal nodes is deprecated, use value instead
Which seems to be triggered by Boolean literals like {{true}}
Can you provide the output of Today, when you have that log spew, it usually mean an addon is out of date, or a custom internal transform hasn't yet been updated to support both the deprecated api and the new api. |
Hi @NullVoxPopuli , thanks for answering, here's the output of the command attached (it's quite big) |
You have a wide range of
|
Ok, it seems to be coming from I'll try to propose a PR soon. As always, thanks for your help @NullVoxPopuli ! |
See the commit message for each individual commits