You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by bd...@apache.org on 2014/11/14 15:05:03 UTC

svn commit: r1639641 [12/15] - in /sling/trunk/contrib/scripting/sightly: ./ engine/ engine/src/ engine/src/main/ engine/src/main/antlr4/ engine/src/main/antlr4/org/ engine/src/main/antlr4/org/apache/ engine/src/main/antlr4/org/apache/sling/ engine/src...

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/UnwrapPlugin.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/UnwrapPlugin.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/UnwrapPlugin.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/UnwrapPlugin.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.plugin;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Properties;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Service;
+
+import org.apache.sling.scripting.sightly.compiler.api.expression.Expression;
+import org.apache.sling.scripting.sightly.compiler.api.expression.ExpressionNode;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.BooleanConstant;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.StringConstant;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.CompilerContext;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.Plugin;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginCallInfo;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginInvoke;
+import org.apache.sling.scripting.sightly.compiler.api.ris.Command;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.Conditional;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.VariableBinding;
+import org.apache.sling.scripting.sightly.compiler.common.DefaultPluginInvoke;
+import org.apache.sling.scripting.sightly.compiler.util.stream.PushStream;
+import org.apache.sling.scripting.sightly.compiler.api.expression.Expression;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.StringConstant;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.CompilerContext;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.Plugin;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginCallInfo;
+import org.apache.sling.scripting.sightly.compiler.api.ris.Command;
+import org.apache.sling.scripting.sightly.compiler.util.stream.PushStream;
+
+/**
+ * The unwrapped plugin
+ */
+@Component
+@Service(Plugin.class)
+@Properties({
+        @Property(name = Plugin.SCR_PROP_NAME_BLOCK_NAME, value = "unwrap"),
+        @Property(name = Plugin.SCR_PROP_NAME_PRIORITY, intValue = 125)
+})
+public class UnwrapPlugin extends PluginComponent {
+
+    @Override
+    public PluginInvoke invoke(final Expression expression,
+                               PluginCallInfo callInfo,
+                               final CompilerContext compilerContext) {
+        return new DefaultPluginInvoke() {
+
+            private final String variable = compilerContext.generateVariable("unwrapCondition");
+            private final Command unwrapTest = new Conditional.Start(variable, false);
+
+            @Override
+            public void beforeElement(PushStream stream, String tagName) {
+                stream.emit(new VariableBinding.Start(variable, testNode()));
+            }
+
+            @Override
+            public void beforeTagOpen(PushStream stream) {
+                stream.emit(unwrapTest);
+            }
+
+            @Override
+            public void afterTagOpen(PushStream stream) {
+                stream.emit(Conditional.END);
+            }
+
+            @Override
+            public void beforeTagClose(PushStream stream, boolean isSelfClosing) {
+                stream.emit(unwrapTest);
+            }
+
+            @Override
+            public void afterTagClose(PushStream stream, boolean isSelfClosing) {
+                stream.emit(Conditional.END);
+            }
+
+            @Override
+            public void afterElement(PushStream stream) {
+                stream.emit(VariableBinding.END);
+            }
+
+            private ExpressionNode testNode() {
+                return (isEmptyExpression(expression.getRoot())) ? BooleanConstant.TRUE : expression.getRoot();
+            }
+
+            private boolean isEmptyExpression(ExpressionNode node) {
+                return node instanceof StringConstant && ((StringConstant) node).getText().isEmpty();
+            }
+        };
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/UsePlugin.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/UsePlugin.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/UsePlugin.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/UsePlugin.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.plugin;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Properties;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Service;
+
+import org.apache.sling.scripting.sightly.compiler.api.expression.Expression;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.MapLiteral;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.RuntimeCall;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.CompilerContext;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.Plugin;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginCallInfo;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginInvoke;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.VariableBinding;
+import org.apache.sling.scripting.sightly.compiler.common.DefaultPluginInvoke;
+import org.apache.sling.scripting.sightly.compiler.util.stream.PushStream;
+import org.apache.sling.scripting.sightly.compiler.api.expression.Expression;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.CompilerContext;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.Plugin;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginCallInfo;
+
+@Component
+@Service
+@Properties({
+        @Property(name = "service.description", value = "Sightly Use Block Plugin"),
+        @Property(name = Plugin.SCR_PROP_NAME_BLOCK_NAME, value = "use"),
+        @Property(name = Plugin.SCR_PROP_NAME_PRIORITY, intValue = 1)
+})
+public class UsePlugin extends PluginComponent {
+
+    public static final String FUNCTION_NAME = "use";
+
+    private static final String DEFAULT_VARIABLE_NAME = "useBean";
+
+    @Override
+    public PluginInvoke invoke(final Expression expression,
+                               final PluginCallInfo callInfo,
+                               final CompilerContext compilerContext) {
+        return new DefaultPluginInvoke() {
+
+            @Override
+            public void beforeElement(PushStream stream, String tagName) {
+                String variableName = decodeVariableName();
+                stream.emit(new VariableBinding.Global(variableName,
+                        new RuntimeCall(FUNCTION_NAME, expression.getRoot(), new MapLiteral(expression.getOptions()))));
+            }
+
+            private String decodeVariableName() {
+                String[] arguments = callInfo.getArguments();
+                if (arguments.length > 0) {
+                    return arguments[0];
+                }
+                return DEFAULT_VARIABLE_NAME;
+            }
+        };
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/resources/templates/compiled_unit_template.txt
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/resources/templates/compiled_unit_template.txt?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/resources/templates/compiled_unit_template.txt (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/resources/templates/compiled_unit_template.txt Fri Nov 14 14:04:56 2014
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package ##PackageName##;
+
+import java.util.Collection;
+import javax.script.Bindings;
+
+import org.apache.sling.scripting.sightly.api.ObjectModel;
+import org.apache.sling.scripting.sightly.api.StackedWriter;
+import org.apache.sling.scripting.sightly.api.SightlyRuntime;
+import org.apache.sling.scripting.sightly.api.BaseRenderUnit;
+import org.apache.sling.scripting.sightly.api.RenderContext;
+
+public final class ##ClassName## extends BaseRenderUnit {
+
+    @Override
+    protected final void render(StackedWriter out,
+                                Bindings bindings,
+                                Bindings arguments,
+                                ObjectModel objectModel,
+                                SightlyRuntime runtime,
+                                RenderContext renderContext) {
+// Main Template Body -----------------------------------------------------------------------------
+
+##MainBody##
+
+// End Of Main Template Body ----------------------------------------------------------------------
+    }
+
+
+
+    {
+//Sub-Templates Initialization --------------------------------------------------------------------
+
+##SubTemplateMapInit##
+
+//End of Sub-Templates Initialization -------------------------------------------------------------
+    }
+
+}
+

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/resources/templates/subtemplate.txt
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/resources/templates/subtemplate.txt?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/resources/templates/subtemplate.txt (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/resources/templates/subtemplate.txt Fri Nov 14 14:04:56 2014
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+addSubTemplate("##Name##", new BaseRenderUnit() {
+
+    @Override
+    protected final void render(StackedWriter out,
+                                Bindings bindings,
+                                Bindings arguments,
+                                ObjectModel objectModel,
+                                SightlyRuntime runtime,
+                                RenderContext renderContext) {
+// Main Sub-Template Body -------------------------------------------------------------------------
+
+##MainBody##
+
+// End Of Main Sub-Template Body ------------------------------------------------------------------
+    }
+
+
+
+    {
+//Sub-Sub-Templates Initialization ----------------------------------------------------------------
+
+##SubTemplateMapInit##
+
+//End of Sub-Sub-Templates Initialization ---------------------------------------------------------
+    }
+    
+});

Propchange: sling/trunk/contrib/scripting/sightly/js-use-provider/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Fri Nov 14 14:04:56 2014
@@ -0,0 +1,15 @@
+target
+bin
+*.iml
+*.ipr
+*.iws
+.settings
+.project
+.classpath
+.externalToolBuilders
+maven-eclipse.xml
+felix-cache
+sling-crankstart
+derby.log
+
+

Added: sling/trunk/contrib/scripting/sightly/js-use-provider/README.md
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/js-use-provider/README.md?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/js-use-provider/README.md (added)
+++ sling/trunk/contrib/scripting/sightly/js-use-provider/README.md Fri Nov 14 14:04:56 2014
@@ -0,0 +1,8 @@
+Apache Sling Scripting Sightly JavaScript Use Provider
+=====================================
+
+This bundle allows Sightly's USE API to access JS scripts. It also wraps Sling's JS engine in a simulated event loop.
+
+The bundle also contains a bindings values provider that adds an API layer accessible from Sightly & JS.
+
+The implementation of that API can be found in `src/main/resources/SLING-INF`.

Added: sling/trunk/contrib/scripting/sightly/js-use-provider/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/js-use-provider/pom.xml?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/js-use-provider/pom.xml (added)
+++ sling/trunk/contrib/scripting/sightly/js-use-provider/pom.xml Fri Nov 14 14:04:56 2014
@@ -0,0 +1,164 @@
+<?xml version="1.0"?>
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License.  You may obtain a copy of the License at
+  ~
+  ~   http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <!-- ======================================================================= -->
+    <!-- P A R E N T   P R O J E C T                                             -->
+    <!-- ======================================================================= -->
+    <parent>
+        <groupId>org.apache.sling</groupId>
+        <artifactId>sling</artifactId>
+        <version>20</version>
+        <relativePath/>
+    </parent>
+
+    <!-- ======================================================================= -->
+    <!-- P R O J E C T                                                           -->
+    <!-- ======================================================================= -->
+    <artifactId>org.apache.sling.scripting.sightly.js.provider</artifactId>
+    <version>1.0.0-SNAPSHOT</version>
+    <packaging>bundle</packaging>
+
+    <name>Apache Sling Scripting Sightly JavaScript Use Provider</name>
+
+    <description>
+        The Apache Sling Sightly JavaScript Use Provider adds support for accessing JS scripts from Sightly's Use-API.
+    </description>
+
+    <scm>
+        <connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/bundles/scripting/sightly/js-use-provider</connection>
+        <developerConnection>scm:svn:https://svn.apache.org/repos/asf/sling/trunk/bundles/scripting/sightly/js-use-provider</developerConnection>
+        <url>http://svn.apache.org/repos/asf/sling/trunk/bundles/scripting/sightly/js-use-provider</url>
+    </scm>
+
+    <properties>
+        <sling.java.version>6</sling.java.version>
+    </properties>
+
+    <!-- ======================================================================= -->
+    <!-- B U I L D                                                               -->
+    <!-- ======================================================================= -->
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-scr-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Sling-Initial-Content>SLING-INF;overwrite=true</Sling-Initial-Content>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <!-- ======================================================================= -->
+    <!-- D E P E N D E N C I E S                                                 -->
+    <!-- ======================================================================= -->
+    <dependencies>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.compendium</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <!-- Sling -->
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.api</artifactId>
+            <version>2.8.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.scripting.api</artifactId>
+            <version>2.1.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.scripting.javascript</artifactId>
+            <version>2.0.12</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.apache.sling</groupId>
+                    <artifactId>org.apache.sling.jcr.resource</artifactId>
+                </exclusion>
+            </exclusions>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.commons.osgi</artifactId>
+            <version>2.2.0</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <!-- Sightly -->
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.scripting.sightly</artifactId>
+            <version>1.0.0-SNAPSHOT</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <!-- Logging -->
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <!-- Apache Commons -->
+        <dependency>
+            <groupId>commons-lang</groupId>
+            <artifactId>commons-lang</artifactId>
+            <version>2.5</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>2.4</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>servlet-api</artifactId>
+            <version>2.5</version>
+            <scope>provided</scope>
+        </dependency>
+
+
+        <!-- Rhino -->
+        <dependency>
+            <groupId>org.mozilla</groupId>
+            <artifactId>rhino</artifactId>
+            <version>1.7R4</version>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+</project>

Added: sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/Console.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/Console.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/Console.java (added)
+++ sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/Console.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.js;
+
+import org.slf4j.Logger;
+
+/**
+ * The console object, used for logging
+ */
+public class Console {
+
+    private final Logger logger;
+
+    public Console(Logger logger) {
+        this.logger = logger;
+    }
+
+    public void log(String msg) {
+        logger.info(msg);
+    }
+
+    public void warn(String msg) {
+        logger.warn(msg);
+    }
+
+    public void error(String msg) {
+        logger.error(msg);
+    }
+
+    public void debug(String msg) {
+        logger.debug(msg);
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/JsEnvironment.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/JsEnvironment.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/JsEnvironment.java (added)
+++ sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/JsEnvironment.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,174 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.js;
+
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+
+import javax.script.Bindings;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+import javax.script.SimpleBindings;
+import javax.script.SimpleScriptContext;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.scripting.SlingBindings;
+import org.apache.sling.api.scripting.SlingScriptHelper;
+import org.apache.sling.scripting.sightly.api.ResourceResolution;
+import org.apache.sling.scripting.sightly.api.SightlyUseException;
+import org.mozilla.javascript.Context;
+import org.slf4j.LoggerFactory;
+
+import org.apache.sling.scripting.sightly.js.async.AsyncContainer;
+import org.apache.sling.scripting.sightly.js.async.TimingBindingsValuesProvider;
+import org.apache.sling.scripting.sightly.js.async.UnaryCallback;
+import org.apache.sling.scripting.sightly.js.cjs.CommonJsModule;
+import org.apache.sling.scripting.sightly.js.loop.EventLoop;
+import org.apache.sling.scripting.sightly.js.loop.EventLoopInterop;
+import org.apache.sling.scripting.sightly.js.loop.Task;
+import org.apache.sling.scripting.sightly.js.use.DependencyResolver;
+import org.apache.sling.scripting.sightly.js.use.UseFunction;
+
+/**
+ * Environment for running JS scripts
+ */
+public class JsEnvironment {
+
+    private final ScriptEngine jsEngine;
+    private final Bindings engineBindings;
+    private EventLoop eventLoop;
+
+    public JsEnvironment(ScriptEngine jsEngine) {
+        this.jsEngine = jsEngine;
+        engineBindings = new SimpleBindings();
+        TimingBindingsValuesProvider.INSTANCE.addBindings(engineBindings);
+    }
+
+    public void initialize() {
+        Context context = Context.enter();
+        eventLoop = EventLoopInterop.obtainEventLoop(context);
+    }
+
+    public void cleanup() {
+        Context context = Context.getCurrentContext();
+        if (context == null) {
+            throw new IllegalStateException("No current context");
+        }
+        EventLoopInterop.cleanupEventLoop(context);
+        Context.exit();
+    }
+
+    /**
+     * Run a Js script at a given path
+     * @param caller the resource of the script that invokes the Js code
+     * @param path the path to the JS script
+     * @param globalBindings the global bindings for the script
+     * @param arguments the arguments from the use-plugin
+     * @param callback callback that will receive the result of the script
+     */
+    public void run(Resource caller, String path, Bindings globalBindings, Bindings arguments, UnaryCallback callback) {
+        Resource scriptResource = caller.getChild(path);
+        SlingScriptHelper scriptHelper = (SlingScriptHelper) globalBindings.get(SlingBindings.SLING);
+        Resource componentCaller = ResourceResolution.resolveComponentForRequest(caller.getResourceResolver(), scriptHelper.getRequest());
+        if (scriptResource == null) {
+            scriptResource = ResourceResolution.resolveComponentRelative(caller.getResourceResolver(), componentCaller, path);
+        }
+        if (scriptResource == null) {
+            scriptResource = ResourceResolution.resolveComponentRelative(caller.getResourceResolver(), caller, path);
+        }
+        if (scriptResource == null) {
+            throw new SightlyUseException("Required script resource could not be located: " + path);
+        }
+        runResource(scriptResource, globalBindings, arguments, callback);
+    }
+
+    public void runResource(Resource scriptResource, Bindings globalBindings, Bindings arguments, UnaryCallback callback) {
+        ScriptContext scriptContext = new SimpleScriptContext();
+        CommonJsModule module = new CommonJsModule();
+        Bindings scriptBindings = buildBindings(scriptResource, globalBindings, arguments, module);
+        scriptContext.setBindings(scriptBindings, ScriptContext.ENGINE_SCOPE);
+        runScript(scriptResource, scriptContext, callback, module);
+    }
+
+    public AsyncContainer runResource(Resource scriptResource, Bindings globalBindings, Bindings arguments) {
+        AsyncContainer asyncContainer = new AsyncContainer();
+        runResource(scriptResource, globalBindings, arguments, asyncContainer.createCompletionCallback());
+        return asyncContainer;
+    }
+
+    /**
+     * Run a script at a given path
+     * @param caller the resource of the script that invokes the Js code
+     * @param path the path to the JS script
+     * @param globalBindings bindings for the JS script
+     * @return an asynchronous container for the result
+     * @throws UnsupportedOperationException if this method is run when the event loop is not empty
+     */
+    public AsyncContainer run(Resource caller, String path, Bindings globalBindings, Bindings arguments) {
+        AsyncContainer asyncContainer = new AsyncContainer();
+        run(caller, path, globalBindings, arguments, asyncContainer.createCompletionCallback());
+        return asyncContainer;
+    }
+
+    private Bindings buildBindings(Resource scriptResource, Bindings local, Bindings arguments, CommonJsModule commonJsModule) {
+        Bindings bindings = new SimpleBindings();
+        bindings.putAll(engineBindings);
+        DependencyResolver dependencyResolver = new DependencyResolver(scriptResource, this, local);
+        UseFunction useFunction = new UseFunction(dependencyResolver, arguments);
+        bindings.put(Variables.JS_USE, useFunction);
+        bindings.put(Variables.MODULE, commonJsModule);
+        bindings.put(Variables.EXPORTS, commonJsModule.getExports());
+        bindings.put(Variables.CONSOLE, new Console(LoggerFactory.getLogger(scriptResource.getName())));
+        bindings.putAll(local);
+        return bindings;
+    }
+
+    private void runScript(Resource scriptResource, ScriptContext scriptContext, UnaryCallback callback, CommonJsModule commonJsModule) {
+        eventLoop.schedule(scriptTask(scriptResource, scriptContext, callback, commonJsModule));
+    }
+
+    private Task scriptTask(final Resource scriptResource, final ScriptContext scriptContext,
+                            final UnaryCallback callback, final CommonJsModule commonJsModule) {
+        return new Task(new Runnable() {
+            @Override
+            public void run() {
+                Reader reader = null;
+                try {
+                    reader = new InputStreamReader(scriptResource.adaptTo(InputStream.class));
+                    Object result = jsEngine.eval(reader, scriptContext);
+                    if (commonJsModule.isModified()) {
+                        result = commonJsModule.getExports();
+                    }
+                    if (result instanceof AsyncContainer) {
+                        ((AsyncContainer) result).addListener(callback);
+                    } else {
+                        callback.invoke(result);
+                    }
+                } catch (ScriptException e) {
+                    throw new SightlyUseException(e);
+                } finally {
+                    IOUtils.closeQuietly(reader);
+                }
+            }
+        });
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/JsUseProvider.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/JsUseProvider.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/JsUseProvider.java (added)
+++ sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/JsUseProvider.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.js;
+
+import javax.script.Bindings;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.api.resource.LoginException;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.apache.sling.api.scripting.SlingScriptHelper;
+import org.apache.sling.scripting.sightly.api.ProviderOutcome;
+import org.apache.sling.scripting.sightly.api.RenderContext;
+import org.apache.sling.scripting.sightly.api.UseProvider;
+import org.apache.sling.scripting.sightly.api.UseProviderComponent;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.sling.scripting.sightly.js.async.AsyncContainer;
+import org.apache.sling.scripting.sightly.js.async.AsyncExtractor;
+import org.apache.sling.scripting.sightly.js.rhino.JsValueAdapter;
+
+/**
+ * Use provider for JS scripts. Ensures proper integration between Sightly & JS code-behind.
+ */
+@Component
+@Service(UseProvider.class)
+@Property(name = UseProviderComponent.PRIORITY, intValue = -1)
+public class JsUseProvider extends UseProviderComponent {
+
+    private static final String JS_ENGINE_NAME = "javascript";
+
+    private static final Logger log = LoggerFactory.getLogger(JsUseProvider.class);
+    private static final JsValueAdapter jsValueAdapter = new JsValueAdapter(new AsyncExtractor());
+
+    @Reference
+    private ScriptEngineManager scriptEngineManager = null;
+
+    @Reference
+    private ResourceResolverFactory rrf = null;
+
+    @Override
+    public ProviderOutcome provide(String identifier, RenderContext renderContext, Bindings arguments) {
+        Bindings globalBindings = renderContext.getBindings();
+        if (!Utils.isJsScript(identifier)) {
+            return ProviderOutcome.failure();
+        }
+        ScriptEngine jsEngine = obtainEngine();
+        if (jsEngine == null) {
+            log.warn("No JavaScript engine defined");
+            return ProviderOutcome.failure();
+        }
+        SlingScriptHelper scriptHelper = Utils.getHelper(globalBindings);
+        JsEnvironment environment = null;
+        ResourceResolver adminResolver = null;
+        try {
+            environment = new JsEnvironment(jsEngine);
+            environment.initialize();
+            String callerPath = scriptHelper.getScript().getScriptResource().getPath();
+            boolean allowedExecutablePath = false;
+            adminResolver = rrf.getAdministrativeResourceResolver(null);
+            for (String path : adminResolver.getSearchPath()) {
+                if (callerPath.startsWith(path)) {
+                    allowedExecutablePath = true;
+                    break;
+                }
+            }
+            if (allowedExecutablePath) {
+                Resource caller = adminResolver.getResource(callerPath);
+                AsyncContainer asyncContainer = environment.run(caller, identifier, globalBindings, arguments);
+                return ProviderOutcome.success(jsValueAdapter.adapt(asyncContainer));
+            }
+            return ProviderOutcome.failure();
+        } catch (LoginException e) {
+            log.error("Unable to load JS script " + identifier, e);
+        } finally {
+            if (environment != null) {
+                environment.cleanup();
+            }
+            if (adminResolver != null) {
+                adminResolver.close();
+            }
+        }
+        return ProviderOutcome.failure();
+    }
+
+    private ScriptEngine obtainEngine() {
+        return scriptEngineManager.getEngineByName(JS_ENGINE_NAME);
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/Utils.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/Utils.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/Utils.java (added)
+++ sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/Utils.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.js;
+
+import javax.script.Bindings;
+import javax.script.SimpleBindings;
+import java.util.Collections;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.sling.api.scripting.SlingBindings;
+import org.apache.sling.api.scripting.SlingScriptHelper;
+
+/**
+ * Utilities for script evaluation
+ */
+public class Utils {
+    private static final String EXTENSION = "js";
+
+    public static final Bindings EMPTY_BINDINGS = new SimpleBindings(Collections.<String, Object>emptyMap());
+
+    public static SlingScriptHelper getHelper(Bindings bindings) {
+        return (SlingScriptHelper) bindings.get(SlingBindings.SLING);
+    }
+
+    public static boolean isJsScript(String identifier) {
+        String extension = StringUtils.substringAfterLast(identifier, ".");
+        return EXTENSION.equalsIgnoreCase(extension);
+    }
+
+}

Added: sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/Variables.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/Variables.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/Variables.java (added)
+++ sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/Variables.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.js;
+
+/**
+ * Variables exposed to js scripts
+ */
+public final class Variables {
+
+    public static final String CONSOLE = "console";
+
+    public static final String JS_USE = "use";
+    public static final String SET_TIMEOUT = "setTimeout";
+    public static final String SET_IMMEDIATE = "setImmediate";
+
+    public static final String MODULE = "module";
+    public static final String EXPORTS = "exports";
+}

Added: sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/async/AsyncContainer.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/async/AsyncContainer.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/async/AsyncContainer.java (added)
+++ sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/async/AsyncContainer.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.js.async;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Simple container for asynchronously provided values
+ */
+public class AsyncContainer {
+
+    private Object value;
+    private boolean completed;
+    private List<UnaryCallback> callbacks = new ArrayList<UnaryCallback>();
+
+    /**
+     * Add a listener that will receive the value in this container when it will
+     * be filled. If the container already has a value, the callback is called
+     * immediately.
+     * @param unaryCallback the callback that will receive the result
+     */
+    public void addListener(UnaryCallback unaryCallback) {
+        callbacks.add(unaryCallback);
+        if (completed) {
+            notifyListener(unaryCallback);
+        }
+    }
+
+    /**
+     * Get the result of this holder
+     * @return the holder result
+     * @throws java.util.NoSuchElementException if the result has not yet been set
+     */
+    public Object getResult() {
+        return value;
+    }
+
+    /**
+     * Check whether the container was completed with a value
+     * @return the completion status
+     */
+    public boolean isCompleted() {
+        return completed;
+    }
+
+    /**
+     * Complete this async container with a value
+     * @param value the result value
+     * @throws java.lang.IllegalStateException if the container has been previously filled
+     */
+    public void complete(Object value) {
+        if (completed) {
+            throw new IllegalStateException("Value was already completed");
+        }
+        completed = true;
+        this.value = value;
+        for (UnaryCallback callback : callbacks) {
+            notifyListener(callback);
+        }
+    }
+
+    /**
+     * Create a callback that will complete this container
+     * @return the completion callback
+     */
+    public UnaryCallback createCompletionCallback() {
+        return new UnaryCallback() {
+            @Override
+            public void invoke(Object arg) {
+                complete(arg);
+            }
+        };
+    }
+
+    private void notifyListener(UnaryCallback unaryCallback) {
+        unaryCallback.invoke(value);
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/async/AsyncExtractor.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/async/AsyncExtractor.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/async/AsyncExtractor.java (added)
+++ sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/async/AsyncExtractor.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.js.async;
+
+import org.apache.sling.scripting.sightly.api.SightlyUseException;
+import org.mozilla.javascript.BaseFunction;
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.Function;
+import org.mozilla.javascript.Scriptable;
+import org.mozilla.javascript.ScriptableObject;
+
+import org.apache.sling.scripting.sightly.js.loop.EventLoopInterop;
+
+/**
+ *
+ */
+public class AsyncExtractor {
+
+    public static final String THEN_METHOD = "then";
+
+    public void extract(Object jsObj, UnaryCallback unaryCallback) {
+        if (!isPromise(jsObj)) {
+            unaryCallback.invoke(jsObj);
+        }
+        if (jsObj instanceof AsyncContainer) {
+            ((AsyncContainer) jsObj).addListener(unaryCallback);
+        }
+        if (jsObj instanceof ScriptableObject) {
+            ScriptableObject scriptableObject = (ScriptableObject) jsObj;
+            decodeJSPromise(scriptableObject, unaryCallback);
+        }
+    }
+
+    private void decodeJSPromise(final Scriptable promise, final UnaryCallback callback) {
+        try {
+            Context context = Context.enter();
+            final AsyncContainer errorContainer = new AsyncContainer();
+            final Function errorHandler = createErrorHandler(errorContainer);
+            final Function successHandler = convertCallback(callback);
+            EventLoopInterop.schedule(context, new Runnable() {
+                @Override
+                public void run() {
+                    ScriptableObject.callMethod(promise, THEN_METHOD,
+                            new Object[] {successHandler, errorHandler});
+                }
+            });
+            if (errorContainer.isCompleted()) {
+                throw new SightlyUseException("Promise has completed with failure: " +
+                        Context.toString(errorContainer.getResult()));
+            }
+        } finally {
+            Context.exit();
+        }
+    }
+
+    private Function createErrorHandler(AsyncContainer asyncContainer) {
+        return convertCallback(asyncContainer.createCompletionCallback());
+    }
+
+    public boolean isPromise(Object jsObj) {
+        if (jsObj instanceof AsyncContainer) {
+            return true;
+        }
+        if (jsObj instanceof ScriptableObject) {
+            Scriptable scriptable = (Scriptable) jsObj;
+            return ScriptableObject.hasProperty(scriptable, THEN_METHOD);
+        }
+        return false;
+    }
+
+    private static Function convertCallback(final UnaryCallback unaryCallback) {
+        return new BaseFunction() {
+            @Override
+            public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
+                Object arg = (args.length == 0) ? Context.getUndefinedValue() : args[0];
+                unaryCallback.invoke(arg);
+                return Context.getUndefinedValue();
+            }
+        };
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/async/TimingBindingsValuesProvider.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/async/TimingBindingsValuesProvider.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/async/TimingBindingsValuesProvider.java (added)
+++ sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/async/TimingBindingsValuesProvider.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.js.async;
+
+import javax.script.Bindings;
+
+import org.apache.sling.scripting.api.BindingsValuesProvider;
+
+import org.apache.sling.scripting.sightly.js.Variables;
+
+/**
+ * Value provider for timing functions
+ */
+public final class TimingBindingsValuesProvider implements BindingsValuesProvider {
+
+    public static final TimingBindingsValuesProvider INSTANCE = new TimingBindingsValuesProvider();
+
+    private TimingBindingsValuesProvider() {
+    }
+
+    @Override
+    public void addBindings(Bindings bindings) {
+        bindings.put(Variables.SET_TIMEOUT, TimingFunction.INSTANCE);
+        bindings.put(Variables.SET_IMMEDIATE, TimingFunction.INSTANCE);
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/async/TimingFunction.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/async/TimingFunction.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/async/TimingFunction.java (added)
+++ sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/async/TimingFunction.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.js.async;
+
+import org.mozilla.javascript.BaseFunction;
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.Function;
+import org.mozilla.javascript.Scriptable;
+
+import org.apache.sling.scripting.sightly.js.loop.EventLoopInterop;
+import org.apache.sling.scripting.sightly.js.rhino.JsUtils;
+
+/**
+ * Timing function for JS scripts that use async constructs
+ */
+public final class TimingFunction extends BaseFunction {
+
+    public static final TimingFunction INSTANCE = new TimingFunction();
+
+    private TimingFunction() {
+    }
+
+    @Override
+    public Object call(final Context cx, final Scriptable scope, Scriptable thisObj, Object[] args) {
+        if (args.length == 0) {
+            return Context.getUndefinedValue();
+        }
+        if (!(args[0] instanceof Function)) {
+            throw new IllegalArgumentException("Timing function must receive a function as the first argument");
+        }
+        final Function function = (Function) args[0];
+        return EventLoopInterop.schedule(cx, new Runnable() {
+            @Override
+            public void run() {
+                JsUtils.callFn(function, cx, scope, null, new Object[0]);
+            }
+        });
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/async/UnaryCallback.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/async/UnaryCallback.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/async/UnaryCallback.java (added)
+++ sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/async/UnaryCallback.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.js.async;
+
+/**
+ * Unary callback function
+ */
+public interface UnaryCallback {
+
+    /**
+     * Call the callback with one argument
+     * @param arg the callback argument
+     */
+    void invoke(Object arg);
+}

Added: sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/cjs/CommonJsModule.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/cjs/CommonJsModule.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/cjs/CommonJsModule.java (added)
+++ sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/cjs/CommonJsModule.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.js.cjs;
+
+import org.mozilla.javascript.Scriptable;
+import org.mozilla.javascript.ScriptableObject;
+
+/**
+ * CommonJS module implementation
+ */
+public class CommonJsModule extends ScriptableObject {
+
+    private static final String EXPORTS = "exports";
+
+    private Object exports = new ExportsObject();
+    private boolean modifiedModule;
+
+
+    @Override
+    public Object get(String name, Scriptable start) {
+        if (name.equals(EXPORTS)) {
+            return exports;
+        }
+        return super.get(name, start);
+    }
+
+    @Override
+    public void put(String name, Scriptable start, Object value) {
+        if (name.equals(EXPORTS)) {
+            setExports(value);
+        } else {
+            super.put(name, start, value);
+        }
+    }
+
+    public Object getExports() {
+        return exports;
+    }
+
+    public void setExports(Object exports) {
+        modifiedModule = true;
+        this.exports = exports;
+    }
+
+    public boolean isModified() {
+        return modifiedModule || ((ExportsObject) exports).isModified();
+    }
+
+    @Override
+    public String getClassName() {
+        return "Module";
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/cjs/ExportsObject.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/cjs/ExportsObject.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/cjs/ExportsObject.java (added)
+++ sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/cjs/ExportsObject.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.js.cjs;
+
+
+import org.mozilla.javascript.Scriptable;
+import org.mozilla.javascript.ScriptableObject;
+
+/**
+ * The default exports object
+ */
+public class ExportsObject extends ScriptableObject {
+
+    private boolean modified;
+
+    @Override
+    public void put(String name, Scriptable start, Object value) {
+        modified = true;
+        super.put(name, start, value);
+    }
+
+    public boolean isModified() {
+        return modified;
+    }
+
+    @Override
+    public String getClassName() {
+        return "exports";
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/jsapi/SlyBindingsValuesProvider.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/jsapi/SlyBindingsValuesProvider.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/jsapi/SlyBindingsValuesProvider.java (added)
+++ sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/jsapi/SlyBindingsValuesProvider.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,314 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.js.jsapi;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Map;
+import javax.script.Bindings;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.SimpleBindings;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Properties;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.PropertyUnbounded;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.api.resource.LoginException;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.apache.sling.api.scripting.SlingBindings;
+import org.apache.sling.commons.osgi.PropertiesUtil;
+import org.apache.sling.scripting.api.BindingsValuesProvider;
+import org.apache.sling.scripting.sightly.js.JsEnvironment;
+import org.apache.sling.scripting.sightly.js.Variables;
+import org.apache.sling.scripting.sightly.js.async.AsyncContainer;
+import org.apache.sling.scripting.sightly.js.async.AsyncExtractor;
+import org.apache.sling.scripting.sightly.js.async.TimingBindingsValuesProvider;
+import org.apache.sling.scripting.sightly.js.async.TimingFunction;
+import org.apache.sling.scripting.sightly.js.cjs.CommonJsModule;
+import org.apache.sling.scripting.sightly.js.rhino.HybridObject;
+import org.apache.sling.scripting.sightly.js.rhino.JsValueAdapter;
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.Function;
+import org.mozilla.javascript.Script;
+import org.mozilla.javascript.Scriptable;
+import org.mozilla.javascript.ScriptableObject;
+import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Provides the {@code sly} and {@code aem} namespaces for usage in Sightly & JS scripts
+ * called from Sightly
+ */
+@Component(metatype = true, label = "Apache Sling Scripting Sightly JavaScript Bindings Provider",
+        description = "The Apache Sling Scripting Sightly JavaScript Bindings Provider loads the JS Use-API and makes it available in the" +
+                " bindings map.")
+@Service(BindingsValuesProvider.class)
+@Properties({
+        @Property(name = "javax.script.name", value = "sightly", propertyPrivate = true),
+        @Property(name = "service.ranking", intValue = 100),
+        @Property(
+                name = SlyBindingsValuesProvider.SCR_PROP_JS_BINDING_IMPLEMENTATIONS,
+                value = {
+                    "sightly:" + SlyBindingsValuesProvider.SLING_NS_PATH
+                },
+                unbounded = PropertyUnbounded.ARRAY,
+                label = "Script Factories",
+                description = "Script factories to load in the bindings map. The entries should be in the form " +
+                        "'namespace:/path/from/repository'."
+        )
+})
+@SuppressWarnings("unused")
+public class SlyBindingsValuesProvider implements BindingsValuesProvider {
+
+    public static final String SCR_PROP_JS_BINDING_IMPLEMENTATIONS = "org.apache.sling.scripting.sightly.js.bindings";
+
+    public static final String SLING_NS_PATH = "/libs/sling/sightly/js/internal/sly.js";
+    public static final String Q_PATH = "/libs/sling/sightly/js/3rd-party/q.js";
+
+    private static final String REQ_NS = SlyBindingsValuesProvider.class.getCanonicalName();
+
+    private static final Logger log = LoggerFactory.getLogger(SlyBindingsValuesProvider.class);
+
+    @Reference
+    private ScriptEngineManager scriptEngineManager;
+
+    @Reference
+    private ResourceResolverFactory rrf = null;
+
+    private final AsyncExtractor asyncExtractor = new AsyncExtractor();
+    private final JsValueAdapter jsValueAdapter = new JsValueAdapter(asyncExtractor);
+
+    private Map<String, String> scriptPaths = new HashMap<String, String>();
+    private Map<String, Function> factories = new HashMap<String, Function>();
+
+    private Script qScript;
+    private final ScriptableObject qScope = createQScope();
+
+    @Override
+    public void addBindings(Bindings bindings) {
+        if (needsInit()) {
+            init(bindings);
+        }
+        Context context = null;
+        try {
+            context = Context.enter();
+            Object qInstance = obtainQInstance(context, bindings);
+            if (qInstance == null) {
+                return;
+            }
+            for (Map.Entry<String, Function> entry : factories.entrySet()) {
+                addBinding(context, entry.getValue(), bindings, entry.getKey(), qInstance);
+            }
+        } finally {
+            if (context != null) {
+                Context.exit();
+            }
+        }
+    }
+
+    @Activate
+    protected void activate(ComponentContext componentContext) {
+        Dictionary properties = componentContext.getProperties();
+        String[] factories = PropertiesUtil.toStringArray(properties.get(SCR_PROP_JS_BINDING_IMPLEMENTATIONS), new String[]{SLING_NS_PATH});
+        scriptPaths = new HashMap<String, String>(factories.length);
+        for (String f : factories) {
+            String[] parts = f.split(":");
+            if (parts.length == 2) {
+                scriptPaths.put(parts[0], parts[1]);
+            }
+        }
+    }
+
+    @Deactivate
+    protected void deactivate(ComponentContext componentContext) {
+        if (scriptPaths != null) {
+            scriptPaths.clear();
+        }
+        if (factories != null) {
+            factories.clear();
+        }
+    }
+
+
+    private void addBinding(Context context, Function factory, Bindings bindings, String globalName, Object qInstance) {
+        if (factory == null) {
+            return;
+        }
+        Object result = factory.call(context, factory, factory, new Object[] {bindings, qInstance});
+        HybridObject global = new HybridObject((Scriptable) result, jsValueAdapter);
+        bindings.put(globalName, global);
+    }
+
+    private boolean needsInit() {
+        return factories == null || factories.isEmpty() || qScript == null;
+    }
+
+    private synchronized void init(Bindings bindings) {
+        if (needsInit()) {
+            ensureFactoriesLoaded(bindings);
+        }
+    }
+
+    private void ensureFactoriesLoaded(Bindings bindings) {
+        JsEnvironment jsEnvironment = null;
+        try {
+            ScriptEngine scriptEngine = obtainEngine();
+            if (scriptEngine == null) {
+                return;
+            }
+            jsEnvironment = new JsEnvironment(scriptEngine);
+            jsEnvironment.initialize();
+            factories = new HashMap<String, Function>(scriptPaths.size());
+            for (Map.Entry<String, String> entry : scriptPaths.entrySet()) {
+                factories.put(entry.getKey(), loadFactory(jsEnvironment, entry.getValue(), bindings));
+            }
+            qScript = loadQScript();
+        } finally {
+            if (jsEnvironment != null) {
+                jsEnvironment.cleanup();
+            }
+        }
+    }
+
+    private Function loadFactory(JsEnvironment jsEnvironment, String path, Bindings bindings) {
+        ResourceResolver resolver = null;
+        try {
+            resolver = rrf.getAdministrativeResourceResolver(null);
+            Resource resource = resolver.getResource(path);
+            if (resource == null) {
+                log.warn("Sly namespace loader could not find the following script: " + path);
+                return null;
+            }
+            AsyncContainer container = jsEnvironment.runResource(resource, createBindings(bindings), new SimpleBindings());
+            Object obj = container.getResult();
+            if (!(obj instanceof Function)) {
+                log.warn("Script was expected to return a function");
+                return null;
+            }
+            return (Function) obj;
+        } catch (LoginException e) {
+            log.error("Cannot evaluate script " + path, e);
+            return null;
+        } finally {
+            if (resolver != null) {
+                resolver.close();
+            }
+        }
+    }
+
+    private Bindings createBindings(Bindings global) {
+        Bindings bindings = new SimpleBindings();
+        bindings.putAll(global);
+        TimingBindingsValuesProvider.INSTANCE.addBindings(bindings);
+        return bindings;
+    }
+
+    private ScriptEngine obtainEngine() {
+        return scriptEngineManager.getEngineByName("javascript");
+    }
+
+    private Object obtainQInstance(Context context, Bindings bindings) {
+        if (qScript == null) {
+            return null;
+        }
+        HttpServletRequest request = (HttpServletRequest) bindings.get(SlingBindings.REQUEST);
+        Object qInstance = null;
+        if (request != null) {
+            qInstance = request.getAttribute(REQ_NS);
+        }
+        if (qInstance == null) {
+            qInstance = createQInstance(context, qScript);
+            if (request != null) {
+                request.setAttribute(REQ_NS, qInstance);
+            }
+        }
+        return qInstance;
+    }
+
+    private ScriptableObject createQScope() {
+        Context context = Context.enter();
+        try {
+            ScriptableObject scope = context.initStandardObjects();
+            ScriptableObject.putProperty(scope, Variables.SET_IMMEDIATE, TimingFunction.INSTANCE);
+            ScriptableObject.putProperty(scope, Variables.SET_TIMEOUT, TimingFunction.INSTANCE);
+            return scope;
+        } finally {
+            Context.exit();
+        }
+    }
+
+    private Object createQInstance(Context context, Script qScript) {
+        CommonJsModule module = new CommonJsModule();
+        Scriptable tempScope = context.newObject(qScope);
+        ScriptableObject.putProperty(tempScope, Variables.MODULE, module);
+        ScriptableObject.putProperty(tempScope, Variables.EXPORTS, module.getExports());
+        qScript.exec(context, tempScope);
+        return module.getExports();
+    }
+
+    private Script loadQScript() {
+        ResourceResolver resourceResolver = null;
+        Context context = Context.enter();
+        context.initStandardObjects();
+        context.setOptimizationLevel(9);
+        InputStream reader = null;
+        try {
+            resourceResolver = rrf.getAdministrativeResourceResolver(null);
+            Resource resource = resourceResolver.getResource(Q_PATH);
+            if (resource == null) {
+                log.warn("Could not load Q library at path: " + Q_PATH);
+                return null;
+            }
+            reader = resource.adaptTo(InputStream.class);
+            if (reader == null) {
+                log.warn("Could not read content of Q library");
+                return null;
+            }
+            return context.compileReader(new InputStreamReader(reader), Q_PATH, 0, null);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        } finally {
+            Context.exit();
+            if (reader != null) {
+                try {
+                    reader.close();
+                } catch (IOException e) {
+                    log.error("Error while closing reader", e);
+                }
+            }
+            if (resourceResolver != null) {
+                resourceResolver.close();
+            }
+        }
+    }
+
+}

Added: sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/loop/EventLoop.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/loop/EventLoop.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/loop/EventLoop.java (added)
+++ sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/loop/EventLoop.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.js.loop;
+
+import java.util.LinkedList;
+import java.util.Queue;
+
+import org.apache.sling.scripting.sightly.api.SightlyUseException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * Simulates an event loop for the Rhino JS engine.
+ */
+public class EventLoop {
+
+    private static final Logger log = LoggerFactory.getLogger(EventLoop.class);
+
+    private Queue<Task> taskQueue = new LinkedList<Task>();
+    private boolean isRunning;
+
+    /**
+     * Add a task to the queue. If the queue is empty, start running tasks. If it
+     * isn't empty, continue running the available tasks
+     * @param task the task to be added
+     */
+    public void schedule(Task task) {
+        taskQueue.offer(task);
+        run();
+    }
+
+    private void run() {
+        if (isRunning) {
+            return;
+        }
+        isRunning = true;
+        try {
+            // Holds the first exception encountered. If there is such a first exception, it will be
+            // rethrown
+            Exception thrownException = null;
+            while (!taskQueue.isEmpty()) {
+                Task task = taskQueue.poll();
+                try {
+                    task.run();
+                } catch (Exception e) {
+                    if (thrownException == null) {
+                        thrownException = e; //first exception
+                    } else {
+                        log.error("Additional error occurred while running JS script: ", e);
+                    }
+                }
+            }
+            if (thrownException != null) {
+                throw new SightlyUseException(thrownException);
+            }
+        } finally {
+            isRunning = false;
+        }
+    }
+
+}

Added: sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/loop/EventLoopInterop.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/loop/EventLoopInterop.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/loop/EventLoopInterop.java (added)
+++ sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/loop/EventLoopInterop.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.js.loop;
+
+import org.mozilla.javascript.Context;
+
+/**
+ * Event-loop utilities for interoperability with JS code
+ */
+public class EventLoopInterop {
+
+    public static final String EVENT_LOOP_KEY = "EventLoop";
+
+    public static EventLoop obtainEventLoop(Context context) {
+        EventLoop eventLoop = getEventLoop(context);
+        if (eventLoop == null) {
+            eventLoop = new EventLoop();
+            context.putThreadLocal(EVENT_LOOP_KEY, eventLoop);
+        }
+        return eventLoop;
+    }
+
+    public static void cleanupEventLoop(Context context) {
+        context.removeThreadLocal(EVENT_LOOP_KEY);
+    }
+
+    public static Task schedule(Context context, Runnable runnable) {
+        Task task = new Task(runnable);
+        obtainEventLoop(context).schedule(task);
+        return task;
+    }
+
+    private static EventLoop getEventLoop(Context context) {
+        return (EventLoop) context.getThreadLocal(EVENT_LOOP_KEY);
+    }
+
+}

Added: sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/loop/Task.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/loop/Task.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/loop/Task.java (added)
+++ sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/loop/Task.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.js.loop;
+
+/**
+ * Task in an event loop
+ */
+public class Task {
+
+    private final Runnable runnable;
+    private boolean active;
+
+    public Task(Runnable runnable) {
+        this.runnable = runnable;
+        this.active = true;
+    }
+
+    public void run() {
+        if (active) {
+            runnable.run();
+        }
+    }
+
+    public void deactivate() {
+        this.active = false;
+    }
+}