-
Notifications
You must be signed in to change notification settings - Fork 35
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
Document rules: introduce "where" key which accepts an array of conditions #177
Document rules: introduce "where" key which accepts an array of conditions #177
Conversation
The extra If I also made that change and combined it with #169 it would reduce the example down to {
"prerender": [
{"where": [
{"href_matches": "/*"},
{"not": {"href_matches": "/logout"}},
{"not": {"selector_matches": ".no-prerender"}}
],
"score": 0.1}
]
} WDYT? Also not explicit in the example is that URL patterns can be constructed either from a single string or from a structured object with the same syntax as |
And additionally if arrays are optional then the |
My main question is figuring out exactly what boolean algebra we're giving, both implicitly and explicitly. From what I can see we have:
I guess every formula in a boolean algebra can be put into disjunctive normal form so the minimum we could provide is: outer-or, inner-and, innermost-not. E.g., separate document rules, multiple array elements under That said, maybe we should not be including separate document rules in this analysis; maybe we want you to be able to express any formula within a single document rule (and thus not have to duplicate things like score or referrer policy). So from that perspective what you have so far works well (and corresopnds to conjunctive normal form). Either way, it seems like we may be able to preempt any further expansion desires since everything is already expressible, so "In the future, a more complete boolean algebra could be added if needed" is maybe not necessary. That leaves me with the following thoughts:
Also, an interesting link... https://stackoverflow.com/q/20737045. Attempt at something inspired by https://jsonlogic.com/{
"where": [ // "or"
{
"and": [
{ "href_matches": "/*" },
{ "not": { "href_matches": "/logout" } },
{ "not": { "selector_matches": ".no-prerender" } },
]
},
{ "selector_matches": ".definitely-prerender" }
]
} {
"where": [ // "and"
{
"or": [
{ "href_matches": "/good-stuff/*" },
{ "selector_matches": ".please-prerender" },
]
},
{ "not": { "selector_matches": ".no-prerender" } }
]
} The killer problem is just what the top-level |
I also noticed that CSS's |
I'm not super convinced by the argument that things can be converted to DNF or CNF because the normal form isn't always remotely ergonomic -- or efficient to compute, for that matter. Authors can arguably express any logic by adding/removing a class name and using CSS selectors to match on that. CSS One way to avoid the It did seem natural if not obvious to me that CSS selectors have builtin combinators so an array isn't actually necessary there but is there for convenience more than anything. URL patterns, though, I expect it to be common to say things like "everything is safe, except for /logout, /shred/* and /incinerate/*", which isn't expressible with a single pattern. And to say that concisely, you want "or". So while they're not all the same I think this is the sense which I expect to be most frequently useful. Some random alternatives to feed the brainstorm: explicit all/any {
"where": {"all": [
{"href_matches": "/*"},
{"not": {"href_matches": "/logout"}},
{"not": {"selector_matches": ".no-prerender"}}
]}
} combining logical operators with adjacent nodes using string prefixes Inlining the "not" into particular conditions was part of the starting point. Maybe it's not so bad if we simply define a number of common patterns for the keys that apply in a standardized way. {
"where_all": [
{"href_matches": "/*"},
{"not_href_matches": "/logout"},
{"not_selector_matches": ".no-prerender"}
]
} Honestly, expression syntax We could just give up on using JSON as a way to represent conditions and just give a proper expression syntax. {"where": "href_matches('/*') && !href_matches('/logout') && !selector_matches('.no-prerender')"} This immediately creates annoyances around string escaping rules, though, in addition to interpreting this requiring a parser. expression syntax, prepared statement style {
"where": [
"href_matches($1) and not href_matches($2) and not selector_matches($3)",
"/*", "/logout", ".no-prerender"
]
} This extracts the strings similar to how SQL prepared statements work but ends up being very ugly. expression syntax only for boolean algebra {
"where": {
"expression": "is_local && !is_logout && !is_no_prerender",
"$is_local": {"href_matches": "/*"},
"$is_logout": {"href_matches": "/logout"},
"$is_no_prerender": {"selector_matches": ".no-prerender"}
}
} This allows an expression syntax limited to identifiers, &&, || and parentheses (so requires parsing, but simpler parsing) and makes all of those identifiers correspond to condition objects. |
I generally agree with all your points; thanks for spelling them out! The only pushback is that
This seems pretty OK, especially with that indentation style. I guess you could also feed it a single non-logical rule, e.g.
I agree that I find the simplicity of inlining
This is... not terrible? It's not really like anything I've seen before, but I think it could be pretty reasonable to use. Overall I would be happy with any of:
I think the explainer should include brief writeups of whatever alternatives you don't choose, and try to get feedback on them ASAP (e.g. by pinging #160 which should notify Lea, and asking current or future speculationrules users). |
Alright, removed implicit-and for We can always extend with "I have a really complicated boolean function" features in the future if it proves necessary, which I hope it won't. |
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.
Looks great! I'm pretty happy with where this landed, personally.
This isn't quite full boolean algebra, but addresses #160. It's tempting to go for a full parsed expression syntax but that introduces a fairly significant complexity, escaping, etc.