Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

executionContext

14 views
Skip to first unread message

John J. Barton

unread,
Nov 5, 2009, 12:43:43 AM11/5/09
to
When you hit a breakpoint, Chromebug wants to stop the JS and poke
around in the DOM. Mostly this works well, but now we have cases where
it fails. We are using:
jsdIStackFrame.executionContext.scriptsEnabled = false;
and I *think* that the problem is perhaps that another executionContext
runs?

How are executionContext objects related to nsIDOMWindows? When I've
poked around with jsd.enumerateContexts() I found jsdIContext-s with
nsiDOMWindow globalObjects and some "other stuff". Some of the other
stuff has
var isTimer = (jscontext.privateData instanceof nsITimerCallback);
but I could find nothing else useful.

"Rubbing the electric lamp is not particularly rewarding. Anyway,
nothing exciting happens."

jjb

Boris Zbarsky

unread,
Nov 5, 2009, 12:45:50 AM11/5/09
to
On 11/5/09 12:43 AM, John J. Barton wrote:
> How are executionContext objects related to nsIDOMWindows?

From my brief look at the relevant jsd guts just now, it looks like an
executionContext more or less corresponds to a JSContext. That
JSContext may or may not be one for a DOM window, of course. It might
also be a sandbox, a JS component scope, a subscript loader context, a
DOM worker, the safe context, etc. See the various callers of
JS_NewContext.

Setting scriptsEnabled only works (doesn't throw) if the JSContext has
an associated nsIScriptContext. In that case it might or might not
correspond to a window, but if it has script running on it, then it
_probably_ does. Nothing guarantees that, but I think in practice it's
true in Firefox (since the only nsIScriptContext things around should be
the XBL and XUL proto globals/context, which compile script but don't
run it, and window contexts).

> When I've
> poked around with jsd.enumerateContexts() I found jsdIContext-s with
> nsiDOMWindow globalObjects and some "other stuff". Some of the other
> stuff has
> var isTimer = (jscontext.privateData instanceof nsITimerCallback);
> but I could find nothing else useful.

The privateData in this case is more or less guaranteed to be an
nsIScriptContext.... That said, the only nsIScriptContext I see around
that implements nsITimerCallback is nsPythonContext. I really doubt
you're seeing those here!

So if the above was supposed to mean that the RHS of that assignment is
true, then I have no idea why that happens for you.

Hope the above helps; not sure it does, but then I'm not sure what the
question was, past "what exactly is a jsdIContext?"

-Boris

John J. Barton

unread,
Nov 5, 2009, 1:32:46 AM11/5/09
to
Boris Zbarsky wrote:
> On 11/5/09 12:43 AM, John J. Barton wrote:
>> How are executionContext objects related to nsIDOMWindows?
>
> From my brief look at the relevant jsd guts just now, it looks like an
> executionContext more or less corresponds to a JSContext. That
> JSContext may or may not be one for a DOM window, of course. It might
> also be a sandbox, a JS component scope, a subscript loader context, a
> DOM worker, the safe context, etc. See the various callers of
> JS_NewContext.

According to what we are seeing, this.onBlur is called while our
executionContext.scriptsEnabled is false:
win.addEventListener("blur", this.onBlur, true);
where win is a XUL browser element that corresponds to our executionContext.

So can the eventListener be run in an executionContext other than the
'win' content? (FF 3.6)

>
...


>> var isTimer = (jscontext.privateData instanceof nsITimerCallback);
>> but I could find nothing else useful.
>
> The privateData in this case is more or less guaranteed to be an
> nsIScriptContext.... That said, the only nsIScriptContext I see around
> that implements nsITimerCallback is nsPythonContext. I really doubt
> you're seeing those here!

I guess there is another one, very common lurking. In fact I think these
are setTimeouts? (I did this investigation back in FF3.0 I think; and
this is just FYI, not about the real problem I have above).

jjb

Boris Zbarsky

unread,
Nov 5, 2009, 1:51:19 AM11/5/09
to
On 11/5/09 1:32 AM, John J. Barton wrote:
> According to what we are seeing, this.onBlur is called while our
> executionContext.scriptsEnabled is false:
> win.addEventListener("blur", this.onBlur, true);
> where win is a XUL browser element that corresponds to our
> executionContext.

Corresponds in what sense? And I really doubt a <xul:browser> is
stashed in a variable named |win|; I'd think that's a Window object....

> So can the eventListener be run in an executionContext other than the
> 'win' content? (FF 3.6)

In the above situation, this.onBlur will be called on win's JSContext.

> I guess there is another one, very common lurking. In fact I think these
> are setTimeouts? (I did this investigation back in FF3.0 I think

Oh, ancient history. I had checked 1.9.1 and m-c, but not 1.9.0. In
1.9.0, nsJSContext implemented nsITimerCallback. That's all gone in
1.9.1 and later; it's using a callback function instead.

-Boris

P.S. If what you really meant is that |win| is a Window whose JSContext
is the thing your executionContext reflects then you may well just be
seeing <https://bugzilla.mozilla.org/show_bug.cgi?id=409737>. Disabling
script on an nsIScriptContext disables attempts to compile/run new
scripts or run timeouts; it doesn't affect execution of existing scripts
that are in the middle of running and doesn't affect
addEventListener-added event listeners, or other JS-implemented XPCOM
interface kinda things, per the bug cited above. Oh, and not sure about
XBL constructors, for that matter....

-Boris

John J. Barton

unread,
Nov 5, 2009, 11:15:46 AM11/5/09
to
Boris Zbarsky wrote:
> On 11/5/09 1:32 AM, John J. Barton wrote:
>> According to what we are seeing, this.onBlur is called while our
>> executionContext.scriptsEnabled is false:
>> win.addEventListener("blur", this.onBlur, true);
>> where win is a XUL browser element that corresponds to our
>> executionContext.
>
> Corresponds in what sense? And I really doubt a <xul:browser> is
> stashed in a variable named |win|; I'd think that's a Window object....

Corresponds in the sense that "|win| is a Window whose JSContext


is the thing your executionContext reflects"

>

>> So can the eventListener be run in an executionContext other than the
>> 'win' content? (FF 3.6)
>
> In the above situation, this.onBlur will be called on win's JSContext.

But to your point below, this executionContext.scriptsEnabled call
fails, so it's worse than another context.

> P.S. If what you really meant is that |win| is a Window whose JSContext
> is the thing your executionContext reflects then you may well just be
> seeing <https://bugzilla.mozilla.org/show_bug.cgi?id=409737>. Disabling
> script on an nsIScriptContext disables attempts to compile/run new
> scripts or run timeouts; it doesn't affect execution of existing scripts
> that are in the middle of running and doesn't affect
> addEventListener-added event listeners, or other JS-implemented XPCOM
> interface kinda things, per the bug cited above. Oh, and not sure about
> XBL constructors, for that matter....

This is real bad. It means we cannot trust anything we see in
Firebug/Chromebug because the state can be changing while we examine a
snapshot.

jjb

Boris Zbarsky

unread,
Nov 5, 2009, 11:13:28 AM11/5/09
to
On 11/5/09 11:15 AM, John J. Barton wrote:
> This is real bad. It means we cannot trust anything we see in
> Firebug/Chromebug because the state can be changing while we examine a
> snapshot.

Can you just put the debuggee window in the mode it's in during sync
XHR, where events are buffered instead of being delivered?

-Boris

Boris Zbarsky

unread,
Nov 5, 2009, 11:20:07 AM11/5/09
to
On 11/5/09 11:13 AM, Boris Zbarsky wrote:
> Can you just put the debuggee window in the mode it's in during sync
> XHR, where events are buffered instead of being delivered?

"You" probably being the jsd guts, since I think this involves nsIDocument.

-Boris

Steven Roussey

unread,
Nov 5, 2009, 11:20:28 AM11/5/09
to
> This is real bad. It means we cannot trust anything we see in
> Firebug/Chromebug because the state can be changing while we examine a
> snapshot.

Exactly. That is why I tell web developers that if they are seeing
something that defies logic, then to switch to another browser/
debugger to verify.

In the cases of JS frameworks like ExtJS, jQuery, etc., they have
their own addListeners so it looks to the browser like it is always
the same function being called (thus the limited usefulness of seeing
the JS code in eventbug too). With all events pouring through the same
function, and continuing to do so after stopping in the debugger, you
can imagine the mess. Thankfully, they all try and normalize events
between browsers -- so they copy out the important info, and leave a
reference to the original event. This tends to protect many users from
noticing.

Also, most of the time you can live with some other event running.
However, events that happen in pairs (I'm thinking mouseover/mouseout,
etc), tend to share data, and stuff breaks down. Not to mention all
the side effects of other code running. I don't even know what happens
when you are stopped on a breakpoint and some other code runs and has
a JS error. Or infinite loop.

I wonder if this is at all related to Firefox showing the long running
script dialog when you are stopped at a breakpoint...

-steve roussey-

John J. Barton

unread,
Nov 5, 2009, 11:39:17 AM11/5/09
to

But that would mean chaos when the developer continues execution after
debugging. The developer pushes "continue" and a huge slug of events arrive.

Maybe we could walk the event listener info list, remove them, debug,
add them.

jjb

Boris Zbarsky

unread,
Nov 5, 2009, 11:28:09 AM11/5/09
to
On 11/5/09 11:39 AM, John J. Barton wrote:
> But that would mean chaos when the developer continues execution after
> debugging. The developer pushes "continue" and a huge slug of events
> arrive.

You already have that "problem" on any page that has an async XHR in
flight, or any other network activity, at the moment when you pause the
script. As soon as you unpause, it'll receive all the buffered-up
network events all at once. I don't see why this is an issue.

> Maybe we could walk the event listener info list, remove them, debug,
> add them.

For everything in the web page?

Seriously, you might want to check with smaug, but I suspect the sync
XHR mode might be what you want here. Depending on what you want, of
course.

-Boris

John J. Barton

unread,
Nov 5, 2009, 12:09:25 PM11/5/09
to
Boris Zbarsky wrote:
> On 11/5/09 11:39 AM, John J. Barton wrote:
>> But that would mean chaos when the developer continues execution after
>> debugging. The developer pushes "continue" and a huge slug of events
>> arrive.
>
> You already have that "problem" on any page that has an async XHR in
> flight, or any other network activity, at the moment when you pause the
> script. As soon as you unpause, it'll receive all the buffered-up
> network events all at once. I don't see why this is an issue.

How about blur, mouseover?

>
>> Maybe we could walk the event listener info list, remove them, debug,
>> add them.
>
> For everything in the web page?

Why not yes?

>
> Seriously, you might want to check with smaug, but I suspect the sync
> XHR mode might be what you want here. Depending on what you want, of
> course.

I want what jsdIContext.scriptsEnabled promises:
|true| if this context should be allowed to run scripts, |false|
otherwise.

But there must be something else going on. I guess the event queue must
purge events or the events must arrive on the context and be discarded
when scriptsEnabled == false.

jjb

Steven Roussey

unread,
Nov 5, 2009, 11:57:24 AM11/5/09
to
> But that would mean chaos when the developer continues execution after
> debugging. The developer pushes "continue" and a huge slug of events arrive.
>
> Maybe we could walk the event listener info list, remove them, debug,
> add them.

I'd suggest just removing them. That seems to mimic what it means to
have the JS engine "stopped". No one really wants 100 mouseover events
to flood in when you have a breakpoint on a mouseover event, and move
your mouse across the page to the debugger. It is non-intuitive to hit
continue and then be right back at the breakpoint for something you
didn't just do.

-steve--

Boris Zbarsky

unread,
Nov 5, 2009, 12:13:33 PM11/5/09
to
On 11/5/09 11:57 AM, Steven Roussey wrote:
> I'd suggest just removing them. That seems to mimic what it means to
> have the JS engine "stopped". No one really wants 100 mouseover events
> to flood in when you have a breakpoint on a mouseover event, and move
> your mouse across the page to the debugger. It is non-intuitive to hit
> continue and then be right back at the breakpoint for something you
> didn't just do.

How about looking at the code before saying things that are completely
irrelevant? In the sync XHR mode, not _all_ events are buffered. Most
are just completely ignored. In particular, mouseover is not buffered.
What's buffered, as far as I can tell, are focus, blur, mousedown,
mouseup, and some keyboard events.

-Boris

Boris Zbarsky

unread,
Nov 5, 2009, 12:16:52 PM11/5/09
to
On 11/5/09 12:09 PM, John J. Barton wrote:
>> You already have that "problem" on any page that has an async XHR in
>> flight, or any other network activity, at the moment when you pause
>> the script. As soon as you unpause, it'll receive all the buffered-up
>> network events all at once. I don't see why this is an issue.
>
> How about blur, mouseover?

What about them?

>> For everything in the web page?
>
> Why not yes?

Because that sounds like a security nightmare. Furthermore, you
wouldn't be able to remove the chrome event listeners, so if you click
in the page chrome might still run script on that page. That might run
on the chrome jscontext, of course, but can definitely change the page.

> I want what jsdIContext.scriptsEnabled promises:
> |true| if this context should be allowed to run scripts, |false| otherwise.

No, what you want is to completely freeze the state of the DOM, layout,
and script data structures on the page. .scriptsEnabled doesn't promise
that, nor deliver it.

Not least because a context being not allowed to run scripts says
nothing about scripts on the page running: they can be called on some
other context (a simple cross-window function call will do the trick).

> But there must be something else going on. I guess the event queue must
> purge events or the events must arrive on the context and be discarded
> when scriptsEnabled == false.

I'm not sure what you're trying to get at here.

-Boris

Boris Zbarsky

unread,
Nov 5, 2009, 12:17:43 PM11/5/09
to
On 11/5/09 12:16 PM, Boris Zbarsky wrote:
>>> For everything in the web page?
>>
>> Why not yes?
>
> Because that sounds like a security nightmare.

I _meant_ to say performance nightmare. Though it'd obviously need a
security review too, of course; I suspect it can probably be done
safely, though.

-Boris

John J. Barton

unread,
Nov 5, 2009, 12:48:57 PM11/5/09
to
Boris Zbarsky wrote:
...

>> But there must be something else going on. I guess the event queue must
>> purge events or the events must arrive on the context and be discarded
>> when scriptsEnabled == false.
>
> I'm not sure what you're trying to get at here.

I am confused because Firebug works pretty well for several years then
suddenly we learn that a fundamental aspect was broken the whole time.
It does not add up.

jjb

Steven Roussey

unread,
Nov 5, 2009, 12:35:35 PM11/5/09
to
> How about looking at the code before saying things that are completely
> irrelevant?  In the sync XHR mode, not _all_ events are buffered.  Most
> are just completely ignored.  In particular, mouseover is not buffered.
>   What's buffered, as far as I can tell, are focus, blur, mousedown,
> mouseup, and some keyboard events.

My bad. You wouldn't happen to know off the top of your head where to
look for the sync XHR mode code is so I can look it up?

I'm not even sure about getting rid of them now.

What happens to code for mouseover/mouseout when it is written such
that they always happen in pairs? That there will be a mouseout before
another mouseover on the same (or not the same, but related) element?

I always thought it was strange that things like events, event
listers, and visual stuff like hover still work when the debugger has
things stopped.

My $0.02

-steve--

Boris Zbarsky

unread,
Nov 5, 2009, 12:43:35 PM11/5/09
to
On 11/5/09 12:35 PM, Steven Roussey wrote:
>> How about looking at the code before saying things that are completely
>> irrelevant? In the sync XHR mode, not _all_ events are buffered. Most
>> are just completely ignored. In particular, mouseover is not buffered.
>> What's buffered, as far as I can tell, are focus, blur, mousedown,
>> mouseup, and some keyboard events.
>
> My bad. You wouldn't happen to know off the top of your head where to
> look for the sync XHR mode code is so I can look it up?

Look for callers of SuppressEventHandling(), EventHandlingSuppressed().

> What happens to code for mouseover/mouseout when it is written such
> that they always happen in pairs? That there will be a mouseout before
> another mouseover on the same (or not the same, but related) element?

Check with smaug?

-Boris

Boris Zbarsky

unread,
Nov 5, 2009, 12:44:44 PM11/5/09
to
On 11/5/09 12:48 PM, John J. Barton wrote:
> I am confused because Firebug works pretty well for several years then
> suddenly we learn that a fundamental aspect was broken the whole time.
> It does not add up.

Chances are:

1) It didn't actually work as well as you thought it did.
2) The hard cases that cause it to completely fall down
are comparatively rare.

At the very least. Possibly something else going on too.

-Boris

John J. Barton

unread,
Nov 5, 2009, 2:40:36 PM11/5/09
to
Boris Zbarsky wrote:
> On 11/5/09 12:35 PM, Steven Roussey wrote:
>>> How about looking at the code before saying things that are completely
>>> irrelevant? In the sync XHR mode, not _all_ events are buffered. Most
>>> are just completely ignored. In particular, mouseover is not buffered.
>>> What's buffered, as far as I can tell, are focus, blur, mousedown,
>>> mouseup, and some keyboard events.
>>
>> My bad. You wouldn't happen to know off the top of your head where to
>> look for the sync XHR mode code is so I can look it up?
>
> Look for callers of SuppressEventHandling(), EventHandlingSuppressed().

Ok this helps a lot. I don't know what sync XHR mode is but,
nsIDOMWindowUtils is a script callable interface for nsIDOMWindows:

http://mxr.mozilla.org/mozilla-central/source/dom/interfaces/base/nsIDOMWindowUtils.idl#328

The other function seems to be C++.

jjb

John J. Barton

unread,
Nov 5, 2009, 3:04:19 PM11/5/09
to
John J. Barton wrote:
> Boris Zbarsky wrote:
...

>> Look for callers of SuppressEventHandling(), EventHandlingSuppressed().
>
> Ok this helps a lot. I don't know what sync XHR mode is but,
> nsIDOMWindowUtils is a script callable interface for nsIDOMWindows.

Unfortunately a quick test of this idea fails for Chromebug debugging
Firebug. The problem I believe is that the JS code is in browser.xul, so
Chromebug calls suppressEventHandling() on browser.xul, but the onBlur()
functions are added to Firebug's panels which are browser elements
inside of browser.xul. They may not count as a "subwindow". The general
case may be hard to sort out, but Firebug on web pages may still work.

jjb

John J. Barton

unread,
Nov 5, 2009, 3:33:04 PM11/5/09
to
John J. Barton wrote:
> John J. Barton wrote:
>> Boris Zbarsky wrote:
> ...
>>> Look for callers of SuppressEventHandling(), EventHandlingSuppressed().
>>
>> Ok this helps a lot. I don't know what sync XHR mode is but,
>> nsIDOMWindowUtils is a script callable interface for nsIDOMWindows.
>
> Unfortunately a quick test of this idea fails for Chromebug debugging

Like quick tests often are, that result was just bogus, the interface
has to be obtained through a different incantation,
getInterface(nsIDOMWindowUtils). Events are suppressed during debugging
now. Thanks Boris once again.

jjb

Steven Roussey

unread,
Nov 5, 2009, 3:24:34 PM11/5/09
to
On Nov 5, 9:44 am, Boris Zbarsky <bzbar...@mit.edu> wrote:
> On 11/5/09 12:48 PM, John J. Barton wrote:
>
> > I am confused because Firebug works pretty well for several years then
> > suddenly we learn that a fundamental aspect was broken the whole time.

I think people give Firebug a bit of leeway. It is an extension after
all, written in JS itself. I don't know if people expect the same kind
of correctness from it as they would if it were part of Firefox itself
(IE4 and Script Debugger nailed correctness a long time ago). Firebug
is so feaking usable, we all overlook any of its flaws...

Not to mention the people that know what is going on probably find it
in their own interests to just hack around this issue. It is like all
the Fx bugs related to display:none that have been around near a
decade. Real developers know that it is a lot of work to create real
bug reports. Casual developers won't be able to tell you what the
problem really is. Bug reports are a bad indicator of importance
anyway. Hearing people curse at their PCs can be more telling. ;)

> Chances are:
>
> 1)  It didn't actually work as well as you thought it did.
> 2)  The hard cases that cause it to completely fall down
>      are comparatively rare.

3) Lots of people use helper JS libs like ExtCore, ExtJS, jQuery, YUI,
etc. They all have work-arounds to some degree.

-s

Boris Zbarsky

unread,
Nov 5, 2009, 5:28:54 PM11/5/09
to
On 11/5/09 3:24 PM, Steven Roussey wrote:
> Not to mention the people that know what is going on probably find it
> in their own interests to just hack around this issue. It is like all
> the Fx bugs related to display:none that have been around near a
> decade.

Uh... example?

-Boris

Boris Zbarsky

unread,
Nov 5, 2009, 5:29:42 PM11/5/09
to
On 11/5/09 3:33 PM, John J. Barton wrote:
> Like quick tests often are, that result was just bogus, the interface
> has to be obtained through a different incantation,
> getInterface(nsIDOMWindowUtils). Events are suppressed during debugging
> now. Thanks Boris once again.

Hey, I didn't even know we had that exposed on nsIDOMWindowUtils. I was
figuring we'd need to add more black magic into jsd. Good to know we
don't. ;)

-Boris

Steven Roussey

unread,
Nov 6, 2009, 3:28:49 AM11/6/09
to

I don't want to waste your time. There are bug reports already out
there. But take a div and try throwing a flash object or an iframe set
to design mode and then set the div to display none and back. The
videos get reset to the beginning (or whatever the flash object was)
and design mode changes in a display none (worse -- in a block that
switches to display none during the asyncronous design mode change) is
just a bag of hurt. The flash issue has been around a decade, and
it's hard to worry too much about display none and design mode when
creating a wysiwyg editor has so many other freaky bugs to worry
about. Display:none has some other weird side effects on stuff. I'd
have to check on code I've written to remember. Though, that's the
point. I've gotten over that hurdle. So I'm ahead of those who have
not. So I no longer care that they get fixed.

And it's fun to see when projects get to the point where they come up
with workarounds. Leaking anon divs into user's js code comes to mind.
You can look at comit times for that workaround in jquey, dojo, extjs,
mootools, etc to see when their code became useful enough and used
enough to show the bug and demand a fix. Last I looked, only ExtJs
found a workaround that got around the security context error and this
doesn't need a try/catch. That bug in Fx is now fixed, btw.

Steven Roussey

unread,
Nov 6, 2009, 3:32:19 AM11/6/09
to

Even better, John already comitted a fix to svn! Woohoo!

-Steve--

Boris Zbarsky

unread,
Nov 6, 2009, 9:02:33 AM11/6/09
to
On 11/6/09 3:28 AM, Steven Roussey wrote:
> But take a div and try throwing a flash object or an iframe set
> to design mode and then set the div to display none and back. The
> videos get reset to the beginning (or whatever the flash object was)
> and design mode changes in a display none (worse -- in a block that
> switches to display none during the asyncronous design mode change) is
> just a bag of hurt.

Ah, ok. So not display:none per se, but issues where state is stored in
frames. Sure. That makes a lot more sense.

-Boris

0 new messages