Re: [whatwg] RFC: Alternatives to storage mutex for cookies and localStorage

2009-09-09 Thread Jeremy Orlow
Great analysis.  I only have a few comments/questions:

On Wed, Sep 9, 2009 at 1:41 PM, Chris Jones cjo...@mozilla.com wrote:

 Jeremy Orlow wrote:

 On Wed, Sep 9, 2009 at 4:39 AM, Chris Jones cjo...@mozilla.com mailto:
 cjo...@mozilla.com wrote:

Aaron Boodman wrote:

On Tue, Sep 8, 2009 at 11:23 AM, Chris Jonescjo...@mozilla.com
mailto:cjo...@mozilla.com wrote:

In general, I agree with Rob about this proposal.  What
problem with storage
mutex as spec'd today does your proposal solve?


The spec requires a single storage mutex for the entire UA.
Therefore
in a MELUA a web page can become unresponsive while waiting for
 some
other page to give up the lock. This is not good and something
we have
tried to avoid everywhere else in the spec.

Attempts to address this by doing per-origin locks wind up with
deadlocks being possible.

Aaron Boodman wrote:

On Tue, Sep 8, 2009 at 1:41 AM, Robert
O'Callahanrob...@ocallahan.org
mailto:rob...@ocallahan.org

wrote:

What is the intended semantics here? Chris' explicit
commitTransaction
would
throw an exception if the transaction was aborted
due to data
inconsistency,
leaving it up to the script to retry --- and making
it clear to script
authors that non-storage side effects during the
transaction are not
undone.
How would you handle transaction aborts?

Calls to transaction() are queued and executed serially
per-origin
with exclusive access. There is no such thing as a
transaction abort
because there cannot be consistency problems because of
the serialized
access.

No, transactions can still fail.  They can fail in ways
immediately hidden
from the script that requested them if the UA has to
interrupt the
conceptually executing transaction in the ways enumerated in
a separate
branch of this thread.  Later script executions can observe
inconsistent
state unless more is specified by your proposal.

Transactions can also fail visibly if write-to-disk fails
(probably also in
other ways I haven't considered).  It's not clear what
should happen wrt to
your proposal in this case.


If so, I agree with roc's responses to them that they could
 probably
be handled without surfacing errors to the developer.

OTOH, I'm not really against adding the concept of fallibility
 here.

In fact, I believe that the Synchronous database API
describes the same
transaction semantics as I proposed in the OP.  That spec
adds implicit
begin/commitTransaction and read-only transactions, but
otherwise the
semantics are the same.

So I'd like to amend my original proposal to be

 Use Synchronous Web Database API transaction semantics.
 Except do not
offer readTransaction: a transaction is implicitly a
read-only transaction
if only getItem() is called on localStorage from within
localStorage.transaction().


Agree. That is what I was trying to propose, too. I'm not sure
 where
we disagree :). Is it just that my proposal has no concept of
errors?
I'm not against adding them, mainly I was trying to keep my
 proposal
simple for purposes of discussion.


Ay, there's the rub: I think the disagreement is between mutex vs.
transaction semantics.  So far, I think perhaps mutex has been
used as shorthand for transaction.  But they aren't the same.

I think we all agree that a script may fail to modify localStorage
in some situations (irrespective of global mutex vs. per-domain
mutex). One camp, wanting mutex semantics, would prefer to pretend
that the failures never happen and let scripts clean up the mess
(partially-applied changes) if they do occur.  This is semantically
broken, IMHO.

The second camp, wanting transaction semantics, explicitly
acknowledge to web authors that localStorage is fallible, guarantee
that modifications to localStorage are atomic, and notify scripts
when modifications can't be made atomically.  This is the same
approach taken by Web Database.  IMHO, this is much better
semantically because (i) it gives web apps stronger guarantees; and
(ii) it makes the discussion about global 

Re: [whatwg] Surrogate pairs and character references

2009-09-09 Thread Øistein E . Andersen

On 8 Sep 2009, at 23:39, I wrote:


UTF-16BE


Actually, endianness is immaterial.  Please read this as UTF-16  
instead.


Sorry for the extra message.

--
Øistein E. Andersen

Re: [whatwg] Web Address and its escape

2009-09-09 Thread Anne van Kesteren

On Tue, 08 Sep 2009 21:40:22 +0200, NARUSE, Yui nar...@airemix.jp wrote:

First is about 4.10.16.4 URL-encoded form data.
http://www.whatwg.org/specs/web-apps/current-work/#application/x-www-form-urlencoded-encoding-algorithm

In this algorithm at 6.2.1,
SP, *, -, ., 0 .. 9, A .. Z, _, a .. z is not escaped.
But many other specs which use application/x-www-form-urlencoded refers


Which other specifications?



URI's unreserved. And it in RFC3986 is
   unreserved= ALPHA / DIGIT / - / . / _ / ~
Why ~ is escaped and * is not escaped?


What do browsers do?



Third is about Web addresses in HTML 5. (this spec is also this ML?)
http://www.w3.org/html/wg/href/draft


You want public-...@w3.org or public-h...@w3.org for that draft.


--
Anne van Kesteren
http://annevankesteren.nl/


Re: [whatwg] Web Address and its escape

2009-09-09 Thread NARUSE, Yui
Anne van Kesteren wrote:
 On Tue, 08 Sep 2009 21:40:22 +0200, NARUSE, Yui nar...@airemix.jp wrote:
 First is about 4.10.16.4 URL-encoded form data.
 http://www.whatwg.org/specs/web-apps/current-work/#application/x-www-form-urlencoded-encoding-algorithm


 In this algorithm at 6.2.1,
 SP, *, -, ., 0 .. 9, A .. Z, _, a .. z is not escaped.
 But many other specs which use application/x-www-form-urlencoded refers
 
 Which other specifications?

Following specifications. (sorry some of them are earlier RFC)

XForms 1.0
  http://www.w3.org/TR/xforms/#serialize-urlencode
  then non-ASCII and reserved characters (as defined by [RFC 2396] as
  amended by subsequent documents in the IETF track) are escaped
  - so RFC3986

HTML 4
  http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1
  reserved characters are escaped as described in [RFC1738]
  RFC1738 http://www.faqs.org/rfcs/rfc1738.html
unreserved = alpha | digit | safe | extra
safe   = $ | - | _ | . | +
extra  = ! | * | ' | ( | ) | ,

TAG Finding
  refer to section 2.1 of [RFC2396].
  http://www.w3.org/2001/tag/doc/whenToUseGet.html#i18n
  RFC2396 http://www.faqs.org/rfcs/rfc2396.html
  unreserved  = alphanum | mark
  mark= - | _ | . | ! | ~ | * | ' | ( | )

WSDL 2.0
  http://www.w3.org/TR/wsdl20-bindings/#_http_x-www-form-urlencoded
  Replacement values falling outside the range (ALPHA and DIGIT below are 
defined
  as per [IETF RFC 4234]): ALPHA | DIGIT | - | . | _ | ~ | ! |
  $ |  | ' | ( | ) | * | + | , | ; | = | : | @,
  MUST be percent-encoded.

 URI's unreserved. And it in RFC3986 is
unreserved= ALPHA / DIGIT / - / . / _ / ~
 Why ~ is escaped and * is not escaped?
 
 What do browsers do?

IE8
QUERY_STRING: 
t=+%21%5c%22%5c%23%24%25%26%27%28%29*%2b%2c-.%2f0123456789%3a%3b%3c%3d%3e...@abcdefghijklmnopqrstuvwxyz%5b%5c%5c%5d%5e_%60abcdefghijklmnopqrstuvwxyz%7b%7c%7d%7e
not escaped: *...@_

Firefox 3.5
QUERY_STRING: 
t=+%21%5C%22%5C%23%24%25%26%27%28%29*%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D%7E
not escaped: *-._

Chrome2
QUERY_STRING: 
t=+%21%5C%22%5C%23%24%25%26%27%28%29*%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D%7E
not escaped: *-._

Opera9
QUERY_STRING: 
t=+%21%5C%22%5C%23%24%25%26%27%28%29%2A%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D%7E
not escaped: -._

Hmm, Firefox and Chrome follow this, IE adds @, Opera removes *.
If this spec use safer side, * may be also escaped.

 Third is about Web addresses in HTML 5. (this spec is also this ML?)
 http://www.w3.org/html/wg/href/draft
 
 You want public-...@w3.org or public-h...@w3.org for that draft.

Thanks, I'll send it.

-- 
NARUSE, Yui  nar...@airemix.jp


Re: [whatwg] RFC: Alternatives to storage mutex for cookies and localStorage

2009-09-09 Thread Chris Jones

Jeremy Orlow wrote:

Those who want a queue.  I.e. those who want an asynchronous
callback based interface and the UA will only call one callback
at a time.  Perhaps on a per-origin basis.  Note that this can
never fail, need to be rolled back, etc.


This sounds to me like { traditional transactions, async,
unobservable transaction failures } which is the same as your first
camp above except async only.  Or are you proposing that the unit of
atomicity/consistency is not all operations performed in the
callback; i.e., that modifications done in the callback can be
partially applied?


It's just an implementational difference.  A queue means that the event 
loop can continue processing stuff while waiting for the 'lock' (which 
maybe is better described as an 'update token' or something).  If you 
implement it as a lock (which you would for a synchronous interface) 
then the event loop is blocked.
 


OK, agreed.  What we describe reduce to the same thing --- the trylock 
implementation Rob O'Callahan and I discussed would also never block the 
event loop.  But I better understand now what you have in mind.  (I'm 
not sure which is better, but that's what implementation details are all 
about!)




I believe Aaron is in the queue camp with me.  I'm becoming more
and more convinced that Chromium should/will not implement the
storage mutex at all (even for LocalStorage) unless we can come
up with a way for event loops to not be blocked.  And, as far as
I can tell, Async interfaces are the only way to accomplish this.


In general, agreed.  I still believe that a sync API


The problem with a sync interface, especially if it's one that can be 
held after the top level script context, is deadlock issues with 
WebDatabase (and possibly others).  What's there now doesn't have this 
issue because you'd never have the lock when calling the database 
transaction callback.
 


I didn't think of Web Database, although I had in mind a nonblocking 
implementation of localStorage (i.e., no mutex) that would prevent it 
from participating in deadlocks.


But in general, nesting transactions, both { localStorage { Web DataBase 
} } and { localStorage { localStorage  } }, is something the spec should 
explicitly disallow.  There's not a clearly best way to resolve the 
semantic problems that arise.  (Note that preventing nested transactions 
also eliminates deadlock concerns for mutex implementations.)




with exposed transaction failures


You'll only have transaction failures in an optimistic transaction 
model, right?  So is that what you're suggesting?
 


(as I proposed in the OP) and the right implementation could do
quite well.  But I now think that an async version of that same API
could perform even better.  In addition, that API is most flexible
in terms of possible UA implementations.


IOW, I think that { traditional transactions, async, observable
failures } subsumes both { traditional transactions, sync,
observable failures } (OP's proposal) *and* { traditional
transactions, async, unobservable failures } (your and Aaron's
proposal).


IMHO there are two remaining questions: first, whether the ideal
localStorage transactional API should allow observable transaction
failures.  I believe that it should, as this allows for the widest
variety of efficient implementations without changing ACID (best
effort) guarantees given to authors or significantly complicating
the localStorage API.


What failures could there be in a pesimistic/queue model?



I'm trying to think of a universal failure, something that could arise 
in any implementation of any proposal.  I think that universal failure 
is exceeded localStorage space quota.  (I believe there are others, 
but one is enough for this discussion.)


So there are really two questions: first, what happens if you detect 
quota exceeded in the middle of a localStorage.transaction() callback? 
 Are the modifications made *up to* the quota exceeded error applied to 
backing store?  Or are they rolled back?  This is the 
atomicity/consistency design decision I described: what is the unit of 
atomic modification (all applied or none applied).


And second, can scripts be notified that the transaction failed (or was 
only partially applied) because of quota exceeded?


AFAICT this is irrespective of sync/async/optimistic/pessimistic/queue. 
 Any implementation has to deal with this error somehow.


In the current localStorage spec, if a setItem() fails because space is 
exhausted, it raises QUOTA_EXCEEDED_ERR and does *not* apply any part of 
the change in setItem().  That is, setItem() is atomic --- it either 
applies or not (not partially applied).  But modifications to 
localStorage *before* that failing setItem(), within the same storage 
mutex acquire/release set, *are* applied to backing store.


In the 

Re: [whatwg] Proposal for local-storage file management

2009-09-09 Thread Jens Alfke


On Sep 4, 2009, at 2:38 PM, Ian Hickson wrote:


Right. My point is the site can do that already, since we don't ever
_stop_ the site from using the local storage area. It can prompt you  
for

a name directly, without UA involvement.


I'm sorry, I don't understand that. We must somehow be talking about  
completely different things. Sure, the site can call prompt() to get a  
name, but how can the site then create a file on the user's machine?  
I'm talking about the user agent responding to the site's request for  
local storage by putting up a platform Save As dialog to let the user  
choose where to put it (with a reasonable default location.)


You can't store 50MB of data in a cookie. I'm talking about the  
entire

local storage of a site here, not a 40-byte session ID or something.


Then that distinction can be what is exposed in the UI to distinguish
boring storage from important storage.


Size isn't an indicator of importance, if that's what you mean. A 100- 
byte email draft could be vitally important, while 50MB of downloaded  
cached textures for a game isn't. Importance is an application- 
specific property and the UA's not going to be able to guess it.


—Jens

[whatwg] Application defined locks

2009-09-09 Thread Darin Fisher
The recent discussion about the storage mutex for Cookies and LocalStorage
got me thinking
Perhaps instead of trying to build implicit locking into those features, we
should give web apps the tools to manage exclusive access to shared
resources.



I imagine a simple lock API:

window.acquireLock(name)
window.releaseLock(name)

acquireLock works like pthread_mutex_trylock in that it is non-blocking.  it
returns true if you succeeded in acquiring the lock, else it returns false.
 releaseLock does as its name suggests: releases the lock so that others may
acquire it.

Any locks acquired would be automatically released when the DOM window is
destroyed or navigated cross origin.  This API could also be supported by
workers.

The name parameter is scoped to the origin of the page.  So, this locking
API only works between pages in the same origin.



We could also extend acquireLock to support an asynchronous callback when
the lock becomes available:

window.acquireLock(name, function() { /* lock acquired */ });

If the callback function is given, then upon lock acquisition, the callback
function would be invoked.  In this case, the return value of acquireLock is
true if the function was invoked or false if the function will be invoked
once the lock can be acquired.



Finally, there could be a helper for scoping lock acquisition:

window.acquireScopedLock(name, function() { /* lock acquired for this
scope only */ });



This lock API would provide developers with the ability to indicate that
their instance of the web app is the only one that should play with
LocalStorage.  Other instances could then know that they don't have
exclusive access and could take appropriate action.

This API seems like it could be used to allow LocalStorage to be usable from
workers.  Also, as we start developing other means of local storage (File
APIs), it seems like having to again invent a reasonable implicit locking
system will be a pain.  Perhaps it would just be better to develop something
explicit that application developers can use independent of the local
storage mechanism :-)



It may be the case that we want to only provide acquireScopedLock (or
something like it) to enforce fine grained locking, but I think that would
only force people to implement long-lived locks by setting a field in
LocalStorage.  That would then result in the locks not being managed by the
UA, which means that they cannot be reliably cleaned up when the page
closes.  I think it is very important that we provide facilities to guide
people away from building such ad-hoc locks on top of LocalStorage.  This is
why I like the explicit (non-blocking!) acquireLock and releaseLock methods.

-Darin


Re: [whatwg] Application defined locks

2009-09-09 Thread Michael Nordman
+1, a nice refactoring of the implied locking gunk in the storage api.

On Wed, Sep 9, 2009 at 10:55 AM, Darin Fisher da...@chromium.org wrote:

 The recent discussion about the storage mutex for Cookies and LocalStorage
 got me thinking
 Perhaps instead of trying to build implicit locking into those features, we
 should give web apps the tools to manage exclusive access to shared
 resources.

 

 I imagine a simple lock API:

 window.acquireLock(name)
 window.releaseLock(name)

 acquireLock works like pthread_mutex_trylock in that it is non-blocking.
  it returns true if you succeeded in acquiring the lock, else it returns
 false.  releaseLock does as its name suggests: releases the lock so that
 others may acquire it.

 Any locks acquired would be automatically released when the DOM window is
 destroyed or navigated cross origin.  This API could also be supported by
 workers.

 The name parameter is scoped to the origin of the page.  So, this locking
 API only works between pages in the same origin.

 

 We could also extend acquireLock to support an asynchronous callback when
 the lock becomes available:

 window.acquireLock(name, function() { /* lock acquired */ });

 If the callback function is given, then upon lock acquisition, the callback
 function would be invoked.  In this case, the return value of acquireLock is
 true if the function was invoked or false if the function will be invoked
 once the lock can be acquired.

 

 Finally, there could be a helper for scoping lock acquisition:

 window.acquireScopedLock(name, function() { /* lock acquired for this
 scope only */ });

 

 This lock API would provide developers with the ability to indicate that
 their instance of the web app is the only one that should play with
 LocalStorage.  Other instances could then know that they don't have
 exclusive access and could take appropriate action.

 This API seems like it could be used to allow LocalStorage to be usable
 from workers.  Also, as we start developing other means of local storage
 (File APIs), it seems like having to again invent a reasonable implicit
 locking system will be a pain.  Perhaps it would just be better to develop
 something explicit that application developers can use independent of the
 local storage mechanism :-)

 

 It may be the case that we want to only provide acquireScopedLock (or
 something like it) to enforce fine grained locking, but I think that would
 only force people to implement long-lived locks by setting a field in
 LocalStorage.  That would then result in the locks not being managed by the
 UA, which means that they cannot be reliably cleaned up when the page
 closes.  I think it is very important that we provide facilities to guide
 people away from building such ad-hoc locks on top of LocalStorage.  This is
 why I like the explicit (non-blocking!) acquireLock and releaseLock methods.

 -Darin



Re: [whatwg] Application defined locks

2009-09-09 Thread Aaron Boodman
On Wed, Sep 9, 2009 at 10:55 AM, Darin Fisherda...@chromium.org wrote:
 I imagine a simple lock API:
 window.acquireLock(name)
 window.releaseLock(name)

I do not think it is a good idea to allow long-lived (past a stack
frame) locks on the types of things we've been discussing (local
storage, databases, etc).

 This API seems like it could be used to allow LocalStorage to be usable from
 workers.  Also, as we start developing other means of local storage (File
 APIs), it seems like having to again invent a reasonable implicit locking
 system will be a pain.  Perhaps it would just be better to develop something
 explicit that application developers can use independent of the local
 storage mechanism :-)

There would presumably have to be a separate name value for each API,
though, right? So we're talking about the difference between:

window.acquireLock(localStorage, function() {
...
});

and:

window.acquireLocalStorage(function() {
...
});

It doesn't seem like much of a win for reusability IMO.

 It may be the case that we want to only provide acquireScopedLock (or
 something like it) to enforce fine grained locking, but I think that would
 only force people to implement long-lived locks by setting a field in
 LocalStorage.

Do you have an example of a place where we want to allow long-lived locks?

- a


Re: [whatwg] Application defined locks

2009-09-09 Thread Darin Fisher
On Wed, Sep 9, 2009 at 11:08 AM, Aaron Boodman a...@google.com wrote:

 On Wed, Sep 9, 2009 at 10:55 AM, Darin Fisherda...@chromium.org wrote:
  I imagine a simple lock API:
  window.acquireLock(name)
  window.releaseLock(name)

 I do not think it is a good idea to allow long-lived (past a stack
 frame) locks on the types of things we've been discussing (local
 storage, databases, etc).

  This API seems like it could be used to allow LocalStorage to be usable
 from
  workers.  Also, as we start developing other means of local storage (File
  APIs), it seems like having to again invent a reasonable implicit locking
  system will be a pain.  Perhaps it would just be better to develop
 something
  explicit that application developers can use independent of the local
  storage mechanism :-)

 There would presumably have to be a separate name value for each API,
 though, right? So we're talking about the difference between:

 window.acquireLock(localStorage, function() {
 ...
 });

 and:

 window.acquireLocalStorage(function() {
 ...
 });

 It doesn't seem like much of a win for reusability IMO.


I wanted to leave it up to the app developer to choose the name so that they
could define how the lock is interpreted.

For example, they might want to partition the keyspace for local storage and
have separate locks for separate keys.  Or, they might want to have a single
lock that is inclusive of several storage mechanisms: LocalStorage and
FileAPI.

Besides, once we have an explicit locking API, why not just be generic and
give it a name divorced from LocalStorage or any kind of storage features
for that matter?  Locking can be useful to other applications that do not
even use local storage...




  It may be the case that we want to only provide acquireScopedLock (or
  something like it) to enforce fine grained locking, but I think that
 would
  only force people to implement long-lived locks by setting a field in
  LocalStorage.

 Do you have an example of a place where we want to allow long-lived locks?



It is important to think of these differently from normal mutexes that you
might program with in C++.  Maybe I should have used the term flag instead
of lock ;-)

You might use a long lived lock to indicate that you are the instance
responsible for X.  I can imagine applications where there could be a master
/ slave relationships between the instances.  One instance is the master and
the rest are the slaves.

If we only had fine grained locking, then we are saying that we want
simulaneous instances of the same web app to be able to stop on each others
data in LocalStorage.  Instead, a web app developer might want to disable
LocalStorage features in all but the first instance of their web app.  The
problem is that your state is held not just in LocalStorage but also in JS
variables, the DOM, and perhaps in session state held by the server.  It is
easy for LocalStorage to get corrupted even with proper fine-grained
locking.  You still need a way to have a big flag that says... hey, i'm
the one messing with LocalStorage.  A good example is the browser's profile
directory.  Chrome and Firefox both only allow one instance of the app per
profile.  A long-lived lock is held to support such behavior.

I suspect there is some overlap with my proposal and shared workers.
 Perhaps what I am trying to accomplish here could even be implemented on
top of shared workers, although using shared workers to achieve mutual
exclusion locks seems rather heavyweight.

-Darin


Re: [whatwg] Application defined locks

2009-09-09 Thread Aaron Boodman
On Wed, Sep 9, 2009 at 11:23 AM, Darin Fisherda...@chromium.org wrote:
 On Wed, Sep 9, 2009 at 11:08 AM, Aaron Boodman a...@google.com wrote:
 There would presumably have to be a separate name value for each API,
 though, right? So we're talking about the difference between:

 window.acquireLock(localStorage, function() {
 ...
 });

 and:

 window.acquireLocalStorage(function() {
 ...
 });

 It doesn't seem like much of a win for reusability IMO.

 I wanted to leave it up to the app developer to choose the name so that they
 could define how the lock is interpreted.
 For example, they might want to partition the keyspace for local storage and
 have separate locks for separate keys.  Or, they might want to have a single
 lock that is inclusive of several storage mechanisms: LocalStorage and
 FileAPI.
 Besides, once we have an explicit locking API, why not just be generic and
 give it a name divorced from LocalStorage or any kind of storage features
 for that matter?  Locking can be useful to other applications that do not
 even use local storage...

I see.

So you are suggesting the localStorage could have zero concurrency
guarantees and it is simply up to the developer to arrange things
themselves using this new primitive.

That is an interesting idea. You're right that it overlaps with the
ideas that inspired shared workers, and the global script proposal.

- a


Re: [whatwg] Application defined locks

2009-09-09 Thread Darin Fisher
On Wed, Sep 9, 2009 at 11:30 AM, Aaron Boodman a...@google.com wrote:

 On Wed, Sep 9, 2009 at 11:23 AM, Darin Fisherda...@chromium.org wrote:
  On Wed, Sep 9, 2009 at 11:08 AM, Aaron Boodman a...@google.com wrote:
  There would presumably have to be a separate name value for each API,
  though, right? So we're talking about the difference between:
 
  window.acquireLock(localStorage, function() {
  ...
  });
 
  and:
 
  window.acquireLocalStorage(function() {
  ...
  });
 
  It doesn't seem like much of a win for reusability IMO.
 
  I wanted to leave it up to the app developer to choose the name so that
 they
  could define how the lock is interpreted.
  For example, they might want to partition the keyspace for local storage
 and
  have separate locks for separate keys.  Or, they might want to have a
 single
  lock that is inclusive of several storage mechanisms: LocalStorage and
  FileAPI.
  Besides, once we have an explicit locking API, why not just be generic
 and
  give it a name divorced from LocalStorage or any kind of storage features
  for that matter?  Locking can be useful to other applications that do not
  even use local storage...

 I see.

 So you are suggesting the localStorage could have zero concurrency
 guarantees and it is simply up to the developer to arrange things
 themselves using this new primitive.


Yes, exactly. Sorry for not making this clear.  I believe implicit locking
for LocalStorage (and the implicit unlocking) is going to yield something
very confusing and hard to implement well.  The potential for dead locks
when you fail to implicitly unlock properly scares me.

-Darin




 That is an interesting idea. You're right that it overlaps with the
 ideas that inspired shared workers, and the global script proposal.

 - a



Re: [whatwg] Application defined locks

2009-09-09 Thread Maciej Stachowiak


On Sep 9, 2009, at 10:55 AM, Darin Fisher wrote:

The recent discussion about the storage mutex for Cookies and  
LocalStorage got me thinking


Perhaps instead of trying to build implicit locking into those  
features, we should give web apps the tools to manage exclusive  
access to shared resources.


I'm really hesitant to expose explicit locking to the Web platform.  
Mutexes are incredibly hard to program with correctly, and we will  
surely end up with stuck locks, race conditions, livelocks, and so  
forth. For Workers I was happy that we managed to avoid any locking  
primitives by using a message-passing model, but explicit mutexes  
would ruin that.


 - Maciej





I imagine a simple lock API:

window.acquireLock(name)
window.releaseLock(name)

acquireLock works like pthread_mutex_trylock in that it is non- 
blocking.  it returns true if you succeeded in acquiring the lock,  
else it returns false.  releaseLock does as its name suggests:  
releases the lock so that others may acquire it.


Any locks acquired would be automatically released when the DOM  
window is destroyed or navigated cross origin.  This API could also  
be supported by workers.


The name parameter is scoped to the origin of the page.  So, this  
locking API only works between pages in the same origin.




We could also extend acquireLock to support an asynchronous callback  
when the lock becomes available:


window.acquireLock(name, function() { /* lock acquired */ });

If the callback function is given, then upon lock acquisition, the  
callback function would be invoked.  In this case, the return value  
of acquireLock is true if the function was invoked or false if the  
function will be invoked once the lock can be acquired.




Finally, there could be a helper for scoping lock acquisition:

window.acquireScopedLock(name, function() { /* lock acquired for  
this scope only */ });




This lock API would provide developers with the ability to indicate  
that their instance of the web app is the only one that should play  
with LocalStorage.  Other instances could then know that they don't  
have exclusive access and could take appropriate action.


This API seems like it could be used to allow LocalStorage to be  
usable from workers.  Also, as we start developing other means of  
local storage (File APIs), it seems like having to again invent a  
reasonable implicit locking system will be a pain.  Perhaps it would  
just be better to develop something explicit that application  
developers can use independent of the local storage mechanism :-)




It may be the case that we want to only provide acquireScopedLock  
(or something like it) to enforce fine grained locking, but I think  
that would only force people to implement long-lived locks by  
setting a field in LocalStorage.  That would then result in the  
locks not being managed by the UA, which means that they cannot be  
reliably cleaned up when the page closes.  I think it is very  
important that we provide facilities to guide people away from  
building such ad-hoc locks on top of LocalStorage.  This is why I  
like the explicit (non-blocking!) acquireLock and releaseLock methods.


-Darin




Re: [whatwg] Application defined locks

2009-09-09 Thread Darin Fisher
On Wed, Sep 9, 2009 at 3:37 PM, Maciej Stachowiak m...@apple.com wrote:


 On Sep 9, 2009, at 10:55 AM, Darin Fisher wrote:

  The recent discussion about the storage mutex for Cookies and LocalStorage
 got me thinking

 Perhaps instead of trying to build implicit locking into those features,
 we should give web apps the tools to manage exclusive access to shared
 resources.


 I'm really hesitant to expose explicit locking to the Web platform. Mutexes
 are incredibly hard to program with correctly, and we will surely end up
 with stuck locks, race conditions, livelocks, and so forth. For Workers I
 was happy that we managed to avoid any locking primitives by using a
 message-passing model, but explicit mutexes would ruin that.

  - Maciej



Note: I probably made a mistake calling these locks since they do not work
like normal mutexes.  You can only wait for one of these locks
asynchronously.  There is no synchronous blocking, which avoids most of the
problems you mention.  Also, the locks are cleared when the page is
destroyed or navigated to another domain, so you lose the problem of stuck
locks.

What motivated this was that I wanted the ability to simulate the database
transaction model.  Since we support that, we might as well support a
similar system that is independent of a particular storage mechanism.  Seems
reasonable to me.

Alternatively, if we had a way to set a value in local storage and read the
value that was there, then a web page could implement a flag to indicate
mutual exclusion. Someone interested in acquiring a flag could wait for a
storage event to indicate that the flag was cleared.  However, what is
missing is that there isn't a way for the flag to be auto-cleared when the
DOM window is closed or navigated to another domain.

-Darin





 

 I imagine a simple lock API:

 window.acquireLock(name)
 window.releaseLock(name)

 acquireLock works like pthread_mutex_trylock in that it is non-blocking.
  it returns true if you succeeded in acquiring the lock, else it returns
 false.  releaseLock does as its name suggests: releases the lock so that
 others may acquire it.

 Any locks acquired would be automatically released when the DOM window is
 destroyed or navigated cross origin.  This API could also be supported by
 workers.

 The name parameter is scoped to the origin of the page.  So, this locking
 API only works between pages in the same origin.

 

 We could also extend acquireLock to support an asynchronous callback when
 the lock becomes available:

 window.acquireLock(name, function() { /* lock acquired */ });

 If the callback function is given, then upon lock acquisition, the
 callback function would be invoked.  In this case, the return value of
 acquireLock is true if the function was invoked or false if the function
 will be invoked once the lock can be acquired.

 

 Finally, there could be a helper for scoping lock acquisition:

 window.acquireScopedLock(name, function() { /* lock acquired for this
 scope only */ });

 

 This lock API would provide developers with the ability to indicate that
 their instance of the web app is the only one that should play with
 LocalStorage.  Other instances could then know that they don't have
 exclusive access and could take appropriate action.

 This API seems like it could be used to allow LocalStorage to be usable
 from workers.  Also, as we start developing other means of local storage
 (File APIs), it seems like having to again invent a reasonable implicit
 locking system will be a pain.  Perhaps it would just be better to develop
 something explicit that application developers can use independent of the
 local storage mechanism :-)

 

 It may be the case that we want to only provide acquireScopedLock (or
 something like it) to enforce fine grained locking, but I think that would
 only force people to implement long-lived locks by setting a field in
 LocalStorage.  That would then result in the locks not being managed by the
 UA, which means that they cannot be reliably cleaned up when the page
 closes.  I think it is very important that we provide facilities to guide
 people away from building such ad-hoc locks on top of LocalStorage.  This is
 why I like the explicit (non-blocking!) acquireLock and releaseLock methods.

 -Darin





Re: [whatwg] Application defined locks

2009-09-09 Thread Robert O'Callahan
On Thu, Sep 10, 2009 at 6:37 AM, Darin Fisher da...@chromium.org wrote:

 Yes, exactly. Sorry for not making this clear.  I believe implicit locking
 for LocalStorage (and the implicit unlocking) is going to yield something
 very confusing and hard to implement well.  The potential for dead locks
 when you fail to implicitly unlock properly scares me


You mean when the browser implementation has a bug and fails to implicitly
unlock?

Giving Web authors the crappy race-prone and deadlock-prone locking
programming model scares *me*. Yes, your acquireLock can't get you into a
hard deadlock, strictly speaking, but you can still effectively deadlock
your application by waiting for a lock to become available that never can.
Also, how many authors will forget to test the result of acquireLock
(because they're used to other locking APIs that block) and find that things
are OK in their testing?

I think we should be willing to accept a very high implementation burden on
browser vendors in exchange for minimizing the burden on Web authors. Now,
if we find that authors are needing to build explicit locks using
localStorage, we should figure out their use-cases and see what a better
solution for those use-cases might be, instead of giving them a more
convenient way to endanger themselves.

Rob
-- 
He was pierced for our transgressions, he was crushed for our iniquities;
the punishment that brought us peace was upon him, and by his wounds we are
healed. We all, like sheep, have gone astray, each of us has turned to his
own way; and the LORD has laid on him the iniquity of us all. [Isaiah
53:5-6]


Re: [whatwg] Application defined locks

2009-09-09 Thread Olli Pettay

On 9/10/09 2:24 AM, Robert O'Callahan wrote:

On Thu, Sep 10, 2009 at 6:37 AM, Darin Fisher da...@chromium.org
mailto:da...@chromium.org wrote:

Yes, exactly. Sorry for not making this clear.  I believe implicit
locking for LocalStorage (and the implicit unlocking) is going to
yield something very confusing and hard to implement well.  The
potential for dead locks when you fail to implicitly unlock properly
scares me

You mean when the browser implementation has a bug and fails to
implicitly unlock?

Giving Web authors the crappy race-prone and deadlock-prone locking
programming model scares *me*. Yes, your acquireLock can't get you into
a hard deadlock, strictly speaking, but you can still effectively
deadlock your application by waiting for a lock to become available that
never can. Also, how many authors will forget to test the result of
acquireLock (because they're used to other locking APIs that block) and
find that things are OK in their testing?

If you're concerned about that, make acquireLock to throw an exception.
Authors sure will notice that things aren't quite right, if the flag
isn't acquired.
And if the acquireLock(flag, callback) approach is used, it is
harder to make the mistake to not check whether the flag was really got.

As you said on IRC, perhaps there should be a way to acquire
many flags at once and then call the callback.


-Olli





Re: [whatwg] Application defined locks

2009-09-09 Thread Jeremy Orlow
In general this seems like a pretty interesting idea.  It definitely would
be nice to completely abstract away all concepts of concurrency from web
developers, but some of our solutions thus far (message passing, async
interfaces, etc) have not been terribly appreciated by developers either.
 The GlobalScript proposal is a good example: to us, shared workers were an
adequate solution, but in practice the lack of shared state is very
difficult for some developers to work around.  Possibly even more difficult
than dealing with some levels of concurrency.

I think it'd be interesting to introduce this as an experimental API and see
what web developers do with it.


As for the idea of a sync API:  What if some library/framework and the
embedding page use these flags/locks?  I know you can't actually deadlock
with this API, but I worry some developers will just do
|while(!acquireLock(flag)) {}| which could lead to deadlocks.  Only
allowing an async API would fix this, but developers have typically not
liked async APIs.

Here's another idea that I think is actually kind of cool:  What if we kept
track of locking precedence (i.e. the graph of which locks have been taken
while other locks were held) and threw an exception if any lock was ever
taken in a way that violated the graph.  In other words, we wouldn't make
the developer tell us the locking precedence, and we wouldn't wait until you
hit an actual deadlock.  Instead we would look for the first call site that
_could_ have deadlocked.  A long time ago, I was working on a project that
had some deadlock problems.  We implemented exactly this and it worked
pretty well.


On Thu, Sep 10, 2009 at 9:22 AM, Olli Pettay olli.pet...@helsinki.fiwrote:

 On 9/10/09 2:24 AM, Robert O'Callahan wrote:

 On Thu, Sep 10, 2009 at 6:37 AM, Darin Fisher da...@chromium.org
 mailto:da...@chromium.org wrote:

Yes, exactly. Sorry for not making this clear.  I believe implicit
locking for LocalStorage (and the implicit unlocking) is going to
yield something very confusing and hard to implement well.  The
potential for dead locks when you fail to implicitly unlock properly
scares me

 You mean when the browser implementation has a bug and fails to
 implicitly unlock?

 Giving Web authors the crappy race-prone and deadlock-prone locking
 programming model scares *me*. Yes, your acquireLock can't get you into
 a hard deadlock, strictly speaking, but you can still effectively
 deadlock your application by waiting for a lock to become available that
 never can. Also, how many authors will forget to test the result of
 acquireLock (because they're used to other locking APIs that block) and
 find that things are OK in their testing?

 If you're concerned about that, make acquireLock to throw an exception.
 Authors sure will notice that things aren't quite right, if the flag
 isn't acquired.
 And if the acquireLock(flag, callback) approach is used, it is
 harder to make the mistake to not check whether the flag was really got.


This seems like a good idea.

As you said on IRC, perhaps there should be a way to acquire
 many flags at once and then call the callback.


I like this idea as well.


Re: [whatwg] Application defined locks

2009-09-09 Thread Aaron Boodman
On Wed, Sep 9, 2009 at 11:30 AM, Aaron Boodmana...@google.com wrote:
 I see.

 So you are suggesting the localStorage could have zero concurrency
 guarantees and it is simply up to the developer to arrange things
 themselves using this new primitive.

 That is an interesting idea. You're right that it overlaps with the
 ideas that inspired shared workers, and the global script proposal.

Ok, after thinking about this for a day, I'm going to say I think this
is a very cool idea, and a worthwhile addition, but I don't think it
should substitute for having the local storage API work correctly by
default.

The web platform is supposed to work for developers of all experience
levels. If we make local storage have no concurrency guarantees, it
will seem like it works in the overwhelming majority of cases. It will
work in all SELUAs, and it will only NOT work in MELUAs in cases that
are basically impossible to test, let alone see during development.

We have tried hard with the design of the web platform to avoid these
sort of untestable non-deterministic scenarios, and I think it is to
the overall value of the platform to continue this.

Therefore, my position continues to be that to access local storage,
there should be an API that asynchronously acquires exclusive access
to storage.

- a


Re: [whatwg] RFC: Alternatives to storage mutex for cookies and localStorage

2009-09-09 Thread Jeremy Orlow
On Thu, Sep 10, 2009 at 1:59 AM, Chris Jones cjo...@mozilla.com wrote:

 Jeremy Orlow wrote:

 What failures could there be in a pesimistic/queue model?


 I'm trying to think of a universal failure, something that could arise in
 any implementation of any proposal.  I think that universal failure is
 exceeded localStorage space quota.  (I believe there are others, but one
 is enough for this discussion.)

 So there are really two questions: first, what happens if you detect quota
 exceeded in the middle of a localStorage.transaction() callback?  Are the
 modifications made *up to* the quota exceeded error applied to backing
 store?  Or are they rolled back?  This is the atomicity/consistency design
 decision I described: what is the unit of atomic modification (all applied
 or none applied).

 And second, can scripts be notified that the transaction failed (or was
 only partially applied) because of quota exceeded?

 AFAICT this is irrespective of sync/async/optimistic/pessimistic/queue.
  Any implementation has to deal with this error somehow.

 In the current localStorage spec, if a setItem() fails because space is
 exhausted, it raises QUOTA_EXCEEDED_ERR and does *not* apply any part of the
 change in setItem().  That is, setItem() is atomic --- it either applies or
 not (not partially applied).  But modifications to localStorage *before*
 that failing setItem(), within the same storage mutex acquire/release set,
 *are* applied to backing store.

 In the Web Database spec, if executing a SQL statement in a Transaction
 would cause space quota to be exceeded, then *none* of the statements in the
 transaction are executed (i.e. none committed to backing store), and the
 Transaction fails with QUOTA_ERR.  The unit of atomicity for Web Database is
 that Transaction object --- either all statements in Transaction
 successfully execute or none do.

 I'm not sure whether you're proposing that modifications within a
 localStorage.transaction() callback are atomic (all applied or none applied)
 in the face of quota exceeded.  (I'm proposing that they *should* be
 atomic.)

 It sounds like you're proposing that scripts *cannot* be notified of quota
 exceeded.  If this is true, then there are some semantic issues I'd like to
 discuss.  But I want to make sure we're on the same page first :).  (I'm
 proposing that scripts *should* be able to be notified of this.)


The way it works right now is that an exception is thrown and that's it.  I
think it'd be perfectly acceptable for the behavior to remain, even if it's
inside a transaction.  In other words, I don't think the transaction
necessarily needs to stop or anything.  I think most app developers will
want to explicitly handle out of space errors (they're not just going to go
away on their own), but probably won't want to explicitly deal with
transient errors (like what you can see with optimistic transactions).

I don't think quota errors should be grouped in with any atomicity
guarantees, in other words.

Are there any other examples of failures you can have within a pessimistic
transaction?


Re: [whatwg] Application defined locks

2009-09-09 Thread Michael Nordman
If this feature existed, we likely would have used it for offline Gmail to
coordinate which instance of the app (page with gmail in it) should be
responsible for sync'ing the local database with the mail service. In the
absence of a feature like this, instead we used the local database itself to
register which page was the 'syncagent'. This involved periodically updating
the db by the syncagent, and periodic polling by the would be syncagents
waiting to possibly take over. Much ugliness.
var isSyncAgent = false;
window.acquireFlag(syncAgency, function() { isSyncAgent = true; });

Much nicer.


On Wed, Sep 9, 2009 at 7:02 PM, Maciej Stachowiak m...@apple.com wrote:


 On Sep 9, 2009, at 6:33 PM, Jeremy Orlow wrote:

 In general this seems like a pretty interesting idea.  It definitely would
 be nice to completely abstract away all concepts of concurrency from web
 developers, but some of our solutions thus far (message passing, async
 interfaces, etc) have not been terribly appreciated by developers either.
  The GlobalScript proposal is a good example: to us, shared workers were an
 adequate solution, but in practice the lack of shared state is very
 difficult for some developers to work around.  Possibly even more difficult
 than dealing with some levels of concurrency.

 I think it'd be interesting to introduce this as an experimental API and
 see what web developers do with it.


 I think it's predictable that it will be used in badly wrong ways without
 implementing it. Explicit application-managed locking is a massive failure
 as a mechanism for managing concurrency.

 As for the idea of a sync API:  What if some library/framework and the
 embedding page use these flags/locks?  I know you can't actually deadlock
 with this API, but I worry some developers will just do
 |while(!acquireLock(flag)) {}| which could lead to deadlocks.  Only
 allowing an async API would fix this, but developers have typically not
 liked async APIs.


 If we want to go async, then I'd rather have an asynchronous way to acquire
 an *actual* lock on the resource (as with the LocalStorage async transaction
 proposal), than an async advisory locking model. Having both asynchronicity
 *and* advisory locks seems like the worst of both worlds.

 On the other hand, if we offer only the equivalent of tryLock() and not a
 blocking lock(), it's almost certain Web apps will build spin locks in the
 way you describe, leading to wasteful CPU usage, bad performance, and the
 possibility of deadlocks.



 Here's another idea that I think is actually kind of cool:  What if we kept
 track of locking precedence (i.e. the graph of which locks have been taken
 while other locks were held) and threw an exception if any lock was ever
 taken in a way that violated the graph.  In other words, we wouldn't make
 the developer tell us the locking precedence, and we wouldn't wait until you
 hit an actual deadlock.  Instead we would look for the first call site that
 _could_ have deadlocked.  A long time ago, I was working on a project that
 had some deadlock problems.  We implemented exactly this and it worked
 pretty well.


 This seems like a very challenging programming model for little gain. If
 the locks are purely advisory, they do not prevent race conditions, but a
 discipline to prevent deadlocks will still make them very hard to use. Note
 also that the possibility of synchronous cross-site code execution would
 require a lock precedence graph to be cross-site to really prevent
 deadlocks, but it would be impossible for a Web application to guarantee
 anything about lock order with respect to Web apps in different origins. The
 other possibility is to drop all locks in the case of synchronous
 cross-origin code execution, but then these advisory locks would not even be
 useful for preventing race conditions.

 Locking is broken - just don't do it.

 Regards,
 Maciej




 On Thu, Sep 10, 2009 at 9:22 AM, Olli Pettay olli.pet...@helsinki.fiwrote:

 On 9/10/09 2:24 AM, Robert O'Callahan wrote:

 On Thu, Sep 10, 2009 at 6:37 AM, Darin Fisher da...@chromium.org
 mailto:da...@chromium.org wrote:

Yes, exactly. Sorry for not making this clear.  I believe implicit
locking for LocalStorage (and the implicit unlocking) is going to
yield something very confusing and hard to implement well.  The
potential for dead locks when you fail to implicitly unlock properly
scares me

 You mean when the browser implementation has a bug and fails to
 implicitly unlock?

 Giving Web authors the crappy race-prone and deadlock-prone locking
 programming model scares *me*. Yes, your acquireLock can't get you into
 a hard deadlock, strictly speaking, but you can still effectively
 deadlock your application by waiting for a lock to become available that
 never can. Also, how many authors will forget to test the result of
 acquireLock (because they're used to other locking APIs that block) and
 find that things are OK in their testing?

 If you're 

Re: [whatwg] Application defined locks

2009-09-09 Thread Robert O'Callahan
On Thu, Sep 10, 2009 at 1:33 PM, Jeremy Orlow jor...@chromium.org wrote:

 In general this seems like a pretty interesting idea.  It definitely would
 be nice to completely abstract away all concepts of concurrency from web
 developers, but some of our solutions thus far (message passing, async
 interfaces, etc) have not been terribly appreciated by developers either.


You have to be careful with developer feedback. Developers inexperienced
with pthread-style threads-and-locks typically like the model, since it's a
simple abstraction that *superficially* appears to map easily onto their
existing sequential code (e.g. because they can carry on using lots of
shared state). It's not until you get more experienced with it in a large
system that you really feel the pain, and appreciate why an apparently more
restrictive model might work better.

Rob
-- 
He was pierced for our transgressions, he was crushed for our iniquities;
the punishment that brought us peace was upon him, and by his wounds we are
healed. We all, like sheep, have gone astray, each of us has turned to his
own way; and the LORD has laid on him the iniquity of us all. [Isaiah
53:5-6]


Re: [whatwg] Application defined locks

2009-09-09 Thread Robert O'Callahan
On Thu, Sep 10, 2009 at 2:38 PM, Michael Nordman micha...@google.comwrote:

 If this feature existed, we likely would have used it for offline Gmail to
 coordinate which instance of the app (page with gmail in it) should be
 responsible for sync'ing the local database with the mail service. In the
 absence of a feature like this, instead we used the local database itself to
 register which page was the 'syncagent'. This involved periodically updating
 the db by the syncagent, and periodic polling by the would be syncagents
 waiting to possibly take over. Much ugliness.
 var isSyncAgent = false;
 window.acquireFlag(syncAgency, function() { isSyncAgent = true; });

 Much nicer.


How do you deal with the user closing the syncagent while other app
instances remain open?

Rob
-- 
He was pierced for our transgressions, he was crushed for our iniquities;
the punishment that brought us peace was upon him, and by his wounds we are
healed. We all, like sheep, have gone astray, each of us has turned to his
own way; and the LORD has laid on him the iniquity of us all. [Isaiah
53:5-6]


Re: [whatwg] Application defined locks

2009-09-09 Thread Darin Fisher
On Wed, Sep 9, 2009 at 4:24 PM, Robert O'Callahan rob...@ocallahan.orgwrote:

 On Thu, Sep 10, 2009 at 6:37 AM, Darin Fisher da...@chromium.org wrote:

 Yes, exactly. Sorry for not making this clear.  I believe implicit locking
 for LocalStorage (and the implicit unlocking) is going to yield something
 very confusing and hard to implement well.  The potential for dead locks
 when you fail to implicitly unlock properly scares me


 You mean when the browser implementation has a bug and fails to implicitly
 unlock?


What concerns me are the cases where synchronous events (e.g., resizing an
iframe) can cause script to execute in another domain.  As spec'd, there is
a potential dead lock with the storage mutex.  We must carefully unlock in
situations like this.  However, such unlocking will appear quite mysterious
to users, so much so that I question the value of the implicit storage
mutex.

That led me down this path of imagining a more explicit locking mechanism
that would give the app control over how local storage is protected.

I agree that explicit locking can be a big dangerous hammer, but that's why
I tried to soften it by removing blocking behavior.




 Giving Web authors the crappy race-prone and deadlock-prone locking
 programming model scares *me*.


Me too.  I don't believe that I'm proposing such an API.



 Yes, your acquireLock can't get you into a hard deadlock, strictly
 speaking, but you can still effectively deadlock your application by waiting
 for a lock to become available that never can.


Sure, but at least the thread of execution isn't blocked, and the user can
recover by closing the tab or what have you.  By the way, you can already
pretty much create my acquireLock / releaseLock API on top of SharedWorkers
today, but in a slightly crappier way.  Are SharedWorkers problematic
because of this?  I don't think so.



 Also, how many authors will forget to test the result of acquireLock
 (because they're used to other locking APIs that block) and find that things
 are OK in their testing?


Perhaps the API could be different.  Perhaps the name lock is part of the
problem.




 I think we should be willing to accept a very high implementation burden on
 browser vendors in exchange for minimizing the burden on Web authors.


Yes, I wholeheartedly agree.  Note: my concern is that there is no good
implementation for the storage mutex.  Implicitly dropping it at weird times
is not a good answer.

-Darin


Re: [whatwg] Application defined locks

2009-09-09 Thread Robert O'Callahan
On Thu, Sep 10, 2009 at 3:53 PM, Darin Fisher da...@chromium.org wrote:

 What concerns me are the cases where synchronous events (e.g., resizing an
 iframe) can cause script to execute in another domain.  As spec'd, there is
 a potential dead lock with the storage mutex.  We must carefully unlock in
 situations like this.  However, such unlocking will appear quite mysterious
 to users, so much so that I question the value of the implicit storage
 mutex.


Right now I'm not sure how big a problem this actually is. The resize event
for a document in a frame can surely be dispatched asynchronously so no
unlocking is required. I would like to have a much better idea of how many
places absolutely must release the storage mutex before deciding that
approach is unworkable.

Rob
-- 
He was pierced for our transgressions, he was crushed for our iniquities;
the punishment that brought us peace was upon him, and by his wounds we are
healed. We all, like sheep, have gone astray, each of us has turned to his
own way; and the LORD has laid on him the iniquity of us all. [Isaiah
53:5-6]


Re: [whatwg] Application defined locks

2009-09-09 Thread Darin Fisher
On Wed, Sep 9, 2009 at 9:07 PM, Robert O'Callahan rob...@ocallahan.orgwrote:

 On Thu, Sep 10, 2009 at 3:53 PM, Darin Fisher da...@chromium.org wrote:

 What concerns me are the cases where synchronous events (e.g., resizing an
 iframe) can cause script to execute in another domain.  As spec'd, there is
 a potential dead lock with the storage mutex.  We must carefully unlock in
 situations like this.  However, such unlocking will appear quite mysterious
 to users, so much so that I question the value of the implicit storage
 mutex.


 Right now I'm not sure how big a problem this actually is. The resize event
 for a document in a frame can surely be dispatched asynchronously so no
 unlocking is required. I would like to have a much better idea of how many
 places absolutely must release the storage mutex before deciding that
 approach is unworkable.

 Rob



What about navigating an iframe to a reference fragment, which could trigger
a scroll event?  The scrolling has to be done synchronously for compat with
the web.

-Darin


Re: [whatwg] Application defined locks

2009-09-09 Thread Darin Fisher
On Wed, Sep 9, 2009 at 6:46 PM, Aaron Boodman a...@google.com wrote:

 On Wed, Sep 9, 2009 at 11:30 AM, Aaron Boodmana...@google.com wrote:
  I see.
 
  So you are suggesting the localStorage could have zero concurrency
  guarantees and it is simply up to the developer to arrange things
  themselves using this new primitive.
 
  That is an interesting idea. You're right that it overlaps with the
  ideas that inspired shared workers, and the global script proposal.

 Ok, after thinking about this for a day, I'm going to say I think this
 is a very cool idea, and a worthwhile addition, but I don't think it
 should substitute for having the local storage API work correctly by
 default.

 The web platform is supposed to work for developers of all experience
 levels. If we make local storage have no concurrency guarantees, it
 will seem like it works in the overwhelming majority of cases. It will
 work in all SELUAs, and it will only NOT work in MELUAs in cases that
 are basically impossible to test, let alone see during development.

 We have tried hard with the design of the web platform to avoid these
 sort of untestable non-deterministic scenarios, and I think it is to
 the overall value of the platform to continue this.

 Therefore, my position continues to be that to access local storage,
 there should be an API that asynchronously acquires exclusive access
 to storage.

 - a



Yeah, if you had to call an API that asynchronously acquires exclusive
access
to storage, then I believe that would nicely address most of the issues.  It
is the
solution we have for database transactions.

I say most because I'm not sure that it eliminates the need to drop the
storage
mutex in the showModalDialog case.

If I call showModalDialog from within a database transaction, and then
showModalDialog
tries to create another database transaction, should I expect that the
transaction
can be started within the nested run loop of the modal dialog?  If not, then
it may cause
the app to get confused and never allow the dialog to be closed (e.g.,
perhaps the close
action is predicated on a database query.)

Nested loops suck.  showModalDialog sucks :-)

-Darin


Re: [whatwg] Application defined locks

2009-09-09 Thread Jeremy Orlow
On Thu, Sep 10, 2009 at 1:13 PM, Darin Fisher da...@chromium.org wrote:

 On Wed, Sep 9, 2009 at 6:46 PM, Aaron Boodman a...@google.com wrote:

 On Wed, Sep 9, 2009 at 11:30 AM, Aaron Boodmana...@google.com wrote:
  I see.
 
  So you are suggesting the localStorage could have zero concurrency
  guarantees and it is simply up to the developer to arrange things
  themselves using this new primitive.
 
  That is an interesting idea. You're right that it overlaps with the
  ideas that inspired shared workers, and the global script proposal.

 Ok, after thinking about this for a day, I'm going to say I think this
 is a very cool idea, and a worthwhile addition, but I don't think it
 should substitute for having the local storage API work correctly by
 default.

 The web platform is supposed to work for developers of all experience
 levels. If we make local storage have no concurrency guarantees, it
 will seem like it works in the overwhelming majority of cases. It will
 work in all SELUAs, and it will only NOT work in MELUAs in cases that
 are basically impossible to test, let alone see during development.

 We have tried hard with the design of the web platform to avoid these
 sort of untestable non-deterministic scenarios, and I think it is to
 the overall value of the platform to continue this.

 Therefore, my position continues to be that to access local storage,
 there should be an API that asynchronously acquires exclusive access
 to storage.

 - a



 Yeah, if you had to call an API that asynchronously acquires exclusive
 access
 to storage, then I believe that would nicely address most of the issues.
  It is the
 solution we have for database transactions.

 I say most because I'm not sure that it eliminates the need to drop the
 storage
 mutex in the showModalDialog case.

 If I call showModalDialog from within a database transaction, and then
 showModalDialog
 tries to create another database transaction, should I expect that the
 transaction
 can be started within the nested run loop of the modal dialog?  If not,
 then it may cause
 the app to get confused and never allow the dialog to be closed (e.g.,
 perhaps the close
 action is predicated on a database query.)

 Nested loops suck.  showModalDialog sucks :-)


We could just disallow showModalDialog and any other trouble APIs like that
during localStorage and database transactions.  Doing so seems better than
silently dropping transactional semantics.


Re: [whatwg] Application defined locks

2009-09-09 Thread Robert O'Callahan
On Thu, Sep 10, 2009 at 4:11 PM, Darin Fisher da...@chromium.org wrote:

 On Wed, Sep 9, 2009 at 9:07 PM, Robert O'Callahan rob...@ocallahan.orgwrote:

 On Thu, Sep 10, 2009 at 3:53 PM, Darin Fisher da...@chromium.org wrote:

 What concerns me are the cases where synchronous events (e.g., resizing
 an iframe) can cause script to execute in another domain.  As spec'd, there
 is a potential dead lock with the storage mutex.  We must carefully unlock
 in situations like this.  However, such unlocking will appear quite
 mysterious to users, so much so that I question the value of the implicit
 storage mutex.


 Right now I'm not sure how big a problem this actually is. The resize
 event for a document in a frame can surely be dispatched asynchronously so
 no unlocking is required. I would like to have a much better idea of how
 many places absolutely must release the storage mutex before deciding that
 approach is unworkable.

 Rob


 What about navigating an iframe to a reference fragment, which could
 trigger a scroll event?  The scrolling has to be done synchronously for
 compat with the web.


The scrolling itself may have to be synchronous, at least as far as updating
scrollLeft/scrollTop if not visually ... but in this case the script
execution in the frame would be an onscroll event handler, right? That's
asynchronous in Gecko.

Rob
-- 
He was pierced for our transgressions, he was crushed for our iniquities;
the punishment that brought us peace was upon him, and by his wounds we are
healed. We all, like sheep, have gone astray, each of us has turned to his
own way; and the LORD has laid on him the iniquity of us all. [Isaiah
53:5-6]


Re: [whatwg] Application defined locks

2009-09-09 Thread Darin Fisher
On Wed, Sep 9, 2009 at 9:27 PM, Jeremy Orlow jor...@chromium.org wrote:

 On Thu, Sep 10, 2009 at 1:13 PM, Darin Fisher da...@chromium.org wrote:

 On Wed, Sep 9, 2009 at 6:46 PM, Aaron Boodman a...@google.com wrote:

 On Wed, Sep 9, 2009 at 11:30 AM, Aaron Boodmana...@google.com wrote:
  I see.
 
  So you are suggesting the localStorage could have zero concurrency
  guarantees and it is simply up to the developer to arrange things
  themselves using this new primitive.
 
  That is an interesting idea. You're right that it overlaps with the
  ideas that inspired shared workers, and the global script proposal.

 Ok, after thinking about this for a day, I'm going to say I think this
 is a very cool idea, and a worthwhile addition, but I don't think it
 should substitute for having the local storage API work correctly by
 default.

 The web platform is supposed to work for developers of all experience
 levels. If we make local storage have no concurrency guarantees, it
 will seem like it works in the overwhelming majority of cases. It will
 work in all SELUAs, and it will only NOT work in MELUAs in cases that
 are basically impossible to test, let alone see during development.

 We have tried hard with the design of the web platform to avoid these
 sort of untestable non-deterministic scenarios, and I think it is to
 the overall value of the platform to continue this.

 Therefore, my position continues to be that to access local storage,
 there should be an API that asynchronously acquires exclusive access
 to storage.

 - a



 Yeah, if you had to call an API that asynchronously acquires exclusive
 access
 to storage, then I believe that would nicely address most of the issues.
  It is the
 solution we have for database transactions.

 I say most because I'm not sure that it eliminates the need to drop the
 storage
 mutex in the showModalDialog case.

 If I call showModalDialog from within a database transaction, and then
 showModalDialog
 tries to create another database transaction, should I expect that the
 transaction
 can be started within the nested run loop of the modal dialog?  If not,
 then it may cause
 the app to get confused and never allow the dialog to be closed (e.g.,
 perhaps the close
 action is predicated on a database query.)

 Nested loops suck.  showModalDialog sucks :-)


 We could just disallow showModalDialog and any other trouble APIs like that
 during localStorage and database transactions.  Doing so seems better than
 silently dropping transactional semantics.



It may not be so easy to disallow showModalDialog.  Imagine if you script a
plugin inside the transaction, and before returning, the plugin scripts
another window, where it calls showModalDialog.  There could have been a
process hop there.

-Darin


Re: [whatwg] Application defined locks

2009-09-09 Thread Robert O'Callahan
On Thu, Sep 10, 2009 at 4:37 PM, Darin Fisher da...@chromium.org wrote:

  Imagine if you script a plugin inside the transaction, and before
 returning, the plugin scripts another window,


I'm curious, how common is that anyway? Can we just tell plugins not to do
that, and abort any plugin that tries?

Rob
-- 
He was pierced for our transgressions, he was crushed for our iniquities;
the punishment that brought us peace was upon him, and by his wounds we are
healed. We all, like sheep, have gone astray, each of us has turned to his
own way; and the LORD has laid on him the iniquity of us all. [Isaiah
53:5-6]


Re: [whatwg] Application defined locks

2009-09-09 Thread Jeremy Orlow
On Thu, Sep 10, 2009 at 1:37 PM, Darin Fisher da...@chromium.org wrote:

 On Wed, Sep 9, 2009 at 9:27 PM, Jeremy Orlow jor...@chromium.org wrote:

 On Thu, Sep 10, 2009 at 1:13 PM, Darin Fisher da...@chromium.org wrote:

 On Wed, Sep 9, 2009 at 6:46 PM, Aaron Boodman a...@google.com wrote:

 On Wed, Sep 9, 2009 at 11:30 AM, Aaron Boodmana...@google.com wrote:
  I see.
 
  So you are suggesting the localStorage could have zero concurrency
  guarantees and it is simply up to the developer to arrange things
  themselves using this new primitive.
 
  That is an interesting idea. You're right that it overlaps with the
  ideas that inspired shared workers, and the global script proposal.

 Ok, after thinking about this for a day, I'm going to say I think this
 is a very cool idea, and a worthwhile addition, but I don't think it
 should substitute for having the local storage API work correctly by
 default.

 The web platform is supposed to work for developers of all experience
 levels. If we make local storage have no concurrency guarantees, it
 will seem like it works in the overwhelming majority of cases. It will
 work in all SELUAs, and it will only NOT work in MELUAs in cases that
 are basically impossible to test, let alone see during development.

 We have tried hard with the design of the web platform to avoid these
 sort of untestable non-deterministic scenarios, and I think it is to
 the overall value of the platform to continue this.

 Therefore, my position continues to be that to access local storage,
 there should be an API that asynchronously acquires exclusive access
 to storage.

 - a



 Yeah, if you had to call an API that asynchronously acquires exclusive
 access
 to storage, then I believe that would nicely address most of the issues.
  It is the
 solution we have for database transactions.

 I say most because I'm not sure that it eliminates the need to drop the
 storage
 mutex in the showModalDialog case.

 If I call showModalDialog from within a database transaction, and then
 showModalDialog
 tries to create another database transaction, should I expect that the
 transaction
 can be started within the nested run loop of the modal dialog?  If not,
 then it may cause
 the app to get confused and never allow the dialog to be closed (e.g.,
 perhaps the close
 action is predicated on a database query.)

 Nested loops suck.  showModalDialog sucks :-)


 We could just disallow showModalDialog and any other trouble APIs like
 that during localStorage and database transactions.  Doing so seems better
 than silently dropping transactional semantics.



 It may not be so easy to disallow showModalDialog.  Imagine if you script a
 plugin inside the transaction, and before returning, the plugin scripts
 another window, where it calls showModalDialog.  There could have been a
 process hop there.


I'd count plugins as trouble APIs.  :-)


Re: [whatwg] Application defined locks

2009-09-09 Thread Darin Fisher
On Wed, Sep 9, 2009 at 9:28 PM, Robert O'Callahan rob...@ocallahan.orgwrote:

 On Thu, Sep 10, 2009 at 4:11 PM, Darin Fisher da...@chromium.org wrote:

 On Wed, Sep 9, 2009 at 9:07 PM, Robert O'Callahan 
 rob...@ocallahan.orgwrote:

 On Thu, Sep 10, 2009 at 3:53 PM, Darin Fisher da...@chromium.orgwrote:

 What concerns me are the cases where synchronous events (e.g., resizing
 an iframe) can cause script to execute in another domain.  As spec'd, there
 is a potential dead lock with the storage mutex.  We must carefully unlock
 in situations like this.  However, such unlocking will appear quite
 mysterious to users, so much so that I question the value of the implicit
 storage mutex.


 Right now I'm not sure how big a problem this actually is. The resize
 event for a document in a frame can surely be dispatched asynchronously so
 no unlocking is required. I would like to have a much better idea of how
 many places absolutely must release the storage mutex before deciding that
 approach is unworkable.

 Rob


 What about navigating an iframe to a reference fragment, which could
 trigger a scroll event?  The scrolling has to be done synchronously for
 compat with the web.


 The scrolling itself may have to be synchronous, at least as far as
 updating scrollLeft/scrollTop if not visually ... but in this case the
 script execution in the frame would be an onscroll event handler, right?
 That's asynchronous in Gecko.


Interesting.  Gecko seems to be the odd man out there.  Both MSHTML and
WebKit dispatch the onscroll event handler synchronously.  Maybe my
assertion about that being important for web compat was overreaching.

At any rate, this should at least give us pause.  There could be other ways
in which script execution across domains could be nested :-/

-Darin


Re: [whatwg] Application defined locks

2009-09-09 Thread Darin Fisher
On Wed, Sep 9, 2009 at 9:43 PM, Robert O'Callahan rob...@ocallahan.orgwrote:

 On Thu, Sep 10, 2009 at 4:37 PM, Darin Fisher da...@chromium.org wrote:

  Imagine if you script a plugin inside the transaction, and before
 returning, the plugin scripts another window,


 I'm curious, how common is that anyway? Can we just tell plugins not to do
 that, and abort any plugin that tries?


I don't know.  Are you saying that a plugin should not be able to invoke a
function that may trigger showModalDialog?  The code that calls
showModalDialog may be far removed / unrelated to the plugin script.  It may
just be an unfortunate side effect of invoking a method on a DOM window.

-Darin


Re: [whatwg] Application defined locks

2009-09-09 Thread Aaron Boodman
On Wed, Sep 9, 2009 at 9:13 PM, Darin Fisherda...@chromium.org wrote:
 If I call showModalDialog from within a database transaction, and then
 showModalDialog
 tries to create another database transaction, should I expect that the
 transaction
 can be started within the nested run loop of the modal dialog?

By definition, in that case, the second transaction would not start
until the dialog was closed.

 If not, then it may cause
 the app to get confused and never allow the dialog to be closed (e.g.,
 perhaps the close
 action is predicated on a database query.)

That is true, but it is an easily reproducible, deterministic
application bug. It also doesn't destabilize the environment -- by
making tabs or dialogs unclosable or whatever.

 Nested loops suck.  showModalDialog sucks :-)

Fair enough.

- a


Re: [whatwg] Application defined locks

2009-09-09 Thread Darin Fisher
On Wed, Sep 9, 2009 at 10:01 PM, Robert O'Callahan rob...@ocallahan.orgwrote:

 On Thu, Sep 10, 2009 at 4:57 PM, Darin Fisher da...@chromium.org wrote:

 On Wed, Sep 9, 2009 at 9:43 PM, Robert O'Callahan 
 rob...@ocallahan.orgwrote:

 On Thu, Sep 10, 2009 at 4:37 PM, Darin Fisher da...@chromium.orgwrote:

  Imagine if you script a plugin inside the transaction, and before
 returning, the plugin scripts another window,


 I'm curious, how common is that anyway? Can we just tell plugins not to
 do that, and abort any plugin that tries?


 I don't know.  Are you saying that a plugin should not be able to invoke a
 function that may trigger showModalDialog?  The code that calls
 showModalDialog may be far removed / unrelated to the plugin script.  It may
 just be an unfortunate side effect of invoking a method on a DOM window.


 No, I'm saying when a script in window A calls into a plugin, the plugin
 should not be allowed to synchronously call back out to script in window B.
 I realize that is currently allowed (i.e. not forbidden by anything in
 NPAPI), but do plugins actually do it in practice?



Yes, this is something that we have observed real plugins doing.  It is easy
for a plugin to have references to multiple windows.  They also like to
script the page in response to random NPP_ calls, like NPP_HandleEvent and
NPP_SetWindow, which perhaps is not too surprising.  NPP_HandleEvent
generally corresponds to input processing and painting for windowless
plugins, and NPP_SetWindow corresponds to a resize event.

-Darin


Re: [whatwg] Application defined locks

2009-09-09 Thread Darin Fisher
On Wed, Sep 9, 2009 at 10:03 PM, Aaron Boodman a...@google.com wrote:

 On Wed, Sep 9, 2009 at 9:13 PM, Darin Fisherda...@chromium.org wrote:
  If I call showModalDialog from within a database transaction, and then
  showModalDialog
  tries to create another database transaction, should I expect that the
  transaction
  can be started within the nested run loop of the modal dialog?

 By definition, in that case, the second transaction would not start
 until the dialog was closed.


Good, but



  If not, then it may cause
  the app to get confused and never allow the dialog to be closed (e.g.,
  perhaps the close
  action is predicated on a database query.)

 That is true, but it is an easily reproducible, deterministic
 application bug. It also doesn't destabilize the environment -- by
 making tabs or dialogs unclosable or whatever.


Well, the problem is that the creator of the transaction and the code
associated with the showModalDialog call may not be related.  The
showModalDialog code might normally be used outside the context of a
transaction, in which case the code would normally work fine.  However, if
triggered from within a transaction, the dialog would be stuck.

-Darin


Re: [whatwg] Application defined locks

2009-09-09 Thread Robert O'Callahan
On Thu, Sep 10, 2009 at 4:57 PM, Darin Fisher da...@chromium.org wrote:

 On Wed, Sep 9, 2009 at 9:43 PM, Robert O'Callahan rob...@ocallahan.orgwrote:

 On Thu, Sep 10, 2009 at 4:37 PM, Darin Fisher da...@chromium.org wrote:

  Imagine if you script a plugin inside the transaction, and before
 returning, the plugin scripts another window,


 I'm curious, how common is that anyway? Can we just tell plugins not to do
 that, and abort any plugin that tries?


 I don't know.  Are you saying that a plugin should not be able to invoke a
 function that may trigger showModalDialog?  The code that calls
 showModalDialog may be far removed / unrelated to the plugin script.  It may
 just be an unfortunate side effect of invoking a method on a DOM window.


No, I'm saying when a script in window A calls into a plugin, the plugin
should not be allowed to synchronously call back out to script in window B.
I realize that is currently allowed (i.e. not forbidden by anything in
NPAPI), but do plugins actually do it in practice?

Rob
-- 
He was pierced for our transgressions, he was crushed for our iniquities;
the punishment that brought us peace was upon him, and by his wounds we are
healed. We all, like sheep, have gone astray, each of us has turned to his
own way; and the LORD has laid on him the iniquity of us all. [Isaiah
53:5-6]


Re: [whatwg] Application defined locks

2009-09-09 Thread Aaron Boodman
On Wed, Sep 9, 2009 at 10:07 PM, Darin Fisherda...@chromium.org wrote:
 Well, the problem is that the creator of the transaction and the code
 associated with the showModalDialog call may not be related.  The
 showModalDialog code might normally be used outside the context of a
 transaction, in which case the code would normally work fine.  However, if
 triggered from within a transaction, the dialog would be stuck.

I agree that is possible.

It at least meets the bar that every time this code path is executed
it will behave exactly the same way (we have spec'd things before
where we didn't even get this far, because of gc issues).

But it would be better to not have weird edge cases like this in
uncommon paths.

OTOH, it seems like showModalDialog() is just a sharp edge that is
likely to hurt you no matter what. Even with your proposal, unless you
carefully arranged things in preparation for showModalDialog(), you
could get stuck the same way.

- a


[whatwg] cloneNode and HTML elements

2009-09-09 Thread Robert O'Callahan
If you call cloneNode on a media element, the state of the resulting media
element seems unspecified. Should it be playing the same media resource at
the same current time as the original?

Similar questions arise when you clone form elements; is the state that's
not visible in the DOM cloned?

Who should be responsible for defining this?

Rob
-- 
He was pierced for our transgressions, he was crushed for our iniquities;
the punishment that brought us peace was upon him, and by his wounds we are
healed. We all, like sheep, have gone astray, each of us has turned to his
own way; and the LORD has laid on him the iniquity of us all. [Isaiah
53:5-6]