Skip to content

Conversation

hotpineapple
Copy link
Contributor

@hotpineapple hotpineapple commented Aug 24, 2025

check if there is transform stream and its member in transfer list

this make wpt test transform-stream-members.any.js pass

@nodejs-github-bot
Copy link
Collaborator

nodejs-github-bot commented Aug 24, 2025

Review requested:

  • @nodejs/web-standards

@nodejs-github-bot nodejs-github-bot added needs-ci PRs that need a full CI run. worker Issues and PRs related to Worker support. labels Aug 24, 2025
@hotpineapple hotpineapple force-pushed the implement-transform-stream-memeber-check branch from 5d4342b to 4b20401 Compare August 24, 2025 10:36
Copy link

codecov bot commented Aug 24, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 89.85%. Comparing base (08556f0) to head (6559712).
⚠️ Report is 15 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #59610      +/-   ##
==========================================
- Coverage   89.89%   89.85%   -0.05%     
==========================================
  Files         667      667              
  Lines      195320   196191     +871     
  Branches    38349    38549     +200     
==========================================
+ Hits       175578   176281     +703     
- Misses      12217    12361     +144     
- Partials     7525     7549      +24     
Files with missing lines Coverage Δ
lib/internal/worker/js_transferable.js 98.68% <100.00%> (+0.13%) ⬆️

... and 51 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@@ -123,6 +125,18 @@ function structuredClone(value, options) {
},
);

const transferList = idlOptions.transfer;
for (let i = 0; i < transferList.length; i++) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should use ArrayPrototypeForEach to make it resilient to prototype pollution

@hotpineapple hotpineapple force-pushed the implement-transform-stream-memeber-check branch from 4b20401 to 6559712 Compare August 24, 2025 12:02
check if there is transform stream and its member in transfer list
if (isTransformStream(outer)) {
ArrayPrototypeForEach(transferList, (inner, j) => {
if (i !== j && (inner === outer.readable || inner === outer.writable)) {
throw new DOMException('Cannot transfer a stream and its members', 'DataCloneError');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These steps aren't explicitly listed in the specification for structuredClone. It also seems weird to handle a highly specific edge case like this here, especially since there are many other ways than just structuredClone that can trigger a transfer, e.g. postMessage. If we really needed a workaround specific to TransformStreams, I would expect to find it near the implementation of its transfer steps, so that it is handled correctly regardless of how the transfer was triggered.

But to be honest, I don't think we should be fixing the test failure by adding extra code to detect this exact edge case. The streams specification requires that the transfer fails if the readable or writable side of the TransformStream is locked, which should be the case if either side was transferred before. It seems like Node's current implementation doesn't do these checks correctly, and we should investigate and fix the root cause of that problem instead.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking a bit closer, I believe the transfer steps for TransformStream are not implemented correctly. Steps 3 and 4 of the specification require readable and writable to be structurally cloned during the transfer steps of TransformStream. However, Node's implementation simply creates a data object with the not-yet-transferred readable and writable streams... 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MattiasBuelens I really appreciate your detailed explanation! I'll review it again based on what you said.🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs-ci PRs that need a full CI run. worker Issues and PRs related to Worker support.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants