зеркало из https://github.com/mozilla/pjs.git
1. Allow to monitor from application top script or function calls: now they go through ContextFactory.doTopCall which can be overridden.
2. Context.observeInstructionCount now calls ContxtFactory.observeInstructionCount so it can overridden without extra Context class.
This commit is contained in:
Родитель
26d7b8a8f8
Коммит
35acfd58fc
|
@ -640,11 +640,17 @@ public class Context
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return {@link ContextFactory} instance used to create this Context.
|
* Return {@link ContextFactory} instance used to create this Context
|
||||||
|
* or the result of {@link ContextFactory#getGlobal()} if no factory
|
||||||
|
* was used for Context creation.
|
||||||
*/
|
*/
|
||||||
public ContextFactory getFactory()
|
public final ContextFactory getFactory()
|
||||||
{
|
{
|
||||||
return factory;
|
ContextFactory result = factory;
|
||||||
|
if (result == null) {
|
||||||
|
result = ContextFactory.getGlobal();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2073,6 +2079,7 @@ public class Context
|
||||||
* that allows to customize Context behavior without introducing
|
* that allows to customize Context behavior without introducing
|
||||||
* Context subclasses. {@link ContextFactory} documentation gives
|
* Context subclasses. {@link ContextFactory} documentation gives
|
||||||
* an example of hasFeature implementation.
|
* an example of hasFeature implementation.
|
||||||
|
*
|
||||||
* @param featureIndex feature index to check
|
* @param featureIndex feature index to check
|
||||||
* @return true if the <code>featureIndex</code> feature is turned on
|
* @return true if the <code>featureIndex</code> feature is turned on
|
||||||
* @see #FEATURE_NON_ECMA_GET_YEAR
|
* @see #FEATURE_NON_ECMA_GET_YEAR
|
||||||
|
@ -2084,10 +2091,7 @@ public class Context
|
||||||
*/
|
*/
|
||||||
public boolean hasFeature(int featureIndex)
|
public boolean hasFeature(int featureIndex)
|
||||||
{
|
{
|
||||||
ContextFactory f = factory;
|
ContextFactory f = getFactory();
|
||||||
if (f == null) {
|
|
||||||
f = ContextFactory.getGlobal();
|
|
||||||
}
|
|
||||||
return f.hasFeature(this, featureIndex);
|
return f.hasFeature(this, featureIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2121,6 +2125,13 @@ public class Context
|
||||||
* <p>
|
* <p>
|
||||||
* The instruction counting support is available only for interpreted
|
* The instruction counting support is available only for interpreted
|
||||||
* scripts generated when the optimization level is set to -1.
|
* scripts generated when the optimization level is set to -1.
|
||||||
|
* <p>
|
||||||
|
* The default implementation calls
|
||||||
|
* {@link ContextFactory#observeInstructionCount(Context cx,
|
||||||
|
* int instructionCount)}
|
||||||
|
* that allows to customize Context behavior without introducing
|
||||||
|
* Context subclasses.
|
||||||
|
*
|
||||||
* @param instructionCount amount of script instruction executed since
|
* @param instructionCount amount of script instruction executed since
|
||||||
* last call to <code>observeInstructionCount</code>
|
* last call to <code>observeInstructionCount</code>
|
||||||
* @throws Error to terminate the script
|
* @throws Error to terminate the script
|
||||||
|
@ -2128,6 +2139,8 @@ public class Context
|
||||||
*/
|
*/
|
||||||
protected void observeInstructionCount(int instructionCount)
|
protected void observeInstructionCount(int instructionCount)
|
||||||
{
|
{
|
||||||
|
ContextFactory f = getFactory();
|
||||||
|
f.observeInstructionCount(this, instructionCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public GeneratedClassLoader createClassLoader(ClassLoader parent)
|
public GeneratedClassLoader createClassLoader(ClassLoader parent)
|
||||||
|
|
|
@ -61,6 +61,13 @@ package org.mozilla.javascript;
|
||||||
*
|
*
|
||||||
* class MyFactory extends ContextFactory
|
* class MyFactory extends ContextFactory
|
||||||
* {
|
* {
|
||||||
|
*
|
||||||
|
* // Custom {@link Context} to store execution time.
|
||||||
|
* private static class MyContext extends Context
|
||||||
|
* {
|
||||||
|
* long startTime;
|
||||||
|
* }
|
||||||
|
*
|
||||||
* static {
|
* static {
|
||||||
* // Initialize GlobalFactory with custom factory
|
* // Initialize GlobalFactory with custom factory
|
||||||
* ContextFactory.initGlobal(new MyFactory());
|
* ContextFactory.initGlobal(new MyFactory());
|
||||||
|
@ -71,9 +78,9 @@ package org.mozilla.javascript;
|
||||||
* {
|
* {
|
||||||
* MyContext cx = new MyContext();
|
* MyContext cx = new MyContext();
|
||||||
* // Use pure interpreter mode to allow for
|
* // Use pure interpreter mode to allow for
|
||||||
* // {@link Context#observeInstructionCount(int)} to work
|
* // {@link #observeInstructionCount(Context, int)} to work
|
||||||
* cx.setOptimizationLevel(-1);
|
* cx.setOptimizationLevel(-1);
|
||||||
* // Make Rhino runtime to call MyContext.observeInstructionCount(int)
|
* // Make Rhino runtime to call observeInstructionCount
|
||||||
* // each 10000 bytecode instructions
|
* // each 10000 bytecode instructions
|
||||||
* cx.setInstructionObserverThreshold(10000);
|
* cx.setInstructionObserverThreshold(10000);
|
||||||
* return cx;
|
* return cx;
|
||||||
|
@ -82,33 +89,29 @@ package org.mozilla.javascript;
|
||||||
* // Override {@link #hasFeature(Context, int)}
|
* // Override {@link #hasFeature(Context, int)}
|
||||||
* public boolean hasFeature(Context cx, int featureIndex)
|
* public boolean hasFeature(Context cx, int featureIndex)
|
||||||
* {
|
* {
|
||||||
* // Turn on maximim compatibility with MSIE scripts
|
* // Turn on maximum compatibility with MSIE scripts
|
||||||
* switch (featureIndex) {
|
* switch (featureIndex) {
|
||||||
* case Context.FEATURE_NON_ECMA_GET_YEAR:
|
* case {@link Context#FEATURE_NON_ECMA_GET_YEAR}:
|
||||||
* return true;
|
* return true;
|
||||||
*
|
*
|
||||||
* case Context.FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME:
|
* case {@link Context#FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME}:
|
||||||
* return true;
|
* return true;
|
||||||
*
|
*
|
||||||
* case Context.FEATURE_RESERVED_KEYWORD_AS_IDENTIFIER:
|
* case {@link Context#FEATURE_RESERVED_KEYWORD_AS_IDENTIFIER}:
|
||||||
* return true;
|
* return true;
|
||||||
*
|
*
|
||||||
* case Context.FEATURE_PARENT_PROTO_PROPRTIES:
|
* case {@link Context#FEATURE_PARENT_PROTO_PROPRTIES}:
|
||||||
* return false;
|
* return false;
|
||||||
* }
|
* }
|
||||||
* return super.hasFeature(cx, featureIndex);
|
* return super.hasFeature(cx, featureIndex);
|
||||||
* }
|
* }
|
||||||
* }
|
|
||||||
*
|
*
|
||||||
* class MyContext extends Context
|
* // Override {@link #observeInstructionCount(Context, int)}
|
||||||
* {
|
* protected void observeInstructionCount(Context cx, int instructionCount)
|
||||||
* private long creationTime = System.currentTimeMillis();
|
|
||||||
*
|
|
||||||
* // Override {@link Context#observeInstructionCount(int)}
|
|
||||||
* protected void observeInstructionCount(int instructionCount)
|
|
||||||
* {
|
* {
|
||||||
|
* MyContext mcx = (MyContext)cx;
|
||||||
* long currentTime = System.currentTimeMillis();
|
* long currentTime = System.currentTimeMillis();
|
||||||
* if (currentTime - creationTime > 10000) {
|
* if (currentTime - mcx.startTime > 10*1000) {
|
||||||
* // More then 10 seconds from Context creation time:
|
* // More then 10 seconds from Context creation time:
|
||||||
* // it is time to stop the script.
|
* // it is time to stop the script.
|
||||||
* // Throw Error instance to ensure that script will never
|
* // Throw Error instance to ensure that script will never
|
||||||
|
@ -117,7 +120,19 @@ package org.mozilla.javascript;
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
|
* // Override {@link #doTopCall(Callable, Context, Scriptable scope, Scriptable thisObj, Object[] args)}
|
||||||
|
* protected Object doTopCall(Callable callable,
|
||||||
|
* Context cx, Scriptable scope,
|
||||||
|
* Scriptable thisObj, Object[] args)
|
||||||
|
* {
|
||||||
|
* MyContext mcx = (MyContext)cx;
|
||||||
|
* mcx.startTime = System.currentTimeMillis();
|
||||||
|
*
|
||||||
|
* return super.doTopCall(callable, cx, scope, thisObj, args);
|
||||||
* }
|
* }
|
||||||
|
*
|
||||||
|
* }
|
||||||
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -258,6 +273,30 @@ public class ContextFactory
|
||||||
throw new IllegalArgumentException(String.valueOf(featureIndex));
|
throw new IllegalArgumentException(String.valueOf(featureIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute top call to script or function.
|
||||||
|
* When the runtime is about to execute a script or function that will
|
||||||
|
* create the first stack frame with scriptable code, it calls this method
|
||||||
|
* to perform the real call. In this way execution of any script
|
||||||
|
* happens inside this function.
|
||||||
|
*/
|
||||||
|
protected Object doTopCall(Callable callable,
|
||||||
|
Context cx, Scriptable scope,
|
||||||
|
Scriptable thisObj, Object[] args)
|
||||||
|
{
|
||||||
|
return callable.call(cx, scope, thisObj, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of
|
||||||
|
* {@link Context#observeInstructionCount(int instructionCount)}.
|
||||||
|
* This can be used to customize {@link Context} without introducing
|
||||||
|
* additional subclasses.
|
||||||
|
*/
|
||||||
|
protected void observeInstructionCount(Context cx, int instructionCount)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
protected void onContextCreated(Context cx)
|
protected void onContextCreated(Context cx)
|
||||||
{
|
{
|
||||||
Object listeners = this.listeners;
|
Object listeners = this.listeners;
|
||||||
|
|
|
@ -2787,6 +2787,33 @@ public class ScriptRuntime {
|
||||||
return (cx.topCallScope != null);
|
return (cx.topCallScope != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Object doTopCall(Callable callable,
|
||||||
|
Context cx, Scriptable scope,
|
||||||
|
Scriptable thisObj, Object[] args)
|
||||||
|
{
|
||||||
|
if (scope == null) throw new IllegalArgumentException();
|
||||||
|
if (cx.topCallScope != null) throw new IllegalStateException();
|
||||||
|
|
||||||
|
Object result;
|
||||||
|
cx.topCallScope = ScriptableObject.getTopLevelScope(scope);
|
||||||
|
cx.useDynamicScope = cx.hasFeature(Context.FEATURE_DYNAMIC_SCOPE);
|
||||||
|
ContextFactory f = cx.getFactory();
|
||||||
|
try {
|
||||||
|
result = f.doTopCall(callable, cx, scope, thisObj, args);
|
||||||
|
} finally {
|
||||||
|
cx.topCallScope = null;
|
||||||
|
// Cleanup cached references
|
||||||
|
cx.cachedXMLLib = null;
|
||||||
|
|
||||||
|
if (cx.currentActivationCall != null) {
|
||||||
|
// Function should always call exitActivationFunction
|
||||||
|
// if it creates activation record
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private static Scriptable locateDynamicScope(Context cx, Scriptable scope)
|
private static Scriptable locateDynamicScope(Context cx, Scriptable scope)
|
||||||
{
|
{
|
||||||
// Return cx.topCallScope is scope is present on its prototype chain
|
// Return cx.topCallScope is scope is present on its prototype chain
|
||||||
|
@ -2807,37 +2834,6 @@ public class ScriptRuntime {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object doTopCall(Callable callable,
|
|
||||||
Context cx, Scriptable scope,
|
|
||||||
Scriptable thisObj, Object[] args)
|
|
||||||
{
|
|
||||||
if (cx.topCallScope != null)
|
|
||||||
throw new IllegalStateException();
|
|
||||||
|
|
||||||
Object result;
|
|
||||||
cx.topCallScope = ScriptableObject.getTopLevelScope(scope);
|
|
||||||
cx.useDynamicScope = cx.hasFeature(Context.FEATURE_DYNAMIC_SCOPE);
|
|
||||||
try {
|
|
||||||
result = callable.call(cx, scope, thisObj, args);
|
|
||||||
} finally {
|
|
||||||
releaseTopCall(cx);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void releaseTopCall(Context cx)
|
|
||||||
{
|
|
||||||
cx.topCallScope = null;
|
|
||||||
// Cleanup cached references
|
|
||||||
cx.cachedXMLLib = null;
|
|
||||||
|
|
||||||
if (cx.currentActivationCall != null) {
|
|
||||||
// Function should always call exitActivationFunction
|
|
||||||
// if it creates activation record
|
|
||||||
throw new IllegalStateException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void initScript(NativeFunction funObj, Scriptable thisObj,
|
public static void initScript(NativeFunction funObj, Scriptable thisObj,
|
||||||
Context cx, Scriptable scope,
|
Context cx, Scriptable scope,
|
||||||
boolean evalScript)
|
boolean evalScript)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче