public Object eval()

in src/main/java/org/apache/sling/scripting/javascript/internal/RhinoJavaScriptEngine.java [235:352]


        public Object eval(ScriptContext scriptContext) throws ScriptException {
            Bindings bindings = scriptContext.getBindings(ScriptContext.ENGINE_SCOPE);

            // container for replaced properties
            Map<String, Object> replacedProperties = null;
            Scriptable scope = null;
            boolean isTopLevelCall = false;

            // create a rhino Context and execute the script
            try {

                final Context rhinoContext = Context.enter();
                rhinoContext.setLanguageVersion(((RhinoJavaScriptEngineFactory)getFactory()).rhinoLanguageVersion());
                rhinoContext.setOptimizationLevel(optimizationLevel());

                if (ScriptRuntime.hasTopCall(rhinoContext)) {
                    // reuse the top scope if we are included
                    scope = ScriptRuntime.getTopCallScope(rhinoContext);

                } else {
                    // create the request top scope, use the ImporterToplevel here
                    // to support the importPackage and importClasses functions
                    scope = new ImporterTopLevel();

                    // Set the global scope to be our prototype
                    scope.setPrototype(rootScope);

                    // We want "scope" to be a new top-level scope, so set its
                    // parent scope to null. This means that any variables created
                    // by assignments will be properties of "scope".
                    scope.setParentScope(null);

                    // setup the context for use
                    WrapFactory wrapFactory = ((RhinoJavaScriptEngineFactory) getFactory()).getWrapFactory();
                    rhinoContext.setWrapFactory(wrapFactory);

                    // this is the top level call
                    isTopLevelCall = true;
                }

                // add initial properties to the scope
                replacedProperties = setBoundProperties(scope, bindings);

                Object result = script.exec(rhinoContext, scope);

                if (result instanceof Wrapper) {
                    result = ((Wrapper) result).unwrap();
                }

                return (result instanceof Undefined) ? null : result;

            } catch (JavaScriptException t) {

                // prevent variables to be pushed back in case of errors
                isTopLevelCall = false;

                final ScriptException se = new ScriptException(t.details(),
                        t.sourceName(), t.lineNumber());

                // log the script stack trace
                ((Logger) bindings.get(SlingBindings.LOG)).error(t.getScriptStackTrace());

                // set the exception cause
                Object value = t.getValue();
                if (value != null) {
                    if (value instanceof Wrapper) {
                        value = ((Wrapper) value).unwrap();
                    }
                    if (value instanceof Throwable) {
                        se.initCause((Throwable) value);
                    }
                }

                // if the cause could not be set, overwrite the stack trace
                if (se.getCause() == null) {
                    se.setStackTrace(t.getStackTrace());
                }

                throw se;

            } catch (Throwable t) {

                // prevent variables to be pushed back in case of errors
                isTopLevelCall = false;
                String scriptName = getScriptName(scriptContext);
                final ScriptException se = new ScriptException("Failure running script " + scriptName + ": " + t.getMessage());
                se.initCause(t);
                throw se;

            } finally {

                // if we are the top call (the Context is now null) we have to
                // play back any properties from the scope back to the bindings
                if (isTopLevelCall) {
                    getBoundProperties(scope, bindings);
                }

                // if properties have been replaced, reset them
                resetBoundProperties(scope, replacedProperties);
                ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
                if (classLoader instanceof DynamicClassLoader) {
                    DynamicClassLoader dynamicClassLoader = (DynamicClassLoader) classLoader;
                    if (!dynamicClassLoader.isLive()) {
                        /**
                         * if the class loader on this thread is a dynamic class loader and it's dirty we should clear Rhino's class cache
                         * to avoid class loader leaks
                         */
                        if (scope != null) {
                            ClassCache classCache = ClassCache.get(scope);
                            classCache.clearCaches();
                            LOGGER.info("Detected dirty class loader on thread {}. Emptying Rhino's class cache.", Thread.currentThread()
                                    .getName());
                        }
                    }
                }
                Context.exit();
            }
        }