Skip to content
This repository has been archived by the owner on Feb 12, 2024. It is now read-only.

ipfs-message-port-* should ensure no transferables are duplicated #3402

Closed
Gozala opened this issue Nov 17, 2020 · 11 comments · Fixed by #3421 or #3573
Closed

ipfs-message-port-* should ensure no transferables are duplicated #3402

Gozala opened this issue Nov 17, 2020 · 11 comments · Fixed by #3421 or #3573
Assignees
Labels

Comments

@Gozala
Copy link
Contributor

Gozala commented Nov 17, 2020

Forking #3252 (comment) into separate issue.

Looks like some of our API calls return values that refer to same ArrayBuffer, which in turn causes one of the encoder functions https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-message-port-protocol/src to add it to the transfer list twice and error on postMessage.

@Gozala Gozala added need/triage Needs initial labeling and prioritization good first issue Good issue for new contributors help wanted Seeking public contribution on this issue labels Nov 17, 2020
@Gozala
Copy link
Contributor Author

Gozala commented Nov 17, 2020

It should be fairly straight forward to fix this problem by switching from array of transferables to a set. Spec is bit vague about what transfer list should be https://html.spec.whatwg.org/multipage/web-messaging.html#dom-postmessageoptions-transfer (array or any iterable), but quick check on Firefox and Chrome suggest it works as expected.

@icidasset
Copy link
Contributor

const value = await query.result
port.postMessage(
{ type: 'result', id, result: { ok: true, value } },
value.transfer || []
)

Could it be because we're sending the transfer list twice here?
In other words, shouldn't line 216 say value: value.value or something like that?
Since value contains the transfer array.

@Gozala
Copy link
Contributor Author

Gozala commented Nov 17, 2020

Could it be because we're sending the transfer list twice here?

I don't believe so.

In other words, shouldn't line 216 say value: value.value or something like that?
Since value contains the transfer array.

I don't believe there is an issue with passing transfer as message data and there is no guarantee value.value will be a thing either, because this is the type of query.result:

type Return<T> = T extends Promise<infer U>
? Promise<U & TransferOptions>
: Promise<T & TransferOptions>

I do have to admit it does look a bit awkward, but I would consider improving it as a separate endeavor. You could probably easily verify that by changing line 217 to:

new Set(value.transfer || [])

@Gozala
Copy link
Contributor Author

Gozala commented Nov 17, 2020

@icidasset since you're looking at it I've assigned it to you 🥺. If you find yourself unable to work on this please drop a message & I'll unassigned.

@icidasset
Copy link
Contributor

icidasset commented Nov 24, 2020

I started working on this, but got stuck on a different error.

Screenshot 2020-11-24 at 17 21 53

Is it me or does this Uint8Array look weird? It's length is supposedly 2, but the buffer looks entirely different.
And then it's claiming that value.Data isn't a buffer. That code worked perfectly before I started using this shared worker setup 🤔

Here are my changes so far:
master...icidasset:unique-transferables

@icidasset
Copy link
Contributor

icidasset commented Nov 25, 2020

Ok weird, I updated ipld-dag-pb to the latest version and added https://www.npmjs.com/package/buffer to our dependencies for the Buffer type, and now it that error is gone 🤔 🤷‍♂️

Anyhow, I made a PR to fix the issue at hand:
#3421

@Gozala
Copy link
Contributor Author

Gozala commented Nov 25, 2020

Is it me or does this Uint8Array look weird? It's length is supposedly 2

That just means that Uint8Array is just view into the larger buffer e.g.:

const buffer = new ArrayBuffer(128)
const bytes = new Uint8Array(buffer, 0, 2)

@Gozala Gozala reopened this Dec 1, 2020
@Gozala
Copy link
Contributor Author

Gozala commented Dec 1, 2020

Here is the few things we need to do before we close this:

  • Current solution eliminates duplicates in postMessage by doing [...new Set(...transfer)]. This works, but we should change transfer type to Set.
  • postMessage can be passed a Set instance (or any iterable) as a transfer list, so we should not do conversion to an array.
  • We should revisit tests and integrate it into existing ipfs-message-port-protocol tests to exercise moving nodes e.g with duplicates CIDs.

@icidasset
Copy link
Contributor

@Gozala I'll take another look at this. I seem to have missed something which is causing a few occassional errors on Firefox. Will do the Set changes describe above as well.

Errors:

  • postMessage, Arraybuffer at index 0 is already detached (error in ipfs-message-port-server, handleQuery)
  • Attempting to access detached ArrayBuffer (error seems to be in js-ipfs itself 🤔 )

@icidasset
Copy link
Contributor

Made a separate issue for the ArrayBuffer at index 0 error, not sure how to proceed with that one: #3480

@icidasset
Copy link
Contributor

Made a PR: #3481
I addressed the Set iterable stuff there.

@lidel lidel added status/in-progress In progress and removed need/triage Needs initial labeling and prioritization good first issue Good issue for new contributors help wanted Seeking public contribution on this issue labels Apr 26, 2021
@lidel lidel assigned Gozala and unassigned icidasset Apr 26, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants