Bug 1166351 - Unable to access new tabs and unable to close any tab
Hmmm...

I just closed the tab

Was on golem.de with machine under heavy load (building) after activating the Flash on the page.

Huh… looks like all of the browsers are missing their webNavigation.

TabSwitcher assumes the browser we're switching to has a currentURI… but the one I'm looking at doesn't seem to ahve one.

The browser doesn't seem to have destructed…

https://people.mozilla.org/~sguo/cleopatra/#report=8cd32dddd817eb7d5d2439c95f47b165d6020dec

Theory:

The <xul:browser> binding has been removed, but the browser is still being referred to.

Question:

Could this have something to do with pinned tabs? Mossop just saw a loss of aBrowser.webProgress after a crash for his pinned tabs in bug 1175023 , and I see that kbrosnan has pinned tabs in his screenshot:

So perhaps I'll try along that front.

Hrm. Nothing yet…

blassey has suggested I add and land some logging / instrumentation to try to confirm or discount some theories.

There are, as far as I can tell, only two ways an XBL binding can be removed:
  1. The node with the binding is removed from the DOM
  2. The style that's applying the binding is removed.

Let's look at this second case. What are the bindings we care about:

In order:

browser.xml#browser
remote-browser.xml#remote-browser
tabbrowser.xml#tabbrowser-remote-browser

Where are these styles applied?

browser.xml is applied to every <xul:browser>.
remote-browser.xml is never actually applied (except for the view-source case), but extended by tabbrowser-remote-browser.
tabbrowser-remote-browser is only applied when a browser with the remote attribute set to true is a child of .browserStack.

Perhaps the problem resides somewhere in the async tab switcher. This thing has some logging facilities… maybe I can augment them.

Could it be that the async tab switcher is not prepared for cases where tabs / browsers stop existing?
Come up with logging for theories

Ok, logging is in Nightly's. The trap is set. Let's see what happens.

Margaret ran into this during Whistler. I was able to dig into the busted newtab browser with the Browser Toolbox.

The bug appears to be that the tabbrowser-browser binding is properly attached, but the binding that we're extending, the base browser binding, is NOT attached.

OK, we can remove the trap now. Or maybe modify it.

let utils = Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
let urls = utils.getBindingURLs(browser);

Ok, new instrumentation patch written. Up for review.

Aaaand landed on integration. Let's see what we get.

Just happened again! But to tabs and not browsers! WTF!

The binding URLs are:

"chrome://browser/content/tabbrowser.xml#tabbrowser-tab"
"chrome://global/content/bindings/tabbox.xml#tab"
"chrome://global/content/bindings/general.xml#control-item"
"chrome://global/content/bindings/general.xml#basetext"
"chrome://global/content/bindings/general.xml#basecontrol"

"ATTRIBUTE_NODE, CDATA_SECTION_NODE, COMMENT_NODE, DOCUMENT_FRAGMENT_NODE, DOCUMENT_NODE, DOCUMENT_POSITION_CONTAINED_BY, DOCUMENT_POSITION_CONTAINS, DOCUMENT_POSITION_DISCONNECTED, DOCUMENT_POSITION_FOLLOWING, DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC, DOCUMENT_POSITION_PRECEDING, DOCUMENT_TYPE_NODE, ELEMENT_NODE, ENTITY_NODE, ENTITY_REFERENCE_NODE, NOTATION_NODE, PROCESSING_INSTRUCTION_NODE, TEXT_NODE, TelemetryStopwatch, _animStartTime, _fullyOpen, _lastAccessed, _mouseenter, _mouseleave, _selected, _tPos, accessKey, addEventListener, align, allowEvents, appendChild, attributes, baseURI, baseURIObject, blur, boxObject, builder, childElementCount, childNodes, children, classList, className, click, clientHeight, clientLeft, clientTop, clientWidth, cloneNode, closest, collapsed, command, compareDocumentPosition, contains, contextMenu, controllers, convertPointFromNode, convertQuadFromNode, convertRectFromNode, crop, database, datasources, dir, disabled, dispatchEvent, doCommand, firstChild, firstElementChild, flex, flexGroup, focus, fontSizeInflation, frameLoader, getAnimations, getAttribute, getAttributeNS, getAttributeNode, getAttributeNodeNS, getBoundMutationObservers, getBoundingClientRect, getBoxQuads, getClientRects, getElementsByAttribute, getElementsByAttributeNS, getElementsByClassName, getElementsByTagName, getElementsByTagNameNS, getEventHandler, getUserData, hasAttribute, hasAttributeNS, hasAttributes, hasChildNodes, height, hidden, id, image, innerHTML, insertAdjacentHTML, insertBefore, isDefaultNamespace, isEqualNode, label, lastAccessed, lastChild, lastElementChild, left, linkedBrowser, localName, lookupNamespaceURI, lookupPrefix, mCorrespondingMenuitem, mOverCloseButton, matches, maxHeight, maxWidth, menu, minHeight, minWidth, mozMatchesSelector, mozRequestFullScreen, mozRequestPointerLock, mozScrollSnap, namespaceURI, nextElementSibling, nextSibling, nodeName, nodePrincipal, nodeType, nodeValue, normalize, observes, onabort, onblur, oncanplay, oncanplaythrough, onchange, onclick, oncontextmenu, ondblclick, ondrag, ondragend, ondragenter, ondragleave, ondragover, ondragstart, ondrop, ondurationchange, onemptied, onended, onerror, onfocus, ongotpointercapture, oninput, oninvalid, onkeydown, onkeypress, onkeyup, onload, onloadeddata, onloadedmetadata, onloadstart, onlostpointercapture, onmousedown, onmouseenter, onmouseleave, onmousemove, onmouseout, onmouseover, onmouseup, onmozfullscreenchange, onmozfullscreenerror, onmozpointerlockchange, onmozpointerlockerror, onpause, onplay, onplaying, onpointercancel, onpointerdown, onpointerenter, onpointerleave, onpointermove, onpointerout, onpointerover, onpointerup, onprogress, onratechange, onreset, onresize, onscroll, onseeked, onseeking, onselect, onshow, onstalled, onsubmit, onsuspend, ontimeupdate, onvolumechange, onwaiting, onwheel, ordinal, orient, outerHTML, owner, ownerDocument, ownerGlobal, pack, parentElement, parentNode, persist, pinned, prefix, previousElementSibling, previousSibling, querySelector, querySelectorAll, ref, releaseCapture, releasePointerCapture, remove, removeAttribute, removeAttributeNS, removeAttributeNode, removeChild, removeEventListener, replaceChild, resource, scroll, scrollBy, scrollByNoFlush, scrollHeight, scrollIntoView, scrollLeft, scrollLeftMax, scrollTo, scrollTop, scrollTopMax, scrollWidth, setAttribute, setAttributeNS, setAttributeNode, setAttributeNodeNS, setCapture, setEventHandler, setIsPrerendered, setPointerCapture, setUserData, statusText, style, swapFrameLoaders, tabIndex, tagName, textContent, tmp, tooltip, tooltipText, top, value, visibleLabel, width"

11:53 AM < mconley > Enn: ping
11:53 AM < Enn > hello
11:54 AM AlexanderSalas quit (Instantbird@moz-n40.2eh.84.200.IP) Quit: Instantbird 1.6a1pre -- http://www.instantbird.com
11:54 AM < mconley > Enn: hi! I'm in that really weird state right now in my Nightly, where a parent binding doesn't appear to be attached
11:54 AM < Enn > ok
11:54 AM < mconley > Enn: this time, it seems to be for the tabbox.xml tab binding
11:54 AM < mconley > Enn: where the tabbrowser-tab binding appears to be attached, but tabbox's tab is not
11:55 AM < mconley > Enn: so, this is an opt build, and I'm not seeing anything particularly helpful in the Browser Console
11:55 AM < mconley > Enn: and according to Ci.inIDOMUtils, the binding is _supposed_ to be attached - like, getBindingURLs is returning:
11:55 AM < mconley > Enn: do you have any suggestions on how I can debug this in my current state? Any XPCOM foo I can use to try to diagnose what's going on?
11:56 AM < mconley > and unfortunately I'm not in the office today, otherwise I'd show you in person. :/
11:56 AM < Enn > can you iterate over the properties? (for a in obj)
11:56 AM < mconley > Yes - one second.
11:58 AM < mconley > Enn: sorted property names:
11:58 AM < mconley > Enn: linkedPanel is absent, for example
11:59 AM < Enn > but a child property exists?
12:00 PM < mconley > Enn: I don't think I understand you - there is no "child" property defined
12:00 PM < mconley > oh
12:00 PM < Enn > I meant a property in the child binding
12:00 PM < mconley > Enn: you mean that a property on the child binding is applied?
12:00 PM < mconley > yes
12:01 PM < mconley > Enn: visibleLabel, for example
12:01 PM < Enn > does it have the right value?
12:01 PM < mconley > Enn: seems to
12:03 PM < Enn > the TelemetryStopwatch property appears to exist (defined in tabbox.xml#tab
12:03 PM < mconley > Enn: yes, that is true
12:04 PM < Enn > but none of the other properties
12:04 PM < mconley > Enn: correct
12:05 PM < mconley > Enn: if accessing a property like TelemetryStopwatch goes wrong, could that potentially cause binding breakage?
12:05 PM < Enn > but the ones from tabs's inherited binding (general.xml#control-item) do exist
12:06 PM < Enn > it seems more like an odd situation where an error occured applying the binding or the element was removed and reinserted in a strange way
12:06 PM < mconley > Enn: note that before this error occurred, I wasn't attempting to do anything funky. I think I was just opening a new tab
12:07 PM < Enn > mconley: do you have the startup cache enabled?
12:07 PM < mconley > so, unless some add-on freaked out, I don't think the tabs should have been removed and re-added to the DOM
12:07 PM < mconley > Enn: possibly - how do I check that?
12:07 PM < Enn > f
12:08 PM < mconley > checking
12:08 PM < mconley > Enn: that pref is not set.
12:09 PM < Enn > so it is enabled. I don't think that should be a problem since these are builds you made yourself I assume
12:09 PM < mconley > Enn: no - this is a Nightly that I did not build
12:10 PM < mconley > Enn: I'm running (and experiencing this problem) in a Nightly I got from nightly.mozilla.org
12:10 PM < Enn > too bad we can't reliably reproduce this :(
12:10 PM < mconley > Enn: I know, right? :/
12:11 PM < mconley > every time I get into this state, it's like the horse has already left the barn
12:11 PM < mconley > Enn: but if there's something, anything I can do to gather intel on how we got into this state... well, now's our chance, I guess. :)
12:12 PM < Enn > the only thing I can think of is some strange error happening while processing the implementation part of the binding.
12:12 PM < Enn > that failure could cause the symptom you see.
12:13 PM < Enn > since it returns NS_OK
12:13 PM < mconley > Enn: should that be returning an error nsresult instead?
12:14 PM < mconley > would it be possible to instrument the hell out of this method, so that we print errors to the Browser Console for any non-success case?
12:14 PM < Enn > don't know, but if you could get the issue in one of your builds, you could add some debugging in there to see if you're hitting one of the early returns in there
12:14 PM < mconley > Enn: I've had zero luck reproducing this in any of my local builds.
12:15 PM < mconley > I wrote an automated test to try to expose it
12:15 PM < Enn > :(
12:15 PM < mconley > opening and closing newtabs like crazy
12:15 PM < mconley > opening and closing windows
12:15 PM < mconley > left it running overnight. No dice.
12:15 PM < mconley > there's something we're missing.
12:15 PM < Enn > but that test fails easily on a nightly build?
12:15 PM < mconley > Enn: I've not tried it on a Nightly build that I didn't build myself
12:16 PM < mconley > I could try that, I suppose
12:16 PM < mconley > Enn: are there some optimizations in opt builds from nightly.mozilla.org that could contribute to this bug?
12:16 PM < mconley > optimizations that I don't have in my local builds?
12:17 PM < Enn > the problem occurs on the tab you just created?
12:18 PM < mconley > Enn: well, in this current manifestation of this bug, it seems to have affected all of my tabs
12:18 PM < Enn > wild!
12:18 PM < mconley > Enn: I know, right? :)
12:18 PM < Enn > so, you created a new tab, and the tabbox that you've been using for a while broke?
12:18 PM < mconley > Let me confirm that - I'll loop through the tabs checking for linkedPanel
12:18 PM < mconley > one sec
12:19 PM < mconley > yeah, none of them have linkedPanel defined
12:19 PM < mconley > Enn: and yes, that's correct
12:19 PM < mconley > I created a new tab, and then all of a sudden, everything just got into this weird state
12:21 PM < Enn > lunch time
12:21 PM < mconley > Enn: okay - I'll keep my browser in this state for a while
12:21 PM < mconley > I guess
12:21 PM < mconley > Enn: let me know if there's anything else I can try

OH SHIT - dholbert just saw this with non-e10s. RUH ROH.

Not an e10s bug!


23:35 mconley bholley: needinfo'd ya
23:35 bholley mconley: in terms of where to put the call, I'm not really sure, but neil had a suggestion
23:37 mconley bholley: right - so where do I get the CX and scope when the time comes?
23:37 bholley mconley: I would look at the other code that uses the maps
23:38 bholley mconley: you may need a higher-level signature
23:39 mconley bholley: but that's all getting kicked off by JS-ish activity, right? Like, if there's JS on the stack, getting the scope and CX is straightforward, I think
23:39 bholley mconley: I don't think binding installation gets kicked off by JS
23:39 mconley Ah, interesting. Didn't realize that. Okay, in that case, I'll study this further
23:39 mconley Thanks!
23:40 bholley mconley: looks like it all funnels down from nsXBLProtoImpl::InitTargetObjects
23:40 bholley mconley: basically, you'll want to create an AutoJSAPI with a global somewhere
23:40 bholley mconley: the trick is finding the right place to put your API so that the caller has the right stuff to call it and it can do what it needs to do
23:41 bholley mconley: i.e. the usual software engineering stuff, just extra-hard because XBL isn't designed all that well ;-)
23:41 mconley Gotcha.
23:41 mconley Thanks!
23:42 bholley mconley: np :-)
23:45 bholley mconley: though you do realize that by writing this patch, you are setting yourself for future needinfos just as I did years ago when I wrote the last one ;-)
23:45 bholley XBL is all guilt by association
23:45 mconley The usual software engineering stuff. :)
23:46 mconley Well, happy to give some cover fire, at any rate.
23:46 bholley mconley: <3

2:40 PM < bz > mconley: So really you want to hunt down all the XPCWrappedNativeScope that matter to you, right?
2:40 PM jgilbert joined (Jeff@moz-c1gech.2rkg.9kg1.0101.2620.IP)
2:40 PM < mconley > bz: I suppose. I see that XPCWrappedNativeScope has a gScopes static
2:40 PM < mconley > and I’m wondering if that’s what I want to iterate
2:41 PM < bz > mconley: And then for each one, you want to examine its mContentXBLScope and mGlobalJSObject?
2:41 PM < mconley > Yes, assuming they have an mContentXBLScope. If they don’t, I _think_ I can skip it
2:41 PM < mconley > basically
2:41 PM < bz > And yes, walking the gScopes list seems like the way to go
2:41 PM < bz > Yes, agreed.
2:42 PM < mconley > hmm, okay
2:42 PM < mconley > so I guess I’m doing this inside XPCWrappedNativeScope then
2:42 PM mconley scratches chin
2:42 PM < mconley > heh, “Deep Magic"
2:43 PM < bz > yes
2:43 PM < bz > Just add a static XPCWrappedNativeScope function
2:43 PM < bz > "just"
2:43 PM < mconley > :)
2:43 PM < mconley > I think I can do that.
2:43 PM < mconley > bz: what about the system principal’d window cases?
2:44 PM < mconley > are those scopes in gScopes as well?
2:44 PM < bz > yes
2:44 PM < mconley > ah, excellent
2:44 PM < bz > That's why I said mGlobalJSObject
2:44 PM < bz > Check whether that's a Window and system-principaled
2:44 PM < mconley > I gotcha
2:44 PM < mconley > okay
2:44 PM < mconley > starting to piece this together

Patches are up, fools!

GAH. Oranges. 😔 Hitting my assertion a lot. Why? Okay, let’s try to narrow it...

[browser_bug553455.js]
skip-if = buildapp == 'mulet' # Bug 1066070 - I don't think either popup notifications nor addon install stuff works on mulet?

[browser_bug567306.js]

Scope:
GLOBAL: 0x7f6cefc6c060
cached binding: 0x496a470
cached prototype binding: 0x42699b0
cached implementation: 0x426a010
cached binding docinfo: 0x4268f10
cached binding manager: 0x3783f60

The nsXBLBinding that causes the registration of the prototype: 0x5e629c0

It looks as if there’s a stale XBL doc info sticking around… and that’s what we’re getting the out-of-date XBL binding prototype from, and that’s what we’re stashing into the WeakMap...

new binding:  0x26756a0
new binding docinfo: 0x2529760
Document for the docinfo: 0x248cef0

New binding docinfo is created after the flush… put into 0x17c3670… and 0x6082e00...



Why did the XBLDocumentInfo get changed for the bound document? Like, why is the new docinfo needed?

Back to first principles: theories, tests, results.

Theory: After the cache flush, with the XULPrototypeCache empty, nsXBLService::LoadBindingDocumentInfo tries to load up that general.xml binding, doesn’t find it, and so create a new nsXBLDocumentInfo for those bindings, and shoves that into the cache.

Later on, when a pre-existing bound document attempts to create a binding, it checks the cache, and finds the NEW prototype. The problem is that the new prototype doesn’t match the one in the WeakMap.

THE NEW one is in the XULPrototypeCache because of the NEW nsXBLDocumentInfo that gets put in there.

  1. We create the nsBindingManager for the page we care about
  2. We load the nsXBLDocumentInfo and shove that mutha into the nsXULPrototypeCache
  3. We also put the nsXBLDocumentInfo into the nsBindingManager
  4. Cache is flushed
  5. New nsXBLDocumentInfo X is constructed and put into the cache
  6. ???
  7. When constructing a new nsXBLBinding, we get at the new nsXBLDocumentInfo X that was cached above, and use that to get at the NEW nsXBLPrototypeBinding Y that’s going to cause us to fail our assertion.

Question:
How and why is the OLD nsXBLDocumentInfo / cachedBinding put into the WeakMap?

Because there is a pre-existing BindingManager for this document scope, and it has its own cache of nsXBLDocumentInfo’s. When the binding is installed for that scope, we use that nsXBLDocumentInfo in order to get at the nsXBLPrototypeBinding.

That happens to get used first, so that’s what gets put into the WeakMap.

Then… how come the new one shows up? Like, how come we do get the same nsXBLDocumentInfo when we try to install the binding that calls the assertion failure?

There’s only one binding manager. And it has a nsXBLDocumentInfo table that never gets cleared. So once it’s set, it’s set.

We load the original nsXBLDocumentInfo and put it in the cache.
We put the nsXBLDocumentInfo into the never-cleared nsXBLDocumentInfo cache.
Cache is flushed.
New nsXBLDocumentInfo X is constructed and put into the cache.
Then, later, a binding for our original nsBindingManager is required, and when it starts to load it, it checks the XUL prototype cache first, and gets a hit! So it uses the NEW one, when in fact, we’d already done a write to the WeakMap using the original.

What is the stack when we add the out-of-date nsXBLPrototypeBinding to the WeakMap after the cache flush?

#0  nsXBLBinding::DoInitJSClass (cx=0x10dd390, obj=..., aClassName=..., aProtoBinding=0x42699b0, aClassObject=..., aNew=0x7ffe796a8482)
at /media/mikeconley/Projects/mozilla/mozilla-central/dom/xbl/nsXBLBinding.cpp:1008
#1  0x00007f6d73696cd2 in nsXBLPrototypeBinding::InitClass (this=0x42699b0, aClassName=..., aContext=0x10dd390, aScriptObject=..., aClassObject=..., aNew=0x7ffe796a8482)
at /media/mikeconley/Projects/mozilla/mozilla-central/dom/xbl/nsXBLPrototypeBinding.cpp:463
#2  0x00007f6d7368e5d3 in nsXBLProtoImpl::InitTargetObjects (this=0x426a010, aBinding=0x42699b0, aBoundElement=0x471b850, aTargetClassObject=..., aTargetIsNew=0x7ffe796a8482)
at /media/mikeconley/Projects/mozilla/mozilla-central/dom/xbl/nsXBLProtoImpl.cpp:229
#3  0x00007f6d7368d4d3 in nsXBLProtoImpl::InstallImplementation (this=0x426a010, aPrototypeBinding=0x42699b0, aBinding=0x5e629c0)
at /media/mikeconley/Projects/mozilla/mozilla-central/dom/xbl/nsXBLProtoImpl.cpp:69
#4  0x00007f6d73696546 in nsXBLPrototypeBinding::InstallImplementation (this=0x42699b0, aBinding=0x5e629c0)
at /media/mikeconley/Projects/mozilla/mozilla-central/dom/xbl/nsXBLPrototypeBinding.cpp:319
#5  0x00007f6d73683c9e in nsXBLBinding::InstallImplementation (this=0x5e629c0) at /media/mikeconley/Projects/mozilla/mozilla-central/dom/xbl/nsXBLBinding.cpp:576
#6  0x00007f6d73683bf6 in nsXBLBinding::InstallImplementation (this=0x5e62a20) at /media/mikeconley/Projects/mozilla/mozilla-central/dom/xbl/nsXBLBinding.cpp:570
#7  0x00007f6d73683bf6 in nsXBLBinding::InstallImplementation (this=0x5e62b10) at /media/mikeconley/Projects/mozilla/mozilla-central/dom/xbl/nsXBLBinding.cpp:570
#8  0x00007f6d73683bf6 in nsXBLBinding::InstallImplementation (this=0x5e62b70) at /media/mikeconley/Projects/mozilla/mozilla-central/dom/xbl/nsXBLBinding.cpp:570
#9  0x00007f6d73683bf6 in nsXBLBinding::InstallImplementation (this=0x5e62bd0) at /media/mikeconley/Projects/mozilla/mozilla-central/dom/xbl/nsXBLBinding.cpp:570
#10 0x00007f6d736a6a3a in nsXBLService::LoadBindings (this=0x13ecfa0, aContent=0x471b850, aURL=0x487ee50, aOriginPrincipal=0x10dd260, aBinding=0x5e62908,
aResolveStyle=0x7ffe796a8b40) at /media/mikeconley/Projects/mozilla/mozilla-central/dom/xbl/nsXBLService.cpp:495

Front-runner theory:

There are a few players here:

  1. The global nsXULPrototypeCache, which caches lots of information, including references to all nsXBLDocumentInfo’s that get loaded.
  2. nsBindingManager - there’s one of these per document, I believe. This also holds references to the nsXBLDocumentInfo’s that have been loaded for bindings within the document that it belongs to.
  3. nsXBLService - this is a singleton that does the work of loading bindings off the disk. What’s important to know is that when the nsXBLService loads a binding for some document, it will first check the nsXULPrototypeCache for the appropriate nsXBLDocumentInfo for that binding. If it doesn’t find it in the nsXULPrototypeCache, it’ll then check the nsBindingManager for the document that the binding is being used within. Failing that, it’ll go load it fresh off of the disk.

Here’s why I think I’m hitting my assertion:

  1. An XBL binding B is loaded, and the nsXBLDocumentInfo for that binding is cached both in nsXULPrototypeCache, along with the nsBindingManager that the binding is being loaded into. Let’s call this nsBindingManager X.
  2. When the XBL binding is loaded, it also creates the JS prototype object that’s being spliced into the binding target’s prototype chain - this gets tossed into the WeakMap for that global via nsXBLBinding::DoInitJSClass
  3. The cache if flushed - so that nsXBLDocumentInfo is removed from the nsXULPrototypeCache. Due to my patches, this also clears out the WeakMap of JS prototype objects. It is _not_, however, removed from the nsBindingManager X for the documents for which XBL binding B has been loaded into.
  4. Later on, the document with nsBindingManager X tries loading another instance of XBL binding B. It can’t find the nsXBLDocumentInfo in the nsXULPrototypeCache, so it falls back to checking the nsBindingManager. It finds the pre-flush nsXBLDocumentInfo, and calls nsXBLBinding::DoInitJSClass, which puts the prototype binding from the pre-flush nsXBLDocumentInfo into the WeakMap!
  5. Later, some other document tries to load XBL binding B. It’s not in the nsXULPrototypeCache, and it’s not in the nsBindingManager for that document (since it’s never been loaded before), so it loads it from the disk.
  6. Once the load from disk is completed, the newly created nsXBLDocumentInfo for that binding document is put into the nsXULPrototypeCache.
  7. Back in the document with nsBindingManager X, another copy of XBL binding B is being used - so nsXBLService goes to load the nsXBLDocumentInfo, and finds the newly created nsXBLDocumentInfo that’s now in the nsXULPrototypeCache. This is what it gets the nsXBLPrototypeBinding from, and this is what eventually gets passed to nsXBLBinding::DoInitJSClass.
  8. And we assert, because this new nsXBLPrototypeBinding does not match what was cached in the WeakMap.

Huh. If that’s true, why do we even need to clear the WeakMaps?

Okay, now I’ve made it so that we prioritize getting at the nsBindingManager nsXBLDocumentInfo - but I’m still asserting in some cases. What gives?

global: 0x7f07bb39c380

cached binding document info URI: chrome://global/content/bindings/general.xml#iframe
cached binding document info: 0x3bc0be0
cached binding prototype: 0x23bae50
cached binding manager: 0x4c2b410

new binding document info URI: chrome://global/content/bindings/general.xml
new binding document info: 0x53775a0
new binding prototype: 0x6e8f250
new binding manager: 0x4c2b410
new binding bound document: 0x295fc20
new binding manager: 0x50d46a0



When content process starts: 41728

Interesting event: 22769
scope: 0x7f6c6756c060
Proto binding for menulist: 0x42eb1c0
…whoa - maybe _actual_ proto binding for menulist: 0x42ef9d0

Doc info: 0x42e9850
Proto binding manager?: 0x32c27b0