Back to index

lightning-sunbird  0.9+nobinonly
Classes | Public Member Functions | Protected Member Functions | Protected Attributes | Static Private Member Functions | Private Attributes | Friends
nsJSContext Class Reference

#include <nsJSEnvironment.h>

Inheritance diagram for nsJSContext:
Inheritance graph
[legend]
Collaboration diagram for nsJSContext:
Collaboration graph
[legend]

List of all members.

Classes

struct  TerminationFuncClosure
struct  TerminationFuncHolder

Public Member Functions

 nsJSContext (JSRuntime *aRuntime)
virtual ~nsJSContext ()
virtual NS_DECL_ISUPPORTS nsresult EvaluateString (const nsAString &aScript, void *aScopeObject, nsIPrincipal *principal, const char *aURL, PRUint32 aLineNo, const char *aVersion, nsAString *aRetValue, PRBool *aIsUndefined)
 Compile and execute a script.
virtual nsresult EvaluateStringWithValue (const nsAString &aScript, void *aScopeObject, nsIPrincipal *aPrincipal, const char *aURL, PRUint32 aLineNo, const char *aVersion, void *aRetValue, PRBool *aIsUndefined)
virtual nsresult CompileScript (const PRUnichar *aText, PRInt32 aTextLength, void *aScopeObject, nsIPrincipal *principal, const char *aURL, PRUint32 aLineNo, const char *aVersion, void **aScriptObject)
 Compile a script.
virtual nsresult ExecuteScript (void *aScriptObject, void *aScopeObject, nsAString *aRetValue, PRBool *aIsUndefined)
 Execute a precompiled script object.
virtual nsresult CompileEventHandler (void *aTarget, nsIAtom *aName, const char *aEventName, const nsAString &aBody, const char *aURL, PRUint32 aLineNo, PRBool aShared, void **aHandler)
 Compile the event handler named by atom aName, with function body aBody into a function object returned if ok via *aHandler.
virtual nsresult CallEventHandler (JSObject *aTarget, JSObject *aHandler, uintN argc, jsval *argv, jsval *rval)
 Call the function object with given args and return its boolean result, or true if the result isn't boolean.
virtual nsresult BindCompiledEventHandler (void *aTarget, nsIAtom *aName, void *aHandler)
 Bind an already-compiled event handler function to a name in the given scope object.
virtual nsresult CompileFunction (void *aTarget, const nsACString &aName, PRUint32 aArgCount, const char **aArgArray, const nsAString &aBody, const char *aURL, PRUint32 aLineNo, PRBool aShared, void **aFunctionObject)
virtual void SetDefaultLanguageVersion (const char *aVersion)
 Set the default scripting language version for this context, which must be a context specific to a particular scripting language.
virtual nsIScriptGlobalObjectGetGlobalObject ()
 Return the global object.
virtual voidGetNativeContext ()
 Return the native script context.
virtual nsresult InitContext (nsIScriptGlobalObject *aGlobalObject)
 Init this context.
virtual PRBool IsContextInitialized ()
 Check to see if context is as yet intialized.
virtual void GC ()
 For garbage collected systems, do a synchronous collection pass.
virtual void ScriptEvaluated (PRBool aTerminated)
 Inform the context that a script was evaluated.
virtual void SetOwner (nsIScriptContextOwner *owner)
 Let the script context know who its owner is.
virtual nsIScriptContextOwnerGetOwner ()
 Get the script context of the owner.
virtual nsresult SetTerminationFunction (nsScriptTerminationFunc aFunc, nsISupports *aRef)
 Called to specify a function that should be called when the current script (if there is one) terminates.
virtual PRBool GetScriptsEnabled ()
 Called to disable/enable script execution in this context.
virtual void SetScriptsEnabled (PRBool aEnabled, PRBool aFireTimeouts)
virtual PRBool GetProcessingScriptTag ()
 Called to set/get information if the script context is currently processing a script tag.
virtual void SetProcessingScriptTag (PRBool aResult)
virtual void SetGCOnDestruction (PRBool aGCOnDestruction)
 Tell the context whether or not to GC when destroyed.
virtual nsresult InitClasses (JSObject *aGlobalObj)
 Initialize DOM classes on aGlobalObj, always call WillInitializeContext() before calling InitContext(), and always call DidInitializeContext() when a context is fully (successfully) initialized.
virtual void WillInitializeContext ()
 Tell the context we're about to be reinitialize it.
virtual void DidInitializeContext ()
 Dell the context we're done reinitializing it.
void ScriptExecuted ()
 Method invoked when a script has been executed by XPConnect.
void preserveWrapper (in nsIXPConnectWrappedNative wrapper)
 Method invoked to preserve an nsIXPConnectWrappedNative as needed.
void notify (in nsITimer timer)

Protected Member Functions

nsresult InitializeExternalClasses ()
nsresult InitializeLiveConnectClasses (JSObject *aGlobalObj)
nsresult FindXPCNativeWrapperClass (nsIXPConnectJSObjectHolder *aHolder)
void FireGCTimer ()

Protected Attributes

TerminationFuncClosuremTerminations

Static Private Member Functions

static int PR_CALLBACK JSOptionChangedCallback (const char *pref, void *data)
static JSBool JS_DLL_CALLBACK DOMBranchCallback (JSContext *cx, JSScript *script)

Private Attributes

JSContextmContext
PRUint32 mNumEvaluations
nsIScriptContextOwnermOwner
PRPackedBool mIsInitialized
PRPackedBool mScriptsEnabled
PRPackedBool mGCOnDestruction
PRPackedBool mProcessingScriptTag
PRPackedBool mIsTrackingChromeCodeTime
PRUint32 mBranchCallbackCount
PRTime mBranchCallbackTime
PRUint32 mDefaultJSOptions
nsCOMPtr< nsISupports > mGlobalWrapperRef

Friends

struct TerminationFuncHolder

Detailed Description

Definition at line 51 of file nsJSEnvironment.h.


Constructor & Destructor Documentation

Definition at line 720 of file nsJSEnvironment.cpp.

                                            : mGCOnDestruction(PR_TRUE)
{

  ++sContextCount;

  mDefaultJSOptions = JSOPTION_PRIVATE_IS_NSISUPPORTS
                    | JSOPTION_NATIVE_BRANCH_CALLBACK
#ifdef DEBUG
                    | JSOPTION_STRICT   // lint catching for development
#endif
    ;

  // Let xpconnect resync its JSContext tracker. We do this before creating
  // a new JSContext just in case the heap manager recycles the JSContext
  // struct.
  nsContentUtils::XPConnect()->SyncJSContexts();

  mContext = ::JS_NewContext(aRuntime, gStackSize);
  if (mContext) {
    ::JS_SetContextPrivate(mContext, NS_STATIC_CAST(nsIScriptContext *, this));

    // Make sure the new context gets the default context options
    ::JS_SetOptions(mContext, mDefaultJSOptions);

    // Check for the JS strict option, which enables extra error checks
    nsContentUtils::RegisterPrefCallback(js_options_dot_str,
                                         JSOptionChangedCallback,
                                         this);
    JSOptionChangedCallback(js_options_dot_str, this);

    ::JS_SetBranchCallback(mContext, DOMBranchCallback);

    static JSLocaleCallbacks localeCallbacks =
      {
        LocaleToUpperCase,
        LocaleToLowerCase,
        LocaleCompare,
        LocaleToUnicode
      };

    ::JS_SetLocaleCallbacks(mContext, &localeCallbacks);
  }
  mIsInitialized = PR_FALSE;
  mNumEvaluations = 0;
  mOwner = nsnull;
  mTerminations = nsnull;
  mScriptsEnabled = PR_TRUE;
  mBranchCallbackCount = 0;
  mBranchCallbackTime = LL_ZERO;
  mProcessingScriptTag = PR_FALSE;
  mIsTrackingChromeCodeTime = PR_FALSE;

  InvalidateContextAndWrapperCache();
}

Here is the call graph for this function:

Definition at line 775 of file nsJSEnvironment.cpp.

{
  NS_PRECONDITION(!mTerminations, "Shouldn't have termination funcs by now");
                  
  // Cope with JS_NewContext failure in ctor (XXXbe move NewContext to Init?)
  if (!mContext)
    return;

  // Clear our entry in the JSContext, bugzilla bug 66413
  ::JS_SetContextPrivate(mContext, nsnull);

  // Clear the branch callback, bugzilla bug 238218
  ::JS_SetBranchCallback(mContext, nsnull);

  // Unregister our "javascript.options.*" pref-changed callback.
  nsContentUtils::UnregisterPrefCallback(js_options_dot_str,
                                         JSOptionChangedCallback,
                                         this);

  // Release mGlobalWrapperRef before the context is destroyed
  mGlobalWrapperRef = nsnull;

  // Let xpconnect destroy the JSContext when it thinks the time is right.
  nsIXPConnect *xpc = nsContentUtils::XPConnect();
  if (xpc) {
    PRBool do_gc = mGCOnDestruction && !sGCTimer && sReadyForGC;

    xpc->ReleaseJSContext(mContext, !do_gc);
  } else {
    ::JS_DestroyContext(mContext);
  }

  --sContextCount;

  if (!sContextCount && sDidShutdown) {
    // The last context is being deleted, and we're already in the
    // process of shutting down, release the JS runtime service, and
    // the security manager.

    NS_IF_RELEASE(sRuntimeService);
    NS_IF_RELEASE(sSecurityManager);
    NS_IF_RELEASE(gCollation);
    NS_IF_RELEASE(gDecoder);
  }
}

Here is the call graph for this function:


Member Function Documentation

nsresult nsJSContext::BindCompiledEventHandler ( void aTarget,
nsIAtom aName,
void aHandler 
) [virtual]

Bind an already-compiled event handler function to a name in the given scope object.

The same restrictions on aName (lowercase ASCII, not too long) applies here as for CompileEventHandler. Scripting languages with static scoping must re-bind the scope chain for aHandler to begin (after the activation scope for aHandler itself, typically) with aTarget's scope.

Parameters:
aTargetan object telling the scope in which to bind the compiled event handler function.
aNamean nsIAtom pointer naming the function; it must be lowercase and ASCII, and should not be longer than 63 chars. This bound on length is enforced only by assertions, so caveat caller!
aHandlerthe function object to name, created by an earlier call to CompileEventHandler
Returns:
NS_OK if the function was successfully bound to the name

Implements nsIScriptContext.

Definition at line 1540 of file nsJSEnvironment.cpp.

{
  NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);

  const char *charName = AtomToEventHandlerName(aName);

  JSObject *funobj = (JSObject*) aHandler;
  JSObject *target = (JSObject*) aTarget;

  nsresult rv;

  // Push our JSContext on our thread's context stack, in case native code
  // called from JS calls back into JS via XPConnect.
  nsCOMPtr<nsIJSContextStack> stack =
           do_GetService("@mozilla.org/js/xpc/ContextStack;1", &rv);
  if (NS_FAILED(rv) || NS_FAILED(stack->Push(mContext))) {
    return NS_ERROR_FAILURE;
  }

  // Make sure the handler function is parented by its event target object
  if (funobj && ::JS_GetParent(mContext, funobj) != target) {
    funobj = ::JS_CloneFunctionObject(mContext, funobj, target);
    if (!funobj)
      rv = NS_ERROR_OUT_OF_MEMORY;
  }

  if (NS_SUCCEEDED(rv) &&
      !::JS_DefineProperty(mContext, target, charName,
                           OBJECT_TO_JSVAL(funobj), nsnull, nsnull,
                           JSPROP_ENUMERATE | JSPROP_PERMANENT)) {
    rv = NS_ERROR_FAILURE;
  }

  if (NS_FAILED(stack->Pop(nsnull)) && NS_SUCCEEDED(rv)) {
    rv = NS_ERROR_FAILURE;
  }

  return rv;
}

Here is the call graph for this function:

nsresult nsJSContext::CallEventHandler ( JSObject aTarget,
JSObject aHandler,
uintN  argc,
jsval argv,
jsval rval 
) [virtual]

Call the function object with given args and return its boolean result, or true if the result isn't boolean.

Parameters:
aTargetan object telling the scope in which to bind the compiled event handler function.
aHandlerfunction object (function and static scope) to invoke.
argcactual argument count; length of argv
argvvector of arguments; length is argc
aBoolResultout parameter returning boolean function result, or true if the result was not boolean.

Implements nsIScriptContext.

Definition at line 1429 of file nsJSEnvironment.cpp.

{
  NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);

  *rval = JSVAL_VOID;

  if (!mScriptsEnabled) {
    return NS_OK;
  }

  // This one's a lot easier than EvaluateString because we don't have to
  // hassle with principals: they're already compiled into the JS function.
  nsresult rv;

  nsCOMPtr<nsIJSContextStack> stack =
    do_GetService("@mozilla.org/js/xpc/ContextStack;1", &rv);
  if (NS_FAILED(rv) || NS_FAILED(stack->Push(mContext)))
    return NS_ERROR_FAILURE;

  // check if the event handler can be run on the object in question
  rv = sSecurityManager->CheckFunctionAccess(mContext, aHandler, aTarget);
  if (NS_SUCCEEDED(rv)) {
    // We're not done yet!  Some event listeners are confused about their
    // script context, so check whether we might actually be the wrong script
    // context.  To be safe, do CheckFunctionAccess checks for both.
    nsCOMPtr<nsIContent> content;
    const JSClass *jsClass = JS_GET_CLASS(mContext, aTarget);
    if (jsClass &&
        !((~jsClass->flags) & (JSCLASS_HAS_PRIVATE |
                               JSCLASS_PRIVATE_IS_NSISUPPORTS))) {
      nsISupports *priv =
        NS_STATIC_CAST(nsISupports *, JS_GetPrivate(mContext, aTarget));
      nsCOMPtr<nsIXPConnectWrappedNative> xpcWrapper = do_QueryInterface(priv);
      if (xpcWrapper) {
        content = do_QueryWrappedNative(xpcWrapper);
      }
    }
    if (content) {
      // XXXbz XBL2/sXBL issue
      nsIDocument* ownerDoc = content->GetOwnerDoc();
      if (ownerDoc) {
        nsIScriptGlobalObject* global = ownerDoc->GetScriptGlobalObject();
        if (global) {
          nsIScriptContext* context = global->GetContext();
          if (context && context != this) {
            JSContext* cx =
              NS_STATIC_CAST(JSContext*, context->GetNativeContext());
            rv = stack->Push(cx);
            if (NS_SUCCEEDED(rv)) {
              rv = sSecurityManager->CheckFunctionAccess(cx, aHandler,
                                                         aTarget);
              // Here we lose no matter what; we don't want to leave the wrong
              // cx on the stack.  I guess default to leaving mContext, to
              // cover those cases when we really do have a different context
              // for the handler and the node.  That's probably safer.
              if (NS_FAILED(stack->Pop(nsnull))) {
                return NS_ERROR_FAILURE;
              }
            }
          }
        }
      }
    }
  }

  nsJSContext::TerminationFuncHolder holder(this);

  if (NS_SUCCEEDED(rv)) {
    jsval funval = OBJECT_TO_JSVAL(aHandler);
    PRBool ok = ::JS_CallFunctionValue(mContext, aTarget, funval, argc, argv,
                                       rval);

    if (!ok) {
      // Tell XPConnect about any pending exceptions. This is needed
      // to avoid dropping JS exceptions in case we got here through
      // nested calls through XPConnect.

      nsContentUtils::NotifyXPCIfExceptionPending(mContext);

      // Don't pass back results from failed calls.
      *rval = JSVAL_VOID;

      // Tell the caller that the handler threw an error.
      rv = NS_ERROR_FAILURE;
    }
  }

  if (NS_FAILED(stack->Pop(nsnull)))
    return NS_ERROR_FAILURE;

  // Need to lock, since ScriptEvaluated can GC.
  PRBool locked = PR_FALSE;
  if (NS_SUCCEEDED(rv) && JSVAL_IS_GCTHING(*rval)) {
    locked = ::JS_LockGCThing(mContext, JSVAL_TO_GCTHING(*rval));
    if (!locked) {
      rv = NS_ERROR_OUT_OF_MEMORY;
    }
  }

  // ScriptEvaluated needs to come after we pop the stack
  ScriptEvaluated(PR_TRUE);

  if (locked) {
    ::JS_UnlockGCThing(mContext, JSVAL_TO_GCTHING(*rval));
  }

  return rv;
}

Here is the call graph for this function:

nsresult nsJSContext::CompileEventHandler ( void aTarget,
nsIAtom aName,
const char *  aEventName,
const nsAString &  aBody,
const char *  aURL,
PRUint32  aLineNo,
PRBool  aShared,
void **  aHandler 
) [virtual]

Compile the event handler named by atom aName, with function body aBody into a function object returned if ok via *aHandler.

Bind the lowercase ASCII name to the function in its parent object aTarget.

Parameters:
aTargetan object telling the scope in which to bind the compiled event handler function to aName.
aNamean nsIAtom pointer naming the function; it must be lowercase and ASCII, and should not be longer than 63 chars. This bound on length is enforced only by assertions, so caveat caller!
aEventNamethe name that the event object should be bound to
aBodythe event handler function's body
aURLthe URL or filename for error messages
aLineNothe starting line number of the script for error messages
aSharedflag telling whether the compiled event handler will be shared via nsIScriptEventHandlerOwner, in which case any static link compiled into it based on aTarget should be cleared, both to avoid entraining garbage to be collected, and to trigger static link re-binding in BindCompiledEventHandler (see below).
aHandlerthe out parameter in which a void pointer to the compiled function object is returned on success; may be null, meaning the caller doesn't need to store the handler for later use.
Returns:
NS_OK if the function body was valid and got compiled

Implements nsIScriptContext.

Definition at line 1321 of file nsJSEnvironment.cpp.

{
  NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);

  if (!sSecurityManager) {
    NS_ERROR("Huh, we need a script security manager to compile "
             "an event handler!");

    return NS_ERROR_UNEXPECTED;
  }

  JSObject *target = (JSObject*)aTarget;

  JSPrincipals *jsprin = nsnull;

  if (target) {
    // Get the principal of the event target (the object principal),
    // don't get the principal of the global object in this context
    // since that opens up security exploits with delayed event
    // handler compilation on stale DOM objects (objects that live in
    // a document that has already been unloaded).
    nsCOMPtr<nsIPrincipal> prin;
    nsresult rv = sSecurityManager->GetObjectPrincipal(mContext, target,
                                                       getter_AddRefs(prin));
    NS_ENSURE_SUCCESS(rv, rv);

    prin->GetJSPrincipals(mContext, &jsprin);
    NS_ENSURE_TRUE(jsprin, NS_ERROR_NOT_AVAILABLE);
  }

  const char *charName = AtomToEventHandlerName(aName);

  const char *argList[] = { aEventName };

  JSFunction* fun =
      ::JS_CompileUCFunctionForPrincipals(mContext,
                                          aShared ? nsnull : target, jsprin,
                                          charName, 1, argList,
                                          (jschar*)PromiseFlatString(aBody).get(),
                                          aBody.Length(),
                                          aURL, aLineNo);

  if (jsprin) {
    JSPRINCIPALS_DROP(mContext, jsprin);
  }
  if (!fun) {
    return NS_ERROR_FAILURE;
  }

  JSObject *handler = ::JS_GetFunctionObject(fun);
  if (aHandler)
    *aHandler = (void*) handler;
  return NS_OK;
}

Here is the call graph for this function:

nsresult nsJSContext::CompileFunction ( void aTarget,
const nsACString &  aName,
PRUint32  aArgCount,
const char **  aArgArray,
const nsAString &  aBody,
const char *  aURL,
PRUint32  aLineNo,
PRBool  aShared,
void **  aFunctionObject 
) [virtual]

Implements nsIScriptContext.

Definition at line 1381 of file nsJSEnvironment.cpp.

{
  NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);

  JSPrincipals *jsprin = nsnull;

  nsIScriptGlobalObject *global = GetGlobalObject();
  if (global) {
    // XXXbe why the two-step QI? speed up via a new GetGlobalObjectData func?
    nsCOMPtr<nsIScriptObjectPrincipal> globalData = do_QueryInterface(global);
    if (globalData) {
      nsIPrincipal *prin = globalData->GetPrincipal();
      if (!prin)
        return NS_ERROR_FAILURE;
      prin->GetJSPrincipals(mContext, &jsprin);
    }
  }

  JSObject *target = (JSObject*)aTarget;
  JSFunction* fun =
      ::JS_CompileUCFunctionForPrincipals(mContext,
                                          aShared ? nsnull : target, jsprin,
                                          PromiseFlatCString(aName).get(),
                                          aArgCount, aArgArray,
                                          (jschar*)PromiseFlatString(aBody).get(),
                                          aBody.Length(),
                                          aURL, aLineNo);

  if (jsprin)
    JSPRINCIPALS_DROP(mContext, jsprin);
  if (!fun)
    return NS_ERROR_FAILURE;

  JSObject *handler = ::JS_GetFunctionObject(fun);
  if (aFunctionObject)
    *aFunctionObject = (void*) handler;
  return NS_OK;
}

Here is the call graph for this function:

nsresult nsJSContext::CompileScript ( const PRUnichar aText,
PRInt32  aTextLength,
void aScopeObject,
nsIPrincipal aPrincipal,
const char *  aURL,
PRUint32  aLineNo,
const char *  aVersion,
void **  aScriptObject 
) [virtual]

Compile a script.

Parameters:
aTexta PRUnichar buffer containing script source
aTextLengthnumber of characters in aText
aScopeObjectan object telling the scope in which to execute, or nsnull to use a default scope
aPrincipalthe principal that produced the script
aURLthe URL or filename for error messages
aLineNothe starting line number of the script for error messages
aVersionthe script language version to use when executing
aScriptObjectan executable object that's the result of compiling the script. The caller is responsible for GC rooting this object.
Returns:
NS_OK if the script source was valid and got compiled

Implements nsIScriptContext.

Definition at line 1151 of file nsJSEnvironment.cpp.

{
  NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);

  nsresult rv;
  NS_ENSURE_ARG_POINTER(aPrincipal);

  if (!aScopeObject)
    aScopeObject = ::JS_GetGlobalObject(mContext);

  JSPrincipals *jsprin;
  aPrincipal->GetJSPrincipals(mContext, &jsprin);
  // From here on, we must JSPRINCIPALS_DROP(jsprin) before returning...

  PRBool ok = PR_FALSE;

  rv = sSecurityManager->CanExecuteScripts(mContext, aPrincipal, &ok);
  if (NS_FAILED(rv)) {
    JSPRINCIPALS_DROP(mContext, jsprin);
    return NS_ERROR_FAILURE;
  }

  *aScriptObject = nsnull;
  if (ok) {
    JSVersion newVersion = JSVERSION_UNKNOWN;

    // SecurityManager said "ok", but don't compile if aVersion is specified
    // and unknown.  Do compile with the default version (and avoid thrashing
    // the context's version) if aVersion is not specified.
    if (!aVersion ||
        (newVersion = ::JS_StringToVersion(aVersion)) != JSVERSION_UNKNOWN) {
      JSVersion oldVersion = JSVERSION_UNKNOWN;
      if (aVersion)
        oldVersion = ::JS_SetVersion(mContext, newVersion);

      JSScript* script =
        ::JS_CompileUCScriptForPrincipals(mContext,
                                          (JSObject*) aScopeObject,
                                          jsprin,
                                          (jschar*) aText,
                                          aTextLength,
                                          aURL,
                                          aLineNo);
      if (script) {
        *aScriptObject = (void*) ::JS_NewScriptObject(mContext, script);
        if (! *aScriptObject) {
          ::JS_DestroyScript(mContext, script);
          script = nsnull;
        }
      }
      if (!script)
        rv = NS_ERROR_OUT_OF_MEMORY;

      if (aVersion)
        ::JS_SetVersion(mContext, oldVersion);
    }
  }

  // Whew!  Finally done with these manually ref-counted things.
  JSPRINCIPALS_DROP(mContext, jsprin);
  return rv;
}

Here is the call graph for this function:

Dell the context we're done reinitializing it.

Implements nsIScriptContext.

Definition at line 2101 of file nsJSEnvironment.cpp.

JSBool JS_DLL_CALLBACK nsJSContext::DOMBranchCallback ( JSContext cx,
JSScript script 
) [static, private]

Definition at line 497 of file nsJSEnvironment.cpp.

{
  // Get the native context
  nsJSContext *ctx = NS_STATIC_CAST(nsJSContext *, ::JS_GetContextPrivate(cx));

  PRUint32 callbackCount = ++ctx->mBranchCallbackCount;

  if (callbackCount & INITIALIZE_TIME_BRANCH_COUNT_MASK) {
    return JS_TRUE;
  }

  if (callbackCount == INITIALIZE_TIME_BRANCH_COUNT_MASK + 1 &&
      LL_IS_ZERO(ctx->mBranchCallbackTime)) {
    // Initialize mBranchCallbackTime to start timing how long the
    // script has run
    ctx->mBranchCallbackTime = PR_Now();

    ctx->mIsTrackingChromeCodeTime =
      ::JS_IsSystemObject(cx, ::JS_GetGlobalObject(cx));

    return JS_TRUE;
  }

  if (callbackCount & MAYBE_GC_BRANCH_COUNT_MASK) {
    return JS_TRUE;
  }

  // XXX Save the branch callback time so we can restore it after the GC,
  // because GCing can cause JS to run on our context, causing our
  // ScriptEvaluated to be called, and clearing our branch callback time and
  // count. See bug 302333.
  PRTime callbackTime = ctx->mBranchCallbackTime;

  // Run the GC if we get this far.
  JS_MaybeGC(cx);

  // Now restore the callback time and count, in case they got reset.
  ctx->mBranchCallbackTime = callbackTime;
  ctx->mBranchCallbackCount = callbackCount;

  PRTime now = PR_Now();

  PRTime duration;
  LL_SUB(duration, now, callbackTime);

  // Check the amount of time this script has been running
  if (duration < (ctx->mIsTrackingChromeCodeTime ?
                  sMaxChromeScriptRunTime : sMaxScriptRunTime)) {
    return JS_TRUE;
  }

  // If we get here we're most likely executing an infinite loop in JS,
  // we'll tell the user about this and we'll give the user the option
  // of stopping the execution of the script.
  nsIScriptGlobalObject *global = ctx->GetGlobalObject();
  NS_ENSURE_TRUE(global, JS_TRUE);

  nsIDocShell *docShell = global->GetDocShell();
  NS_ENSURE_TRUE(docShell, JS_TRUE);

  nsCOMPtr<nsIInterfaceRequestor> ireq(do_QueryInterface(docShell));
  NS_ENSURE_TRUE(ireq, JS_TRUE);

  // Get the nsIPrompt interface from the docshell
  nsCOMPtr<nsIPrompt> prompt;
  ireq->GetInterface(NS_GET_IID(nsIPrompt), getter_AddRefs(prompt));
  NS_ENSURE_TRUE(prompt, JS_TRUE);

  nsresult rv;

  // Check if we should offer the option to debug
  PRBool debugPossible = (cx->runtime && cx->runtime->debuggerHandler);
#ifdef MOZ_JSDEBUGGER
  // Get the debugger service if necessary.
  if (debugPossible) {
    PRBool jsds_IsOn = PR_FALSE;
    const char jsdServiceCtrID[] = "@mozilla.org/js/jsd/debugger-service;1";
    nsCOMPtr<jsdIExecutionHook> jsdHook;  
    nsCOMPtr<jsdIDebuggerService> jsds = do_GetService(jsdServiceCtrID, &rv);
  
    // Check if there's a user for the debugger service that's 'on' for us
    if (NS_SUCCEEDED(rv)) {
      jsds->GetDebuggerHook(getter_AddRefs(jsdHook));
      jsds->GetIsOn(&jsds_IsOn);
      if (jsds_IsOn) { // If this is not true, the next call would start jsd...
        rv = jsds->OnForRuntime(cx->runtime);
        jsds_IsOn = NS_SUCCEEDED(rv);
      }
    }

    // If there is a debug handler registered for this runtime AND
    // ((jsd is on AND has a hook) OR (jsd isn't on (something else debugs)))
    // then something useful will be done with our request to debug.
    debugPossible = ((jsds_IsOn && (jsdHook != nsnull)) || !jsds_IsOn);
  }
#endif

  // Get localizable strings
  nsCOMPtr<nsIStringBundleService>
    stringService(do_GetService(NS_STRINGBUNDLE_CONTRACTID));
  if (!stringService)
    return JS_TRUE;

  nsCOMPtr<nsIStringBundle> bundle;
  stringService->CreateBundle(kDOMStringBundleURL, getter_AddRefs(bundle));
  if (!bundle)
    return JS_TRUE;

  nsXPIDLString title, msg, stopButton, waitButton, debugButton;

  rv = bundle->GetStringFromName(NS_LITERAL_STRING("KillScriptTitle").get(),
                                  getter_Copies(title));
  rv |= bundle->GetStringFromName(NS_LITERAL_STRING("StopScriptButton").get(),
                                  getter_Copies(stopButton));
  rv |= bundle->GetStringFromName(NS_LITERAL_STRING("WaitForScriptButton").get(),
                                  getter_Copies(waitButton));

  if (debugPossible) {
    rv |= bundle->GetStringFromName(NS_LITERAL_STRING("DebugScriptButton").get(),
                                    getter_Copies(debugButton));
    rv |= bundle->GetStringFromName(NS_LITERAL_STRING("KillScriptWithDebugMessage").get(),
                                   getter_Copies(msg));
  }
  else {
    rv |= bundle->GetStringFromName(NS_LITERAL_STRING("KillScriptMessage").get(),
                                   getter_Copies(msg));
  }

  //GetStringFromName can return NS_OK and still give NULL string
  if (NS_FAILED(rv) || !title || !msg || !stopButton || !waitButton ||
      (debugPossible && !debugButton)) {
    NS_ERROR("Failed to get localized strings.");
    return JS_TRUE;
  }

  PRInt32 buttonPressed = 1; //In case user exits dialog by clicking X
  PRUint32 buttonFlags = (nsIPrompt::BUTTON_TITLE_IS_STRING *
                          (nsIPrompt::BUTTON_POS_0 + nsIPrompt::BUTTON_POS_1));

  // Add a third button if necessary:
  if (debugPossible)
    buttonFlags += nsIPrompt::BUTTON_TITLE_IS_STRING * nsIPrompt::BUTTON_POS_2;

  // Open the dialog.
  rv = prompt->ConfirmEx(title, msg, buttonFlags, stopButton, waitButton,
                         debugButton, nsnull, nsnull, &buttonPressed);

  if (NS_FAILED(rv) || (buttonPressed == 1)) {
    // Allow the script to run this long again
    ctx->mBranchCallbackTime = PR_Now();
    return JS_TRUE;
  }
  else if ((buttonPressed == 2) && debugPossible) {
    // Debug the script
    jsval rval;
    switch(cx->runtime->debuggerHandler(cx, script, cx->fp->pc, &rval, 
                                        cx->runtime->debuggerHandlerData)) {
      case JSTRAP_RETURN:
        cx->fp->rval = rval;
        return JS_TRUE;
      case JSTRAP_ERROR:
        cx->throwing = JS_FALSE;
        return JS_FALSE;
      case JSTRAP_THROW:
        JS_SetPendingException(cx, rval);
        return JS_FALSE;
      case JSTRAP_CONTINUE:
      default:
        return JS_TRUE;
    }
  }

  return JS_FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult nsJSContext::EvaluateString ( const nsAString &  aScript,
void aScopeObject,
nsIPrincipal aPrincipal,
const char *  aURL,
PRUint32  aLineNo,
const char *  aVersion,
nsAString *  aRetValue,
PRBool aIsUndefined 
) [virtual]

Compile and execute a script.

Parameters:
aScripta string representing the script to be executed
aScopeObjecta JavaScript JSObject for the scope to execute in, or nsnull to use a default scope
aPrincipalthe principal that produced the script
aURLthe URL or filename for error messages
aLineNothe starting line number of the script for error messages
aVersionthe script language version to use when executing
aRetValuethe result of executing the script, or null for no result. If this is a JS context, it's the caller's responsibility to preserve aRetValue from GC across this call
aIsUndefinedtrue if the result of executing the script is the undefined value
Returns:
NS_OK if the script was valid and got executed

Implements nsIScriptContext.

Definition at line 1015 of file nsJSEnvironment.cpp.

{
  NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);

  if (!mScriptsEnabled) {
    *aIsUndefined = PR_TRUE;

    if (aRetValue) {
      aRetValue->Truncate();
    }

    return NS_OK;
  }

  nsresult rv;
  if (!aScopeObject)
    aScopeObject = ::JS_GetGlobalObject(mContext);

  // Safety first: get an object representing the script's principals, i.e.,
  // the entities who signed this script, or the fully-qualified-domain-name
  // or "codebase" from which it was loaded.
  JSPrincipals *jsprin;
  nsIPrincipal *principal = aPrincipal;
  if (aPrincipal) {
    aPrincipal->GetJSPrincipals(mContext, &jsprin);
  }
  else {
    nsCOMPtr<nsIScriptObjectPrincipal> objPrincipal =
      do_QueryInterface(GetGlobalObject(), &rv);
    if (NS_FAILED(rv))
      return NS_ERROR_FAILURE;
    principal = objPrincipal->GetPrincipal();
    if (!principal)
      return NS_ERROR_FAILURE;
    principal->GetJSPrincipals(mContext, &jsprin);
  }

  // From here on, we must JSPRINCIPALS_DROP(jsprin) before returning...

  PRBool ok = PR_FALSE;

  rv = sSecurityManager->CanExecuteScripts(mContext, principal, &ok);
  if (NS_FAILED(rv)) {
    JSPRINCIPALS_DROP(mContext, jsprin);
    return NS_ERROR_FAILURE;
  }

  // Push our JSContext on the current thread's context stack so JS called
  // from native code via XPConnect uses the right context.  Do this whether
  // or not the SecurityManager said "ok", in order to simplify control flow
  // below where we pop before returning.
  nsCOMPtr<nsIJSContextStack> stack =
           do_GetService("@mozilla.org/js/xpc/ContextStack;1", &rv);
  if (NS_FAILED(rv) || NS_FAILED(stack->Push(mContext))) {
    JSPRINCIPALS_DROP(mContext, jsprin);
    return NS_ERROR_FAILURE;
  }

  // The result of evaluation, used only if there were no errors.  This need
  // not be a GC root currently, provided we run the GC only from the branch
  // callback or from ScriptEvaluated.  TODO: use JS_Begin/EndRequest to keep
  // the GC from racing with JS execution on any thread.
  jsval val;

  nsJSContext::TerminationFuncHolder holder(this);
  if (ok) {
    JSVersion newVersion = JSVERSION_UNKNOWN;

    // SecurityManager said "ok", but don't execute if aVersion is specified
    // and unknown.  Do execute with the default version (and avoid thrashing
    // the context's version) if aVersion is not specified.
    ok = (!aVersion ||
          (newVersion = ::JS_StringToVersion(aVersion)) != JSVERSION_UNKNOWN);
    if (ok) {
      JSVersion oldVersion = JSVERSION_UNKNOWN;

      if (aVersion)
        oldVersion = ::JS_SetVersion(mContext, newVersion);
      ok = ::JS_EvaluateUCScriptForPrincipals(mContext,
                                              (JSObject *)aScopeObject,
                                              jsprin,
                                              (jschar*)PromiseFlatString(aScript).get(),
                                              aScript.Length(),
                                              aURL,
                                              aLineNo,
                                              &val);

      if (aVersion) {
        ::JS_SetVersion(mContext, oldVersion);
      }

      if (!ok) {
        // Tell XPConnect about any pending exceptions. This is needed
        // to avoid dropping JS exceptions in case we got here through
        // nested calls through XPConnect.

        nsContentUtils::NotifyXPCIfExceptionPending(mContext);
      }
    }
  }

  // Whew!  Finally done with these manually ref-counted things.
  JSPRINCIPALS_DROP(mContext, jsprin);

  // If all went well, convert val to a string (XXXbe unless undefined?).
  if (ok) {
    rv = JSValueToAString(mContext, val, aRetValue, aIsUndefined);
  }
  else {
    if (aIsUndefined) {
      *aIsUndefined = PR_TRUE;
    }

    if (aRetValue) {
      aRetValue->Truncate();
    }
  }

  // Pop here, after JS_ValueToString and any other possible evaluation.
  if (NS_FAILED(stack->Pop(nsnull)))
    rv = NS_ERROR_FAILURE;

  // ScriptEvaluated needs to come after we pop the stack
  ScriptEvaluated(PR_TRUE);

  return rv;
}

Here is the call graph for this function:

NS_INTERFACE_MAP_END nsresult nsJSContext::EvaluateStringWithValue ( const nsAString &  aScript,
void aScopeObject,
nsIPrincipal aPrincipal,
const char *  aURL,
PRUint32  aLineNo,
const char *  aVersion,
void aRetValue,
PRBool aIsUndefined 
) [virtual]

Implements nsIScriptContext.

Definition at line 835 of file nsJSEnvironment.cpp.

{
  NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);

  if (!mScriptsEnabled) {
    if (aIsUndefined) {
      *aIsUndefined = PR_TRUE;
    }

    return NS_OK;
  }

  nsresult rv;
  if (!aScopeObject)
    aScopeObject = ::JS_GetGlobalObject(mContext);

  // Safety first: get an object representing the script's principals, i.e.,
  // the entities who signed this script, or the fully-qualified-domain-name
  // or "codebase" from which it was loaded.
  JSPrincipals *jsprin;
  nsIPrincipal *principal = aPrincipal;
  if (aPrincipal) {
    aPrincipal->GetJSPrincipals(mContext, &jsprin);
  }
  else {
    nsIScriptGlobalObject *global = GetGlobalObject();
    if (!global)
      return NS_ERROR_FAILURE;
    nsCOMPtr<nsIScriptObjectPrincipal> objPrincipal =
      do_QueryInterface(global, &rv);
    if (NS_FAILED(rv))
      return NS_ERROR_FAILURE;
    principal = objPrincipal->GetPrincipal();
    if (!principal)
      return NS_ERROR_FAILURE;
    principal->GetJSPrincipals(mContext, &jsprin);
  }
  // From here on, we must JSPRINCIPALS_DROP(jsprin) before returning...

  PRBool ok = PR_FALSE;

  rv = sSecurityManager->CanExecuteScripts(mContext, principal, &ok);
  if (NS_FAILED(rv)) {
    JSPRINCIPALS_DROP(mContext, jsprin);
    return NS_ERROR_FAILURE;
  }

  // Push our JSContext on the current thread's context stack so JS called
  // from native code via XPConnect uses the right context.  Do this whether
  // or not the SecurityManager said "ok", in order to simplify control flow
  // below where we pop before returning.
  nsCOMPtr<nsIJSContextStack> stack =
           do_GetService("@mozilla.org/js/xpc/ContextStack;1", &rv);
  if (NS_FAILED(rv) || NS_FAILED(stack->Push(mContext))) {
    JSPRINCIPALS_DROP(mContext, jsprin);
    return NS_ERROR_FAILURE;
  }

  jsval val;

  nsJSContext::TerminationFuncHolder holder(this);
  if (ok) {
    JSVersion newVersion = JSVERSION_UNKNOWN;

    // SecurityManager said "ok", but don't execute if aVersion is specified
    // and unknown.  Do execute with the default version (and avoid thrashing
    // the context's version) if aVersion is not specified.
    ok = (!aVersion ||
          (newVersion = ::JS_StringToVersion(aVersion)) != JSVERSION_UNKNOWN);
    if (ok) {
      JSVersion oldVersion = JSVERSION_UNKNOWN;

      if (aVersion)
        oldVersion = ::JS_SetVersion(mContext, newVersion);
      ok = ::JS_EvaluateUCScriptForPrincipals(mContext,
                                              (JSObject *)aScopeObject,
                                              jsprin,
                                              (jschar*)PromiseFlatString(aScript).get(),
                                              aScript.Length(),
                                              aURL,
                                              aLineNo,
                                              &val);

      if (aVersion) {
        ::JS_SetVersion(mContext, oldVersion);
      }

      if (!ok) {
        // Tell XPConnect about any pending exceptions. This is needed
        // to avoid dropping JS exceptions in case we got here through
        // nested calls through XPConnect.

        nsContentUtils::NotifyXPCIfExceptionPending(mContext);
      }
    }
  }

  // Whew!  Finally done with these manually ref-counted things.
  JSPRINCIPALS_DROP(mContext, jsprin);

  // If all went well, convert val to a string (XXXbe unless undefined?).
  if (ok) {
    if (aIsUndefined) {
      *aIsUndefined = JSVAL_IS_VOID(val);
    }

    *NS_STATIC_CAST(jsval*, aRetValue) = val;
  }
  else {
    if (aIsUndefined) {
      *aIsUndefined = PR_TRUE;
    }
  }

  // Pop here, after JS_ValueToString and any other possible evaluation.
  if (NS_FAILED(stack->Pop(nsnull)))
    rv = NS_ERROR_FAILURE;

  // ScriptEvaluated needs to come after we pop the stack
  ScriptEvaluated(PR_TRUE);

  return rv;

}

Here is the call graph for this function:

nsresult nsJSContext::ExecuteScript ( void aScriptObject,
void aScopeObject,
nsAString *  aRetValue,
PRBool aIsUndefined 
) [virtual]

Execute a precompiled script object.

Parameters:
aScriptObjectan object representing the script to be executed
aScopeObjectan object telling the scope in which to execute, or nsnull to use a default scope
aRetValuethe result of executing the script, may be null in which case no result string is computed
aIsUndefinedtrue if the result of executing the script is the undefined value, may be null for "don't care"
Returns:
NS_OK if the script was valid and got executed

Implements nsIScriptContext.

Definition at line 1222 of file nsJSEnvironment.cpp.

{
  NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);

  if (!mScriptsEnabled) {
    if (aIsUndefined) {
      *aIsUndefined = PR_TRUE;
    }

    if (aRetValue) {
      aRetValue->Truncate();
    }

    return NS_OK;
  }

  nsresult rv;

  if (!aScopeObject)
    aScopeObject = ::JS_GetGlobalObject(mContext);

  // Push our JSContext on our thread's context stack, in case native code
  // called from JS calls back into JS via XPConnect.
  nsCOMPtr<nsIJSContextStack> stack =
           do_GetService("@mozilla.org/js/xpc/ContextStack;1", &rv);
  if (NS_FAILED(rv) || NS_FAILED(stack->Push(mContext))) {
    return NS_ERROR_FAILURE;
  }

  // The result of evaluation, used only if there were no errors.  This need
  // not be a GC root currently, provided we run the GC only from the branch
  // callback or from ScriptEvaluated.  TODO: use JS_Begin/EndRequest to keep
  // the GC from racing with JS execution on any thread.
  jsval val;
  JSBool ok;

  nsJSContext::TerminationFuncHolder holder(this);
  ok = ::JS_ExecuteScript(mContext,
                          (JSObject*) aScopeObject,
                          (JSScript*) ::JS_GetPrivate(mContext,
                                                    (JSObject*)aScriptObject),
                          &val);

  if (ok) {
    // If all went well, convert val to a string (XXXbe unless undefined?).

    rv = JSValueToAString(mContext, val, aRetValue, aIsUndefined);
  } else {
    if (aIsUndefined) {
      *aIsUndefined = PR_TRUE;
    }

    if (aRetValue) {
      aRetValue->Truncate();
    }

    // Tell XPConnect about any pending exceptions. This is needed to
    // avoid dropping JS exceptions in case we got here through nested
    // calls through XPConnect.

    nsContentUtils::NotifyXPCIfExceptionPending(mContext);
  }

  // Pop here, after JS_ValueToString and any other possible evaluation.
  if (NS_FAILED(stack->Pop(nsnull)))
    rv = NS_ERROR_FAILURE;

  // ScriptEvaluated needs to come after we pop the stack
  ScriptEvaluated(PR_TRUE);

  return rv;
}

Here is the call graph for this function:

Definition at line 1779 of file nsJSEnvironment.cpp.

{
  NS_ASSERTION(!NS_DOMClassInfo_GetXPCNativeWrapperClass(),
               "Why was this called?");

  JSObject *globalObj;
  aHolder->GetJSObject(&globalObj);
  NS_ASSERTION(globalObj, "Must have global by now!");
      
  const char* arg = "arg";
  NS_NAMED_LITERAL_STRING(body, "return new XPCNativeWrapper(arg);");

  // Can't use CompileFunction() here because our principal isn't
  // inited yet and a null principal makes it fail.
  JSFunction *fun =
    ::JS_CompileUCFunction(mContext,
                           globalObj,
                           "_XPCNativeWrapperCtor",
                           1, &arg,
                           (jschar*)body.get(),
                           body.Length(),
                           "javascript:return new XPCNativeWrapper(arg);",
                           1 // lineno
                           );
  NS_ENSURE_TRUE(fun, NS_ERROR_FAILURE);

  jsval globalVal = OBJECT_TO_JSVAL(globalObj);
  jsval wrapper;
      
  JSBool ok = ::JS_CallFunction(mContext, globalObj, fun,
                                1, &globalVal, &wrapper);
  if (!ok) {
    // No need to notify about pending exceptions here; we don't
    // expect any other than out of memory, really.
    return NS_ERROR_FAILURE;
  }

  NS_ASSERTION(JSVAL_IS_OBJECT(wrapper), "This should be an object!");

  NS_DOMClassInfo_SetXPCNativeWrapperClass(
    ::JS_GetClass(mContext, JSVAL_TO_OBJECT(wrapper)));
  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void nsJSContext::FireGCTimer ( ) [protected]

Definition at line 2244 of file nsJSEnvironment.cpp.

{
  if (sGCTimer) {
    // There's already a timer for GC'ing, just clear newborn roots
    // and return

    ::JS_ClearNewbornRoots(mContext);

    return;
  }

  CallCreateInstance("@mozilla.org/timer;1", &sGCTimer);

  if (!sGCTimer) {
    NS_WARNING("Failed to create timer");

    ::JS_GC(mContext);

    return;
  }

  static PRBool first = PR_TRUE;

  sGCTimer->InitWithCallback(this,
                             first ? NS_FIRST_GC_DELAY : NS_GC_DELAY,
                             nsITimer::TYPE_ONE_SHOT);

  first = PR_FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void nsJSContext::GC ( ) [virtual]

For garbage collected systems, do a synchronous collection pass.

May be a no-op on other systems

Returns:
NS_OK if the method is successful

Implements nsIScriptContext.

Definition at line 2113 of file nsJSEnvironment.cpp.

{
  FireGCTimer();
}

Here is the call graph for this function:

Return the global object.

Implements nsIScriptContext.

Definition at line 1588 of file nsJSEnvironment.cpp.

{
  JSObject *global = ::JS_GetGlobalObject(mContext);

  if (!global) {
    NS_WARNING("Context has no global.");
    return nsnull;
  }

  JSClass *c = JS_GET_CLASS(mContext, global);

  if (!c || ((~c->flags) & (JSCLASS_HAS_PRIVATE |
                            JSCLASS_PRIVATE_IS_NSISUPPORTS))) {
    NS_WARNING("Global is not an nsISupports.");
    return nsnull;
  }

  nsCOMPtr<nsIScriptGlobalObject> sgo;
  nsISupports *priv =
    (nsISupports *)::JS_GetPrivate(mContext, global);

  nsCOMPtr<nsIXPConnectWrappedNative> wrapped_native =
    do_QueryInterface(priv);

  if (wrapped_native) {
    // The global object is a XPConnect wrapped native, the native in
    // the wrapper might be the nsIScriptGlobalObject

    sgo = do_QueryWrappedNative(wrapped_native);
  } else {
    sgo = do_QueryInterface(priv);
  }

  // This'll return a pointer to something we're about to release, but
  // that's ok, the JS object will hold it alive long enough.
  return sgo;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Return the native script context.

Implements nsIScriptContext.

Definition at line 1627 of file nsJSEnvironment.cpp.

{
  return mContext;
}

Get the script context of the owner.

The method addrefs the returned reference according to regular XPCOM rules, even though the internal reference itself is a "weak" reference.

Implements nsIScriptContext.

Definition at line 2160 of file nsJSEnvironment.cpp.

{
  return mOwner;
}

Called to set/get information if the script context is currently processing a script tag.

Implements nsIScriptContext.

Definition at line 2199 of file nsJSEnvironment.cpp.

Called to disable/enable script execution in this context.

Implements nsIScriptContext.

Definition at line 2180 of file nsJSEnvironment.cpp.

{
  return mScriptsEnabled;
}
nsresult nsJSContext::InitClasses ( JSObject aGlobalObj) [virtual]

Initialize DOM classes on aGlobalObj, always call WillInitializeContext() before calling InitContext(), and always call DidInitializeContext() when a context is fully (successfully) initialized.

Implements nsIScriptContext.

Definition at line 2061 of file nsJSEnvironment.cpp.

{
  nsresult rv = NS_OK;

  rv = InitializeExternalClasses();
  NS_ENSURE_SUCCESS(rv, rv);

  rv = InitializeLiveConnectClasses(aGlobalObj);
  NS_ENSURE_SUCCESS(rv, rv);

  // Initialize the options object and set default options in mContext
  JSObject *optionsObj = ::JS_DefineObject(mContext, aGlobalObj, "_options",
                                           &OptionsClass, nsnull, 0);
  if (optionsObj &&
      ::JS_DefineProperties(mContext, optionsObj, OptionsProperties)) {
    ::JS_SetOptions(mContext, mDefaultJSOptions);
  } else {
    rv = NS_ERROR_FAILURE;
  }

#ifdef NS_TRACE_MALLOC
  // Attempt to initialize TraceMalloc functions
  ::JS_DefineFunctions(mContext, aGlobalObj, TraceMallocFunctions);
#endif

#ifdef MOZ_JPROF
  // Attempt to initialize JProf functions
  ::JS_DefineFunctions(mContext, aGlobalObj, JProfFunctions);
#endif

  return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Init this context.

Parameters:
aGlobalObjectthe gobal object
Returns:
NS_OK if context initialization was successful

Implements nsIScriptContext.

Definition at line 1636 of file nsJSEnvironment.cpp.

{
  // Make sure callers of this use
  // WillInitializeContext/DidInitializeContext around this call.
  NS_ENSURE_TRUE(!mIsInitialized, NS_ERROR_ALREADY_INITIALIZED);

  if (!mContext)
    return NS_ERROR_OUT_OF_MEMORY;

  InvalidateContextAndWrapperCache();

  nsresult rv;

  if (!gNameSpaceManager) {
    gNameSpaceManager = new nsScriptNameSpaceManager;
    NS_ENSURE_TRUE(gNameSpaceManager, NS_ERROR_OUT_OF_MEMORY);

    rv = gNameSpaceManager->Init();
    NS_ENSURE_SUCCESS(rv, rv);
  }

  ::JS_SetErrorReporter(mContext, NS_ScriptErrorReporter);

  if (!aGlobalObject) {
    // If we don't get a global object then there's nothing more to do here.

    return NS_OK;
  }

  nsIXPConnect *xpc = nsContentUtils::XPConnect();

  JSObject *global = ::JS_GetGlobalObject(mContext);

  nsCOMPtr<nsIXPConnectJSObjectHolder> holder;

  // If there's already a global object in mContext we won't tell
  // XPConnect to wrap aGlobalObject since it's already wrapped.

  if (!global) {
    nsCOMPtr<nsIDOMChromeWindow> chromeWindow(do_QueryInterface(aGlobalObject));
    PRUint32 flags = 0;
    
    if (chromeWindow) {
      // Flag this object and scripts compiled against it as "system", for
      // optional automated XPCNativeWrapper construction when chrome views
      // a content DOM.
      flags = nsIXPConnect::FLAG_SYSTEM_GLOBAL_OBJECT;

      // Always enable E4X for XUL and other chrome content -- there is no
      // need to preserve the <!-- script hiding hack from JS-in-HTML daze
      // (introduced in 1995 for graceful script degradation in Netscape 1,
      // Mosaic, and other pre-JS browsers).
      ::JS_SetOptions(mContext, ::JS_GetOptions(mContext) | JSOPTION_XML);
    }

    rv = xpc->InitClassesWithNewWrappedGlobal(mContext, aGlobalObject,
                                              NS_GET_IID(nsISupports),
                                              flags,
                                              getter_AddRefs(holder));
    NS_ENSURE_SUCCESS(rv, rv);

    // Now check whether we need to grab a pointer to the
    // XPCNativeWrapper class
    if (!NS_DOMClassInfo_GetXPCNativeWrapperClass()) {
      rv = FindXPCNativeWrapperClass(holder);
      NS_ENSURE_SUCCESS(rv, rv);
    }
  } else {
    // If there's already a global object in mContext we're called
    // after ::JS_ClearScope() was called. We'll have to tell
    // XPConnect to re-initialize the global object to do things like
    // define the Components object on the global again and forget all
    // old prototypes in this scope.
    rv = xpc->InitClasses(mContext, global);
    NS_ENSURE_SUCCESS(rv, rv);

    nsCOMPtr<nsIClassInfo> ci(do_QueryInterface(aGlobalObject));

    if (ci) {
      rv = xpc->WrapNative(mContext, global, aGlobalObject,
                           NS_GET_IID(nsISupports),
                           getter_AddRefs(holder));
      NS_ENSURE_SUCCESS(rv, rv);

      nsCOMPtr<nsIXPConnectWrappedNative> wrapper(do_QueryInterface(holder));
      NS_ENSURE_TRUE(wrapper, NS_ERROR_FAILURE);

      rv = wrapper->RefreshPrototype();
      NS_ENSURE_SUCCESS(rv, rv);
    }
  }

  // Hold a strong reference to the wrapper for the global to avoid
  // rooting and unrooting the global object every time its AddRef()
  // or Release() methods are called
  mGlobalWrapperRef = holder;

  holder->GetJSObject(&global);

  rv = InitClasses(global); // this will complete global object initialization
  NS_ENSURE_SUCCESS(rv, rv);

  return rv;
}

Here is the call graph for this function:

Definition at line 1742 of file nsJSEnvironment.cpp.

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1750 of file nsJSEnvironment.cpp.

{
  nsresult rv = NS_OK;

#ifdef OJI
  nsCOMPtr<nsIJVMManager> jvmManager =
    do_GetService(nsIJVMManager::GetCID(), &rv);

  if (NS_SUCCEEDED(rv) && jvmManager) {
    PRBool javaEnabled = PR_FALSE;

    rv = jvmManager->GetJavaEnabled(&javaEnabled);

    if (NS_SUCCEEDED(rv) && javaEnabled) {
      nsCOMPtr<nsILiveConnectManager> liveConnectManager =
        do_QueryInterface(jvmManager);

      if (liveConnectManager) {
        rv = liveConnectManager->InitLiveConnectClasses(mContext, aGlobalObj);
      }
    }
  }
#endif /* OJI */

  // return all is well until things are stable.
  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Check to see if context is as yet intialized.

Used to prevent reentrancy issues during the initialization process.

Returns:
PR_TRUE if initialized, PR_FALSE if not

Implements nsIScriptContext.

Definition at line 2107 of file nsJSEnvironment.cpp.

{
  return mIsInitialized;
}
int PR_CALLBACK nsJSContext::JSOptionChangedCallback ( const char *  pref,
void data 
) [static, private]

Definition at line 683 of file nsJSEnvironment.cpp.

{
  nsJSContext *context = NS_REINTERPRET_CAST(nsJSContext *, data);
  PRUint32 oldDefaultJSOptions = context->mDefaultJSOptions;
  PRUint32 newDefaultJSOptions = oldDefaultJSOptions;

  PRBool strict = nsContentUtils::GetBoolPref(js_strict_option_str);
  if (strict)
    newDefaultJSOptions |= JSOPTION_STRICT;
  else
    newDefaultJSOptions &= ~JSOPTION_STRICT;

  PRBool werror = nsContentUtils::GetBoolPref(js_werror_option_str);
  if (werror)
    newDefaultJSOptions |= JSOPTION_WERROR;
  else
    newDefaultJSOptions &= ~JSOPTION_WERROR;

  if (newDefaultJSOptions != oldDefaultJSOptions) {
    // Set options only if we used the old defaults; otherwise the page has
    // customized some via the options object and we defer to its wisdom.
    if (::JS_GetOptions(context->mContext) == oldDefaultJSOptions)
      ::JS_SetOptions(context->mContext, newDefaultJSOptions);

    // Save the new defaults for the next page load (InitContext).
    context->mDefaultJSOptions = newDefaultJSOptions;
  }

#ifdef JS_GC_ZEAL
  PRInt32 zeal = nsContentUtils::GetIntPref(js_zeal_option_str, -1);
  if (zeal >= 0)
    ::JS_SetGCZeal(context->mContext, (PRUint8)zeal);
#endif

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void nsITimerCallback::notify ( in nsITimer  timer) [inherited]
Parameters:
aTimerthe timer which has expired

Method invoked to preserve an nsIXPConnectWrappedNative as needed.

void nsJSContext::ScriptEvaluated ( PRBool  aTerminated) [virtual]

Inform the context that a script was evaluated.

A GC may be done if "necessary." This call is necessary if script evaluation is done without using the EvaluateScript method.

Parameters:
aTerminatedIf true then call termination function if it was previously set. Within DOM this will always be true, but outside callers (such as xpconnect) who may do script evaluations nested inside DOM script evaluations can pass false to avoid premature calls to the termination function.
Returns:
NS_OK if the method is successful

Implements nsIScriptContext.

Definition at line 2119 of file nsJSEnvironment.cpp.

{
  if (aTerminated && mTerminations) {
    // Make sure to null out mTerminations before doing anything that
    // might cause new termination funcs to be added!
    nsJSContext::TerminationFuncClosure* start = mTerminations;
    mTerminations = nsnull;
    
    for (nsJSContext::TerminationFuncClosure* cur = start;
         cur;
         cur = cur->mNext) {
      (*(cur->mTerminationFunc))(cur->mTerminationFuncArg);
    }
    delete start;
  }

  mNumEvaluations++;

#ifdef JS_GC_ZEAL
  if (mContext->runtime->gcZeal >= 2) {
    ::JS_MaybeGC(mContext);
  } else
#endif
  if (mNumEvaluations > 20) {
    mNumEvaluations = 0;
    ::JS_MaybeGC(mContext);
  }

  mBranchCallbackCount = 0;
  mBranchCallbackTime = LL_ZERO;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Method invoked when a script has been executed by XPConnect.

void nsJSContext::SetDefaultLanguageVersion ( const char *  aVersion) [virtual]

Set the default scripting language version for this context, which must be a context specific to a particular scripting language.

Implements nsIScriptContext.

Definition at line 1582 of file nsJSEnvironment.cpp.

Here is the call graph for this function:

void nsJSContext::SetGCOnDestruction ( PRBool  aGCOnDestruction) [virtual]

Tell the context whether or not to GC when destroyed.

Implements nsIScriptContext.

Definition at line 2211 of file nsJSEnvironment.cpp.

{
  mGCOnDestruction = aGCOnDestruction;
}

Let the script context know who its owner is.

The script context should not addref the owner. It will be told when the owner goes away.

Returns:
NS_OK if the method is successful

Implements nsIScriptContext.

Definition at line 2152 of file nsJSEnvironment.cpp.

{
  // The owner should not be addrefed!! We'll be told
  // when the owner goes away.
  mOwner = owner;
}

Implements nsIScriptContext.

Definition at line 2205 of file nsJSEnvironment.cpp.

{
  mProcessingScriptTag = aFlag;
}
void nsJSContext::SetScriptsEnabled ( PRBool  aEnabled,
PRBool  aFireTimeouts 
) [virtual]

Implements nsIScriptContext.

Definition at line 2186 of file nsJSEnvironment.cpp.

{
  mScriptsEnabled = aEnabled;

  nsIScriptGlobalObject *global = GetGlobalObject();

  if (global) {
    global->SetScriptsEnabled(aEnabled, aFireTimeouts);
  }
}

Here is the call graph for this function:

nsresult nsJSContext::SetTerminationFunction ( nsScriptTerminationFunc  aFunc,
nsISupports *  aRef 
) [virtual]

Called to specify a function that should be called when the current script (if there is one) terminates.

Generally used if breakdown of script state needs to happen, but should be deferred till the end of script evaluation.

Exceptions:
NS_ERROR_OUT_OF_MEMORYif that happens

Implements nsIScriptContext.

Definition at line 2166 of file nsJSEnvironment.cpp.

{
  nsJSContext::TerminationFuncClosure* newClosure =
    new nsJSContext::TerminationFuncClosure(aFunc, aRef, mTerminations);
  if (!newClosure) {
    return NS_ERROR_OUT_OF_MEMORY;
  }

  mTerminations = newClosure;
  return NS_OK;
}

Tell the context we're about to be reinitialize it.

Implements nsIScriptContext.

Definition at line 2095 of file nsJSEnvironment.cpp.


Friends And Related Function Documentation

friend struct TerminationFuncHolder [friend]

Definition at line 157 of file nsJSEnvironment.h.


Member Data Documentation

Definition at line 217 of file nsJSEnvironment.h.

Definition at line 218 of file nsJSEnvironment.h.

Definition at line 151 of file nsJSEnvironment.h.

Definition at line 219 of file nsJSEnvironment.h.

Definition at line 213 of file nsJSEnvironment.h.

nsCOMPtr<nsISupports> nsJSContext::mGlobalWrapperRef [private]

Definition at line 226 of file nsJSEnvironment.h.

Definition at line 211 of file nsJSEnvironment.h.

Definition at line 215 of file nsJSEnvironment.h.

Definition at line 152 of file nsJSEnvironment.h.

Definition at line 154 of file nsJSEnvironment.h.

Definition at line 214 of file nsJSEnvironment.h.

Definition at line 212 of file nsJSEnvironment.h.

Definition at line 208 of file nsJSEnvironment.h.


The documentation for this class was generated from the following files: