зеркало из https://github.com/mozilla/pjs.git
Deprecation of ContextListener in favour of ContextFactory.Listener:
the later is stored in the factory and not in static variables. For compatibility an instance of ContextFactory stored in static variables is used to provide support for old Context.addContextListener etc. API. The static instance of the factory is also used by Context.enter to create Context instances providing simple way to customize Context: one just need to initialize the global static factory.
This commit is contained in:
Родитель
ff3b81b2d5
Коммит
03fd126f9f
|
@ -86,7 +86,7 @@ import org.mozilla.javascript.debug.*;
|
||||||
public class Context
|
public class Context
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Language versions
|
* Language versions.
|
||||||
*
|
*
|
||||||
* All integral values are reserved for future version numbers.
|
* All integral values are reserved for future version numbers.
|
||||||
*/
|
*/
|
||||||
|
@ -217,30 +217,6 @@ public class Context
|
||||||
optimizationLevel = codegenClass != null ? 0 : -1;
|
optimizationLevel = codegenClass != null ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new Context associated with the given factory.
|
|
||||||
* The factory will be notified about context execution
|
|
||||||
* or it will be used to create Context instances associated
|
|
||||||
* with other threads.
|
|
||||||
* <p>
|
|
||||||
* To associate Context instances created with this constructor
|
|
||||||
* with current execution thread
|
|
||||||
* {@link ContextFactory#call(ContextAction)} must be used.
|
|
||||||
* Using {@link #enter()} or {@link #exit()} methods will
|
|
||||||
* throw an exception if the methods operate on instances
|
|
||||||
* created with this constructor.
|
|
||||||
*
|
|
||||||
* @see ContextFactory#call(ContextAction)
|
|
||||||
*/
|
|
||||||
public Context(ContextFactory factory)
|
|
||||||
{
|
|
||||||
this();
|
|
||||||
if (factory == null) {
|
|
||||||
throw new IllegalArgumentException("Factory should not be null");
|
|
||||||
}
|
|
||||||
this.factory = factory;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a context associated with the current thread, creating
|
* Get a context associated with the current thread, creating
|
||||||
* one if need be.
|
* one if need be.
|
||||||
|
@ -306,10 +282,6 @@ public class Context
|
||||||
*/
|
*/
|
||||||
public static Context enter(Context cx)
|
public static Context enter(Context cx)
|
||||||
{
|
{
|
||||||
if (cx != null && cx.factory != null) {
|
|
||||||
throw new IllegalStateException("Context.enter can not be used to associate with the execution thread Context instances created with Context(ContextFactory) constructor");
|
|
||||||
}
|
|
||||||
|
|
||||||
Context[] storage = getThreadContextStorage();
|
Context[] storage = getThreadContextStorage();
|
||||||
Context old;
|
Context old;
|
||||||
if (storage != null) {
|
if (storage != null) {
|
||||||
|
@ -320,9 +292,6 @@ public class Context
|
||||||
|
|
||||||
if (old != null) {
|
if (old != null) {
|
||||||
if (old.factory != null) {
|
if (old.factory != null) {
|
||||||
throw new IllegalStateException("Context.enter can not be used to recursively enter Context instances created with Context(ContextFactory) constructor");
|
|
||||||
}
|
|
||||||
if (old.enteredUsingCall) {
|
|
||||||
throw new IllegalStateException("Context.enter can not be used to recursively enter Context instances already associated with the current thread using Context.call(ContextAction)");
|
throw new IllegalStateException("Context.enter can not be used to recursively enter Context instances already associated with the current thread using Context.call(ContextAction)");
|
||||||
}
|
}
|
||||||
if (cx != null && cx != old && cx.enterCount != 0) {
|
if (cx != null && cx != old && cx.enterCount != 0) {
|
||||||
|
@ -335,20 +304,20 @@ public class Context
|
||||||
cx = old;
|
cx = old;
|
||||||
} else {
|
} else {
|
||||||
if (cx == null) {
|
if (cx == null) {
|
||||||
cx = new Context();
|
cx = ContextFactory.getGlobal().makeContext();
|
||||||
} else {
|
} else {
|
||||||
if (cx.sealed) onSealedMutation();
|
if (cx.sealed) onSealedMutation();
|
||||||
}
|
}
|
||||||
if (cx.enterCount != 0) Kit.codeBug();
|
if (cx.enterCount != 0 || cx.factory != null) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
|
||||||
if (!cx.creationEventWasSent) {
|
if (!cx.creationEventWasSent) {
|
||||||
cx.creationEventWasSent = true;
|
cx.creationEventWasSent = true;
|
||||||
cx.runListeners(CONTEXT_CREATED_EVENT);
|
ContextFactory.getGlobal().onContextCreated(cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cx.runListeners(CONTEXT_ENTER_EVENT);
|
|
||||||
|
|
||||||
if (old == null) {
|
if (old == null) {
|
||||||
if (storage != null) {
|
if (storage != null) {
|
||||||
storage[0] = cx;
|
storage[0] = cx;
|
||||||
|
@ -390,12 +359,9 @@ public class Context
|
||||||
"Calling Context.exit without previous Context.enter");
|
"Calling Context.exit without previous Context.enter");
|
||||||
}
|
}
|
||||||
if (cx.factory != null) {
|
if (cx.factory != null) {
|
||||||
throw new IllegalStateException("Context.exit can not be used to exit context created with Context(ContextFactory) constructor");
|
|
||||||
}
|
|
||||||
if (cx.enteredUsingCall) {
|
|
||||||
throw new IllegalStateException("Context.exit can not be used to exit context associated with the current thread using Context.call(ContextAction)");
|
throw new IllegalStateException("Context.exit can not be used to exit context associated with the current thread using Context.call(ContextAction)");
|
||||||
}
|
}
|
||||||
if (Context.check && cx.enterCount < 1) Kit.codeBug();
|
if (cx.enterCount < 1) Kit.codeBug();
|
||||||
if (cx.sealed) onSealedMutation();
|
if (cx.sealed) onSealedMutation();
|
||||||
--cx.enterCount;
|
--cx.enterCount;
|
||||||
if (cx.enterCount == 0) {
|
if (cx.enterCount == 0) {
|
||||||
|
@ -406,9 +372,8 @@ public class Context
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cx.runListeners(CONTEXT_EXIT_EVENT);
|
|
||||||
if (cx.enterCount == 0) {
|
if (cx.enterCount == 0) {
|
||||||
cx.runListeners(CONTEXT_RELEASED_EVENT);
|
ContextFactory.getGlobal().onContextReleased(cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -416,15 +381,16 @@ public class Context
|
||||||
* Call {@link ContextAction#run(Context cx)}
|
* Call {@link ContextAction#run(Context cx)}
|
||||||
* using the Context instance associated with the current thread.
|
* using the Context instance associated with the current thread.
|
||||||
* If no Context is associated with the thread, then
|
* If no Context is associated with the thread, then
|
||||||
* <tt>new Context()</tt> will be called to construct
|
* <tt>ContextFactory.getGlobal().makeContext()</tt> will be called to
|
||||||
* new Context instance. The instance will be temporary associated
|
* construct new Context instance. The instance will be temporary
|
||||||
* with the thread during call to {@link ContextAction#run(Context)}.
|
* associated with the thread during call to
|
||||||
|
* {@link ContextAction#run(Context)}.
|
||||||
*
|
*
|
||||||
* @return The result of {@link ContextAction#run(Context)}.
|
* @return The result of {@link ContextAction#run(Context)}.
|
||||||
*/
|
*/
|
||||||
public static Object call(ContextAction action)
|
public static Object call(ContextAction action)
|
||||||
{
|
{
|
||||||
return call(null, action);
|
return call(ContextFactory.getGlobal(), action);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -438,8 +404,8 @@ public class Context
|
||||||
* with the thread during call to {@link ContextAction#run(Context)}.
|
* with the thread during call to {@link ContextAction#run(Context)}.
|
||||||
* <p>
|
* <p>
|
||||||
* It is allowed to use null for <tt>factory</tt> argument
|
* It is allowed to use null for <tt>factory</tt> argument
|
||||||
* in which case <tt>new Context()</tt> will be used to create
|
* in which case <tt>ContextFactory.getGlobal().makeContext()</tt> will be
|
||||||
* new context instances.
|
* used to create new context instances.
|
||||||
*
|
*
|
||||||
* @see ContextFactory#call(ContextAction)
|
* @see ContextFactory#call(ContextAction)
|
||||||
*/
|
*/
|
||||||
|
@ -448,6 +414,9 @@ public class Context
|
||||||
Object[] args)
|
Object[] args)
|
||||||
throws JavaScriptException
|
throws JavaScriptException
|
||||||
{
|
{
|
||||||
|
if (factory == null) {
|
||||||
|
factory = ContextFactory.getGlobal();
|
||||||
|
}
|
||||||
Context[] storage = getThreadContextStorage();
|
Context[] storage = getThreadContextStorage();
|
||||||
Context cx;
|
Context cx;
|
||||||
if (storage != null) {
|
if (storage != null) {
|
||||||
|
@ -457,14 +426,14 @@ public class Context
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cx != null) {
|
if (cx != null) {
|
||||||
if (cx.enteredUsingCall) {
|
if (cx.factory != null) {
|
||||||
return callable.call(cx, scope, thisObj, args);
|
return callable.call(cx, scope, thisObj, args);
|
||||||
} else {
|
} else {
|
||||||
cx.enteredUsingCall = true;
|
cx.factory = factory;
|
||||||
try {
|
try {
|
||||||
return callable.call(cx, scope, thisObj, args);
|
return callable.call(cx, scope, thisObj, args);
|
||||||
} finally {
|
} finally {
|
||||||
cx.enteredUsingCall = false;
|
cx.factory = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -492,14 +461,14 @@ public class Context
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cx != null) {
|
if (cx != null) {
|
||||||
if (cx.enteredUsingCall) {
|
if (cx.factory != null) {
|
||||||
return action.run(cx);
|
return action.run(cx);
|
||||||
} else {
|
} else {
|
||||||
cx.enteredUsingCall = true;
|
cx.factory = factory;
|
||||||
try {
|
try {
|
||||||
return action.run(cx);
|
return action.run(cx);
|
||||||
} finally {
|
} finally {
|
||||||
cx.enteredUsingCall = false;
|
cx.factory = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -515,134 +484,69 @@ public class Context
|
||||||
private static Context prepareNewContext(ContextFactory factory,
|
private static Context prepareNewContext(ContextFactory factory,
|
||||||
Context[] storage)
|
Context[] storage)
|
||||||
{
|
{
|
||||||
Context cx;
|
Context cx = factory.makeContext();
|
||||||
if (factory == null) {
|
if (cx.factory != null || cx.enterCount != 0) {
|
||||||
cx = new Context();
|
throw new IllegalStateException("factory.makeContext() returned Context instance already associated with some thread");
|
||||||
if (!cx.creationEventWasSent) {
|
}
|
||||||
cx.creationEventWasSent = true;
|
cx.factory = factory;
|
||||||
cx.runListeners(CONTEXT_CREATED_EVENT);
|
factory.onContextCreated(cx);
|
||||||
}
|
if (factory.isSealed() && !cx.isSealed()) {
|
||||||
cx.runListeners(CONTEXT_ENTER_EVENT);
|
cx.seal(null);
|
||||||
} else {
|
|
||||||
cx = factory.makeContext();
|
|
||||||
if (cx.factory != factory) {
|
|
||||||
throw new IllegalStateException("factory.makeContext() did not use proper Context constructor");
|
|
||||||
}
|
|
||||||
if (cx.enterCount != 0) { throw new IllegalStateException(); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (storage != null) {
|
if (storage != null) {
|
||||||
storage[0] = cx;
|
storage[0] = cx;
|
||||||
} else {
|
} else {
|
||||||
setThreadContext_jdk11(cx);
|
setThreadContext_jdk11(cx);
|
||||||
}
|
}
|
||||||
cx.enterCount = 1;
|
|
||||||
cx.enteredUsingCall = true;
|
|
||||||
return cx;
|
return cx;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void releaseContext(Context[] storage, Context cx)
|
private static void releaseContext(Context[] storage, Context cx)
|
||||||
{
|
{
|
||||||
if (cx.enterCount != 1) throw new IllegalStateException();
|
|
||||||
cx.enteredUsingCall = false;
|
|
||||||
cx.enterCount = 0;
|
|
||||||
if (storage != null) {
|
if (storage != null) {
|
||||||
storage[0] = null;
|
storage[0] = null;
|
||||||
} else {
|
} else {
|
||||||
setThreadContext_jdk11(null);
|
setThreadContext_jdk11(null);
|
||||||
}
|
}
|
||||||
if (cx.factory == null) {
|
try {
|
||||||
cx.runListeners(CONTEXT_EXIT_EVENT);
|
cx.factory.onContextReleased(cx);
|
||||||
cx.runListeners(CONTEXT_RELEASED_EVENT);
|
} finally {
|
||||||
} else {
|
cx.factory = null;
|
||||||
cx.factory.onContextExit(cx);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a Context listener. The listener will receive notifications about
|
* @deprecated Use
|
||||||
* Context events for Context instances created with the default
|
* {@link ContextFactory#addListener(ContextFactory.Listener)}.
|
||||||
* constructor {@link #Context()}. Rhino runtime never notifies listeners
|
* A simple way to upgrate the current code to new API is to replace
|
||||||
* added with this method for Context instances created with factory
|
* <tt>Context.addContextListener(listener)</tt> with
|
||||||
* constructor {@link #Context(ContextFactory)}.
|
* <tt>ContextFactory.getGlobal().addListener(listener)</tt>.
|
||||||
*
|
|
||||||
* @see #removeContextListener(ContextListener listener)
|
|
||||||
* @see #disableStaticContextListening()
|
|
||||||
*/
|
*/
|
||||||
public static void addContextListener(ContextListener listener)
|
public static void addContextListener(ContextListener listener)
|
||||||
{
|
{
|
||||||
boolean disabled;
|
ContextFactory.getGlobal().addListener(listener);
|
||||||
synchronized (staticListenersLock) {
|
|
||||||
disabled = disabledContextListening;
|
|
||||||
if (!disabled) {
|
|
||||||
staticListeners = Kit.addListener(staticListeners, listener);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (disabled) throw new IllegalStateException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a Context listener.
|
* @deprecated Use
|
||||||
* @param listener the listener to remove.
|
* {@link ContextFactory#removeListener(ContextFactory.Listener)}.
|
||||||
*
|
* A simple way to upgrate the current code to new API is to replace
|
||||||
* @see #addContextListener(ContextListener listener)
|
* <tt>Context.removeContextListener(listener)</tt> with
|
||||||
* @see #disableStaticContextListening()
|
* <tt>ContextFactory.getGlobal().removeListener(listener)</tt>.
|
||||||
*/
|
*/
|
||||||
public static void removeContextListener(ContextListener listener)
|
public static void removeContextListener(ContextListener listener)
|
||||||
{
|
{
|
||||||
synchronized (staticListenersLock) {
|
ContextFactory.getGlobal().addListener(listener);
|
||||||
staticListeners = Kit.removeListener(staticListeners, listener);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disable notifications of listeners registered with
|
* @deprecated Use {@link ContextFactory#seal()} to seal
|
||||||
* {@link #addContextListener(ContextListener)} about Context events.
|
* appropriate <tt>ContextFactory()</tt>.
|
||||||
* All currently registered listeners will be removed and any subsequent
|
|
||||||
* call to {@link #addContextListener(ContextListener)} will throw an
|
|
||||||
* exception.
|
|
||||||
* <p>
|
|
||||||
* Embedding may use this method to prevent Context exposure to potentially
|
|
||||||
* untrusted code.
|
|
||||||
*/
|
*/
|
||||||
public static void disableStaticContextListening()
|
public static void disableStaticContextListening()
|
||||||
{
|
{
|
||||||
synchronized (staticListenersLock) {
|
ContextFactory.getGlobal().disableContextListening();
|
||||||
disabledContextListening = true;
|
|
||||||
staticListeners = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final int CONTEXT_CREATED_EVENT = 1;
|
|
||||||
private static final int CONTEXT_ENTER_EVENT = 2;
|
|
||||||
private static final int CONTEXT_EXIT_EVENT = 3;
|
|
||||||
private static final int CONTEXT_RELEASED_EVENT = 4;
|
|
||||||
|
|
||||||
private void runListeners(int reason)
|
|
||||||
{
|
|
||||||
Object listeners = staticListeners;
|
|
||||||
for (int i = 0; ; ++i) {
|
|
||||||
ContextListener l;
|
|
||||||
l = (ContextListener)Kit.getListener(listeners, i);
|
|
||||||
if (l == null)
|
|
||||||
break;
|
|
||||||
switch (reason) {
|
|
||||||
case CONTEXT_CREATED_EVENT:
|
|
||||||
l.contextCreated(this);
|
|
||||||
break;
|
|
||||||
case CONTEXT_ENTER_EVENT:
|
|
||||||
l.contextEntered(this);
|
|
||||||
break;
|
|
||||||
case CONTEXT_EXIT_EVENT:
|
|
||||||
l.contextExited(this);
|
|
||||||
break;
|
|
||||||
case CONTEXT_RELEASED_EVENT:
|
|
||||||
l.contextReleased(this);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Kit.codeBug();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2674,10 +2578,6 @@ public class Context
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Object staticListenersLock = new Object();
|
|
||||||
private static volatile Object staticListeners;
|
|
||||||
private static boolean disabledContextListening;
|
|
||||||
|
|
||||||
private ContextFactory factory;
|
private ContextFactory factory;
|
||||||
private boolean sealed;
|
private boolean sealed;
|
||||||
private Object sealKey;
|
private Object sealKey;
|
||||||
|
@ -2710,7 +2610,6 @@ public class Context
|
||||||
Debugger debugger;
|
Debugger debugger;
|
||||||
private Object debuggerData;
|
private Object debuggerData;
|
||||||
private int enterCount;
|
private int enterCount;
|
||||||
private boolean enteredUsingCall;
|
|
||||||
private Object propertyListeners;
|
private Object propertyListeners;
|
||||||
private Hashtable hashtable;
|
private Hashtable hashtable;
|
||||||
private ClassLoader applicationClassLoader;
|
private ClassLoader applicationClassLoader;
|
||||||
|
|
|
@ -42,6 +42,32 @@ package org.mozilla.javascript;
|
||||||
|
|
||||||
public class ContextFactory
|
public class ContextFactory
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Listener of {@link Context} creation and release events.
|
||||||
|
*/
|
||||||
|
public interface Listener
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Notify about newly created {@link Context} object.
|
||||||
|
*/
|
||||||
|
public void contextCreated(Context cx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify that the specified {@link Context} instance is no longer
|
||||||
|
* associated with the current thread.
|
||||||
|
*/
|
||||||
|
public void contextReleased(Context cx);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static volatile boolean hasCustomGlobal;
|
||||||
|
private static ContextFactory global = new ContextFactory();
|
||||||
|
|
||||||
|
private volatile boolean sealed;
|
||||||
|
|
||||||
|
private final Object listenersLock = new Object();
|
||||||
|
private volatile Object listeners;
|
||||||
|
private boolean disabledListening;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create new {@link Context} instance to be associated with the current
|
* Create new {@link Context} instance to be associated with the current
|
||||||
* thread.
|
* thread.
|
||||||
|
@ -57,17 +83,112 @@ public class ContextFactory
|
||||||
*/
|
*/
|
||||||
protected Context makeContext()
|
protected Context makeContext()
|
||||||
{
|
{
|
||||||
return new Context(this);
|
return new Context();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onContextCreated(Context cx)
|
||||||
|
{
|
||||||
|
Object listeners = this.listeners;
|
||||||
|
for (int i = 0; ; ++i) {
|
||||||
|
Listener l = (Listener)Kit.getListener(listeners, i);
|
||||||
|
if (l == null)
|
||||||
|
break;
|
||||||
|
l.contextCreated(cx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onContextReleased(Context cx)
|
||||||
|
{
|
||||||
|
Object listeners = this.listeners;
|
||||||
|
for (int i = 0; ; ++i) {
|
||||||
|
Listener l = (Listener)Kit.getListener(listeners, i);
|
||||||
|
if (l == null)
|
||||||
|
break;
|
||||||
|
l.contextReleased(cx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void addListener(Listener listener)
|
||||||
|
{
|
||||||
|
checkNotSealed();
|
||||||
|
synchronized (listenersLock) {
|
||||||
|
if (disabledListening) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
listeners = Kit.addListener(listeners, listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void removeListener(Listener listener)
|
||||||
|
{
|
||||||
|
checkNotSealed();
|
||||||
|
synchronized (listenersLock) {
|
||||||
|
if (disabledListening) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
listeners = Kit.removeListener(listeners, listener);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform cleanup action for {@link Context} instance.
|
* The method is used only to imlement
|
||||||
* Rhino runtime calls the method to notify that {@link Context}
|
* Context.disableStaticContextListening()
|
||||||
* instance created with {@link #makeContext()}
|
|
||||||
* is no longer associated with the current thread.
|
|
||||||
*/
|
*/
|
||||||
protected void onContextExit(Context cx)
|
final void disableContextListening()
|
||||||
{
|
{
|
||||||
|
checkNotSealed();
|
||||||
|
synchronized (listenersLock) {
|
||||||
|
disabledListening = true;
|
||||||
|
listeners = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if this is a sealed ContextFactory.
|
||||||
|
* @see #seal()
|
||||||
|
*/
|
||||||
|
public final boolean isSealed()
|
||||||
|
{
|
||||||
|
return sealed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Seal this ContextFactory so any attempt to modify it like to add or
|
||||||
|
* remove its listeners will throw an exception.
|
||||||
|
* @see #isSealed()
|
||||||
|
*/
|
||||||
|
public final void seal()
|
||||||
|
{
|
||||||
|
checkNotSealed();
|
||||||
|
sealed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final void checkNotSealed()
|
||||||
|
{
|
||||||
|
if (sealed) throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get default ContextFactory.
|
||||||
|
*/
|
||||||
|
public static ContextFactory getGlobal()
|
||||||
|
{
|
||||||
|
return global;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize default ContextFactory. The method can only be called once.
|
||||||
|
*/
|
||||||
|
public static void initGlobal(ContextFactory factory)
|
||||||
|
{
|
||||||
|
if (factory == null) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
if (hasCustomGlobal) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
hasCustomGlobal = true;
|
||||||
|
global = factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -38,16 +38,20 @@
|
||||||
package org.mozilla.javascript;
|
package org.mozilla.javascript;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Embeddings that wish to
|
* @deprecated Embeddings that wish to customize newly created
|
||||||
* @see org.mozilla.javascript.Context#addContextListener
|
* {@link Context} instances should implement
|
||||||
|
* {@link ContextFactory.Listener}.
|
||||||
*/
|
*/
|
||||||
public interface ContextListener {
|
public interface ContextListener extends ContextFactory.Listener
|
||||||
|
{
|
||||||
public void contextCreated(Context cx);
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Rhino runtime never calls the method.
|
||||||
|
*/
|
||||||
public void contextEntered(Context cx);
|
public void contextEntered(Context cx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Rhino runtime never calls the method.
|
||||||
|
*/
|
||||||
public void contextExited(Context cx);
|
public void contextExited(Context cx);
|
||||||
|
|
||||||
public void contextReleased(Context cx);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -419,19 +419,16 @@ class Dim {
|
||||||
|
|
||||||
void enableForAllNewContexts()
|
void enableForAllNewContexts()
|
||||||
{
|
{
|
||||||
Context.addContextListener(new ContextListener() {
|
ContextFactory.Listener l = new ContextFactory.Listener()
|
||||||
|
{
|
||||||
public void contextCreated(Context cx)
|
public void contextCreated(Context cx)
|
||||||
{
|
{
|
||||||
initNewContext(cx);
|
initNewContext(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void contextEntered(Context cx) { }
|
|
||||||
|
|
||||||
public void contextExited(Context cx) { }
|
|
||||||
|
|
||||||
public void contextReleased(Context cx) { }
|
public void contextReleased(Context cx) { }
|
||||||
});
|
};
|
||||||
|
ContextFactory.getGlobal().addListener(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
void initNewContext(Context cx)
|
void initNewContext(Context cx)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче