-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
Add migration to expressions into gl-style-migrate #7095
Conversation
@@ -100,7 +122,7 @@ test('filter', (t) => { | |||
t.equal(f({zoom: 0}, {properties: {foo: true}}), false); | |||
t.equal(f({zoom: 0}, {properties: {foo: false}}), false); | |||
t.equal(f({zoom: 0}, {properties: {foo: null}}), true); | |||
t.equal(f({zoom: 0}, {properties: {foo: undefined}}), false); | |||
// t.equal(f({zoom: 0}, {properties: {foo: undefined}}), false); |
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 expressions system does not treat undefined
as a distinct value, and so it has no way to mimic this aspect of GL JS's legacy filter implementation. Since this isn't even something that can be meaningfully represented in the GeoJSON spec, I'm inclined to just drop these assertions and consider filtering on properties like {foo: undefined}
to be (ahem) undefined behavior.
Excited to see this update!
@anandthakker @jfirebaugh What is the official status now of tokens (
Luckily, for our core styles we've almost completely avoided these, due to nesting restrictions in Studio's UI representation of filters 👍 I did a quick check of current core styles and can only find one example of an (This doesn't actually affect our future core style updates since we've manually migrated these to use expressions. However, I think this is relevant for the many customers who have created custom styles based on our core styles over the last few years and may be interested in auto-migrating those custom styles.) |
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 most difficult case for full-fidelity conversion is the default
property for legacy functions. We couldn't think of a straightforward way to translate the semantics of default
to expressions, and in native, we resorted to supporting it via a special case in the evaluator. Do you have any new ideas on that front?
* allowing the subsequent terms of the outer "any" expression to be evaluated | ||
* (resulting, in this case, in a `true` value, because x > 0). | ||
* | ||
* We account for this by inserting a preflight type-checking expression before |
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.
Can you add a few sentences outlining the motivation for this particular approach as opposed to alternatives? I'm assuming it's to minimize the cases where typechecking is needed (only when "any" is used; other cases are fine to let error out [Are they? Will this produce annoying error messages?]).
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 assuming it's to minimize the cases where typechecking is needed (only when "any" is used; other cases are fine to let error out [Are they? Will this produce annoying error messages?])
Yep, that was the reason. Other cases are fine to let error out, in the sense that they'll produce the correct behavior. It's true that they'll produce annoying warnings in that case. But this (and the other issues that have come up re: evaluation error warnings) makes me wonder whether it might make sense to simply disable these warnings (or some subset of them?) by default, only showing them if a map.expressionDebug
property is set to true...
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.
simply disable these warnings (or some subset of them?)
Another possibility: we currently only log each distinct evaluation error once, with that uniqueness scoped to each expression. If we expanded the uniqueness scope to the whole map, that would dramatically reduce the number of these warnings, while still giving developers a clue if they're trying to figure out why their style isn't doing what they want.
Tokens will continue to work, but they're about the same level of deprecated as legacy functions. @anandthakker, want to add conversion for literal string values? (Token strings in legacy function stops are already handled.) |
Ah, good point @jfirebaugh -- I just relied on the existing conversion implementation in https://github.com/mapbox/mapbox-gl-js/blob/855b850e62196c46f0987ab73600fffddc3e22bc/src/style-spec/function/convert.js, but that implementation doesn't fully handle legacy functions' default semantics. (Specifically, the expressions it produces don't fall back to the user-provided default when there's a type mismatch on the input property.) No new ideas as such--I'd say we could just introduce a similar approach as for filters, including type checks explicitly in the expression when they're needed. |
709e645
to
d9c719f
Compare
The tricky case for defaults turns out to be arrays. For e.g.
The other missing piece is |
b3f39a7
to
1badad1
Compare
I ended up just doing this. This is now ready for review. |
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 spent some time reading through this PR, enough I think to have a rough understanding, but it's too big and with parts I'm too unfamiliar with for me to give much detailed feedback. Are we OK relying on all the review @jfirebaugh and @anandthakker already did together?
The "use 'null' to indicate a fallback argument for 'array'" hack seems... awkward... but I guess reasonable for handling the "default value" case. It doesn't look like we've documented it: is our hope that users will never even discover it?
Yeah, that's kind of my hope. If I was redesigning type assertions I'd do it like |
1badad1
to
9f26bdb
Compare
FYI @mapbox/studio @mapbox/maps-design (who got de-tagged ☝️in the description due to Anand's departure) -- this merged. Please try it out and let us know if you notice any issues with the migration. |
This is tested implicitly via legacy function conversion tests added in #7095, but it's proving difficult to get those passing on native, and we should test this in isolation anyway.
This is tested implicitly via legacy function conversion tests added in #7095, but it's proving difficult to get those passing on native, and we should test this in isolation anyway.
This is tested implicitly via legacy function conversion tests added in #7095, but it's proving difficult to get those passing on native, and we should test this in isolation anyway.
Closes #6927
@mapbox/studio @mapbox/maps-design.
Updates the style-spec's old
gl-style-migrate
script to include conversion of legacy functions and filters to their expression equivalents. Note that because of some subtle differences in how legacy filters and expressions handle type mismatches, the converted expressions for complex filters (particularly "any" or "none" filters) may end up being overly complicated and under-performant. For styles that have those, it would be worth manually inspecting and revising the auto-generated expressions.