fix: fix ReadableStream being incorrectly wrapped by BindingWrapper#128
Conversation
There was a problem hiding this comment.
I'm Bonk, and I've done a quick review of your PR.
This PR prevents _BindingWrapper from wrapping JS objects like ReadableStream that should be passed through directly (e.g. to Response).
Issues
-
(Medium) Coupling
RESPONSE_ACCEPTED_TYPESto binding-wrapping logic is fragile and the helper name is misleading._is_response_accepted_typeis documented as checking "if the given object is an accepted type for a Response body," but_should_wrap_nested_attributerepurposes it to decide whether to skip_BindingWrapperwrapping. These are conceptually different decisions that happen to overlap today. If someone later adds a type toRESPONSE_ACCEPTED_TYPES(e.g. a new body type) or needs to exclude a non-body JsProxy from wrapping (e.g. aHeadersobject accessed via RPC), the coupling will silently break one of the two call sites. Consider either (a) giving_should_wrap_nested_attributeits own set of excluded types, or (b) renaming_is_response_accepted_typeto something more general (e.g._is_known_js_builtin) with a docstring that reflects both use cases. -
(Low) Minor:
Response.__init__accessesbody.constructor.nametwice on the error path. After calling_is_response_accepted_type(body)(which already readsconstructor.name), line 429 readsbody.constructor.nameagain for the error message. Not a bug, but sinceconstructoraccess can have side effects through__getattr__on wrapped objects, you could store the result from the helper to avoid the duplicate access. This is a pre-existing issue though, not introduced by this PR.
|
Review posted successfully on PR #128. Here's a summary of what I flagged:
The fix itself is a reasonable workaround for the described bug, and the test covers the motivating case well. |
6d2f3d4 to
bfd43a3
Compare
dom96
left a comment
There was a problem hiding this comment.
Thanks! I actually ran into this yesterday when I upgraded one of my Workers to the latest SDK. Nice to see you caught as well.
This fixes a bug that the
ReadableStreamobject returned from rpc call is incorrectly wrapped with_BindingWrapper.In #112, I wrapped all JsProxies returned from rpc call with
_BindingWrapper, so that nested rpc objects can be handled properly. However, this was too aggressive that it ended up wrapping objects such asReadableStreamwith the_BindingWrapperas well.This should not be not a problem normally because
_BindingWrapperbasically pass-through all the attributes and parameters. However, when we are accessing theconstructorattribute, which is both an object and callable, we wrap it with a Python function and loose the access to its inner attributes, leading to the following error.This PR is a workaround, avoid wrapping JS objects that can directly passed to the Response object. In the long term, I think the proper fix is to create a Python wrapper for ReadableStream and handle it inside the
python_from_rpcfunction.