If we have a gridded vector source, the grid should have something to do with the source data (e.g. the vector data is available in a regular grid). The vector layer renderer's internal grid is for rendering canvas tiles and doesn't have anything to do with the source.
We should discuss whether post render functions must be run after each render frame or not. If these can be run after multiple render frames, it would make sense to increase the timeout. As it is, it looks like post render functions are run for every render. Hard to see what the benefit is in this case.
This simple expression constructor will be used for symbolizer properties and the layer will generate symbolizer literals for rendering by evaluating any expressions with a feature as the this argument and feature attributes as the scope. This allows generating labels that concatenate multiple attribute values together or displaying point symbols that are sized according to a population attribute divided by an area attribute, for example.
This implementation will not work in environments where the content security policy disallows the use of the Function constructor. This is the case on browser extensions. A more content-security-policy-friendly implementation would be to come up with a restricted grammar and write a lex/parser. This is the road I started down, but this verison is far less code, and I think the security policy limitations are minor at this point. This version will always be faster/lighter than a parser, so one is written in the future, it should only be pulled in where content security policy mandates it.
Assuming browser garbage collection cannot happen while we have listeners in the global registry, we need to listenOnce to avoid memory leaks with the tile queue.