Closed Bug 551225 Opened 10 years ago Closed 9 years ago

Make pushState use structured clone

Categories

(Core :: DOM: Core & HTML, defect)

defect
Not set

Tracking

()

RESOLVED FIXED

People

(Reporter: justin.lebar+bug, Assigned: justin.lebar+bug)

References

Details

(Keywords: dev-doc-complete)

Attachments

(1 file, 4 obsolete files)

Right now, pushState and replaceState serialize their state objects to JSON.  We should use structured clone to be compliant with the spec.
Depends on: 550275
On the other hand, JSON serialization is convenient because it lets us easily serialize state objects for session restore.
Right, what we need here is not the structured clone code developed over in bug 550275. What we need is code to serialize and deserialize such that

obj1 --serialize--> ser --deserialize--> obj2

obj2 is a structured clone of obj1. We'll need this code both for pushState and for localStorage.
Did a quick experiment and it appears that WebKit is doing something similar to us: If you create a state object which contains a function, the function doesn't exist when you get the state object back on popstate.

I like the fact that we can serialize state objects to disk, so I'm not sure we even want to do this.  But if we don't, maybe we should get the spec changed.
We should definitely serialize. Everything supported by the structured clone algorithm is serializable. The user-visible effect of fixing this bug is that you can pushState objects that contain things like ImageData, dates and regexps (the latter not being terribly important obviously).
Blocks: 500328
For my reference, it looks like the JSAPI functions are JS_WriteStructuredClone and JS_ReadStructuredClone.  When we write out to storage, we can Base64-encode the value.  And when we read back in, we'll have to convert any JSON-encoded state objects to the new format.
Attached patch Patch v1 (obsolete) — Splinter Review
I'll ask for review here once I push to try and verify that this works.
(In reply to comment #4)
> We should definitely serialize. Everything supported by the structured clone
> algorithm is serializable. The user-visible effect of fixing this bug is that
> you can pushState objects that contain things like ImageData, dates and regexps

Most importantly, File.  Once structured clones support them, it should be possible to store Files that the user has opened to the history, and to restore them from a serialized session, so users don't have to reopen files each time they restart their browser.
Attached patch Patch v2 (obsolete) — Splinter Review
Attachment #527605 - Flags: review?(jonas)
Attachment #525039 - Attachment is obsolete: true
Is there a reason why nsIStructuredCloneContainer need to live under docshell/ ?
It looks like a very useful interface/class for other use too.

Maybe it could be under dom/intefaces/base ?
Patch is ready for review.  I fixed the one bug from my last try push, so things *should* be green, but I'll push again to be sure.

I'd originally used JS_AutoStructuredClone inside nsIStructuredCloneContainer, but I was getting strange memory management errors.  (I know you don't have to JS_free with the same cx you JS_malloc'ed with, so I'm not exactly sure what I was doing wrong.)  In any case, I think malloc'ing and free'ing manually is sufficiently simple not to worry about this.
(In reply to comment #9)
> Is there a reason why nsIStructuredCloneContainer need to live under docshell/
>
> Maybe it could be under dom/intefaces/base ?

That's fine with me!
Attached patch Patch v2.1 (obsolete) — Splinter Review
Moved nsIContentUtils, per Smaug's suggestion.
Attachment #527617 - Flags: review?(jonas)
Attachment #527605 - Attachment is obsolete: true
Attachment #527605 - Flags: review?(jonas)
er...I moved nsIStructuredCloneContainer (and kin), not nsIContentUtils (which hopefully will cease to exist soon).
(In reply to comment #10)
> Patch is ready for review.  I fixed the one bug from my last try push, so
> things *should* be green, but I'll push again to be sure.

Looks good.

Paul, can you have a look at the sessionstore changes?
Attachment #527617 - Flags: review?(paul)
I should mention that this change will cause a one-time loss of state objects upon session restore; I make no attempt to read the old JSON state objects and convert them to the new format.  I think this isn't a big deal, since persisting state across session restore didn't even work properly until we fixed bug 647028 yesterday.
Comment on attachment 527617 [details] [diff] [review]
Patch v2.1

Can I assume that since there are no tests here, this is covered under some of the other tests you've written? r=me assuming that, but I'll take it back if you tell me I'm wrong.

I'm ok with the one-time data loss. pushState isn't that widely used yet that most people wouldn't even notice.
Attachment #527617 - Flags: review?(paul) → review+
Although I think we get decent coverage with the other tests I wrote, it would be trivial to add a test specifically for session restore to browser_500328.js.  I'll definitely add this.
Attached patch Patch v2.2 (obsolete) — Splinter Review
Added session restore test.
Attachment #530390 - Flags: review?(jonas)
Attachment #527617 - Attachment is obsolete: true
Attachment #527617 - Flags: review?(jonas)
Comment on attachment 530390 [details] [diff] [review]
Patch v2.2

Wow, this looks great
Attachment #530390 - Flags: review?(jonas) → review+
Attached patch Patch v2.3Splinter Review
I forgot to update nsIDocument's CID and check the return value of JSAutoEnterCompartment::Enter in nsStructuredCloneContainer::InitFromVariant.
Attachment #530390 - Attachment is obsolete: true
http://hg.mozilla.org/mozilla-central/rev/0221eb8660f4
Status: NEW → RESOLVED
Closed: 9 years ago
Resolution: --- → FIXED
Depends on: 656354
Assignee: nobody → justin.lebar+bug
Blocks: 675162
Component: DOM → DOM: Core & HTML
You need to log in before you can comment on or make changes to this bug.