Closed annevk closed 11 years ago
In the current spec language you can always push the side effects, if any, to OnSuccessfulTransfer and be done with it.
For example, with MessagePorts, where some state needs indeed to be moved to new port (http://www.w3.org/TR/webmessaging/, clone port), all the state (messages from the queues etc) can be moved in OnSuccessfulTransfer. I guess we should amend OnSuccessfulTransfer, so that it takes two arguments, source and target, and pass whatever state is to be passed.
I actually do not know of any other example where the act of transfer itself changes much of state, at least conceptually. Generally, I view transfer as a "resource ownership transfer" - the resource stays put, it is only the handle to the resource that changes hands. MessagePorts are unfortunate complication of the concept - it had actually arisen from a desire to reuse nice postMessage overload ;)
So transfering ownership is a side effect. Because the ArrayBuffer suddenly has no data anymore. If cloning then throws you end up in a weird state.
That means transfering ownership has to move to after cloning, just before neutering. Right?
For ArrayBuffers it factors nicely: [[Transfer]] creates a new ArrayBuffer and the world is forked - but no one sees the fork until the structured clone completes. After the structured clone completes, one of two things has happened:
So there is no ownership "during" clone, only "before" clone and "after" clone.
But [[Transfer]] as specified now also transfers ownership to "new" prong (TODO in the current algorithm). Meaning "old" prong will have lost ownership in the failure case.
Well, I guess I should make that TODO more clear. All this TODO is supposed to do is to set up a new ArrayBuffer so that it points to the same chunk of memory (or clone of that chunk of memory - it really does not matter).
There is no magic happening here - the only meaning of "ownership transfer" is that the array buffer pointing to that chunk of memory is made available to a target realm, and the old array buffer is neutered so that source realm cannot access it anymore. There is no other underlying concept of "ownership transfer". In case of clone failure, neither new array buffer is available to target realm, nor old buffer is neutered, so the ownership is not transferred.
Does this make sense?
Ah okay, so we don't transfer ownership, but we make them point to the same thing and then neuter the original after cloning. That makes sense. Terminology threw me off.
Cool, we still need to make new object available to OnSuccessfulTransfer, so that MessagePort can dance its dance
Done in 1b66c1d1fd8e62d5c4d04c3f03eb9200273df7ed
Let's move the discussion from https://github.com/dslomov-chromium/ecmascript-structured-clone/commit/9b2050a4d6e2763d4d64cb08f6b4e8369f275c30 here.
So the basic problem with the current approach is that transferring has side effects. And if the cloning ends up failing, those side effects are bad and not present in the original specification.