-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Read-only variables for used modules #3171
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 occasion 8000 ally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I checked a
It is expected. But, joining the question, should it be? |
Although I don't think we can change the default behavior here, I do think it's reasonable to allow module authors to opt into making their variables read-only outside of their module. I don't have a strong design for such a thing in mind, though. |
Do you have any examples of usages that explicitly rely on the writable nature of those variables (I'm not counting sass-spec as such a usage of course, as it is about testing the spec, not about doing actual usages). All open-source examples I found are either explicitly avoiding public module variables (cf guten-type from @Awjin) or are never writing to them from their own downstream modules and probably don't expect them to be writable (cases like design tokens of design systems). I haven't found yet an actual usage. If non-writable variables needs to be opt-in, I don't have an idea about the design either. It should probably be something at the module level rather than having to opt-in each variable, but I don't know how that could look like. |
The cost of a breaking change like this is extremely high, and not something I'm willing to pay unless the old way of doing things is actively causing major harm which I don't think is the case here. Besides, although you may be right that upon consideration most users would choose for most of their module variables to be write-protected, that doesn't necessarily mean that they'd expect them to be write-protected by default. Sass has a long history of making all variables writable by default, and violating that expectation is likely to cause confusion even if it's "better" in some sense. |
@stof I think read-only module members is an interesting idea, though I'm not sure that guten-type is the most illustrative use-case, since it's a toy project and small in scope. It will be interesting to see what user needs arise for read-only vs. writable members, especially in non-trivial use cases (maybe something like Material Web). |
@Awjin the question is also whether authors (not belonging to the Sass core team) realize that exported variables are writable. Last time I checked, the documentation about Sass modules was not telling anything about that (and the emphasis about configuring modules might make them think that those variables are indeed writable only through the configuration, which is why I thought myself until I started reading the code of dart-sass to discover the opposite) |
@stof wrote:
I had no idea, and I would have assumed modules were immutable and that equivalent functionality should be achieved with How would one reason about multiple assignments to mutable variables in namespaces? What is the mapping from the import graph to the state of each variable at the time the styles are finally compiled? |
@AprilArcus styles are compiled on the module execution, the first time it is used. So any module variable re-assignment will not affect the module styles. But it will affect the module API used by other modules (the value of the exported variable, the output of the exported functions/mixins if they use that variable, etc...) |
Uh oh!
There was an error while loading. Please reload this page.
Currently, built-in modules and userland modules have a big difference (which is not clearly explained in the doc IMO): in userland modules, any exported variable is writable by downstream modules, and this impacts other modules importing the same module later. This is even true for variables that are not configurable in
@use
. On the other hand, variables exported by built-in modules (math.$pi
for instance) are immutable.To me, this behavior of builtin modules makes it harder to reason about the behavior of modules, as I cannot look only at upstream modules to find out where a value comes from.
This behavior also makes variables unsuitable for cases where downstream modules are not meant to be allowed to change the values (for instance a color palette of a design system, where downstream modules should only be allowed to use colors).
Reproducing case proving this
Output for
sass b_first.scss
:Output for
sass c_first.scss
:As you can see, the file in
_c.scss
(that knows nothing about_b.scss
) will get a different in the value it receives from_a.scss
depending on the order in which modules gets executed for the first time, which can only be determined by looking at the whole dependency graph starting at the entrypoint (and things are even worse ifmeta.loadCss
adds some module execution in places that cannot be found statically).Being able to expose values that can be read is nice API for anything needing to expose reusable values IMO (and
math.$e
is a good proof of it). But most cases I can think about don't actually expect those members to be writable in downstream modules. https://github.com/Awjin/guten-type/blob/master/_config.scss is another case that seems to prove it, using functions to expose members in a read-only way instead of exposing them directly.Is it expected to make those members writable (the implementation seems to say yes, as I don't see how that could have been implemented by accident) ? And do you think there should be a way for modules to forbid downstream assignments ?
The text was updated successfully, but these errors were encountered: