private static Context PrepareNewContext(AppDomain appDomain, ContextFactory factory)
 {
     Context cx = new Context (appDomain);
     if (cx.factory != null || cx.enterCount != 0) {
         throw new ApplicationException ("factory.makeContext() returned Context instance already associated with some thread");
     }
     cx.factory = factory;
     factory.FireOnContextCreated (cx);
     if (factory.Sealed && !cx.Sealed) {
         cx.Seal ((object)null);
     }
     Thread.SetData (LocalSlot, cx);
     return cx;
 }
        /// <summary> Call {@link
        /// Callable#call(Context cx, Scriptable scope, Scriptable thisObj,
        /// Object[] args)}
        /// using the Context instance associated with the current thread.
        /// If no Context is associated with the thread, then
        /// {@link ContextFactory#makeContext()} will be called to construct
        /// new Context instance. The instance will be temporary associated
        /// with the thread during call to {@link ContextAction#run(Context)}.
        /// <p>
        /// It is allowed to use null for <tt>factory</tt> argument
        /// in which case the factory associated with the scope will be
        /// used to create new context instances.
        /// 
        /// </summary>
        public static object Call(ContextFactory factory, ICallable callable, IScriptable scope, IScriptable thisObj, object [] args)
        {
            if (factory == null) {
                factory = ContextFactory.Global;
            }

            Context cx = CurrentContext;
            if (cx != null) {
                object result;
                if (cx.factory != null) {
                    result = callable.Call (cx, scope, thisObj, args);
                }
                else {
                    // Context was associated with the thread via Context.enter,
                    // set factory to make Context.enter/exit to be no-op
                    // during call
                    cx.factory = factory;
                    try {
                        result = callable.Call (cx, scope, thisObj, args);
                    }
                    finally {
                        cx.factory = null;
                    }
                }
                return result;
            }

            cx = PrepareNewContext (AppDomain.CurrentDomain, factory);
            try {
                return callable.Call (cx, scope, thisObj, args);
            }
            finally {
                ReleaseContext (cx);
            }
        }
 /// <summary> Set global ContextFactory.
 /// The method can only be called once.
 /// 
 /// </summary>		
 public static void InitGlobal(ContextFactory factory)
 {
     if (factory == null) {
         throw new ArgumentException ();
     }
     if (hasCustomGlobal) {
         throw new ApplicationException ();
     }
     hasCustomGlobal = true;
     global = factory;
 }