Open Bug 593910 Opened 14 years ago Updated 2 years ago

Defining history.replaceState as an anonymous function fails randomly

Categories

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

1.9.2 Branch
x86
macOS
defect

Tracking

()

People

(Reporter: bcardarella, Unassigned)

References

Details

(Keywords: testcase, Whiteboard: DUPEME)

User-Agent:       Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-US) AppleWebKit/534.3 (KHTML, like Gecko) Chrome/6.0.472.53 Safari/534.3
Build Identifier: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8

I've confirmed this for FireFox 3.6.3 and 3.6.8 on OSX (Snow Leopard) and 3.6.8 on WindowsXP

I'm backporting support for window.history.pushState and window.history.replaceState for older browsers. However, FireFox randomly and silently fails to assign the anonymous function to window.history.replaceState (or pushState)

Example code:
http://pastie.org/1142965

The browser should refresh forever as on every page load the anonymous function is created and no longer 'undefined'. However, randomly this code will fail.

Thoughts? Is there a reason why this is happening or is it a legit bug?

Reproducible: Sometimes

Steps to Reproduce:
1. assign an anonymous function to window.history
2. load the page
3. randomly the function fails to assign

Actual Results:  
Randomly the function will be undefined

Expected Results:  
A defined anonymous function on a predefined window.history.something object
http://pastie.org/1243898 

Here is a solution to the problem, although I'm not sure why it works.
bz, could you comment if this is something we might fix on a branch and if the workaround is correct?

(posting the snippets here, since pastie.org was down when I first checked this)

http://pastie.org/1142965
<script type="text/javascript">
   window.history.replaceState = function() { }

   function testit() {
     if (typeof(window.history.replaceState) != 'undefined') {
       location.reload();
     } else {
       alert('Undefined!');
     }
   }

   setTimeout('testit();', 2000);
</script>

Workaround <http://pastie.org/1243898>:

window.History.prototype.pushState = function(stateObject, title, URL) {
  //stuff
}
Status: UNCONFIRMED → NEW
Component: General → DOM
Ever confirmed: true
Keywords: testcase
Product: Firefox → Core
QA Contact: general → general
Version: unspecified → 1.9.2 Branch
Setting an expando property on window.history doesn't do anything to pin the JS reflection of the C++ object in memory (unlike DOM nodes, where we do pin it in memory for the lifetime of the C++ object once an expando has been set).  This means that if a garbage collection happens after the replaceState set but before testit() runs, we will collect the old JS reflection with its expando property, and when you ask for window.history in testit() a new JS object will be created.

We have existing bugs asking that expandos always cause stuff to get pinned in memory.

Note that you can also work around with something like:

  var savedHistory = window.history;

in the global scope, which will make sure the history JS object is reachable from JS and can't be collected.

Andreas, worth keeping this situation in mind as we think about GC futures.
Whiteboard: DUPEME
Oh, to answer the questions from comment 2, there's no way this behavior is changing on a stable branch, and the workaround works fine, since History.prototype is reachable at all times from pure JS and hence doesn't get collected.
Can't reproduce on current nightly (and I don't think I could when I made comment 2, hence the question about fixing on the branch). WFM?
https://bugzilla.mozilla.org/show_bug.cgi?id=1472046

Move all DOM bugs that haven't been updated in more than 3 years and has no one currently assigned to P5.

If you have questions, please contact :mdaly.
Priority: -- → P5
Component: DOM → DOM: Core & HTML
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.