W3C home > Mailing lists > Public > whatwg@whatwg.org > October 2009

[whatwg] Structured clone algorithm on LocalStorage

From: Jonas Sicking <jonas@sicking.cc>
Date: Fri, 2 Oct 2009 21:43:51 -0700
Message-ID: <63df84f0910022143t51905a2as99f68bfe78e73704@mail.gmail.com>
>
>   >> >> > Moreover, there are other examples which have been discussed on
>>>> the
>>>> >> >> > list.  There are some DOM operations that can result in a frame
>>>> >> >> > receiving
>>>> >> >> > a DOM event synchronously.  That can result in a nesting of
>>>> storage
>>>> >> >> > locks,
>>>> >> >> > which can force us to have to implicitly unlock the outermost
>>>> lock to
>>>> >> >> > avoid
>>>> >> >> > deadlocks.  Again, the programmer will have very poor visibility
>>>> into
>>>> >> >> > when
>>>> >> >> > these things can happen.
>>>> >> >>
>>>> >> >> So far I don't think it has been shown that these events need to
>>>> be
>>>> >> >> synchronous. They all appear to be asynchronous in gecko, and in
>>>> the
>>>> >> >> case of different-origin frames, I'm not even sure there's a way
>>>> for
>>>> >> >> pages to detect if the event was fired asynchronously or not.
>>>> >> >
>>>> >> > IE and WebKit dispatch some of them synchronously.  It's hard to
>>>> say
>>>> >> > which
>>>> >> > is correct or if it causes any web compat isues.  I'm also not sure
>>>> that
>>>> >> > we
>>>> >> > have covered all of the cases.
>>>> >>
>>>> >> It still seems to me that it's extremely unlikely that pages depend
>>>> on
>>>> >> cross origin events to fire synchronously. I can't even think of a
>>>> way
>>>> >> to test if a browser dispatches these events synchronously or not.
>>>> Can
>>>> >> you?
>>>> >
>>>> > i agree that it seems uncommon.  maybe there could be some odd app
>>>> that
>>>> > does something after resizing an iframe that could be dependent on the
>>>> > event handler setting some data field.  this kind of thing is probably
>>>> even
>>>> > less common in the cross-origin case.
>>>>
>>>> But how would you read that data field in the cross-origin frame? I
>>>> think it might be possible, but extremely hard.
>>>>
>>>>
>>> Yeah.
>>>
>>> My concern is simply that I cannot prove that I don't have to worry about
>>> this
>>> problem.  Future web APIs might also inadvertently make matters worse.
>>>
>>
>> I agree it's not ideal, but at the same time I don't think that not
>> allowing synchronous cross-origin APIs is a huge burden. You campaigned
>> heavily against that when we were designing postMessage for wholly other
>> reasons. I would imagine those reasons will hole true no matter what.
>>
>
> Agreed.  That's a good point.  In that case, I was concerned about stack
> depth.  The same issue might apply here.  Hmm...
>

As far as I can see it does.



>
> ...snip...
>
>>
>>>> >> >> Not quite sure I follow your proposal. How would you for example
>>>> >> >> increase the value of a property by one without risking race
>>>> >> >> conditions? Or keep two values in different properties in sync?
>>>> I.e.
>>>> >> >> so that if you update one always update the other, so that they
>>>> never
>>>> >> >> have different values.
>>>> >> >>
>>>> >> >> / Jonas
>>>> >> >
>>>> >> >
>>>> >> > Easy.  Just like with database, the transaction is the storage
>>>> lock.
>>>> >> >  Any
>>>> >> > storage
>>>> >> > operation performed on that transaction are done atomically.
>>>>  However,
>>>> >> > all
>>>> >> > storage
>>>> >> > operations are asynchronous.  You basically string together
>>>> asynchronous
>>>> >> > storage
>>>> >> > operations by using the same transaction for each.
>>>> >> > We could add methods to get/set multiple items at once to simplify
>>>> life
>>>> >> > for
>>>> >> > the coder.
>>>> >>
>>>> >> I think I still don't understand your proposal, could you give some
>>>> >> code examples?
>>>> >>
>>>> >
>>>> >
>>>> > ripping off database:
>>>> > interface ValueStorage {
>>>> >   void transaction(in DOMString namespace, in
>>>> > ValueStorageTransactionCallback callback);
>>>> > };
>>>> > interface ValueStorageTransactionCallback {
>>>> >   void handleEvent(in ValueStorageTransaction transaction);
>>>> > };
>>>> > interface ValueStorageTransaction {
>>>> >   void readValue(in DOMString name, in ValueStorageReadCallback
>>>> callback);
>>>> >   void writeValue(in DOMString name, in DOMString value);
>>>> > };
>>>> > interface ValueStorageReadCallback {
>>>> >   void handleEvent(in ValueStorageTransaction transaction, in
>>>> DOMString
>>>> > value);
>>>> > };
>>>> > then, to use these interfaces, you could implement thread-safe
>>>> increment:
>>>> > window.localStorage.transaction("slice", function(transaction) {
>>>> >   transaction.readValue("foo", function(transaction, fooValue) {
>>>> >     transaction.writeValue("foo", ++fooValue);
>>>> >   })
>>>> > })
>>>> > to fetch multiple values, you could do this:
>>>> > var values = [];
>>>> > var numValues = 10;
>>>> > function readNextValue(transaction) {
>>>> >   if (values.length == numValues)
>>>> >    return;  // done!
>>>> >   var index = values.length;
>>>> >   transaction.readValue("value" + index, function(transaction, value)
>>>> {
>>>> >     values.push(value);
>>>> >     readNextValue(transaction);
>>>> >   })
>>>> > }
>>>> > window.localStorage.transaction("slice", readNextValue);
>>>> > This has the property that all IO is non-blocking and the "lock" is
>>>> held
>>>> > only
>>>> > for a very limited scope.  The programmer is however free to extend
>>>> the
>>>> > life of the lock as needed.
>>>>
>>>> What do you mean by that the "lock" is held for only a very limited
>>>> scope? You still want to prevent modifications for as long as the
>>>> transaction is being used right? I.e. no modifications can happen
>>>> between the read and the write in the first example, and between the
>>>> different reads in the second.
>>>>
>>>
>>> Yes.  I only meant that the programmer doesn't have to call a special
>>> function to close the transaction.  It closes by virtue of the last
>>> handleEvent
>>> call referring to the transaction returning.
>>>
>>
>> So wouldn't you implement this transaction using a lock? To prevent other
>> pages from accessing the localStorage?
>>
>>
> Yes, but it wouldn't need to be a normal mutex if that's what you mean.
>  You could just defer callbacks until the transaction completes.  It is
> purely asynchronous locking.
>

So how is that then different from from using a Storage API, but only
letting you get a reference to the Storage object using a asynchronous API?
And of course not allowing the Storage object to be stored in a variable and
used outside the callback.

/ Jonas
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.whatwg.org/pipermail/whatwg-whatwg.org/attachments/20091002/dc6f1587/attachment.htm>
Received on Friday, 2 October 2009 21:43:51 UTC

This archive was generated by hypermail 2.4.0 : Wednesday, 22 January 2020 16:59:17 UTC