Difference between revisions of "Jsd"

From FirebugWiki
Jump to: navigation, search
(Relationship to js engine.)
Line 99: Line 99:
== Relationship to js engine. ==
== Relationship to js engine. ==
Edit section
At various points the js engine will call functions that may result in debugger hook calls. For example, the function js_CallNewScriptHook is called five places:
At various points the js engine will call functions that may result in debugger hook calls. For example, the function js_CallNewScriptHook is called five places:

Revision as of 14:59, 15 December 2009


Implementation of the JavaScript interface for debugging Javascript

Source is under js/jsd in the mozilla tree.


definitions of the entry points. Javascript calls these. For example code see Firebug's firebug-service.js. Here is how the onScriptCreated hook is set in firebug:

      jsd.scriptHook = {
           onScriptCreated: hook(this.onScriptCreated),
           onScriptDestroyed: hook(this.onScriptDestroyed)


C++ implementations of the jsdIDebuggerService interfaces. Defines the jsdService object that receives the get/set calls for hooks from Javascript. For example, jsdService::SetScriptHook implements the setter for jsdIDebuggerService.scriptHook.

The set calls store the hook reference and set hooks into a deeper layer called JSD_ Note the caps on this one. The hook function in this C++ file is a static void function with parameters that are JSDContext and other JSD* things (note again the caps). For example, the SetScriptHook() function above calls JSD_SetScriptHook(mCx, jsds_ScriptHookProc, null), where the function jsds_ScriptHookProc is define in this file to match the C function declaration in jsdebug.h.

static void jsds_ScriptHookProc (JSDContext* jsdc, JSDScript* jsdscript, JSBool creating, void* callerdata)


Glue between jsd_xpc.cpp and C code. The header file defines C types callable by the C++ functions in jsd_xpc.cpp. For example,

typedef void (* JSD_ScriptHookProc)(JSDContext* jsdc, JSDScript* jsdscript, JSBool creating, void* callerdata);

Also the header declares the C functions to accept these hook calls, like:

 JSD_SetScriptHook(JSDContext* jsdc, JSD_ScriptHookProc hook, void* callerdata);


C implementations of the JSD_ functions. Unfortunately the implementations are silly they just call jsd_ (lower case) functions declared in jsd.h

JSD_SetScriptHook(JSDContext* jsdc, JSD_ScriptHookProc hook, void* callerdata)
   return jsd_SetScriptHook(jsdc, hook, callerdata);


Declarations of the jsd_ functions called by jsdebug.c. For example:

extern JSBool
jsd_SetScriptHook(JSDContext* jsdc, JSD_ScriptHookProc hook, void* callerdata);

This header is included in a lot of files in the jsd directory, so every time you touch it lots of things get compiled.


Definitions of jsdIScript focused functions of jsd.h. For example

jsd_SetScriptHook(JSDContext* jsdc, JSD_ScriptHookProc hook, void* callerdata)
   jsdc->scriptHook = hook;
   jsdc->scriptHookData = callerdata;
   return JS_TRUE;

So the original Javascript causes the JSDContext to have a field set to a function pointer.

Also in this file is the call to the hook, in the function jsd_NewScriptHookProc:

hook = jsdc->scriptHook; 
if( hook )
       hook(jsdc, jsdscript, JS_TRUE, hookData);

So every time we call jsd_NewScriptHookProc it looks to see if the scriptHook has been set, and if so calls it.

(The function jsd_NewScriptHookProc is called by jsd_ScriptCreated (it only reorders the arguments) and that called by JSD_ScriptCreated back in jsdebug.c. Note again the caps. This path is a dead end). jsd_high.c Edit section

Support for creating jsd wrappers around the JS Context, for turning jsd on and off, and the error reporting connection for jsd. Near the top of the file is jsd_DebuggerOnForUser, which loads all of the pointers like jsd_NewScriptHookProc into the Javascript engine with statements like:

JS_SetNewScriptHookProc(jsdc->jsrt, jsd_NewScriptHookProc, jsdc);

In js/jsdbgapi.cpp, part of the JS engine, we store the hook pointers:

JS_SetNewScriptHook(JSRuntime *rt, JSNewScriptHook hook, void *callerdata) { 
     rt->globalDebugHooks.newScriptHook = hook;      
     rt->globalDebugHooks.newScriptHookData = callerdata;  

These functions like newScriptHook will be by the JS engine at appropriate points, but they will not call back towards Javascript unless jsdIDebuggerService has set hooks into the jsd_xpc layer.

Relationship to js engine.

At various points the js engine will call functions that may result in debugger hook calls. For example, the function js_CallNewScriptHook is called five places:

  1. jsscript.cpp script_compile_sub, the script comes from JSCompiler::compileScript.
  2. jsscript.cpp, script_thaw, the script come from js_XDRScript()
  3. jsscript.cpp js_NewScriptFromCG, the script comes from js_NewScript();
  4. jsxdrapi.cpp js_XDRScript, the script is passed in (see case #2 above).
  5. jsfun.cpp js_XDRFunctionObject, the script seems to come from js_XDRScript in case #4? These are called on startup ReadScriptFromStream().

Platform callers of Javascript compile functions.

Observations for Bug 449464.

script tag

Since I have no idea how the js engine works, I am running the debugger and taking a look. Setting a breakpoint on js_CallNewScriptHook() hits when we compile a script tag.

  • JS_EvaluateUCScriptForPrincipals() calls JSCompiler::compileScript then executes the return value (probably the outerScript). It has the source as a string, chars and length. The second argument is the scope obj. We have to put the onCompilationEnd() call between the compile and execute.
  • Two frames older has nsScriptLoader.EvaluateScript(). The loader has mCurrentScript pointing to an element. If we put the onCompilationBegin() call here we have the includer and source. This function is in content/base/src, so the function we call has to be declared in jsprvtd.h.
  • The context object has GetProcessingScriptTag()
  • For web pages nsscriptLoader fires an event before compiling and after evaluating. There is an nsIScriptLoader interface and an observer for these events but apparently no way to get the loader in JS.


   * XBLProtoImplMethod Calls nsIScriptContext.CompileFunction
   * XBLProtoImplProperty Apparently this is for getter and setters. Calls nsIScriptContext.CompileFunction