Description
- Dart SDK Version: 2.17.5
- I was using Chrome on Windows, but I don't think this is applicable because it's really related to the javascript being generated
I have an open PR for grpc-dart to implement a fetch transport rather than XHR. I just recently realized the code wasn't working in release builds. I had to change the code from calling methods directly on a dynamic object that represents a javascript ReadableStream to using callMethod. The original code worked fine while debugging, but it wasn't until building in release and deploying it that I realized it didn't work.
Here's a link to the commit that works around the issue:
grpc/grpc-dart@5a8818b
The dart code in question from the PR looks something like this (from fetch_transport.dart):
dynamic _response;
dynamic get body =>
_response != null ? js_util.getProperty(_response, 'body') : null;
...
if (status < 200 || status >= 300) {
onErrorController.add(status);
}
final reader = body?.getReader();
if (reader == null) {
onErrorController.add(0);
return;
}
This generates the following javascript:
if(p.gbv(p)<200||p.gbv(p)>=300)p.at.u(0,p.gbv(p))
o=p.ch
o=o!=null?o.body:null
if(o!=null) o.aNq()
The result is a type error o.aNq is not a function
. That's not all that readable so I generated it with --dart-define=Dart2jsOptimization=O0
which results in the following snippet:
if ($async$self.get$status($async$self) < 200 || $async$self.get$status($async$self) >= 300)
$async$self.onErrorController.add$1(0, $async$self.get$status($async$self));
t1 = $async$self._response;
t1 = t1 != null ? t1.body : null;
if (t1 != null)
t1.getReader$0();
$async$self.onErrorController.add$1(0, 0);
// goto return
$async$goto = 1;
This is quite a bit more readable, but it still fails on the getReader$0()
call because this should just be getReader()
. If I change the code to use callMethod this resolves the issue, but results in more code and is less readable. As you can see from the commit I also had to stop calling read directly on the reader and instead use callMethod there too. My biggest complaint is really just the inconsistency between debugging and release though because having it's much easier to debug/troubleshoot it during dev than after it's been deployed.
The final javascript with my changes (Note that it actually just calls stream.getReader()
as expected):
if ($async$self.get$status($async$self) < 200 || $async$self.get$status($async$self) >= 300)
$async$self.onErrorController.add$1(0, $async$self.get$status($async$self));
t2 = $async$self._response;
stream = t2 != null ? t2.body : null;
reader = stream != null ? stream.getReader() : null;
if (reader == null) {
$async$self.onErrorController.add$1(0, 0);
// goto return
$async$goto = 1;
break;
}