-
Notifications
You must be signed in to change notification settings - Fork 430
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
Regression: escaping of "method" breaks JS interop #2523
Comments
Also, let f = x => x##method; gives function f(x) {
return x.method_;
} |
Same for React components, as they are using module SomeComponent = {
[@react.component]
let make = (~method) => React.string(method);
};
<SomeComponent method="GET" />; gives React.createElement(Teest$SomeComponent, {
method_: "GET"
}); |
Maybe [@bs.obj] external request: (~_method: string) => request = ""; which works fine. |
I don't think this is a bug. We did switch the representation, but it's "correct" now. Is the BuckleScript contract that the generated JS names can be relied upon? If we revert this change then there are bugs interacting between Reason and OCaml, and IMO those need to remain fixed. |
I don't know if there is any "official" BuckleScript contract for that, but as a user of BuckleScript defining an external method in Reason syntax [@bs.obj] external request: (~a: string, ~b: string, ~c: string) => t = ""; I definitely expect the resulting JS object to have the fields If the compiler told me that I am not allowed to use |
For example, [@bs.obj] external request: (~type: string) => t = ""; gives me a compile error:
I then change it to [@bs.obj] external request: (~_type: string) => t = ""; and Js.log(request(~_type="GET")); generates
Is it not possible to have the same behavior for |
I suggest we have two modes, regular mode and compat mode. |
We are blocked on this issue. The current situation is a bit worse, since it would compile and break user's code silently |
@bobzhang Is it clear that the name mangling needs to happen even if someone is calling into ocaml code that was not authored in Reason? I believe the name mangling is the right thing to do - and the only reason why we might skip it is just to avoid breakages in existing Reason code. It's not the "right" solution to skip name mangling, but it's the one we might have to do in the mean time. |
It's kind of hard to maintain two "modes" of compatibility, but it might be the easiest path forward. The worst break here would be with BuckleScript users who use these with externs which wouldn't issue compiler errors. Users of non-bucklescript Reason tend to use these names in places that aren't used to generate untyped JS objects, so they would usually get an error if calling out to OCaml code and they would know to fix up their code. How should such a compatibility mode be toggled? In the reason parser library? So that bucklescript could set that option before parsing? |
@jordwalke As I said, the current name mangling scheme is a bit leaky, reason users should not be expected to know that method is a reserved keyword in OCaml. It is hard to do it right in the source level, we hit several regressions in last couple of releases (below is a non complete list). For the two modes, the strict mode is subset of regular mode, so the maintainability is okay(I expect the maintenance is less than keep name mangling)
In general, regular mode is by default, if the reason library is intended to be called by OCaml users in the source level, it should have a strict mode as a sanity check. Note what I am proposing is not having two modes where one mode does name mangling while the other does not, that would be a nightmare to maintain compatibility. Edit: another place where such name mangling is leaky:
|
Alright. I looked more into it and here are things to consider:
There was however a lot of code before this fix that explicitly used But we need proper escaping in general for compatibility with OCaml at least when using native.
Any time we change name mangling (even to fix an issue) - some people will break, which is why it's important to get these fixes in sooner than later. But there's one potential saving option. So my proposal to unblock the BS release is that we use a slightly different escaping convention for labeled names than we use everywhere else. Function label names would then use this convention:
(putting the underscore at the beginning instead of the end). For compatibility with the OCaml ecosystem, all that matters is that there is some complete escaping convention, it doesn't matter too much what that convention is. But - like any change to name mangling, you could always break someone. Fortunately, in this case, it seems like labels of the form |
Isn't this incompatible with punning ? |
As an extra data point, this issue affects out-of-the-box Reason React as well. This previously compiled (e.g. with bsb 5.2.x): <form method="POST" /> But it stopped compiling with bsb 7.0.x. You can get it to compile by changing |
here's an updated summary of this issue: with let x = (~method) => method ^ this becomes with let x ~method_ = method_ but then Melange keys get a so: a) keeping it is sorta bad for OCaml compatibility, but I guess some hope for this is OCaml 5.2, where you can write let x ~\#method:method_ = method_ which is maybe ~fine but then we'd need everyone using reason to be on OCaml 5.2+, which may take 10 years |
The just released BS 7.0.2-dev.1 with the latest refmt compiles
to
I.e. it gives me an object with a field
method_
. In previous versions, I used to get an object with a fieldmethod
(as expected).The text was updated successfully, but these errors were encountered: