-
Notifications
You must be signed in to change notification settings - Fork 192
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
[ENHANCEMENT+CLEANUP] Better compile time errors for strict mode #1557
Conversation
6500ab8
to
da81f20
Compare
`You attempted to render a path (\`{{${resolution.path}}}\`), but ${resolution.head} was not in scope`, | ||
loc | ||
); | ||
} |
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.
TODO: consider deferring these to the validation pass
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.
Basically reconsider all the syntax errors this whole file
`* \`${arg.name}={{(${resolution.path})}}\` if this is meant to invoke the resolved helper, or\n` + | ||
`* \`${arg.name}={{helper "${resolution.path}"}}\` if this is meant to pass the resolved helper by value`, | ||
arg.loc | ||
); |
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.
Note: this is actually a loose mode only error
const Foo = defineComponent({}, '{{bar}}', { | ||
definition: class extends GlimmerishComponent { | ||
bar = 'Hello, world!'; | ||
this.assert.throws( |
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.
🙌
@@ -58,11 +58,11 @@ class ArrayTest extends RenderTest { | |||
@test | |||
'binds multiple values when variables are used'() { | |||
this.render( | |||
strip`{{#with (array this.personOne this.personTwo) as |people|}} |
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'm glad I never used with
😅
meta: { moduleName: 'test-module' }, | ||
}); | ||
}, | ||
syntaxErrorFor( |
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.
this is a really nice error! folks will appreciate this!
@@ -691,14 +693,11 @@ function getSymbolForVar( | |||
export function expressionContextOp(context: VariableResolutionContext): GetContextualFreeOpcode { | |||
switch (context) { | |||
case VariableResolutionContext.Strict: | |||
debugger; |
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.
stray debugger
@@ -112,13 +110,6 @@ export class NormalizeExpressions { | |||
} | |||
} | |||
|
|||
DeprecaedCallExpression( |
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.
no need to fix a typo when we can just delete 🎉
|
||
InElement(inElement: mir.InElement): Result<null> { | ||
return this.Expression(inElement.destination) | ||
// Unfortunately we lost the `insertBefore=` part of the span |
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.
why did we lose it?
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.
There is no AST/mir node (and hence span) for the “name=” part of named arguments; there is AST/mir node for the entire “name=value” thing, but the InElement mir node did not preserve it since it happen to know it will always have (or add one during normalization) the insertBefore key. So we just have the expression node and the entry node was thrown away in earlier normalization pass
@@ -101,6 +84,8 @@ export function resolveComponent( | |||
let type = expr[0]; | |||
|
|||
if (import.meta.env.DEV && expr[0] === SexpOpcodes.GetStrictKeyword) { | |||
assert(!meta.isStrictMode, 'Strict mode errors should already be handled at compile time'); |
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.
glimmer's assert matches node's assert, which is opposite ember's 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.
Yeah 🤷🏻♂️
trusting: false, | ||
}; | ||
if (resolution.result === 'error' && resolution.path !== 'has-block') { | ||
throw generateSyntaxError( |
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.
this is a great error!! thanks!
ComponentOrHelper = 'component or helper', | ||
} | ||
|
||
export default class StrictModeValidationPass { |
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.
does this have tests? I didn't seem the explicitly -- but maybe I missed them?
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.
This is what’s generating the syntax errors in the strict mode tests
This was dropped on Ember side a while back, just never cleaned up Ironically this probably meant when Ember dropped the deprecation/ error, nothing was actually stopping `{{#with}}` from anymore, so perhaps for a while we have actually _re-introduced_ support for the syntax for some time? Extracted from #1557
Removing support for implicit this fallback {{foo}} -> {{this.foo}} When a strict mode template references an undefined variable, it really should produce a compile-time error, arguably that is the point of the feature. However, it seems like previously a lot of these errors ended up propagating and is actually handled by the runtime compiler. The original/primary goal here started out as cleaning up all the code for implicit this fallback, but as I delete code it eventually revaled all the places where strict mode was inappropiately using the same infrastructure ("unresolved free variables", which isn't really a sensible thing). Also: * Removes "deprecated call" @foo={{bar}} * Removes unused opcodes
da81f20
to
8685023
Compare
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 think these changes are solid.
Recently in #1557 we started emitting build time error for strict mode templates containing undefined references. Previously these were not handled until runtime and so we can only emit runtime errors. However, the previous setup allowed for the host environment to implement additional keywords – these are resolved at runtime with the `lookupBuildInHelper` and `lookupBuiltInModifier` hooks, and the error is only emitted if these hooks returned `null`. To allow for this possibility, `precompile` now accept an option for additional strict mode keywords that the host environment is expected to provide.
Recently in #1557 we started emitting build time error for strict mode templates containing undefined references. Previously these were not handled until runtime and so we can only emit runtime errors. However, the previous setup allowed for the host environment to implement additional keywords – these are resolved at runtime with the `lookupBuildInHelper` and `lookupBuiltInModifier` hooks, and the error is only emitted if these hooks returned `null`. To allow for this possibility, `precompile` now accept an option for additional strict mode keywords that the host environment is expected to provide.
Recently in #1557 we started emitting build time error for strict mode templates containing undefined references. Previously these were not handled until runtime and so we can only emit runtime errors. However, the previous setup allowed for the host environment to implement additional keywords – these are resolved at runtime with the `lookupBuildInHelper` and `lookupBuiltInModifier` hooks, and the error is only emitted if these hooks returned `null`. To allow for this possibility, `precompile` now accept an option for additional strict mode keywords that the host environment is expected to provide.
Removing support for implicit this fallback {{foo}} -> {{this.foo}}
When a strict mode template references an undefined variable, it really should produce a compile-time error, arguably that is the point of the feature.
However, it seems like previously a lot of these errors ended up propagating and is actually handled by the runtime compiler.
The original/primary goal here started out as cleaning up all the code for implicit this fallback, but as I delete code it eventually revaled all the places where strict mode was inappropiately using the same infrastructure ("unresolved free variables", which isn't really a sensible thing).
Also:
{{#with}}