You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2017/11/07 10:10:57 UTC

[sling-org-apache-sling-scripting-sightly-js-provider] annotated tag org.apache.sling.scripting.sightly.js.provider-1.0.0 created (now 439ab94)

This is an automated email from the ASF dual-hosted git repository.

rombert pushed a change to annotated tag org.apache.sling.scripting.sightly.js.provider-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-sightly-js-provider.git.


      at 439ab94  (tag)
 tagging 2ff20712685ba62cbca101c4a75db6be9d28bd5f (commit)
      by Radu Cotescu
      on Mon Mar 23 09:06:28 2015 +0000

- Log -----------------------------------------------------------------
org.apache.sling.scripting.sightly.js.provider-1.0.0
-----------------------------------------------------------------------

This annotated tag includes the following new commits:

     new 378982c  SLING-3959 - Sightly contribution
     new d05bbfa  SLING-4206 Refactor Sightly and Sightly JS
     new 6597314  SLING-4206 Refactor Sightly and Sightly JS
     new 31ae7e9  SLING-4182 Downgrade Sling API dependencies to the minimum required API (2.4 instead of 2.8)
     new fd9d13b  SLING-4209 Expose required JavaScript files through the BundleResourceProvider
     new ca30d50  SLING-4241 Improve JS execution performance
     new c7b48be  SLING-4309 Remove redundant RuntimeExtensionException and SightlyUseException from Sightly's API
     new 72fdfd3  SLING-4305 Refactor the Record interface:
     new c6b94f4  SLING-4304 Refactor the ResourceResolution class and improve its JavaDoc
     new 54cba6d  SLING-4323 Fix SCM locations
     new c60ac61  SLING-4400 - The Use-API should return a falsy value if no Use-provider was able to solve the requested object
     new c85c1bb  SLING-4419 - [Regression] Sling Models cannot be used with Sightly Java Use-API
     new 68de359  SLING-4358 - Add the 'Provide-Capability' OSGi header to the org.apache.sling.scripting.sightly bundle
     new 4e32d86  SLING-4506 - Java APIs not consistently available in JavaScript
     new 5b7f8f0  SLING-4515 - Insufficient cleanup of the JavaScript execution engine leads to runtime errors
     new f7ebc2c  @releng: updating o.a.s.s.sightly.engine to 1.0.0
     new 54a876d  [maven-release-plugin] prepare release org.apache.sling.scripting.sightly.js.provider-1.0.0
     new 2ff2071  [maven-release-plugin]  copy for tag org.apache.sling.scripting.sightly.js.provider-1.0.0

The 18 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


-- 
To stop receiving notification emails like this one, please contact
['"commits@sling.apache.org" <co...@sling.apache.org>'].

[sling-org-apache-sling-scripting-sightly-js-provider] 12/18: SLING-4419 - [Regression] Sling Models cannot be used with Sightly Java Use-API

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.scripting.sightly.js.provider-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-sightly-js-provider.git

commit c85c1bb45fb1a7d19c3280c0a70c7120121bab5a
Author: Radu Cotescu <ra...@apache.org>
AuthorDate: Fri Feb 13 11:40:30 2015 +0000

    SLING-4419 - [Regression] Sling Models cannot be used with Sightly Java Use-API
    
    * merged PojoUseProvider with ClassUseProvider into JavaUseProvider which first tries to adapt the object to
    Resource / SlingHttpServletRequest, then tries to load the object as a POJO from the repository
    * provided IT for the Sling specific Use-API implementation
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/scripting/sightly/js-use-provider@1659520 13f79535-47bb-0310-9956-ffa450edef68
---
 .../java/org/apache/sling/scripting/sightly/js/impl/JsUseProvider.java  | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/impl/JsUseProvider.java b/src/main/java/org/apache/sling/scripting/sightly/js/impl/JsUseProvider.java
index 665ff4e..35cc70d 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/js/impl/JsUseProvider.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/impl/JsUseProvider.java
@@ -61,7 +61,7 @@ import org.slf4j.LoggerFactory;
                 label = "Service Ranking",
                 description = "The Service Ranking value acts as the priority with which this Use Provider is queried to return an " +
                         "Use-object. A higher value represents a higher priority.",
-                intValue = 90,
+                intValue = 80,
                 propertyPrivate = false
         )
 })

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-scripting-sightly-js-provider] 06/18: SLING-4241 Improve JS execution performance

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.scripting.sightly.js.provider-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-sightly-js-provider.git

commit ca30d507a105cfb982c4f1f7d327d5ffa9172b4d
Author: Felix Meschberger <fm...@apache.org>
AuthorDate: Mon Dec 15 13:35:27 2014 +0000

    SLING-4241 Improve JS execution performance
    
    (apply patch by Radu Cotescu; thanks a lot)
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/scripting/sightly/js-use-provider@1645656 13f79535-47bb-0310-9956-ffa450edef68
---
 .../sling/scripting/sightly/js/impl/JsUseProvider.java       |  5 +++++
 .../sightly/js/impl/jsapi/SlyBindingsValuesProvider.java     | 12 ++++--------
 2 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/impl/JsUseProvider.java b/src/main/java/org/apache/sling/scripting/sightly/js/impl/JsUseProvider.java
index fa8b0ec..b779c81 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/js/impl/JsUseProvider.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/impl/JsUseProvider.java
@@ -34,6 +34,7 @@ import org.apache.sling.api.resource.ResourceResolverFactory;
 import org.apache.sling.api.scripting.SlingScriptHelper;
 import org.apache.sling.scripting.sightly.js.impl.async.AsyncContainer;
 import org.apache.sling.scripting.sightly.js.impl.async.AsyncExtractor;
+import org.apache.sling.scripting.sightly.js.impl.jsapi.SlyBindingsValuesProvider;
 import org.apache.sling.scripting.sightly.js.impl.rhino.JsValueAdapter;
 import org.apache.sling.scripting.sightly.render.RenderContext;
 import org.apache.sling.scripting.sightly.use.ProviderOutcome;
@@ -74,9 +75,13 @@ public class JsUseProvider implements UseProvider {
     @Reference
     private ResourceResolverFactory rrf = null;
 
+    @Reference
+    private SlyBindingsValuesProvider slyBindingsValuesProvider = null;
+
     @Override
     public ProviderOutcome provide(String identifier, RenderContext renderContext, Bindings arguments) {
         Bindings globalBindings = renderContext.getBindings();
+        slyBindingsValuesProvider.processBindings(globalBindings);
         if (!Utils.isJsScript(identifier)) {
             return ProviderOutcome.failure();
         }
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/impl/jsapi/SlyBindingsValuesProvider.java b/src/main/java/org/apache/sling/scripting/sightly/js/impl/jsapi/SlyBindingsValuesProvider.java
index 72b99a2..6731ed4 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/js/impl/jsapi/SlyBindingsValuesProvider.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/impl/jsapi/SlyBindingsValuesProvider.java
@@ -45,7 +45,6 @@ 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.impl.JsEnvironment;
 import org.apache.sling.scripting.sightly.js.impl.Variables;
 import org.apache.sling.scripting.sightly.js.impl.async.AsyncContainer;
@@ -65,16 +64,14 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * Provides the {@code sly} and {@code aem} namespaces for usage in Sightly & JS scripts
+ * Provides the {@code sightly} namespace 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)
+@Service(SlyBindingsValuesProvider.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 = {
@@ -87,7 +84,7 @@ import org.slf4j.LoggerFactory;
         )
 })
 @SuppressWarnings("unused")
-public class SlyBindingsValuesProvider implements BindingsValuesProvider {
+public class SlyBindingsValuesProvider {
 
     public static final String SCR_PROP_JS_BINDING_IMPLEMENTATIONS = "org.apache.sling.scripting.sightly.js.bindings";
 
@@ -113,8 +110,7 @@ public class SlyBindingsValuesProvider implements BindingsValuesProvider {
     private Script qScript;
     private final ScriptableObject qScope = createQScope();
 
-    @Override
-    public void addBindings(Bindings bindings) {
+    public void processBindings(Bindings bindings) {
         if (needsInit()) {
             init(bindings);
         }

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-scripting-sightly-js-provider] 16/18: @releng: updating o.a.s.s.sightly.engine to 1.0.0

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.scripting.sightly.js.provider-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-sightly-js-provider.git

commit f7ebc2c65df36a00056feda8bc3dff4aa843102d
Author: Radu Cotescu <ra...@apache.org>
AuthorDate: Mon Mar 23 09:05:41 2015 +0000

    @releng: updating o.a.s.s.sightly.engine to 1.0.0
    
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/scripting/sightly/js-use-provider@1668556 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index e10af62..fb9dde2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -128,7 +128,7 @@
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.scripting.sightly</artifactId>
-            <version>1.0.0-SNAPSHOT</version>
+            <version>1.0.0</version>
             <scope>provided</scope>
         </dependency>
 

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-scripting-sightly-js-provider] 05/18: SLING-4209 Expose required JavaScript files through the BundleResourceProvider

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.scripting.sightly.js.provider-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-sightly-js-provider.git

commit fd9d13b6ae11bd203007b8cf8f12f2e69bd213fb
Author: Felix Meschberger <fm...@apache.org>
AuthorDate: Fri Nov 28 13:27:03 2014 +0000

    SLING-4209 Expose required JavaScript files through the BundleResourceProvider
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/scripting/sightly/js-use-provider@1642293 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index 5c4bb65..b4e983c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -68,7 +68,7 @@
                 <extensions>true</extensions>
                 <configuration>
                     <instructions>
-                        <Sling-Initial-Content>SLING-INF;overwrite=true</Sling-Initial-Content>
+                        <Sling-Bundle-Resources>/libs/sling/sightly/js;path:=/SLING-INF/libs/sling/sightly/js</Sling-Bundle-Resources>
                     </instructions>
                 </configuration>
             </plugin>

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-scripting-sightly-js-provider] 15/18: SLING-4515 - Insufficient cleanup of the JavaScript execution engine leads to runtime errors

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.scripting.sightly.js.provider-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-sightly-js-provider.git

commit 5b7f8f094b2ed291b938f9090c12c79e2c94423d
Author: Radu Cotescu <ra...@apache.org>
AuthorDate: Wed Mar 18 16:41:15 2015 +0000

    SLING-4515 - Insufficient cleanup of the JavaScript execution engine leads to runtime errors
    
    * made sure to always call JsEnvironment#cleanup before finishing execution for JsUseProvider#provide
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/scripting/sightly/js-use-provider@1667586 13f79535-47bb-0310-9956-ffa450edef68
---
 .../scripting/sightly/js/impl/JsUseProvider.java    | 21 ++++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/impl/JsUseProvider.java b/src/main/java/org/apache/sling/scripting/sightly/js/impl/JsUseProvider.java
index 35cc70d..ac2c886 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/js/impl/JsUseProvider.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/impl/JsUseProvider.java
@@ -90,12 +90,19 @@ public class JsUseProvider implements UseProvider {
             return ProviderOutcome.failure(new SightlyException("No JavaScript engine was defined."));
         }
         SlingScriptHelper scriptHelper = Utils.getHelper(globalBindings);
-        JsEnvironment environment = new JsEnvironment(jsEngine);
-        environment.initialize();
-        String callerPath = scriptHelper.getScript().getScriptResource().getPath();
-        ResourceResolver adminResolver = renderContext.getScriptResourceResolver();
-        Resource caller = adminResolver.getResource(callerPath);
-        AsyncContainer asyncContainer = environment.run(caller, identifier, globalBindings, arguments);
-        return ProviderOutcome.success(jsValueAdapter.adapt(asyncContainer));
+        JsEnvironment environment = null;
+        try {
+            environment = new JsEnvironment(jsEngine);
+            environment.initialize();
+            String callerPath = scriptHelper.getScript().getScriptResource().getPath();
+            ResourceResolver adminResolver = renderContext.getScriptResourceResolver();
+            Resource caller = adminResolver.getResource(callerPath);
+            AsyncContainer asyncContainer = environment.run(caller, identifier, globalBindings, arguments);
+            return ProviderOutcome.success(jsValueAdapter.adapt(asyncContainer));
+        } finally {
+            if (environment != null) {
+                environment.cleanup();
+            }
+        }
     }
 }

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-scripting-sightly-js-provider] 17/18: [maven-release-plugin] prepare release org.apache.sling.scripting.sightly.js.provider-1.0.0

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.scripting.sightly.js.provider-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-sightly-js-provider.git

commit 54a876dbb8307580195c6cc2f066274d3f98decf
Author: Radu Cotescu <ra...@apache.org>
AuthorDate: Mon Mar 23 09:06:15 2015 +0000

    [maven-release-plugin] prepare release org.apache.sling.scripting.sightly.js.provider-1.0.0
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/scripting/sightly/js-use-provider@1668557 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/pom.xml b/pom.xml
index fb9dde2..8bdf1bf 100644
--- a/pom.xml
+++ b/pom.xml
@@ -17,8 +17,7 @@
   ~ 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">
+<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                                             -->
@@ -27,14 +26,14 @@
         <groupId>org.apache.sling</groupId>
         <artifactId>sling</artifactId>
         <version>20</version>
-        <relativePath/>
+        <relativePath />
     </parent>
 
     <!-- ======================================================================= -->
     <!-- P R O J E C T                                                           -->
     <!-- ======================================================================= -->
     <artifactId>org.apache.sling.scripting.sightly.js.provider</artifactId>
-    <version>1.0.0-SNAPSHOT</version>
+    <version>1.0.0</version>
     <packaging>bundle</packaging>
 
     <name>Apache Sling Scripting Sightly JavaScript Use Provider</name>
@@ -44,9 +43,9 @@
     </description>
 
     <scm>
-        <connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/contrib/scripting/sightly/js-use-provider</connection>
-        <developerConnection>scm:svn:https://svn.apache.org/repos/asf/sling/trunk/contrib/scripting/sightly/js-use-provider</developerConnection>
-        <url>http://svn.apache.org/repos/asf/sling/trunk/contrib/scripting/sightly/js-use-provider</url>
+        <connection>scm:svn:http://svn.apache.org/repos/asf/sling/tags/org.apache.sling.scripting.sightly.js.provider-1.0.0</connection>
+        <developerConnection>scm:svn:https://svn.apache.org/repos/asf/sling/tags/org.apache.sling.scripting.sightly.js.provider-1.0.0</developerConnection>
+        <url>http://svn.apache.org/repos/asf/sling/tags/org.apache.sling.scripting.sightly.js.provider-1.0.0</url>
     </scm>
 
     <properties>
@@ -69,7 +68,7 @@
                 <configuration>
                     <instructions>
                         <Sling-Bundle-Resources>/libs/sling/sightly/js;path:=/SLING-INF/libs/sling/sightly/js</Sling-Bundle-Resources>
-                        <Require-Capability>io.sightly; filter:="(&amp;(version>=1.0)(!(version>=2.0)))"</Require-Capability>
+                        <Require-Capability>io.sightly; filter:="(&amp;(version&gt;=1.0)(!(version&gt;=2.0)))"</Require-Capability>
                     </instructions>
                 </configuration>
             </plugin>

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-scripting-sightly-js-provider] 14/18: SLING-4506 - Java APIs not consistently available in JavaScript

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.scripting.sightly.js.provider-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-sightly-js-provider.git

commit 4e32d86263c85408a4efe894f43ea9d3c1656257
Author: Radu Cotescu <ra...@apache.org>
AuthorDate: Mon Mar 16 13:03:32 2015 +0000

    SLING-4506 - Java APIs not consistently available in JavaScript
    
    * added getName() and getResourceType() for Resource in addition to name and resourceType properties
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/scripting/sightly/js-use-provider@1666983 13f79535-47bb-0310-9956-ffa450edef68
---
 .../libs/sling/sightly/js/internal/resource.js     | 28 +++++++++++++++++-----
 1 file changed, 22 insertions(+), 6 deletions(-)

diff --git a/src/main/resources/SLING-INF/libs/sling/sightly/js/internal/resource.js b/src/main/resources/SLING-INF/libs/sling/sightly/js/internal/resource.js
index b74296c..ba0eb0a 100644
--- a/src/main/resources/SLING-INF/libs/sling/sightly/js/internal/resource.js
+++ b/src/main/resources/SLING-INF/libs/sling/sightly/js/internal/resource.js
@@ -99,6 +99,26 @@ use(['helper.js'], function(helper) {
         },
 
         /**
+         * Returns the name of this resource. The name of a resource is the last segment of the path.
+         * @returns {string} the name of this resource
+         */
+        getName: function () {
+            var index = this.path.lastIndexOf('/');
+            if (index == -1) {
+                return this.path;
+            }
+            return this.path.substring(index + 1);
+        },
+
+        /**
+         * The resource type is meant to point to rendering/processing scripts, editing dialogs, etc.
+         * @return {string} the resource type of this resource
+         */
+        getResourceType: function () {
+            return this.nativeResource.resourceType;
+        },
+
+        /**
          * Resolve a path to a resource. The path may be relative
          * to this path
          * @param  {string} path the requested path
@@ -124,11 +144,7 @@ use(['helper.js'], function(helper) {
          */
         name: {
             get: function() {
-                var index = this.path.lastIndexOf('/');
-                if (index == -1) {
-                    return this.path;
-                }
-                return this.path.substring(index + 1);
+                return this.getName();
             }
         },
 
@@ -140,7 +156,7 @@ use(['helper.js'], function(helper) {
          */
         resourceType: {
             get: function() {
-                return this.nativeResource.resourceType;
+                return this.getResourceType();
             }
         }
     });

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-scripting-sightly-js-provider] 18/18: [maven-release-plugin] copy for tag org.apache.sling.scripting.sightly.js.provider-1.0.0

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.scripting.sightly.js.provider-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-sightly-js-provider.git

commit 2ff20712685ba62cbca101c4a75db6be9d28bd5f
Author: Radu Cotescu <ra...@apache.org>
AuthorDate: Mon Mar 23 09:06:28 2015 +0000

    [maven-release-plugin]  copy for tag org.apache.sling.scripting.sightly.js.provider-1.0.0
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/tags/org.apache.sling.scripting.sightly.js.provider-1.0.0@1668558 13f79535-47bb-0310-9956-ffa450edef68

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-scripting-sightly-js-provider] 04/18: SLING-4182 Downgrade Sling API dependencies to the minimum required API (2.4 instead of 2.8)

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.scripting.sightly.js.provider-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-sightly-js-provider.git

commit 31ae7e94d39302d557372732268b4106397b8ffa
Author: Felix Meschberger <fm...@apache.org>
AuthorDate: Fri Nov 28 13:21:26 2014 +0000

    SLING-4182 Downgrade Sling API dependencies to the minimum required API (2.4 instead of 2.8)
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/scripting/sightly/js-use-provider@1642292 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index 3ac4e73..5c4bb65 100644
--- a/pom.xml
+++ b/pom.xml
@@ -95,7 +95,7 @@
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.api</artifactId>
-            <version>2.8.0</version>
+            <version>2.4.0</version>
             <scope>provided</scope>
         </dependency>
         <dependency>

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-scripting-sightly-js-provider] 01/18: SLING-3959 - Sightly contribution

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.scripting.sightly.js.provider-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-sightly-js-provider.git

commit 378982c1a1ea8ff3400c70a0e05b9465fbb9611f
Author: Bertrand Delacretaz <bd...@apache.org>
AuthorDate: Fri Nov 14 14:04:56 2014 +0000

    SLING-3959 - Sightly contribution
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/scripting/sightly/js-use-provider@1639641 13f79535-47bb-0310-9956-ffa450edef68
---
 README.md                                          |    8 +
 pom.xml                                            |  164 ++
 .../apache/sling/scripting/sightly/js/Console.java |   49 +
 .../sling/scripting/sightly/js/JsEnvironment.java  |  174 ++
 .../sling/scripting/sightly/js/JsUseProvider.java  |  112 ++
 .../apache/sling/scripting/sightly/js/Utils.java   |   46 +
 .../sling/scripting/sightly/js/Variables.java      |   34 +
 .../scripting/sightly/js/async/AsyncContainer.java |   95 +
 .../scripting/sightly/js/async/AsyncExtractor.java |   97 +
 .../js/async/TimingBindingsValuesProvider.java     |   42 +
 .../scripting/sightly/js/async/TimingFunction.java |   55 +
 .../scripting/sightly/js/async/UnaryCallback.java  |   31 +
 .../scripting/sightly/js/cjs/CommonJsModule.java   |   69 +
 .../scripting/sightly/js/cjs/ExportsObject.java    |   46 +
 .../js/jsapi/SlyBindingsValuesProvider.java        |  314 ++++
 .../sling/scripting/sightly/js/loop/EventLoop.java |   78 +
 .../sightly/js/loop/EventLoopInterop.java          |   53 +
 .../sling/scripting/sightly/js/loop/Task.java      |   43 +
 .../scripting/sightly/js/rhino/HybridObject.java   |  163 ++
 .../sling/scripting/sightly/js/rhino/JsUtils.java  |   46 +
 .../scripting/sightly/js/rhino/JsValueAdapter.java |  165 ++
 .../sightly/js/use/DependencyResolver.java         |   58 +
 .../scripting/sightly/js/use/UseFunction.java      |  140 ++
 .../SLING-INF/libs/sling/sightly/js/3rd-party/q.js | 1935 ++++++++++++++++++++
 .../libs/sling/sightly/js/internal/helper.js       |   43 +
 .../libs/sling/sightly/js/internal/promise.js      |   36 +
 .../libs/sling/sightly/js/internal/request.js      |  140 ++
 .../libs/sling/sightly/js/internal/resource.js     |  150 ++
 .../libs/sling/sightly/js/internal/sly.js          |   59 +
 29 files changed, 4445 insertions(+)

diff --git a/README.md b/README.md
new file mode 100644
index 0000000..173e8d3
--- /dev/null
+++ b/README.md
@@ -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`.
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..8fbe66a
--- /dev/null
+++ b/pom.xml
@@ -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>
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/Console.java b/src/main/java/org/apache/sling/scripting/sightly/js/Console.java
new file mode 100644
index 0000000..885c602
--- /dev/null
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/Console.java
@@ -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);
+    }
+}
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/JsEnvironment.java b/src/main/java/org/apache/sling/scripting/sightly/js/JsEnvironment.java
new file mode 100644
index 0000000..58686a7
--- /dev/null
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/JsEnvironment.java
@@ -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);
+                }
+            }
+        });
+    }
+}
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/JsUseProvider.java b/src/main/java/org/apache/sling/scripting/sightly/js/JsUseProvider.java
new file mode 100644
index 0000000..85f5627
--- /dev/null
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/JsUseProvider.java
@@ -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);
+    }
+}
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/Utils.java b/src/main/java/org/apache/sling/scripting/sightly/js/Utils.java
new file mode 100644
index 0000000..1f8128b
--- /dev/null
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/Utils.java
@@ -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);
+    }
+
+}
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/Variables.java b/src/main/java/org/apache/sling/scripting/sightly/js/Variables.java
new file mode 100644
index 0000000..1e1673d
--- /dev/null
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/Variables.java
@@ -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";
+}
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/async/AsyncContainer.java b/src/main/java/org/apache/sling/scripting/sightly/js/async/AsyncContainer.java
new file mode 100644
index 0000000..e4f39dd
--- /dev/null
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/async/AsyncContainer.java
@@ -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);
+    }
+}
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/async/AsyncExtractor.java b/src/main/java/org/apache/sling/scripting/sightly/js/async/AsyncExtractor.java
new file mode 100644
index 0000000..fe43556
--- /dev/null
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/async/AsyncExtractor.java
@@ -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();
+            }
+        };
+    }
+}
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/async/TimingBindingsValuesProvider.java b/src/main/java/org/apache/sling/scripting/sightly/js/async/TimingBindingsValuesProvider.java
new file mode 100644
index 0000000..c823405
--- /dev/null
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/async/TimingBindingsValuesProvider.java
@@ -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);
+    }
+}
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/async/TimingFunction.java b/src/main/java/org/apache/sling/scripting/sightly/js/async/TimingFunction.java
new file mode 100644
index 0000000..2755782
--- /dev/null
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/async/TimingFunction.java
@@ -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]);
+            }
+        });
+    }
+}
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/async/UnaryCallback.java b/src/main/java/org/apache/sling/scripting/sightly/js/async/UnaryCallback.java
new file mode 100644
index 0000000..48e1aee
--- /dev/null
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/async/UnaryCallback.java
@@ -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);
+}
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/cjs/CommonJsModule.java b/src/main/java/org/apache/sling/scripting/sightly/js/cjs/CommonJsModule.java
new file mode 100644
index 0000000..3d1683e
--- /dev/null
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/cjs/CommonJsModule.java
@@ -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";
+    }
+}
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/cjs/ExportsObject.java b/src/main/java/org/apache/sling/scripting/sightly/js/cjs/ExportsObject.java
new file mode 100644
index 0000000..58257f5
--- /dev/null
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/cjs/ExportsObject.java
@@ -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";
+    }
+}
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/jsapi/SlyBindingsValuesProvider.java b/src/main/java/org/apache/sling/scripting/sightly/js/jsapi/SlyBindingsValuesProvider.java
new file mode 100644
index 0000000..4333c4a
--- /dev/null
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/jsapi/SlyBindingsValuesProvider.java
@@ -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();
+            }
+        }
+    }
+
+}
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/loop/EventLoop.java b/src/main/java/org/apache/sling/scripting/sightly/js/loop/EventLoop.java
new file mode 100644
index 0000000..ef4c6d5
--- /dev/null
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/loop/EventLoop.java
@@ -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;
+        }
+    }
+
+}
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/loop/EventLoopInterop.java b/src/main/java/org/apache/sling/scripting/sightly/js/loop/EventLoopInterop.java
new file mode 100644
index 0000000..d847f53
--- /dev/null
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/loop/EventLoopInterop.java
@@ -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);
+    }
+
+}
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/loop/Task.java b/src/main/java/org/apache/sling/scripting/sightly/js/loop/Task.java
new file mode 100644
index 0000000..e218e78
--- /dev/null
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/loop/Task.java
@@ -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;
+    }
+}
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/rhino/HybridObject.java b/src/main/java/org/apache/sling/scripting/sightly/js/rhino/HybridObject.java
new file mode 100644
index 0000000..77875fc
--- /dev/null
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/rhino/HybridObject.java
@@ -0,0 +1,163 @@
+/*******************************************************************************
+ * 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.rhino;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.sling.scripting.sightly.api.Record;
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.Function;
+import org.mozilla.javascript.Scriptable;
+import org.mozilla.javascript.ScriptableObject;
+
+
+/**
+ * Instances of this class can be used in both Sightly & JS scripts
+ */
+public class HybridObject implements Scriptable, Record<Object> {
+
+    private final Scriptable scriptable;
+    private final JsValueAdapter jsValueAdapter;
+
+    public HybridObject(Scriptable scriptable, JsValueAdapter jsValueAdapter) {
+        this.scriptable = scriptable;
+        this.jsValueAdapter = jsValueAdapter;
+    }
+
+    // Record implementation
+
+    @Override
+    public Object get(String name) {
+        if (name == null) {
+            return null;
+        }
+        Context.enter();
+        try {
+            return getAdapted(name);
+        } finally {
+            Context.exit();
+        }
+    }
+
+    @Override
+    public Set<String> properties() {
+        Object[] properties = scriptable.getIds();
+        Set<String> keys = new HashSet<String>();
+        for (Object property: properties) {
+            if (property instanceof String) {
+                keys.add((String) property);
+            }
+        }
+        return keys;
+    }
+
+    private Object getAdapted(String key) {
+        Object obj = ScriptableObject.getProperty(scriptable, key);
+        if (obj == null) {
+            return null;
+        }
+        if (obj instanceof Function) {
+            return jsValueAdapter.adapt(JsUtils.callFn((Function) obj, null, scriptable, scriptable, new Object[0]));
+        }
+        return jsValueAdapter.adapt(obj);
+    }
+
+    // Scriptable implementation
+
+    @Override
+    public String getClassName() {
+        return scriptable.getClassName();
+    }
+
+    @Override
+    public Object get(String name, Scriptable start) {
+        return scriptable.get(name, start);
+    }
+
+    @Override
+    public Object get(int index, Scriptable start) {
+        return scriptable.get(index, start);
+    }
+
+    @Override
+    public boolean has(String name, Scriptable start) {
+        return scriptable.has(name, start);
+    }
+
+    @Override
+    public boolean has(int index, Scriptable start) {
+        return scriptable.has(index, start);
+    }
+
+    @Override
+    public void put(String name, Scriptable start, Object value) {
+        scriptable.put(name, start, value);
+    }
+
+    @Override
+    public void put(int index, Scriptable start, Object value) {
+        scriptable.put(index, start, value);
+    }
+
+    @Override
+    public void delete(String name) {
+        scriptable.delete(name);
+    }
+
+    @Override
+    public void delete(int index) {
+        scriptable.delete(index);
+    }
+
+    @Override
+    public Scriptable getPrototype() {
+        return scriptable.getPrototype();
+    }
+
+    @Override
+    public void setPrototype(Scriptable prototype) {
+        scriptable.setPrototype(prototype);
+    }
+
+    @Override
+    public Scriptable getParentScope() {
+        return scriptable.getParentScope();
+    }
+
+    @Override
+    public void setParentScope(Scriptable parent) {
+        scriptable.setParentScope(parent);
+    }
+
+    @Override
+    public Object[] getIds() {
+        return scriptable.getIds();
+    }
+
+    @Override
+    public Object getDefaultValue(Class hint) {
+        return scriptable.getDefaultValue(hint);
+    }
+
+    @Override
+    public boolean hasInstance(Scriptable instance) {
+        return scriptable.hasInstance(instance);
+    }
+}
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/rhino/JsUtils.java b/src/main/java/org/apache/sling/scripting/sightly/js/rhino/JsUtils.java
new file mode 100644
index 0000000..aa5325f
--- /dev/null
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/rhino/JsUtils.java
@@ -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.rhino;
+
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.Function;
+import org.mozilla.javascript.Scriptable;
+
+/**
+ * Utilities when inter-operating with JS scripts
+ */
+public class JsUtils {
+
+    public static Object callFn(Function function, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
+        boolean exitContext = false;
+        if (Context.getCurrentContext() == null) {
+            Context.enter();
+            exitContext = true;
+        }
+        Context context = (cx == null) ? Context.getCurrentContext() : cx;
+        Object result = function.call(context, scope, thisObj, args);
+        if (exitContext) {
+            Context.exit();
+        }
+        return result;
+    }
+
+
+
+}
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/rhino/JsValueAdapter.java b/src/main/java/org/apache/sling/scripting/sightly/js/rhino/JsValueAdapter.java
new file mode 100644
index 0000000..814a7e4
--- /dev/null
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/rhino/JsValueAdapter.java
@@ -0,0 +1,165 @@
+/*******************************************************************************
+ * 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.rhino;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.Function;
+import org.mozilla.javascript.NativeArray;
+import org.mozilla.javascript.ScriptableObject;
+import org.mozilla.javascript.Wrapper;
+
+import org.apache.sling.scripting.sightly.js.async.AsyncContainer;
+import org.apache.sling.scripting.sightly.js.async.AsyncExtractor;
+
+/**
+ * Converts JS objects to Java objects
+ */
+public class JsValueAdapter {
+
+    private static final Map<String, Class<?>> knownConversions = new HashMap<String, Class<?>>();
+
+    static {
+        knownConversions.put("String", String.class);
+        knownConversions.put("Date", Date.class);
+    }
+
+    private final AsyncExtractor asyncExtractor;
+
+    public JsValueAdapter(AsyncExtractor asyncExtractor) {
+        this.asyncExtractor = asyncExtractor;
+    }
+
+    /**
+     * Convert a given JS value to a Java object
+     * @param jsValue the original JS value
+     * @return the Java correspondent
+     */
+    @SuppressWarnings("unchecked")
+    public Object adapt(Object jsValue) {
+        if (jsValue == null || jsValue == Context.getUndefinedValue() || jsValue == ScriptableObject.NOT_FOUND) {
+            return null;
+        }
+        if (jsValue instanceof Wrapper) {
+            return adapt(((Wrapper) jsValue).unwrap());
+        }
+        if (asyncExtractor.isPromise(jsValue)) {
+            return adapt(forceAsync(jsValue));
+        }
+        if (jsValue instanceof ScriptableObject) {
+            return extractScriptable((ScriptableObject) jsValue);
+        }
+        if (jsValue instanceof CharSequence) {
+            //convert any string-like type to plain java strings
+            return jsValue.toString();
+        }
+        if (jsValue instanceof Map) {
+            return convertMap((Map) jsValue);
+        }
+        if (jsValue instanceof Iterable) {
+            return convertIterable((Iterable) jsValue);
+        }
+        if (jsValue instanceof Number) {
+            return convertNumber((Number) jsValue);
+        }
+        if (jsValue instanceof Object[]) {
+            return convertIterable(Arrays.asList((Object[]) jsValue));
+        }
+        return jsValue;
+    }
+
+    private Object convertNumber(Number numValue) {
+        if (numValue instanceof Double) {
+            if (isLong((Double) numValue)) {
+                return numValue.longValue();
+            }
+        }
+        if (numValue instanceof Float) {
+            if (isLong((Float) numValue)) {
+                return numValue.longValue();
+            }
+        }
+        return numValue;
+    }
+
+    private boolean isLong(double x) {
+        return x == Math.floor(x);
+    }
+
+    private Object forceAsync(Object jsValue) {
+        AsyncContainer asyncContainer = new AsyncContainer();
+        asyncExtractor.extract(jsValue, asyncContainer.createCompletionCallback());
+        return asyncContainer.getResult();
+    }
+
+    private Object extractScriptable(ScriptableObject scriptableObject) {
+        Object obj = tryKnownConversion(scriptableObject);
+        if (obj != null) { return obj; }
+        if (scriptableObject instanceof NativeArray) {
+            return convertNativeArray((NativeArray) scriptableObject);
+        }
+        if (scriptableObject instanceof Function) {
+            return callFunction((Function) scriptableObject);
+        }
+        return new HybridObject(scriptableObject, this);
+    }
+
+    private Object callFunction(Function function) {
+        Object result = JsUtils.callFn(function, null, function, function, new Object[0]);
+        return adapt(result);
+    }
+
+    private Object[] convertNativeArray(NativeArray nativeArray) {
+        int length = (int) nativeArray.getLength();
+        Object[] objects = new Object[length];
+        for (int i = 0; i < length; i++) {
+            Object jsItem = nativeArray.get(i, nativeArray);
+            objects[i] = adapt(jsItem);
+        }
+        return objects;
+    }
+
+    private Map<Object, Object> convertMap(Map<Object, Object> original) {
+        Map<Object, Object> map = new HashMap<Object, Object>();
+        for (Map.Entry<Object, Object> entry : original.entrySet()) {
+            map.put(entry.getKey(), adapt(entry.getValue()));
+        }
+        return map;
+    }
+
+    private List<Object> convertIterable(Iterable<Object> iterable) {
+        List<Object> objects = new ArrayList<Object>();
+        for (Object obj : iterable) {
+            objects.add(adapt(obj));
+        }
+        return objects;
+    }
+
+    private static Object tryKnownConversion(ScriptableObject object) {
+        String className = object.getClassName();
+        Class<?> cls = knownConversions.get(className);
+        return (cls == null) ? null : Context.jsToJava(object, cls);
+    }
+}
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/use/DependencyResolver.java b/src/main/java/org/apache/sling/scripting/sightly/js/use/DependencyResolver.java
new file mode 100644
index 0000000..5df0a86
--- /dev/null
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/use/DependencyResolver.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * 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.use;
+
+import javax.script.Bindings;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.scripting.sightly.api.SightlyUseException;
+
+import org.apache.sling.scripting.sightly.js.JsEnvironment;
+import org.apache.sling.scripting.sightly.js.Utils;
+import org.apache.sling.scripting.sightly.js.async.UnaryCallback;
+
+/**
+ * Resolves dependencies specified by the Use function
+ */
+public class DependencyResolver {
+
+    private final Resource caller;
+    private final JsEnvironment jsEnvironment;
+    private final Bindings globalBindings;
+
+    public DependencyResolver(Resource resource, JsEnvironment jsEnvironment, Bindings globalBindings) {
+        this.caller = resource;
+        this.jsEnvironment = jsEnvironment;
+        this.globalBindings = globalBindings;
+    }
+
+    /**
+     * Resolve a dependency
+     * @param dependency the dependency identifier
+     * @param callback the callback that will receive the resolved dependency
+     */
+    public void resolve(String dependency, UnaryCallback callback) {
+        if (!Utils.isJsScript(dependency)) {
+            throw new SightlyUseException("Only JS scripts are allowed as dependencies. Invalid dependency: " + dependency);
+        }
+        jsEnvironment.run(caller, dependency, globalBindings, Utils.EMPTY_BINDINGS, callback);
+    }
+
+}
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/use/UseFunction.java b/src/main/java/org/apache/sling/scripting/sightly/js/use/UseFunction.java
new file mode 100644
index 0000000..2fe1b22
--- /dev/null
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/use/UseFunction.java
@@ -0,0 +1,140 @@
+/*******************************************************************************
+ * 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.use;
+
+import javax.script.Bindings;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.mozilla.javascript.BaseFunction;
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.Function;
+import org.mozilla.javascript.NativeArray;
+import org.mozilla.javascript.NativeObject;
+import org.mozilla.javascript.Scriptable;
+import org.mozilla.javascript.ScriptableObject;
+
+import org.apache.sling.scripting.sightly.js.async.AsyncContainer;
+import org.apache.sling.scripting.sightly.js.async.UnaryCallback;
+import org.apache.sling.scripting.sightly.js.loop.EventLoopInterop;
+import org.apache.sling.scripting.sightly.js.rhino.JsUtils;
+
+/**
+ * The JavaScript {@code use} function
+ */
+public class UseFunction extends BaseFunction {
+
+    private final DependencyResolver dependencyResolver;
+    private final Scriptable thisObj;
+
+    public UseFunction(DependencyResolver dependencyResolver, Bindings arguments) {
+        this.dependencyResolver = dependencyResolver;
+        this.thisObj = createThisBinding(arguments);
+    }
+
+    @Override
+    public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
+        Function function;
+        List<String> depNames;
+        if (args.length == 0) {
+            throw new IllegalArgumentException("Not enough arguments for use");
+        } else if (args.length == 1) {
+            function = decodeCallback(args[0]);
+            depNames = Collections.emptyList();
+        } else {
+            function = decodeCallback(args[1]);
+            depNames = decodeDepNames(args[0]);
+        }
+        return use(depNames, function, cx, scope);
+    }
+
+    private Object use(List<String> depNames, final Function callback, final Context cx, final Scriptable scope) {
+        final AsyncContainer asyncContainer = new AsyncContainer();
+        if (depNames.isEmpty()) {
+            callImmediate(callback, asyncContainer, cx, scope);
+        } else {
+            final int[] counter = {depNames.size()};
+            final Object[] dependencies = new Object[depNames.size()];
+            for (int i = 0; i < depNames.size(); i++) {
+                final int dependencyPos = i;
+                dependencyResolver.resolve(depNames.get(i), new UnaryCallback() {
+                    @Override
+                    public void invoke(Object arg) {
+                        counter[0]--;
+                        dependencies[dependencyPos] = arg;
+                        if (counter[0] == 0) {
+                            Object result = JsUtils.callFn(callback, cx, scope, thisObj, dependencies);
+                            asyncContainer.complete(result);
+                        }
+                    }
+                });
+            }
+        }
+        return asyncContainer;
+    }
+
+    private void callImmediate(final Function callback, final AsyncContainer asyncContainer, final Context cx, final Scriptable scope) {
+        EventLoopInterop.schedule(cx, new Runnable() {
+            @Override
+            public void run() {
+                Object value = JsUtils.callFn(callback, cx, scope, thisObj, new Object[0]);
+                asyncContainer.complete(value);
+            }
+        });
+    }
+
+    private Function decodeCallback(Object obj) {
+        if (!(obj instanceof Function)) {
+            throw new IllegalArgumentException("No callback argument supplied");
+        }
+        return (Function) obj;
+    }
+
+    private List<String> decodeDepNames(Object obj) {
+        if (obj instanceof NativeArray) {
+            return decodeDepArray((NativeArray) obj);
+        }
+        return Collections.singletonList(jsToString(obj));
+    }
+
+    private List<String> decodeDepArray(NativeArray nativeArray) {
+        int depLength = (int) nativeArray.getLength();
+        List<String> depNames = new ArrayList<String>(depLength);
+        for (int i = 0; i < depLength; i++) {
+            String depName = jsToString(nativeArray.get(i, nativeArray));
+            depNames.add(depName);
+        }
+        return depNames;
+    }
+
+    private String jsToString(Object obj) {
+        return (String) Context.jsToJava(obj, String.class);
+    }
+
+    private Scriptable createThisBinding(Bindings arguments) {
+        NativeObject nativeObject = new NativeObject();
+        for (Map.Entry<String, Object> entry : arguments.entrySet()) {
+            ScriptableObject.putProperty(nativeObject, entry.getKey(), entry.getValue());
+        }
+        return nativeObject;
+    }
+}
diff --git a/src/main/resources/SLING-INF/libs/sling/sightly/js/3rd-party/q.js b/src/main/resources/SLING-INF/libs/sling/sightly/js/3rd-party/q.js
new file mode 100644
index 0000000..5ed1dba
--- /dev/null
+++ b/src/main/resources/SLING-INF/libs/sling/sightly/js/3rd-party/q.js
@@ -0,0 +1,1935 @@
+// vim:ts=4:sts=4:sw=4:
+/*!
+ *
+ * Copyright 2009-2012 Kris Kowal under the terms of the MIT
+ * license found at http://github.com/kriskowal/q/raw/master/LICENSE
+ *
+ * With parts by Tyler Close
+ * Copyright 2007-2009 Tyler Close under the terms of the MIT X license found
+ * at http://www.opensource.org/licenses/mit-license.html
+ * Forked at ref_send.js version: 2009-05-11
+ *
+ * With parts by Mark Miller
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed 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.
+ *
+ */
+
+(function (definition) {
+    // Turn off strict mode for this function so we can assign to global.Q
+    /* jshint strict: false */
+
+    // This file will function properly as a <script> tag, or a module
+    // using CommonJS and NodeJS or RequireJS module formats.  In
+    // Common/Node/RequireJS, the module exports the Q API and when
+    // executed as a simple <script>, it creates a Q global instead.
+
+    // Montage Require
+    if (typeof bootstrap === "function") {
+        bootstrap("promise", definition);
+
+    // CommonJS
+    } else if (typeof exports === "object") {
+        module.exports = definition();
+
+    // RequireJS
+    } else if (typeof define === "function" && define.amd) {
+        define(definition);
+
+    // SES (Secure EcmaScript)
+    } else if (typeof ses !== "undefined") {
+        if (!ses.ok()) {
+            return;
+        } else {
+            ses.makeQ = definition;
+        }
+
+    // <script>
+    } else {
+        Q = definition();
+    }
+
+})(function () {
+"use strict";
+
+var hasStacks = false;
+try {
+    throw new Error();
+} catch (e) {
+    hasStacks = !!e.stack;
+}
+
+// All code after this point will be filtered from stack traces reported
+// by Q.
+var qStartingLine = captureLine();
+var qFileName;
+
+// shims
+
+// used for fallback in "allResolved"
+var noop = function () {};
+
+// Use the fastest possible means to execute a task in a future turn
+// of the event loop.
+var nextTick =(function () {
+    // linked list of tasks (single, with head node)
+    var head = {task: void 0, next: null};
+    var tail = head;
+    var flushing = false;
+    var requestTick = void 0;
+    var isNodeJS = false;
+
+    function flush() {
+        /* jshint loopfunc: true */
+
+        while (head.next) {
+            head = head.next;
+            var task = head.task;
+            head.task = void 0;
+            var domain = head.domain;
+
+            if (domain) {
+                head.domain = void 0;
+                domain.enter();
+            }
+
+            try {
+                task();
+
+            } catch (e) {
+                if (isNodeJS) {
+                    // In node, uncaught exceptions are considered fatal errors.
+                    // Re-throw them synchronously to interrupt flushing!
+
+                    // Ensure continuation if the uncaught exception is suppressed
+                    // listening "uncaughtException" events (as domains does).
+                    // Continue in next event to avoid tick recursion.
+                    if (domain) {
+                        domain.exit();
+                    }
+                    setTimeout(flush, 0);
+                    if (domain) {
+                        domain.enter();
+                    }
+
+                    throw e;
+
+                } else {
+                    // In browsers, uncaught exceptions are not fatal.
+                    // Re-throw them asynchronously to avoid slow-downs.
+                    setTimeout(function() {
+                       throw e;
+                    }, 0);
+                }
+            }
+
+            if (domain) {
+                domain.exit();
+            }
+        }
+
+        flushing = false;
+    }
+
+    nextTick = function (task) {
+        tail = tail.next = {
+            task: task,
+            domain: isNodeJS && process.domain,
+            next: null
+        };
+
+        if (!flushing) {
+            flushing = true;
+            requestTick();
+        }
+    };
+
+    if (typeof process !== "undefined" && process.nextTick) {
+        // Node.js before 0.9. Note that some fake-Node environments, like the
+        // Mocha test runner, introduce a `process` global without a `nextTick`.
+        isNodeJS = true;
+
+        requestTick = function () {
+            process.nextTick(flush);
+        };
+
+    } else if (typeof setImmediate === "function") {
+        // In IE10, Node.js 0.9+, or https://github.com/NobleJS/setImmediate
+        if (typeof window !== "undefined") {
+            requestTick = setImmediate.bind(window, flush);
+        } else {
+            requestTick = function () {
+                setImmediate(flush);
+            };
+        }
+
+    } else if (typeof MessageChannel !== "undefined") {
+        // modern browsers
+        // http://www.nonblocking.io/2011/06/windownexttick.html
+        var channel = new MessageChannel();
+        // At least Safari Version 6.0.5 (8536.30.1) intermittently cannot create
+        // working message ports the first time a page loads.
+        channel.port1.onmessage = function () {
+            requestTick = requestPortTick;
+            channel.port1.onmessage = flush;
+            flush();
+        };
+        var requestPortTick = function () {
+            // Opera requires us to provide a message payload, regardless of
+            // whether we use it.
+            channel.port2.postMessage(0);
+        };
+        requestTick = function () {
+            setTimeout(flush, 0);
+            requestPortTick();
+        };
+
+    } else {
+        // old browsers
+        requestTick = function () {
+            setTimeout(flush, 0);
+        };
+    }
+
+    return nextTick;
+})();
+
+// Attempt to make generics safe in the face of downstream
+// modifications.
+// There is no situation where this is necessary.
+// If you need a security guarantee, these primordials need to be
+// deeply frozen anyway, and if you don’t need a security guarantee,
+// this is just plain paranoid.
+// However, this **might** have the nice side-effect of reducing the size of
+// the minified code by reducing x.call() to merely x()
+// See Mark Miller’s explanation of what this does.
+// http://wiki.ecmascript.org/doku.php?id=conventions:safe_meta_programming
+var call = Function.call;
+function uncurryThis(f) {
+    return function () {
+        return call.apply(f, arguments);
+    };
+}
+// This is equivalent, but slower:
+// uncurryThis = Function_bind.bind(Function_bind.call);
+// http://jsperf.com/uncurrythis
+
+var array_slice = uncurryThis(Array.prototype.slice);
+
+var array_reduce = uncurryThis(
+    Array.prototype.reduce || function (callback, basis) {
+        var index = 0,
+            length = this.length;
+        // concerning the initial value, if one is not provided
+        if (arguments.length === 1) {
+            // seek to the first value in the array, accounting
+            // for the possibility that is is a sparse array
+            do {
+                if (index in this) {
+                    basis = this[index++];
+                    break;
+                }
+                if (++index >= length) {
+                    throw new TypeError();
+                }
+            } while (1);
+        }
+        // reduce
+        for (; index < length; index++) {
+            // account for the possibility that the array is sparse
+            if (index in this) {
+                basis = callback(basis, this[index], index);
+            }
+        }
+        return basis;
+    }
+);
+
+var array_indexOf = uncurryThis(
+    Array.prototype.indexOf || function (value) {
+        // not a very good shim, but good enough for our one use of it
+        for (var i = 0; i < this.length; i++) {
+            if (this[i] === value) {
+                return i;
+            }
+        }
+        return -1;
+    }
+);
+
+var array_map = uncurryThis(
+    Array.prototype.map || function (callback, thisp) {
+        var self = this;
+        var collect = [];
+        array_reduce(self, function (undefined, value, index) {
+            collect.push(callback.call(thisp, value, index, self));
+        }, void 0);
+        return collect;
+    }
+);
+
+var object_create = Object.create || function (prototype) {
+    function Type() { }
+    Type.prototype = prototype;
+    return new Type();
+};
+
+var object_hasOwnProperty = uncurryThis(Object.prototype.hasOwnProperty);
+
+var object_keys = Object.keys || function (object) {
+    var keys = [];
+    for (var key in object) {
+        if (object_hasOwnProperty(object, key)) {
+            keys.push(key);
+        }
+    }
+    return keys;
+};
+
+var object_toString = uncurryThis(Object.prototype.toString);
+
+function isObject(value) {
+    return value === Object(value);
+}
+
+// generator related shims
+
+// FIXME: Remove this function once ES6 generators are in SpiderMonkey.
+function isStopIteration(exception) {
+    return (
+        object_toString(exception) === "[object StopIteration]" ||
+        exception instanceof QReturnValue
+    );
+}
+
+// FIXME: Remove this helper and Q.return once ES6 generators are in
+// SpiderMonkey.
+var QReturnValue;
+if (typeof ReturnValue !== "undefined") {
+    QReturnValue = ReturnValue;
+} else {
+    QReturnValue = function (value) {
+        this.value = value;
+    };
+}
+
+// Until V8 3.19 / Chromium 29 is released, SpiderMonkey is the only
+// engine that has a deployed base of browsers that support generators.
+// However, SM's generators use the Python-inspired semantics of
+// outdated ES6 drafts.  We would like to support ES6, but we'd also
+// like to make it possible to use generators in deployed browsers, so
+// we also support Python-style generators.  At some point we can remove
+// this block.
+var hasES6Generators;
+try {
+    /* jshint evil: true, nonew: false */
+    new Function("(function* (){ yield 1; })");
+    hasES6Generators = true;
+} catch (e) {
+    hasES6Generators = false;
+}
+
+// long stack traces
+
+var STACK_JUMP_SEPARATOR = "From previous event:";
+
+function makeStackTraceLong(error, promise) {
+    // If possible, transform the error stack trace by removing Node and Q
+    // cruft, then concatenating with the stack trace of `promise`. See #57.
+    if (hasStacks &&
+        promise.stack &&
+        typeof error === "object" &&
+        error !== null &&
+        error.stack &&
+        error.stack.indexOf(STACK_JUMP_SEPARATOR) === -1
+    ) {
+        var stacks = [];
+        for (var p = promise; !!p; p = p.source) {
+            if (p.stack) {
+                stacks.unshift(p.stack);
+            }
+        }
+        stacks.unshift(error.stack);
+
+        var concatedStacks = stacks.join("\n" + STACK_JUMP_SEPARATOR + "\n");
+        error.stack = filterStackString(concatedStacks);
+    }
+}
+
+function filterStackString(stackString) {
+    var lines = stackString.split("\n");
+    var desiredLines = [];
+    for (var i = 0; i < lines.length; ++i) {
+        var line = lines[i];
+
+        if (!isInternalFrame(line) && !isNodeFrame(line) && line) {
+            desiredLines.push(line);
+        }
+    }
+    return desiredLines.join("\n");
+}
+
+function isNodeFrame(stackLine) {
+    return stackLine.indexOf("(module.js:") !== -1 ||
+           stackLine.indexOf("(node.js:") !== -1;
+}
+
+function getFileNameAndLineNumber(stackLine) {
+    // Named functions: "at functionName (filename:lineNumber:columnNumber)"
+    // In IE10 function name can have spaces ("Anonymous function") O_o
+    var attempt1 = /at .+ \((.+):(\d+):(?:\d+)\)$/.exec(stackLine);
+    if (attempt1) {
+        return [attempt1[1], Number(attempt1[2])];
+    }
+
+    // Anonymous functions: "at filename:lineNumber:columnNumber"
+    var attempt2 = /at ([^ ]+):(\d+):(?:\d+)$/.exec(stackLine);
+    if (attempt2) {
+        return [attempt2[1], Number(attempt2[2])];
+    }
+
+    // Firefox style: "function@filename:lineNumber or @filename:lineNumber"
+    var attempt3 = /.*@(.+):(\d+)$/.exec(stackLine);
+    if (attempt3) {
+        return [attempt3[1], Number(attempt3[2])];
+    }
+}
+
+function isInternalFrame(stackLine) {
+    var fileNameAndLineNumber = getFileNameAndLineNumber(stackLine);
+
+    if (!fileNameAndLineNumber) {
+        return false;
+    }
+
+    var fileName = fileNameAndLineNumber[0];
+    var lineNumber = fileNameAndLineNumber[1];
+
+    return fileName === qFileName &&
+        lineNumber >= qStartingLine &&
+        lineNumber <= qEndingLine;
+}
+
+// discover own file name and line number range for filtering stack
+// traces
+function captureLine() {
+    if (!hasStacks) {
+        return;
+    }
+
+    try {
+        throw new Error();
+    } catch (e) {
+        var lines = e.stack.split("\n");
+        var firstLine = lines[0].indexOf("@") > 0 ? lines[1] : lines[2];
+        var fileNameAndLineNumber = getFileNameAndLineNumber(firstLine);
+        if (!fileNameAndLineNumber) {
+            return;
+        }
+
+        qFileName = fileNameAndLineNumber[0];
+        return fileNameAndLineNumber[1];
+    }
+}
+
+function deprecate(callback, name, alternative) {
+    return function () {
+        if (typeof console !== "undefined" &&
+            typeof console.warn === "function") {
+            console.warn(name + " is deprecated, use " + alternative +
+                         " instead.", new Error("").stack);
+        }
+        return callback.apply(callback, arguments);
+    };
+}
+
+// end of shims
+// beginning of real work
+
+/**
+ * Constructs a promise for an immediate reference, passes promises through, or
+ * coerces promises from different systems.
+ * @param value immediate reference or promise
+ */
+function Q(value) {
+    // If the object is already a Promise, return it directly.  This enables
+    // the resolve function to both be used to created references from objects,
+    // but to tolerably coerce non-promises to promises.
+    if (isPromise(value)) {
+        return value;
+    }
+
+    // assimilate thenables
+    if (isPromiseAlike(value)) {
+        return coerce(value);
+    } else {
+        return fulfill(value);
+    }
+}
+Q.resolve = Q;
+
+/**
+ * Performs a task in a future turn of the event loop.
+ * @param {Function} task
+ */
+Q.nextTick = nextTick;
+
+/**
+ * Controls whether or not long stack traces will be on
+ */
+Q.longStackSupport = false;
+
+/**
+ * Constructs a {promise, resolve, reject} object.
+ *
+ * `resolve` is a callback to invoke with a more resolved value for the
+ * promise. To fulfill the promise, invoke `resolve` with any value that is
+ * not a thenable. To reject the promise, invoke `resolve` with a rejected
+ * thenable, or invoke `reject` with the reason directly. To resolve the
+ * promise to another thenable, thus putting it in the same state, invoke
+ * `resolve` with that other thenable.
+ */
+Q.defer = defer;
+function defer() {
+    // if "messages" is an "Array", that indicates that the promise has not yet
+    // been resolved.  If it is "undefined", it has been resolved.  Each
+    // element of the messages array is itself an array of complete arguments to
+    // forward to the resolved promise.  We coerce the resolution value to a
+    // promise using the `resolve` function because it handles both fully
+    // non-thenable values and other thenables gracefully.
+    var messages = [], progressListeners = [], resolvedPromise;
+
+    var deferred = object_create(defer.prototype);
+    var promise = object_create(Promise.prototype);
+
+    promise.promiseDispatch = function (resolve, op, operands) {
+        var args = array_slice(arguments);
+        if (messages) {
+            messages.push(args);
+            if (op === "when" && operands[1]) { // progress operand
+                progressListeners.push(operands[1]);
+            }
+        } else {
+            nextTick(function () {
+                resolvedPromise.promiseDispatch.apply(resolvedPromise, args);
+            });
+        }
+    };
+
+    // XXX deprecated
+    promise.valueOf = function () {
+        if (messages) {
+            return promise;
+        }
+        var nearerValue = nearer(resolvedPromise);
+        if (isPromise(nearerValue)) {
+            resolvedPromise = nearerValue; // shorten chain
+        }
+        return nearerValue;
+    };
+
+    promise.inspect = function () {
+        if (!resolvedPromise) {
+            return { state: "pending" };
+        }
+        return resolvedPromise.inspect();
+    };
+
+    if (Q.longStackSupport && hasStacks) {
+        try {
+            throw new Error();
+        } catch (e) {
+            // NOTE: don't try to use `Error.captureStackTrace` or transfer the
+            // accessor around; that causes memory leaks as per GH-111. Just
+            // reify the stack trace as a string ASAP.
+            //
+            // At the same time, cut off the first line; it's always just
+            // "[object Promise]\n", as per the `toString`.
+            promise.stack = e.stack.substring(e.stack.indexOf("\n") + 1);
+        }
+    }
+
+    // NOTE: we do the checks for `resolvedPromise` in each method, instead of
+    // consolidating them into `become`, since otherwise we'd create new
+    // promises with the lines `become(whatever(value))`. See e.g. GH-252.
+
+    function become(newPromise) {
+        resolvedPromise = newPromise;
+        promise.source = newPromise;
+
+        array_reduce(messages, function (undefined, message) {
+            nextTick(function () {
+                newPromise.promiseDispatch.apply(newPromise, message);
+            });
+        }, void 0);
+
+        messages = void 0;
+        progressListeners = void 0;
+    }
+
+    deferred.promise = promise;
+    deferred.resolve = function (value) {
+        if (resolvedPromise) {
+            return;
+        }
+
+        become(Q(value));
+    };
+
+    deferred.fulfill = function (value) {
+        if (resolvedPromise) {
+            return;
+        }
+
+        become(fulfill(value));
+    };
+    deferred.reject = function (reason) {
+        if (resolvedPromise) {
+            return;
+        }
+
+        become(reject(reason));
+    };
+    deferred.notify = function (progress) {
+        if (resolvedPromise) {
+            return;
+        }
+
+        array_reduce(progressListeners, function (undefined, progressListener) {
+            nextTick(function () {
+                progressListener(progress);
+            });
+        }, void 0);
+    };
+
+    return deferred;
+}
+
+/**
+ * Creates a Node-style callback that will resolve or reject the deferred
+ * promise.
+ * @returns a nodeback
+ */
+defer.prototype.makeNodeResolver = function () {
+    var self = this;
+    return function (error, value) {
+        if (error) {
+            self.reject(error);
+        } else if (arguments.length > 2) {
+            self.resolve(array_slice(arguments, 1));
+        } else {
+            self.resolve(value);
+        }
+    };
+};
+
+/**
+ * @param resolver {Function} a function that returns nothing and accepts
+ * the resolve, reject, and notify functions for a deferred.
+ * @returns a promise that may be resolved with the given resolve and reject
+ * functions, or rejected by a thrown exception in resolver
+ */
+Q.promise = promise;
+function promise(resolver) {
+    if (typeof resolver !== "function") {
+        throw new TypeError("resolver must be a function.");
+    }
+    var deferred = defer();
+    try {
+        resolver(deferred.resolve, deferred.reject, deferred.notify);
+    } catch (reason) {
+        deferred.reject(reason);
+    }
+    return deferred.promise;
+}
+
+// XXX experimental.  This method is a way to denote that a local value is
+// serializable and should be immediately dispatched to a remote upon request,
+// instead of passing a reference.
+Q.passByCopy = function (object) {
+    //freeze(object);
+    //passByCopies.set(object, true);
+    return object;
+};
+
+Promise.prototype.passByCopy = function () {
+    //freeze(object);
+    //passByCopies.set(object, true);
+    return this;
+};
+
+/**
+ * If two promises eventually fulfill to the same value, promises that value,
+ * but otherwise rejects.
+ * @param x {Any*}
+ * @param y {Any*}
+ * @returns {Any*} a promise for x and y if they are the same, but a rejection
+ * otherwise.
+ *
+ */
+Q.join = function (x, y) {
+    return Q(x).join(y);
+};
+
+Promise.prototype.join = function (that) {
+    return Q([this, that]).spread(function (x, y) {
+        if (x === y) {
+            // TODO: "===" should be Object.is or equiv
+            return x;
+        } else {
+            throw new Error("Can't join: not the same: " + x + " " + y);
+        }
+    });
+};
+
+/**
+ * Returns a promise for the first of an array of promises to become fulfilled.
+ * @param answers {Array[Any*]} promises to race
+ * @returns {Any*} the first promise to be fulfilled
+ */
+Q.race = race;
+function race(answerPs) {
+    return promise(function(resolve, reject) {
+        // Switch to this once we can assume at least ES5
+        // answerPs.forEach(function(answerP) {
+        //     Q(answerP).then(resolve, reject);
+        // });
+        // Use this in the meantime
+        for (var i = 0, len = answerPs.length; i < len; i++) {
+            Q(answerPs[i]).then(resolve, reject);
+        }
+    });
+}
+
+Promise.prototype.race = function () {
+    return this.then(Q.race);
+};
+
+/**
+ * Constructs a Promise with a promise descriptor object and optional fallback
+ * function.  The descriptor contains methods like when(rejected), get(name),
+ * set(name, value), post(name, args), and delete(name), which all
+ * return either a value, a promise for a value, or a rejection.  The fallback
+ * accepts the operation name, a resolver, and any further arguments that would
+ * have been forwarded to the appropriate method above had a method been
+ * provided with the proper name.  The API makes no guarantees about the nature
+ * of the returned object, apart from that it is usable whereever promises are
+ * bought and sold.
+ */
+Q.makePromise = Promise;
+function Promise(descriptor, fallback, inspect) {
+    if (fallback === void 0) {
+        fallback = function (op) {
+            return reject(new Error(
+                "Promise does not support operation: " + op
+            ));
+        };
+    }
+    if (inspect === void 0) {
+        inspect = function () {
+            return {state: "unknown"};
+        };
+    }
+
+    var promise = object_create(Promise.prototype);
+
+    promise.promiseDispatch = function (resolve, op, args) {
+        var result;
+        try {
+            if (descriptor[op]) {
+                result = descriptor[op].apply(promise, args);
+            } else {
+                result = fallback.call(promise, op, args);
+            }
+        } catch (exception) {
+            result = reject(exception);
+        }
+        if (resolve) {
+            resolve(result);
+        }
+    };
+
+    promise.inspect = inspect;
+
+    // XXX deprecated `valueOf` and `exception` support
+    if (inspect) {
+        var inspected = inspect();
+        if (inspected.state === "rejected") {
+            promise.exception = inspected.reason;
+        }
+
+        promise.valueOf = function () {
+            var inspected = inspect();
+            if (inspected.state === "pending" ||
+                inspected.state === "rejected") {
+                return promise;
+            }
+            return inspected.value;
+        };
+    }
+
+    return promise;
+}
+
+Promise.prototype.toString = function () {
+    return "[object Promise]";
+};
+
+Promise.prototype.then = function (fulfilled, rejected, progressed) {
+    var self = this;
+    var deferred = defer();
+    var done = false;   // ensure the untrusted promise makes at most a
+                        // single call to one of the callbacks
+
+    function _fulfilled(value) {
+        try {
+            return typeof fulfilled === "function" ? fulfilled(value) : value;
+        } catch (exception) {
+            return reject(exception);
+        }
+    }
+
+    function _rejected(exception) {
+        if (typeof rejected === "function") {
+            makeStackTraceLong(exception, self);
+            try {
+                return rejected(exception);
+            } catch (newException) {
+                return reject(newException);
+            }
+        }
+        return reject(exception);
+    }
+
+    function _progressed(value) {
+        return typeof progressed === "function" ? progressed(value) : value;
+    }
+
+    nextTick(function () {
+        self.promiseDispatch(function (value) {
+            if (done) {
+                return;
+            }
+            done = true;
+
+            deferred.resolve(_fulfilled(value));
+        }, "when", [function (exception) {
+            if (done) {
+                return;
+            }
+            done = true;
+
+            deferred.resolve(_rejected(exception));
+        }]);
+    });
+
+    // Progress propagator need to be attached in the current tick.
+    self.promiseDispatch(void 0, "when", [void 0, function (value) {
+        var newValue;
+        var threw = false;
+        try {
+            newValue = _progressed(value);
+        } catch (e) {
+            threw = true;
+            if (Q.onerror) {
+                Q.onerror(e);
+            } else {
+                throw e;
+            }
+        }
+
+        if (!threw) {
+            deferred.notify(newValue);
+        }
+    }]);
+
+    return deferred.promise;
+};
+
+/**
+ * Registers an observer on a promise.
+ *
+ * Guarantees:
+ *
+ * 1. that fulfilled and rejected will be called only once.
+ * 2. that either the fulfilled callback or the rejected callback will be
+ *    called, but not both.
+ * 3. that fulfilled and rejected will not be called in this turn.
+ *
+ * @param value      promise or immediate reference to observe
+ * @param fulfilled  function to be called with the fulfilled value
+ * @param rejected   function to be called with the rejection exception
+ * @param progressed function to be called on any progress notifications
+ * @return promise for the return value from the invoked callback
+ */
+Q.when = when;
+function when(value, fulfilled, rejected, progressed) {
+    return Q(value).then(fulfilled, rejected, progressed);
+}
+
+Promise.prototype.thenResolve = function (value) {
+    return this.then(function () { return value; });
+};
+
+Q.thenResolve = function (promise, value) {
+    return Q(promise).thenResolve(value);
+};
+
+Promise.prototype.thenReject = function (reason) {
+    return this.then(function () { throw reason; });
+};
+
+Q.thenReject = function (promise, reason) {
+    return Q(promise).thenReject(reason);
+};
+
+/**
+ * If an object is not a promise, it is as "near" as possible.
+ * If a promise is rejected, it is as "near" as possible too.
+ * If it’s a fulfilled promise, the fulfillment value is nearer.
+ * If it’s a deferred promise and the deferred has been resolved, the
+ * resolution is "nearer".
+ * @param object
+ * @returns most resolved (nearest) form of the object
+ */
+
+// XXX should we re-do this?
+Q.nearer = nearer;
+function nearer(value) {
+    if (isPromise(value)) {
+        var inspected = value.inspect();
+        if (inspected.state === "fulfilled") {
+            return inspected.value;
+        }
+    }
+    return value;
+}
+
+/**
+ * @returns whether the given object is a promise.
+ * Otherwise it is a fulfilled value.
+ */
+Q.isPromise = isPromise;
+function isPromise(object) {
+    return isObject(object) &&
+        typeof object.promiseDispatch === "function" &&
+        typeof object.inspect === "function";
+}
+
+Q.isPromiseAlike = isPromiseAlike;
+function isPromiseAlike(object) {
+    return isObject(object) && typeof object.then === "function";
+}
+
+/**
+ * @returns whether the given object is a pending promise, meaning not
+ * fulfilled or rejected.
+ */
+Q.isPending = isPending;
+function isPending(object) {
+    return isPromise(object) && object.inspect().state === "pending";
+}
+
+Promise.prototype.isPending = function () {
+    return this.inspect().state === "pending";
+};
+
+/**
+ * @returns whether the given object is a value or fulfilled
+ * promise.
+ */
+Q.isFulfilled = isFulfilled;
+function isFulfilled(object) {
+    return !isPromise(object) || object.inspect().state === "fulfilled";
+}
+
+Promise.prototype.isFulfilled = function () {
+    return this.inspect().state === "fulfilled";
+};
+
+/**
+ * @returns whether the given object is a rejected promise.
+ */
+Q.isRejected = isRejected;
+function isRejected(object) {
+    return isPromise(object) && object.inspect().state === "rejected";
+}
+
+Promise.prototype.isRejected = function () {
+    return this.inspect().state === "rejected";
+};
+
+//// BEGIN UNHANDLED REJECTION TRACKING
+
+// This promise library consumes exceptions thrown in handlers so they can be
+// handled by a subsequent promise.  The exceptions get added to this array when
+// they are created, and removed when they are handled.  Note that in ES6 or
+// shimmed environments, this would naturally be a `Set`.
+var unhandledReasons = [];
+var unhandledRejections = [];
+var unhandledReasonsDisplayed = false;
+var trackUnhandledRejections = true;
+function displayUnhandledReasons() {
+    if (
+        !unhandledReasonsDisplayed &&
+        typeof window !== "undefined" &&
+        window.console
+    ) {
+        console.warn("[Q] Unhandled rejection reasons (should be empty):",
+                     unhandledReasons);
+    }
+
+    unhandledReasonsDisplayed = true;
+}
+
+function logUnhandledReasons() {
+    for (var i = 0; i < unhandledReasons.length; i++) {
+        var reason = unhandledReasons[i];
+        console.warn("Unhandled rejection reason:", reason);
+    }
+}
+
+function resetUnhandledRejections() {
+    unhandledReasons.length = 0;
+    unhandledRejections.length = 0;
+    unhandledReasonsDisplayed = false;
+
+    if (!trackUnhandledRejections) {
+        trackUnhandledRejections = true;
+
+        // Show unhandled rejection reasons if Node exits without handling an
+        // outstanding rejection.  (Note that Browserify presently produces a
+        // `process` global without the `EventEmitter` `on` method.)
+        if (typeof process !== "undefined" && process.on) {
+            process.on("exit", logUnhandledReasons);
+        }
+    }
+}
+
+function trackRejection(promise, reason) {
+    if (!trackUnhandledRejections) {
+        return;
+    }
+
+    unhandledRejections.push(promise);
+    if (reason && typeof reason.stack !== "undefined") {
+        unhandledReasons.push(reason.stack);
+    } else {
+        unhandledReasons.push("(no stack) " + reason);
+    }
+    displayUnhandledReasons();
+}
+
+function untrackRejection(promise) {
+    if (!trackUnhandledRejections) {
+        return;
+    }
+
+    var at = array_indexOf(unhandledRejections, promise);
+    if (at !== -1) {
+        unhandledRejections.splice(at, 1);
+        unhandledReasons.splice(at, 1);
+    }
+}
+
+Q.resetUnhandledRejections = resetUnhandledRejections;
+
+Q.getUnhandledReasons = function () {
+    // Make a copy so that consumers can't interfere with our internal state.
+    return unhandledReasons.slice();
+};
+
+Q.stopUnhandledRejectionTracking = function () {
+    resetUnhandledRejections();
+    if (typeof process !== "undefined" && process.on) {
+        process.removeListener("exit", logUnhandledReasons);
+    }
+    trackUnhandledRejections = false;
+};
+
+resetUnhandledRejections();
+
+//// END UNHANDLED REJECTION TRACKING
+
+/**
+ * Constructs a rejected promise.
+ * @param reason value describing the failure
+ */
+Q.reject = reject;
+function reject(reason) {
+    var rejection = Promise({
+        "when": function (rejected) {
+            // note that the error has been handled
+            if (rejected) {
+                untrackRejection(this);
+            }
+            return rejected ? rejected(reason) : this;
+        }
+    }, function fallback() {
+        return this;
+    }, function inspect() {
+        return { state: "rejected", reason: reason };
+    });
+
+    // Note that the reason has not been handled.
+    trackRejection(rejection, reason);
+
+    return rejection;
+}
+
+/**
+ * Constructs a fulfilled promise for an immediate reference.
+ * @param value immediate reference
+ */
+Q.fulfill = fulfill;
+function fulfill(value) {
+    return Promise({
+        "when": function () {
+            return value;
+        },
+        "get": function (name) {
+            return value[name];
+        },
+        "set": function (name, rhs) {
+            value[name] = rhs;
+        },
+        "delete": function (name) {
+            delete value[name];
+        },
+        "post": function (name, args) {
+            // Mark Miller proposes that post with no name should apply a
+            // promised function.
+            if (name === null || name === void 0) {
+                return value.apply(void 0, args);
+            } else {
+                return value[name].apply(value, args);
+            }
+        },
+        "apply": function (thisp, args) {
+            return value.apply(thisp, args);
+        },
+        "keys": function () {
+            return object_keys(value);
+        }
+    }, void 0, function inspect() {
+        return { state: "fulfilled", value: value };
+    });
+}
+
+/**
+ * Converts thenables to Q promises.
+ * @param promise thenable promise
+ * @returns a Q promise
+ */
+function coerce(promise) {
+    var deferred = defer();
+    nextTick(function () {
+        try {
+            promise.then(deferred.resolve, deferred.reject, deferred.notify);
+        } catch (exception) {
+            deferred.reject(exception);
+        }
+    });
+    return deferred.promise;
+}
+
+/**
+ * Annotates an object such that it will never be
+ * transferred away from this process over any promise
+ * communication channel.
+ * @param object
+ * @returns promise a wrapping of that object that
+ * additionally responds to the "isDef" message
+ * without a rejection.
+ */
+Q.master = master;
+function master(object) {
+    return Promise({
+        "isDef": function () {}
+    }, function fallback(op, args) {
+        return dispatch(object, op, args);
+    }, function () {
+        return Q(object).inspect();
+    });
+}
+
+/**
+ * Spreads the values of a promised array of arguments into the
+ * fulfillment callback.
+ * @param fulfilled callback that receives variadic arguments from the
+ * promised array
+ * @param rejected callback that receives the exception if the promise
+ * is rejected.
+ * @returns a promise for the return value or thrown exception of
+ * either callback.
+ */
+Q.spread = spread;
+function spread(value, fulfilled, rejected) {
+    return Q(value).spread(fulfilled, rejected);
+}
+
+Promise.prototype.spread = function (fulfilled, rejected) {
+    return this.all().then(function (array) {
+        return fulfilled.apply(void 0, array);
+    }, rejected);
+};
+
+/**
+ * The async function is a decorator for generator functions, turning
+ * them into asynchronous generators.  Although generators are only part
+ * of the newest ECMAScript 6 drafts, this code does not cause syntax
+ * errors in older engines.  This code should continue to work and will
+ * in fact improve over time as the language improves.
+ *
+ * ES6 generators are currently part of V8 version 3.19 with the
+ * --harmony-generators runtime flag enabled.  SpiderMonkey has had them
+ * for longer, but under an older Python-inspired form.  This function
+ * works on both kinds of generators.
+ *
+ * Decorates a generator function such that:
+ *  - it may yield promises
+ *  - execution will continue when that promise is fulfilled
+ *  - the value of the yield expression will be the fulfilled value
+ *  - it returns a promise for the return value (when the generator
+ *    stops iterating)
+ *  - the decorated function returns a promise for the return value
+ *    of the generator or the first rejected promise among those
+ *    yielded.
+ *  - if an error is thrown in the generator, it propagates through
+ *    every following yield until it is caught, or until it escapes
+ *    the generator function altogether, and is translated into a
+ *    rejection for the promise returned by the decorated generator.
+ */
+Q.async = async;
+function async(makeGenerator) {
+    return function () {
+        // when verb is "send", arg is a value
+        // when verb is "throw", arg is an exception
+        function continuer(verb, arg) {
+            var result;
+            if (hasES6Generators) {
+                try {
+                    result = generator[verb](arg);
+                } catch (exception) {
+                    return reject(exception);
+                }
+                if (result.done) {
+                    return result.value;
+                } else {
+                    return when(result.value, callback, errback);
+                }
+            } else {
+                // FIXME: Remove this case when SM does ES6 generators.
+                try {
+                    result = generator[verb](arg);
+                } catch (exception) {
+                    if (isStopIteration(exception)) {
+                        return exception.value;
+                    } else {
+                        return reject(exception);
+                    }
+                }
+                return when(result, callback, errback);
+            }
+        }
+        var generator = makeGenerator.apply(this, arguments);
+        var callback = continuer.bind(continuer, "next");
+        var errback = continuer.bind(continuer, "throw");
+        return callback();
+    };
+}
+
+/**
+ * The spawn function is a small wrapper around async that immediately
+ * calls the generator and also ends the promise chain, so that any
+ * unhandled errors are thrown instead of forwarded to the error
+ * handler. This is useful because it's extremely common to run
+ * generators at the top-level to work with libraries.
+ */
+Q.spawn = spawn;
+function spawn(makeGenerator) {
+    Q.done(Q.async(makeGenerator)());
+}
+
+// FIXME: Remove this interface once ES6 generators are in SpiderMonkey.
+/**
+ * Throws a ReturnValue exception to stop an asynchronous generator.
+ *
+ * This interface is a stop-gap measure to support generator return
+ * values in older Firefox/SpiderMonkey.  In browsers that support ES6
+ * generators like Chromium 29, just use "return" in your generator
+ * functions.
+ *
+ * @param value the return value for the surrounding generator
+ * @throws ReturnValue exception with the value.
+ * @example
+ * // ES6 style
+ * Q.async(function* () {
+ *      var foo = yield getFooPromise();
+ *      var bar = yield getBarPromise();
+ *      return foo + bar;
+ * })
+ * // Older SpiderMonkey style
+ * Q.async(function () {
+ *      var foo = yield getFooPromise();
+ *      var bar = yield getBarPromise();
+ *      Q.return(foo + bar);
+ * })
+ */
+Q["return"] = _return;
+function _return(value) {
+    throw new QReturnValue(value);
+}
+
+/**
+ * The promised function decorator ensures that any promise arguments
+ * are settled and passed as values (`this` is also settled and passed
+ * as a value).  It will also ensure that the result of a function is
+ * always a promise.
+ *
+ * @example
+ * var add = Q.promised(function (a, b) {
+ *     return a + b;
+ * });
+ * add(Q(a), Q(B));
+ *
+ * @param {function} callback The function to decorate
+ * @returns {function} a function that has been decorated.
+ */
+Q.promised = promised;
+function promised(callback) {
+    return function () {
+        return spread([this, all(arguments)], function (self, args) {
+            return callback.apply(self, args);
+        });
+    };
+}
+
+/**
+ * sends a message to a value in a future turn
+ * @param object* the recipient
+ * @param op the name of the message operation, e.g., "when",
+ * @param args further arguments to be forwarded to the operation
+ * @returns result {Promise} a promise for the result of the operation
+ */
+Q.dispatch = dispatch;
+function dispatch(object, op, args) {
+    return Q(object).dispatch(op, args);
+}
+
+Promise.prototype.dispatch = function (op, args) {
+    var self = this;
+    var deferred = defer();
+    nextTick(function () {
+        self.promiseDispatch(deferred.resolve, op, args);
+    });
+    return deferred.promise;
+};
+
+/**
+ * Gets the value of a property in a future turn.
+ * @param object    promise or immediate reference for target object
+ * @param name      name of property to get
+ * @return promise for the property value
+ */
+Q.get = function (object, key) {
+    return Q(object).dispatch("get", [key]);
+};
+
+Promise.prototype.get = function (key) {
+    return this.dispatch("get", [key]);
+};
+
+/**
+ * Sets the value of a property in a future turn.
+ * @param object    promise or immediate reference for object object
+ * @param name      name of property to set
+ * @param value     new value of property
+ * @return promise for the return value
+ */
+Q.set = function (object, key, value) {
+    return Q(object).dispatch("set", [key, value]);
+};
+
+Promise.prototype.set = function (key, value) {
+    return this.dispatch("set", [key, value]);
+};
+
+/**
+ * Deletes a property in a future turn.
+ * @param object    promise or immediate reference for target object
+ * @param name      name of property to delete
+ * @return promise for the return value
+ */
+Q.del = // XXX legacy
+Q["delete"] = function (object, key) {
+    return Q(object).dispatch("delete", [key]);
+};
+
+Promise.prototype.del = // XXX legacy
+Promise.prototype["delete"] = function (key) {
+    return this.dispatch("delete", [key]);
+};
+
+/**
+ * Invokes a method in a future turn.
+ * @param object    promise or immediate reference for target object
+ * @param name      name of method to invoke
+ * @param value     a value to post, typically an array of
+ *                  invocation arguments for promises that
+ *                  are ultimately backed with `resolve` values,
+ *                  as opposed to those backed with URLs
+ *                  wherein the posted value can be any
+ *                  JSON serializable object.
+ * @return promise for the return value
+ */
+// bound locally because it is used by other methods
+Q.mapply = // XXX As proposed by "Redsandro"
+Q.post = function (object, name, args) {
+    return Q(object).dispatch("post", [name, args]);
+};
+
+Promise.prototype.mapply = // XXX As proposed by "Redsandro"
+Promise.prototype.post = function (name, args) {
+    return this.dispatch("post", [name, args]);
+};
+
+/**
+ * Invokes a method in a future turn.
+ * @param object    promise or immediate reference for target object
+ * @param name      name of method to invoke
+ * @param ...args   array of invocation arguments
+ * @return promise for the return value
+ */
+Q.send = // XXX Mark Miller's proposed parlance
+Q.mcall = // XXX As proposed by "Redsandro"
+Q.invoke = function (object, name /*...args*/) {
+    return Q(object).dispatch("post", [name, array_slice(arguments, 2)]);
+};
+
+Promise.prototype.send = // XXX Mark Miller's proposed parlance
+Promise.prototype.mcall = // XXX As proposed by "Redsandro"
+Promise.prototype.invoke = function (name /*...args*/) {
+    return this.dispatch("post", [name, array_slice(arguments, 1)]);
+};
+
+/**
+ * Applies the promised function in a future turn.
+ * @param object    promise or immediate reference for target function
+ * @param args      array of application arguments
+ */
+Q.fapply = function (object, args) {
+    return Q(object).dispatch("apply", [void 0, args]);
+};
+
+Promise.prototype.fapply = function (args) {
+    return this.dispatch("apply", [void 0, args]);
+};
+
+/**
+ * Calls the promised function in a future turn.
+ * @param object    promise or immediate reference for target function
+ * @param ...args   array of application arguments
+ */
+Q["try"] =
+Q.fcall = function (object /* ...args*/) {
+    return Q(object).dispatch("apply", [void 0, array_slice(arguments, 1)]);
+};
+
+Promise.prototype.fcall = function (/*...args*/) {
+    return this.dispatch("apply", [void 0, array_slice(arguments)]);
+};
+
+/**
+ * Binds the promised function, transforming return values into a fulfilled
+ * promise and thrown errors into a rejected one.
+ * @param object    promise or immediate reference for target function
+ * @param ...args   array of application arguments
+ */
+Q.fbind = function (object /*...args*/) {
+    var promise = Q(object);
+    var args = array_slice(arguments, 1);
+    return function fbound() {
+        return promise.dispatch("apply", [
+            this,
+            args.concat(array_slice(arguments))
+        ]);
+    };
+};
+Promise.prototype.fbind = function (/*...args*/) {
+    var promise = this;
+    var args = array_slice(arguments);
+    return function fbound() {
+        return promise.dispatch("apply", [
+            this,
+            args.concat(array_slice(arguments))
+        ]);
+    };
+};
+
+/**
+ * Requests the names of the owned properties of a promised
+ * object in a future turn.
+ * @param object    promise or immediate reference for target object
+ * @return promise for the keys of the eventually settled object
+ */
+Q.keys = function (object) {
+    return Q(object).dispatch("keys", []);
+};
+
+Promise.prototype.keys = function () {
+    return this.dispatch("keys", []);
+};
+
+/**
+ * Turns an array of promises into a promise for an array.  If any of
+ * the promises gets rejected, the whole array is rejected immediately.
+ * @param {Array*} an array (or promise for an array) of values (or
+ * promises for values)
+ * @returns a promise for an array of the corresponding values
+ */
+// By Mark Miller
+// http://wiki.ecmascript.org/doku.php?id=strawman:concurrency&rev=1308776521#allfulfilled
+Q.all = all;
+function all(promises) {
+    return when(promises, function (promises) {
+        var countDown = 0;
+        var deferred = defer();
+        array_reduce(promises, function (undefined, promise, index) {
+            var snapshot;
+            if (
+                isPromise(promise) &&
+                (snapshot = promise.inspect()).state === "fulfilled"
+            ) {
+                promises[index] = snapshot.value;
+            } else {
+                ++countDown;
+                when(
+                    promise,
+                    function (value) {
+                        promises[index] = value;
+                        if (--countDown === 0) {
+                            deferred.resolve(promises);
+                        }
+                    },
+                    deferred.reject,
+                    function (progress) {
+                        deferred.notify({ index: index, value: progress });
+                    }
+                );
+            }
+        }, void 0);
+        if (countDown === 0) {
+            deferred.resolve(promises);
+        }
+        return deferred.promise;
+    });
+}
+
+Promise.prototype.all = function () {
+    return all(this);
+};
+
+/**
+ * Waits for all promises to be settled, either fulfilled or
+ * rejected.  This is distinct from `all` since that would stop
+ * waiting at the first rejection.  The promise returned by
+ * `allResolved` will never be rejected.
+ * @param promises a promise for an array (or an array) of promises
+ * (or values)
+ * @return a promise for an array of promises
+ */
+Q.allResolved = deprecate(allResolved, "allResolved", "allSettled");
+function allResolved(promises) {
+    return when(promises, function (promises) {
+        promises = array_map(promises, Q);
+        return when(all(array_map(promises, function (promise) {
+            return when(promise, noop, noop);
+        })), function () {
+            return promises;
+        });
+    });
+}
+
+Promise.prototype.allResolved = function () {
+    return allResolved(this);
+};
+
+/**
+ * @see Promise#allSettled
+ */
+Q.allSettled = allSettled;
+function allSettled(promises) {
+    return Q(promises).allSettled();
+}
+
+/**
+ * Turns an array of promises into a promise for an array of their states (as
+ * returned by `inspect`) when they have all settled.
+ * @param {Array[Any*]} values an array (or promise for an array) of values (or
+ * promises for values)
+ * @returns {Array[State]} an array of states for the respective values.
+ */
+Promise.prototype.allSettled = function () {
+    return this.then(function (promises) {
+        return all(array_map(promises, function (promise) {
+            promise = Q(promise);
+            function regardless() {
+                return promise.inspect();
+            }
+            return promise.then(regardless, regardless);
+        }));
+    });
+};
+
+/**
+ * Captures the failure of a promise, giving an oportunity to recover
+ * with a callback.  If the given promise is fulfilled, the returned
+ * promise is fulfilled.
+ * @param {Any*} promise for something
+ * @param {Function} callback to fulfill the returned promise if the
+ * given promise is rejected
+ * @returns a promise for the return value of the callback
+ */
+Q.fail = // XXX legacy
+Q["catch"] = function (object, rejected) {
+    return Q(object).then(void 0, rejected);
+};
+
+Promise.prototype.fail = // XXX legacy
+Promise.prototype["catch"] = function (rejected) {
+    return this.then(void 0, rejected);
+};
+
+/**
+ * Attaches a listener that can respond to progress notifications from a
+ * promise's originating deferred. This listener receives the exact arguments
+ * passed to ``deferred.notify``.
+ * @param {Any*} promise for something
+ * @param {Function} callback to receive any progress notifications
+ * @returns the given promise, unchanged
+ */
+Q.progress = progress;
+function progress(object, progressed) {
+    return Q(object).then(void 0, void 0, progressed);
+}
+
+Promise.prototype.progress = function (progressed) {
+    return this.then(void 0, void 0, progressed);
+};
+
+/**
+ * Provides an opportunity to observe the settling of a promise,
+ * regardless of whether the promise is fulfilled or rejected.  Forwards
+ * the resolution to the returned promise when the callback is done.
+ * The callback can return a promise to defer completion.
+ * @param {Any*} promise
+ * @param {Function} callback to observe the resolution of the given
+ * promise, takes no arguments.
+ * @returns a promise for the resolution of the given promise when
+ * ``fin`` is done.
+ */
+Q.fin = // XXX legacy
+Q["finally"] = function (object, callback) {
+    return Q(object)["finally"](callback);
+};
+
+Promise.prototype.fin = // XXX legacy
+Promise.prototype["finally"] = function (callback) {
+    callback = Q(callback);
+    return this.then(function (value) {
+        return callback.fcall().then(function () {
+            return value;
+        });
+    }, function (reason) {
+        // TODO attempt to recycle the rejection with "this".
+        return callback.fcall().then(function () {
+            throw reason;
+        });
+    });
+};
+
+/**
+ * Terminates a chain of promises, forcing rejections to be
+ * thrown as exceptions.
+ * @param {Any*} promise at the end of a chain of promises
+ * @returns nothing
+ */
+Q.done = function (object, fulfilled, rejected, progress) {
+    return Q(object).done(fulfilled, rejected, progress);
+};
+
+Promise.prototype.done = function (fulfilled, rejected, progress) {
+    var onUnhandledError = function (error) {
+        // forward to a future turn so that ``when``
+        // does not catch it and turn it into a rejection.
+        nextTick(function () {
+            makeStackTraceLong(error, promise);
+            if (Q.onerror) {
+                Q.onerror(error);
+            } else {
+                throw error;
+            }
+        });
+    };
+
+    // Avoid unnecessary `nextTick`ing via an unnecessary `when`.
+    var promise = fulfilled || rejected || progress ?
+        this.then(fulfilled, rejected, progress) :
+        this;
+
+    if (typeof process === "object" && process && process.domain) {
+        onUnhandledError = process.domain.bind(onUnhandledError);
+    }
+
+    promise.then(void 0, onUnhandledError);
+};
+
+/**
+ * Causes a promise to be rejected if it does not get fulfilled before
+ * some milliseconds time out.
+ * @param {Any*} promise
+ * @param {Number} milliseconds timeout
+ * @param {String} custom error message (optional)
+ * @returns a promise for the resolution of the given promise if it is
+ * fulfilled before the timeout, otherwise rejected.
+ */
+Q.timeout = function (object, ms, message) {
+    return Q(object).timeout(ms, message);
+};
+
+Promise.prototype.timeout = function (ms, message) {
+    var deferred = defer();
+    var timeoutId = setTimeout(function () {
+        deferred.reject(new Error(message || "Timed out after " + ms + " ms"));
+    }, ms);
+
+    this.then(function (value) {
+        clearTimeout(timeoutId);
+        deferred.resolve(value);
+    }, function (exception) {
+        clearTimeout(timeoutId);
+        deferred.reject(exception);
+    }, deferred.notify);
+
+    return deferred.promise;
+};
+
+/**
+ * Returns a promise for the given value (or promised value), some
+ * milliseconds after it resolved. Passes rejections immediately.
+ * @param {Any*} promise
+ * @param {Number} milliseconds
+ * @returns a promise for the resolution of the given promise after milliseconds
+ * time has elapsed since the resolution of the given promise.
+ * If the given promise rejects, that is passed immediately.
+ */
+Q.delay = function (object, timeout) {
+    if (timeout === void 0) {
+        timeout = object;
+        object = void 0;
+    }
+    return Q(object).delay(timeout);
+};
+
+Promise.prototype.delay = function (timeout) {
+    return this.then(function (value) {
+        var deferred = defer();
+        setTimeout(function () {
+            deferred.resolve(value);
+        }, timeout);
+        return deferred.promise;
+    });
+};
+
+/**
+ * Passes a continuation to a Node function, which is called with the given
+ * arguments provided as an array, and returns a promise.
+ *
+ *      Q.nfapply(FS.readFile, [__filename])
+ *      .then(function (content) {
+ *      })
+ *
+ */
+Q.nfapply = function (callback, args) {
+    return Q(callback).nfapply(args);
+};
+
+Promise.prototype.nfapply = function (args) {
+    var deferred = defer();
+    var nodeArgs = array_slice(args);
+    nodeArgs.push(deferred.makeNodeResolver());
+    this.fapply(nodeArgs).fail(deferred.reject);
+    return deferred.promise;
+};
+
+/**
+ * Passes a continuation to a Node function, which is called with the given
+ * arguments provided individually, and returns a promise.
+ * @example
+ * Q.nfcall(FS.readFile, __filename)
+ * .then(function (content) {
+ * })
+ *
+ */
+Q.nfcall = function (callback /*...args*/) {
+    var args = array_slice(arguments, 1);
+    return Q(callback).nfapply(args);
+};
+
+Promise.prototype.nfcall = function (/*...args*/) {
+    var nodeArgs = array_slice(arguments);
+    var deferred = defer();
+    nodeArgs.push(deferred.makeNodeResolver());
+    this.fapply(nodeArgs).fail(deferred.reject);
+    return deferred.promise;
+};
+
+/**
+ * Wraps a NodeJS continuation passing function and returns an equivalent
+ * version that returns a promise.
+ * @example
+ * Q.nfbind(FS.readFile, __filename)("utf-8")
+ * .then(console.log)
+ * .done()
+ */
+Q.nfbind =
+Q.denodeify = function (callback /*...args*/) {
+    var baseArgs = array_slice(arguments, 1);
+    return function () {
+        var nodeArgs = baseArgs.concat(array_slice(arguments));
+        var deferred = defer();
+        nodeArgs.push(deferred.makeNodeResolver());
+        Q(callback).fapply(nodeArgs).fail(deferred.reject);
+        return deferred.promise;
+    };
+};
+
+Promise.prototype.nfbind =
+Promise.prototype.denodeify = function (/*...args*/) {
+    var args = array_slice(arguments);
+    args.unshift(this);
+    return Q.denodeify.apply(void 0, args);
+};
+
+Q.nbind = function (callback, thisp /*...args*/) {
+    var baseArgs = array_slice(arguments, 2);
+    return function () {
+        var nodeArgs = baseArgs.concat(array_slice(arguments));
+        var deferred = defer();
+        nodeArgs.push(deferred.makeNodeResolver());
+        function bound() {
+            return callback.apply(thisp, arguments);
+        }
+        Q(bound).fapply(nodeArgs).fail(deferred.reject);
+        return deferred.promise;
+    };
+};
+
+Promise.prototype.nbind = function (/*thisp, ...args*/) {
+    var args = array_slice(arguments, 0);
+    args.unshift(this);
+    return Q.nbind.apply(void 0, args);
+};
+
+/**
+ * Calls a method of a Node-style object that accepts a Node-style
+ * callback with a given array of arguments, plus a provided callback.
+ * @param object an object that has the named method
+ * @param {String} name name of the method of object
+ * @param {Array} args arguments to pass to the method; the callback
+ * will be provided by Q and appended to these arguments.
+ * @returns a promise for the value or error
+ */
+Q.nmapply = // XXX As proposed by "Redsandro"
+Q.npost = function (object, name, args) {
+    return Q(object).npost(name, args);
+};
+
+Promise.prototype.nmapply = // XXX As proposed by "Redsandro"
+Promise.prototype.npost = function (name, args) {
+    var nodeArgs = array_slice(args || []);
+    var deferred = defer();
+    nodeArgs.push(deferred.makeNodeResolver());
+    this.dispatch("post", [name, nodeArgs]).fail(deferred.reject);
+    return deferred.promise;
+};
+
+/**
+ * Calls a method of a Node-style object that accepts a Node-style
+ * callback, forwarding the given variadic arguments, plus a provided
+ * callback argument.
+ * @param object an object that has the named method
+ * @param {String} name name of the method of object
+ * @param ...args arguments to pass to the method; the callback will
+ * be provided by Q and appended to these arguments.
+ * @returns a promise for the value or error
+ */
+Q.nsend = // XXX Based on Mark Miller's proposed "send"
+Q.nmcall = // XXX Based on "Redsandro's" proposal
+Q.ninvoke = function (object, name /*...args*/) {
+    var nodeArgs = array_slice(arguments, 2);
+    var deferred = defer();
+    nodeArgs.push(deferred.makeNodeResolver());
+    Q(object).dispatch("post", [name, nodeArgs]).fail(deferred.reject);
+    return deferred.promise;
+};
+
+Promise.prototype.nsend = // XXX Based on Mark Miller's proposed "send"
+Promise.prototype.nmcall = // XXX Based on "Redsandro's" proposal
+Promise.prototype.ninvoke = function (name /*...args*/) {
+    var nodeArgs = array_slice(arguments, 1);
+    var deferred = defer();
+    nodeArgs.push(deferred.makeNodeResolver());
+    this.dispatch("post", [name, nodeArgs]).fail(deferred.reject);
+    return deferred.promise;
+};
+
+/**
+ * If a function would like to support both Node continuation-passing-style and
+ * promise-returning-style, it can end its internal promise chain with
+ * `nodeify(nodeback)`, forwarding the optional nodeback argument.  If the user
+ * elects to use a nodeback, the result will be sent there.  If they do not
+ * pass a nodeback, they will receive the result promise.
+ * @param object a result (or a promise for a result)
+ * @param {Function} nodeback a Node.js-style callback
+ * @returns either the promise or nothing
+ */
+Q.nodeify = nodeify;
+function nodeify(object, nodeback) {
+    return Q(object).nodeify(nodeback);
+}
+
+Promise.prototype.nodeify = function (nodeback) {
+    if (nodeback) {
+        this.then(function (value) {
+            nextTick(function () {
+                nodeback(null, value);
+            });
+        }, function (error) {
+            nextTick(function () {
+                nodeback(error);
+            });
+        });
+    } else {
+        return this;
+    }
+};
+
+// All code before this point will be filtered from stack traces.
+var qEndingLine = captureLine();
+
+return Q;
+
+});
diff --git a/src/main/resources/SLING-INF/libs/sling/sightly/js/internal/helper.js b/src/main/resources/SLING-INF/libs/sling/sightly/js/internal/helper.js
new file mode 100644
index 0000000..7f7523c
--- /dev/null
+++ b/src/main/resources/SLING-INF/libs/sling/sightly/js/internal/helper.js
@@ -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.
+ ******************************************************************************/
+
+/**
+ * Utility functions
+ */
+use(function() {
+
+    return {
+        /**
+         * 
+         * Convert a java Map instance to a JS object
+         * @param  {object} javaMap - instance of java.lang.Map
+         * @return {{}} the resulting object
+         * @ignore
+         */
+        mapToObject: function (javaMap) {
+            var props = {};
+            var it = javaMap.entrySet().iterator();
+            while (it.hasNext()) {
+                var entry = it.next();
+                props[entry.getKey()] = entry.getValue();
+            }
+            return props;
+        }
+    };
+});
\ No newline at end of file
diff --git a/src/main/resources/SLING-INF/libs/sling/sightly/js/internal/promise.js b/src/main/resources/SLING-INF/libs/sling/sightly/js/internal/promise.js
new file mode 100644
index 0000000..65b08ae
--- /dev/null
+++ b/src/main/resources/SLING-INF/libs/sling/sightly/js/internal/promise.js
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+
+/**
+ * Wrapper factory that transforms objects
+ * obtained synchronously in promises
+ */
+use(function() {
+    return function(Q) {
+        return {
+            success: function(x) {
+                return Q(x);
+            },
+
+            failure: function(err) {
+                return Q.reject(err);
+            }
+        };
+    }
+});
\ No newline at end of file
diff --git a/src/main/resources/SLING-INF/libs/sling/sightly/js/internal/request.js b/src/main/resources/SLING-INF/libs/sling/sightly/js/internal/request.js
new file mode 100644
index 0000000..1a75d2f
--- /dev/null
+++ b/src/main/resources/SLING-INF/libs/sling/sightly/js/internal/request.js
@@ -0,0 +1,140 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+use(function(_) {
+
+    function convertParams(paramMap) {
+        var result = {};
+        var it = paramMap.entrySet().iterator();
+        while (it.hasNext()) {
+            var entry = it.next();
+            var paramName = entry.getKey();
+            var paramValues = entry.getValue();
+            if (paramValues) {
+                paramValues = paramValues.map(function (param) {
+                    return param.getString();
+                });
+            }
+            result[paramName] = paramValues;
+        }
+        return result;
+    }
+
+    /**
+     * @constructor
+     * @class Properties that contain parts of the request
+     * @name RequestPathInfo
+     * @param {object} nativePathInfo The native path info object
+     */
+    function RequestPathInfo(nativePathInfo) {
+        /** @private */
+        this.nativePathInfo = nativePathInfo;
+    }
+
+    Object.defineProperties(RequestPathInfo.prototype, {
+
+        /**
+         * The resource path
+         * @name RequestPathInfo~resourcePath
+         * @type {String}
+         * @member
+         */
+        resourcePath: {
+            get: function() {
+                return this.nativePathInfo.getResourcePath();
+            }
+        },
+
+        /**
+         * The extension in the path
+         * @name RequestPathInfo~extension
+         * @type {String}
+         * @member
+         */
+        extension: {
+            get: function() {
+                return this.nativePathInfo.getExtension();
+            }
+        },
+
+        /**
+         * The selector string segment
+         * @name RequestPathInfo~selectorString
+         * @type {String}
+         * @member
+         */
+        selectorString: {
+            get: function() {
+                return this.nativePathInfo.getSelectorString();
+            }
+        },
+
+        /**
+         * The selectors in the request
+         * @name RequestPathInfo~selectors
+         * @type {Array.<String>}
+         * @member
+         */
+        selectors: {
+            get: function() {
+                return this.nativePathInfo.getSelectors();
+            }
+        },
+
+        /**
+         * The suffix in the request path
+         * @name RequestPathInfo~suffix
+         * @type {String}
+         * @member
+         */
+        suffix: {
+            get: function() {
+                return this.nativePathInfo.getSuffix();
+            }
+        }
+    });
+
+    /**
+     * @constructor
+     * @name Request
+     * @class The request class
+     * @param {object} nativeRequest The nativeResource request object
+     */
+    function Request(nativeRequest) {
+        /** @private */
+        this.nativeRequest = nativeRequest;
+
+        /**
+         * A map of the parameters in this request
+         * @name Request~parameters
+         * @type {object.<string, string>}
+         * @member
+         */
+        this.parameters = convertParams(nativeRequest.getRequestParameterMap());
+
+        /**
+         * The path info associated with this request
+         * @name Request~pathInfo
+         * @type {RequestPathInfo}
+         * @member
+         */
+        this.pathInfo = new RequestPathInfo(nativeRequest.getRequestPathInfo());
+    }
+
+    return Request;
+});
diff --git a/src/main/resources/SLING-INF/libs/sling/sightly/js/internal/resource.js b/src/main/resources/SLING-INF/libs/sling/sightly/js/internal/resource.js
new file mode 100644
index 0000000..b74296c
--- /dev/null
+++ b/src/main/resources/SLING-INF/libs/sling/sightly/js/internal/resource.js
@@ -0,0 +1,150 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+use(['helper.js'], function(helper) {
+       
+    function getParentPath(path) {
+        var index = path.lastIndexOf('/');
+        if (index == -1) {
+            return null;
+        }
+        return path.substring(0, index);
+    }
+
+
+    function getProperties(nativeResource) {
+        var valueMap = nativeResource.adaptTo(Packages.org.apache.sling.api.resource.ValueMap);
+        return (valueMap) ? helper.mapToObject(valueMap) : {};
+    }
+
+    /**
+     * @name Resource
+     * @constructor
+     * @class The Resource class
+     * @param {object} nativeResource The nativeResource resource object
+     */
+    function Resource(nativeResource, promise) {
+        /**
+         * The absolute path for this resource
+         * @name Resource~path
+         * @member
+         * @type {string}
+         */
+        this.path = nativeResource.getPath();
+
+        /**
+         * The map of properties for this object
+         * @name Resource~properties
+         * @member
+         * @type {object.<string, object>}
+         */
+        this.properties = getProperties(nativeResource);
+
+        /** @private */
+        this.nativeResource = nativeResource;
+
+        if (!promise) {
+            throw new Error('No promise library provided');
+        }
+        this._promise = promise;
+    }
+
+    Resource.prototype = /** @lends Resource.prototype */ {
+        constructor: Resource,
+
+        /**
+         * Get the parent resource
+         * @return {promise.<Resource>} a promise with the parent of this resource, or null if
+         * the resource has no parent
+         */
+        getParent: function() {
+            var parentPath = getParentPath(this.path);
+            if (!parentPath) {
+                return null;
+            }
+            var resolver = this.nativeResource.getResourceResolver();
+            var parent = resolver.resolve(parentPath);
+            return this._promise.success(new Resource(parent, this._promise));
+        },
+
+        /**
+         * Get the children of this resource
+         * @return {promise.<array.<Resource>>} a promise with the array of children resource
+         */
+        getChildren: function() {
+            var resolver = this.nativeResource.getResourceResolver();
+            var children = [];
+            var it = resolver.listChildren(this.nativeResource);
+            var promise = this._promise;
+            while (it.hasNext()) {
+                var childNativeResource = it.next();
+                children.push(new Resource(childNativeResource, promise));
+            }
+            return this._promise.success(children);
+        },
+
+        /**
+         * Resolve a path to a resource. The path may be relative
+         * to this path
+         * @param  {string} path the requested path
+         * @return {promise.<Resource>} the promise of a resource. If the resource
+         * does not exist, the promise will fail
+         */
+        resolve: function(path) {
+            var resolver = this.nativeResource.getResourceResolver();
+            var res = resolver.getResource(this.nativeResource, path);
+            if (res == null) {
+                return this._promise.failure(new Error('No resource found at path: ' + path));
+            }
+            return this._promise.success(new Resource(res, this._promise));
+        }
+    };
+
+    Object.defineProperties(Resource.prototype, {
+        /**
+         * The name of the resource
+         * @name Resource~name
+         * @member
+         * @type {string}
+         */
+        name: {
+            get: function() {
+                var index = this.path.lastIndexOf('/');
+                if (index == -1) {
+                    return this.path;
+                }
+                return this.path.substring(index + 1);
+            }
+        },
+
+        /**
+         * The resource type
+         * @name Resource~resourceType
+         * @member
+         * @type {string}
+         */
+        resourceType: {
+            get: function() {
+                return this.nativeResource.resourceType;
+            }
+        }
+    });
+
+    return Resource;
+
+});
diff --git a/src/main/resources/SLING-INF/libs/sling/sightly/js/internal/sly.js b/src/main/resources/SLING-INF/libs/sling/sightly/js/internal/sly.js
new file mode 100644
index 0000000..82b6770
--- /dev/null
+++ b/src/main/resources/SLING-INF/libs/sling/sightly/js/internal/sly.js
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+use(['resource.js', 'request.js', 'promise.js'], function(Resource, Request, promiseFactory) {
+
+    return function(bindings, Q) {
+        var promiseLib = promiseFactory(Q);
+        var slyResource;
+        var slyProperties;
+        var slyRequest;
+        if (bindings.containsKey('resource')) {
+            slyResource = new Resource(bindings.get('resource'), promiseLib);
+            slyProperties = slyResource.properties;
+        }
+        if (bindings.containsKey('request')) {
+            slyRequest = new Request(bindings.get('request'));
+        }
+
+        /**
+         * @namespace sly
+         */
+        return /** @lends sly */ {
+
+            /**
+             * The current resource of the request
+             * @type {Resource}
+             */
+            resource: slyResource,
+
+            /**
+             * The properties of the current resource
+             * @type {Object.<string, Object>}
+             */
+            properties: slyResource.properties,
+
+            /**
+             * The request object
+             * @type {Request}
+             */
+            request: slyRequest
+        };
+    }
+
+});

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-scripting-sightly-js-provider] 08/18: SLING-4305 Refactor the Record interface:

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.scripting.sightly.js.provider-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-sightly-js-provider.git

commit 72fdfd37553dd6b3663b8f9661b9a834aa94579a
Author: Felix Meschberger <fm...@apache.org>
AuthorDate: Thu Jan 15 17:24:21 2015 +0000

    SLING-4305 Refactor the Record interface:
    
       * get -> getProperty
       * properties -> getPropertyNames
    
    Applied patch by Radu Cotescu (thanks a lot)
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/scripting/sightly/js-use-provider@1652176 13f79535-47bb-0310-9956-ffa450edef68
---
 .../apache/sling/scripting/sightly/js/impl/rhino/HybridObject.java    | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/impl/rhino/HybridObject.java b/src/main/java/org/apache/sling/scripting/sightly/js/impl/rhino/HybridObject.java
index 8318543..2d52120 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/js/impl/rhino/HybridObject.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/impl/rhino/HybridObject.java
@@ -44,7 +44,7 @@ public class HybridObject implements Scriptable, Record<Object> {
     // Record implementation
 
     @Override
-    public Object get(String name) {
+    public Object getProperty(String name) {
         if (name == null) {
             return null;
         }
@@ -57,7 +57,7 @@ public class HybridObject implements Scriptable, Record<Object> {
     }
 
     @Override
-    public Set<String> properties() {
+    public Set<String> getPropertyNames() {
         Object[] properties = scriptable.getIds();
         Set<String> keys = new HashSet<String>();
         for (Object property: properties) {

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-scripting-sightly-js-provider] 13/18: SLING-4358 - Add the 'Provide-Capability' OSGi header to the org.apache.sling.scripting.sightly bundle

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.scripting.sightly.js.provider-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-sightly-js-provider.git

commit 68de3591e65c70c772786fa4ae01b1769beb2b9c
Author: Radu Cotescu <ra...@apache.org>
AuthorDate: Mon Feb 16 15:26:50 2015 +0000

    SLING-4358 - Add the 'Provide-Capability' OSGi header to the org.apache.sling.scripting.sightly bundle
    
    * added Provide-Capability / Require-Capability headers to Sightly bundles
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/scripting/sightly/js-use-provider@1660139 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/pom.xml b/pom.xml
index 399abdf..e10af62 100644
--- a/pom.xml
+++ b/pom.xml
@@ -69,6 +69,7 @@
                 <configuration>
                     <instructions>
                         <Sling-Bundle-Resources>/libs/sling/sightly/js;path:=/SLING-INF/libs/sling/sightly/js</Sling-Bundle-Resources>
+                        <Require-Capability>io.sightly; filter:="(&amp;(version>=1.0)(!(version>=2.0)))"</Require-Capability>
                     </instructions>
                 </configuration>
             </plugin>

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-scripting-sightly-js-provider] 03/18: SLING-4206 Refactor Sightly and Sightly JS

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.scripting.sightly.js.provider-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-sightly-js-provider.git

commit 65973140c736bbbe12d051e9c45b7c0107d46d2b
Author: Felix Meschberger <fm...@apache.org>
AuthorDate: Fri Nov 28 10:34:47 2014 +0000

    SLING-4206 Refactor Sightly and Sightly JS
    
    Remove empty folders after committing the refactoring
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/scripting/sightly/js-use-provider@1642283 13f79535-47bb-0310-9956-ffa450edef68

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-scripting-sightly-js-provider] 10/18: SLING-4323 Fix SCM locations

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.scripting.sightly.js.provider-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-sightly-js-provider.git

commit 54cba6d35f79e0b5b5af54c3fac2be9b11ac4a10
Author: Felix Meschberger <fm...@apache.org>
AuthorDate: Fri Jan 16 14:15:40 2015 +0000

    SLING-4323 Fix SCM locations
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/scripting/sightly/js-use-provider@1652412 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/pom.xml b/pom.xml
index b4e983c..399abdf 100644
--- a/pom.xml
+++ b/pom.xml
@@ -44,9 +44,9 @@
     </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>
+        <connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/contrib/scripting/sightly/js-use-provider</connection>
+        <developerConnection>scm:svn:https://svn.apache.org/repos/asf/sling/trunk/contrib/scripting/sightly/js-use-provider</developerConnection>
+        <url>http://svn.apache.org/repos/asf/sling/trunk/contrib/scripting/sightly/js-use-provider</url>
     </scm>
 
     <properties>

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-scripting-sightly-js-provider] 02/18: SLING-4206 Refactor Sightly and Sightly JS

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.scripting.sightly.js.provider-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-sightly-js-provider.git

commit d05bbfa038e39625bd2f0392708ef258972668ec
Author: Felix Meschberger <fm...@apache.org>
AuthorDate: Fri Nov 28 10:18:01 2014 +0000

    SLING-4206 Refactor Sightly and Sightly JS
    
     - Cleanup API
     - Structure API
     - Move implementations into impl folders
    
    Applying patch by Radu Cotescu (thank you very much)
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/scripting/sightly/js-use-provider@1642281 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml                                            |  7 ++++
 .../scripting/sightly/js/{ => impl}/Console.java   |  2 +-
 .../sightly/js/{ => impl}/JsEnvironment.java       | 25 +++++++--------
 .../sightly/js/{ => impl}/JsUseProvider.java       | 37 +++++++++++++++-------
 .../scripting/sightly/js/{ => impl}/Utils.java     |  2 +-
 .../scripting/sightly/js/{ => impl}/Variables.java |  2 +-
 .../js/{ => impl}/async/AsyncContainer.java        |  2 +-
 .../js/{ => impl}/async/AsyncExtractor.java        |  7 ++--
 .../async/TimingBindingsValuesProvider.java        |  5 ++-
 .../js/{ => impl}/async/TimingFunction.java        |  7 ++--
 .../sightly/js/{ => impl}/async/UnaryCallback.java |  2 +-
 .../sightly/js/{ => impl}/cjs/CommonJsModule.java  |  2 +-
 .../sightly/js/{ => impl}/cjs/ExportsObject.java   |  2 +-
 .../jsapi/SlyBindingsValuesProvider.java           | 21 ++++++------
 .../sightly/js/{ => impl}/loop/EventLoop.java      |  4 +--
 .../js/{ => impl}/loop/EventLoopInterop.java       |  2 +-
 .../scripting/sightly/js/{ => impl}/loop/Task.java |  2 +-
 .../sightly/js/{ => impl}/rhino/HybridObject.java  |  4 +--
 .../sightly/js/{ => impl}/rhino/JsUtils.java       |  2 +-
 .../js/{ => impl}/rhino/JsValueAdapter.java        |  7 ++--
 .../js/{ => impl}/use/DependencyResolver.java      | 11 +++----
 .../sightly/js/{ => impl}/use/UseFunction.java     | 12 +++----
 22 files changed, 91 insertions(+), 76 deletions(-)

diff --git a/pom.xml b/pom.xml
index 8fbe66a..3ac4e73 100644
--- a/pom.xml
+++ b/pom.xml
@@ -79,11 +79,18 @@
     <!-- D E P E N D E N C I E S                                                 -->
     <!-- ======================================================================= -->
     <dependencies>
+        <!-- OSGI -->
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <scope>provided</scope>
+        </dependency>
         <dependency>
             <groupId>org.osgi</groupId>
             <artifactId>org.osgi.compendium</artifactId>
             <scope>provided</scope>
         </dependency>
+
         <!-- Sling -->
         <dependency>
             <groupId>org.apache.sling</groupId>
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/Console.java b/src/main/java/org/apache/sling/scripting/sightly/js/impl/Console.java
similarity index 96%
rename from src/main/java/org/apache/sling/scripting/sightly/js/Console.java
rename to src/main/java/org/apache/sling/scripting/sightly/js/impl/Console.java
index 885c602..355e253 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/js/Console.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/impl/Console.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  ******************************************************************************/
-package org.apache.sling.scripting.sightly.js;
+package org.apache.sling.scripting.sightly.js.impl;
 
 import org.slf4j.Logger;
 
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/JsEnvironment.java b/src/main/java/org/apache/sling/scripting/sightly/js/impl/JsEnvironment.java
similarity index 89%
rename from src/main/java/org/apache/sling/scripting/sightly/js/JsEnvironment.java
rename to src/main/java/org/apache/sling/scripting/sightly/js/impl/JsEnvironment.java
index 58686a7..f1979fb 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/js/JsEnvironment.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/impl/JsEnvironment.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  ******************************************************************************/
-package org.apache.sling.scripting.sightly.js;
+package org.apache.sling.scripting.sightly.js.impl;
 
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -33,20 +33,19 @@ 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.apache.sling.scripting.sightly.ResourceResolution;
 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;
+import org.apache.sling.scripting.sightly.js.impl.async.AsyncContainer;
+import org.apache.sling.scripting.sightly.js.impl.async.TimingBindingsValuesProvider;
+import org.apache.sling.scripting.sightly.js.impl.async.UnaryCallback;
+import org.apache.sling.scripting.sightly.js.impl.cjs.CommonJsModule;
+import org.apache.sling.scripting.sightly.js.impl.loop.EventLoop;
+import org.apache.sling.scripting.sightly.js.impl.loop.EventLoopInterop;
+import org.apache.sling.scripting.sightly.js.impl.loop.Task;
+import org.apache.sling.scripting.sightly.js.impl.use.DependencyResolver;
+import org.apache.sling.scripting.sightly.js.impl.use.UseFunction;
+import org.apache.sling.scripting.sightly.use.SightlyUseException;
 
 /**
  * Environment for running JS scripts
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/JsUseProvider.java b/src/main/java/org/apache/sling/scripting/sightly/js/impl/JsUseProvider.java
similarity index 76%
rename from src/main/java/org/apache/sling/scripting/sightly/js/JsUseProvider.java
rename to src/main/java/org/apache/sling/scripting/sightly/js/impl/JsUseProvider.java
index 85f5627..fa8b0ec 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/js/JsUseProvider.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/impl/JsUseProvider.java
@@ -16,13 +16,14 @@
  * specific language governing permissions and limitations
  * under the License.
  ******************************************************************************/
-package org.apache.sling.scripting.sightly.js;
+package org.apache.sling.scripting.sightly.js.impl;
 
 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.Properties;
 import org.apache.felix.scr.annotations.Property;
 import org.apache.felix.scr.annotations.Reference;
 import org.apache.felix.scr.annotations.Service;
@@ -31,24 +32,36 @@ 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.apache.sling.scripting.sightly.js.impl.async.AsyncContainer;
+import org.apache.sling.scripting.sightly.js.impl.async.AsyncExtractor;
+import org.apache.sling.scripting.sightly.js.impl.rhino.JsValueAdapter;
+import org.apache.sling.scripting.sightly.render.RenderContext;
+import org.apache.sling.scripting.sightly.use.ProviderOutcome;
+import org.apache.sling.scripting.sightly.use.UseProvider;
+import org.osgi.framework.Constants;
 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
+@Component(
+        metatype = true,
+        label = "Apache Sling Scripting Sightly JavaScript Use Provider",
+        description = "The JavaScript Use Provider is responsible for instantiating JavaScript Use-API objects."
+)
 @Service(UseProvider.class)
-@Property(name = UseProviderComponent.PRIORITY, intValue = -1)
-public class JsUseProvider extends UseProviderComponent {
+@Properties({
+        @Property(
+                name = Constants.SERVICE_RANKING,
+                label = "Service Ranking",
+                description = "The Service Ranking value acts as the priority with which this Use Provider is queried to return an " +
+                        "Use-object. A higher value represents a higher priority.",
+                intValue = 90,
+                propertyPrivate = false
+        )
+})
+public class JsUseProvider implements UseProvider {
 
     private static final String JS_ENGINE_NAME = "javascript";
 
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/Utils.java b/src/main/java/org/apache/sling/scripting/sightly/js/impl/Utils.java
similarity index 97%
rename from src/main/java/org/apache/sling/scripting/sightly/js/Utils.java
rename to src/main/java/org/apache/sling/scripting/sightly/js/impl/Utils.java
index 1f8128b..7d22159 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/js/Utils.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/impl/Utils.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  ******************************************************************************/
-package org.apache.sling.scripting.sightly.js;
+package org.apache.sling.scripting.sightly.js.impl;
 
 import javax.script.Bindings;
 import javax.script.SimpleBindings;
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/Variables.java b/src/main/java/org/apache/sling/scripting/sightly/js/impl/Variables.java
similarity index 96%
rename from src/main/java/org/apache/sling/scripting/sightly/js/Variables.java
rename to src/main/java/org/apache/sling/scripting/sightly/js/impl/Variables.java
index 1e1673d..176e85f 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/js/Variables.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/impl/Variables.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  ******************************************************************************/
-package org.apache.sling.scripting.sightly.js;
+package org.apache.sling.scripting.sightly.js.impl;
 
 /**
  * Variables exposed to js scripts
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/async/AsyncContainer.java b/src/main/java/org/apache/sling/scripting/sightly/js/impl/async/AsyncContainer.java
similarity index 98%
rename from src/main/java/org/apache/sling/scripting/sightly/js/async/AsyncContainer.java
rename to src/main/java/org/apache/sling/scripting/sightly/js/impl/async/AsyncContainer.java
index e4f39dd..b9bbd5c 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/js/async/AsyncContainer.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/impl/async/AsyncContainer.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  ******************************************************************************/
-package org.apache.sling.scripting.sightly.js.async;
+package org.apache.sling.scripting.sightly.js.impl.async;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/async/AsyncExtractor.java b/src/main/java/org/apache/sling/scripting/sightly/js/impl/async/AsyncExtractor.java
similarity index 94%
rename from src/main/java/org/apache/sling/scripting/sightly/js/async/AsyncExtractor.java
rename to src/main/java/org/apache/sling/scripting/sightly/js/impl/async/AsyncExtractor.java
index fe43556..bf2d933 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/js/async/AsyncExtractor.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/impl/async/AsyncExtractor.java
@@ -16,16 +16,15 @@
  * specific language governing permissions and limitations
  * under the License.
  ******************************************************************************/
-package org.apache.sling.scripting.sightly.js.async;
+package org.apache.sling.scripting.sightly.js.impl.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;
+import org.apache.sling.scripting.sightly.js.impl.loop.EventLoopInterop;
+import org.apache.sling.scripting.sightly.use.SightlyUseException;
 
 /**
  *
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/async/TimingBindingsValuesProvider.java b/src/main/java/org/apache/sling/scripting/sightly/js/impl/async/TimingBindingsValuesProvider.java
similarity index 92%
rename from src/main/java/org/apache/sling/scripting/sightly/js/async/TimingBindingsValuesProvider.java
rename to src/main/java/org/apache/sling/scripting/sightly/js/impl/async/TimingBindingsValuesProvider.java
index c823405..623de69 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/js/async/TimingBindingsValuesProvider.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/impl/async/TimingBindingsValuesProvider.java
@@ -16,13 +16,12 @@
  * specific language governing permissions and limitations
  * under the License.
  ******************************************************************************/
-package org.apache.sling.scripting.sightly.js.async;
+package org.apache.sling.scripting.sightly.js.impl.async;
 
 import javax.script.Bindings;
 
 import org.apache.sling.scripting.api.BindingsValuesProvider;
-
-import org.apache.sling.scripting.sightly.js.Variables;
+import org.apache.sling.scripting.sightly.js.impl.Variables;
 
 /**
  * Value provider for timing functions
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/async/TimingFunction.java b/src/main/java/org/apache/sling/scripting/sightly/js/impl/async/TimingFunction.java
similarity index 91%
rename from src/main/java/org/apache/sling/scripting/sightly/js/async/TimingFunction.java
rename to src/main/java/org/apache/sling/scripting/sightly/js/impl/async/TimingFunction.java
index 2755782..5cf43b7 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/js/async/TimingFunction.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/impl/async/TimingFunction.java
@@ -16,15 +16,14 @@
  * specific language governing permissions and limitations
  * under the License.
  ******************************************************************************/
-package org.apache.sling.scripting.sightly.js.async;
+package org.apache.sling.scripting.sightly.js.impl.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;
+import org.apache.sling.scripting.sightly.js.impl.loop.EventLoopInterop;
+import org.apache.sling.scripting.sightly.js.impl.rhino.JsUtils;
 
 /**
  * Timing function for JS scripts that use async constructs
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/async/UnaryCallback.java b/src/main/java/org/apache/sling/scripting/sightly/js/impl/async/UnaryCallback.java
similarity index 95%
rename from src/main/java/org/apache/sling/scripting/sightly/js/async/UnaryCallback.java
rename to src/main/java/org/apache/sling/scripting/sightly/js/impl/async/UnaryCallback.java
index 48e1aee..0ec0e61 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/js/async/UnaryCallback.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/impl/async/UnaryCallback.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  ******************************************************************************/
-package org.apache.sling.scripting.sightly.js.async;
+package org.apache.sling.scripting.sightly.js.impl.async;
 
 /**
  * Unary callback function
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/cjs/CommonJsModule.java b/src/main/java/org/apache/sling/scripting/sightly/js/impl/cjs/CommonJsModule.java
similarity index 97%
rename from src/main/java/org/apache/sling/scripting/sightly/js/cjs/CommonJsModule.java
rename to src/main/java/org/apache/sling/scripting/sightly/js/impl/cjs/CommonJsModule.java
index 3d1683e..9b1c675 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/js/cjs/CommonJsModule.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/impl/cjs/CommonJsModule.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  ******************************************************************************/
-package org.apache.sling.scripting.sightly.js.cjs;
+package org.apache.sling.scripting.sightly.js.impl.cjs;
 
 import org.mozilla.javascript.Scriptable;
 import org.mozilla.javascript.ScriptableObject;
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/cjs/ExportsObject.java b/src/main/java/org/apache/sling/scripting/sightly/js/impl/cjs/ExportsObject.java
similarity index 96%
rename from src/main/java/org/apache/sling/scripting/sightly/js/cjs/ExportsObject.java
rename to src/main/java/org/apache/sling/scripting/sightly/js/impl/cjs/ExportsObject.java
index 58257f5..3822861 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/js/cjs/ExportsObject.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/impl/cjs/ExportsObject.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  ******************************************************************************/
-package org.apache.sling.scripting.sightly.js.cjs;
+package org.apache.sling.scripting.sightly.js.impl.cjs;
 
 
 import org.mozilla.javascript.Scriptable;
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/jsapi/SlyBindingsValuesProvider.java b/src/main/java/org/apache/sling/scripting/sightly/js/impl/jsapi/SlyBindingsValuesProvider.java
similarity index 94%
rename from src/main/java/org/apache/sling/scripting/sightly/js/jsapi/SlyBindingsValuesProvider.java
rename to src/main/java/org/apache/sling/scripting/sightly/js/impl/jsapi/SlyBindingsValuesProvider.java
index 4333c4a..72b99a2 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/js/jsapi/SlyBindingsValuesProvider.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/impl/jsapi/SlyBindingsValuesProvider.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  ******************************************************************************/
-package org.apache.sling.scripting.sightly.js.jsapi;
+package org.apache.sling.scripting.sightly.js.impl.jsapi;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -24,6 +24,7 @@ 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;
@@ -45,15 +46,15 @@ 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.apache.sling.scripting.sightly.js.impl.JsEnvironment;
+import org.apache.sling.scripting.sightly.js.impl.Variables;
+import org.apache.sling.scripting.sightly.js.impl.async.AsyncContainer;
+import org.apache.sling.scripting.sightly.js.impl.async.AsyncExtractor;
+import org.apache.sling.scripting.sightly.js.impl.async.TimingBindingsValuesProvider;
+import org.apache.sling.scripting.sightly.js.impl.async.TimingFunction;
+import org.apache.sling.scripting.sightly.js.impl.cjs.CommonJsModule;
+import org.apache.sling.scripting.sightly.js.impl.rhino.HybridObject;
+import org.apache.sling.scripting.sightly.js.impl.rhino.JsValueAdapter;
 import org.mozilla.javascript.Context;
 import org.mozilla.javascript.Function;
 import org.mozilla.javascript.Script;
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/loop/EventLoop.java b/src/main/java/org/apache/sling/scripting/sightly/js/impl/loop/EventLoop.java
similarity index 95%
rename from src/main/java/org/apache/sling/scripting/sightly/js/loop/EventLoop.java
rename to src/main/java/org/apache/sling/scripting/sightly/js/impl/loop/EventLoop.java
index ef4c6d5..29480f2 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/js/loop/EventLoop.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/impl/loop/EventLoop.java
@@ -16,12 +16,12 @@
  * specific language governing permissions and limitations
  * under the License.
  ******************************************************************************/
-package org.apache.sling.scripting.sightly.js.loop;
+package org.apache.sling.scripting.sightly.js.impl.loop;
 
 import java.util.LinkedList;
 import java.util.Queue;
 
-import org.apache.sling.scripting.sightly.api.SightlyUseException;
+import org.apache.sling.scripting.sightly.use.SightlyUseException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/loop/EventLoopInterop.java b/src/main/java/org/apache/sling/scripting/sightly/js/impl/loop/EventLoopInterop.java
similarity index 97%
rename from src/main/java/org/apache/sling/scripting/sightly/js/loop/EventLoopInterop.java
rename to src/main/java/org/apache/sling/scripting/sightly/js/impl/loop/EventLoopInterop.java
index d847f53..af9b8d5 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/js/loop/EventLoopInterop.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/impl/loop/EventLoopInterop.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  ******************************************************************************/
-package org.apache.sling.scripting.sightly.js.loop;
+package org.apache.sling.scripting.sightly.js.impl.loop;
 
 import org.mozilla.javascript.Context;
 
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/loop/Task.java b/src/main/java/org/apache/sling/scripting/sightly/js/impl/loop/Task.java
similarity index 95%
rename from src/main/java/org/apache/sling/scripting/sightly/js/loop/Task.java
rename to src/main/java/org/apache/sling/scripting/sightly/js/impl/loop/Task.java
index e218e78..1a96a12 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/js/loop/Task.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/impl/loop/Task.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  ******************************************************************************/
-package org.apache.sling.scripting.sightly.js.loop;
+package org.apache.sling.scripting.sightly.js.impl.loop;
 
 /**
  * Task in an event loop
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/rhino/HybridObject.java b/src/main/java/org/apache/sling/scripting/sightly/js/impl/rhino/HybridObject.java
similarity index 97%
rename from src/main/java/org/apache/sling/scripting/sightly/js/rhino/HybridObject.java
rename to src/main/java/org/apache/sling/scripting/sightly/js/impl/rhino/HybridObject.java
index 77875fc..8318543 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/js/rhino/HybridObject.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/impl/rhino/HybridObject.java
@@ -16,12 +16,12 @@
  * specific language governing permissions and limitations
  * under the License.
  ******************************************************************************/
-package org.apache.sling.scripting.sightly.js.rhino;
+package org.apache.sling.scripting.sightly.js.impl.rhino;
 
 import java.util.HashSet;
 import java.util.Set;
 
-import org.apache.sling.scripting.sightly.api.Record;
+import org.apache.sling.scripting.sightly.Record;
 import org.mozilla.javascript.Context;
 import org.mozilla.javascript.Function;
 import org.mozilla.javascript.Scriptable;
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/rhino/JsUtils.java b/src/main/java/org/apache/sling/scripting/sightly/js/impl/rhino/JsUtils.java
similarity index 96%
rename from src/main/java/org/apache/sling/scripting/sightly/js/rhino/JsUtils.java
rename to src/main/java/org/apache/sling/scripting/sightly/js/impl/rhino/JsUtils.java
index aa5325f..cfc6cad 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/js/rhino/JsUtils.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/impl/rhino/JsUtils.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  ******************************************************************************/
-package org.apache.sling.scripting.sightly.js.rhino;
+package org.apache.sling.scripting.sightly.js.impl.rhino;
 
 import org.mozilla.javascript.Context;
 import org.mozilla.javascript.Function;
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/rhino/JsValueAdapter.java b/src/main/java/org/apache/sling/scripting/sightly/js/impl/rhino/JsValueAdapter.java
similarity index 96%
rename from src/main/java/org/apache/sling/scripting/sightly/js/rhino/JsValueAdapter.java
rename to src/main/java/org/apache/sling/scripting/sightly/js/impl/rhino/JsValueAdapter.java
index 814a7e4..81226c6 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/js/rhino/JsValueAdapter.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/impl/rhino/JsValueAdapter.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  ******************************************************************************/
-package org.apache.sling.scripting.sightly.js.rhino;
+package org.apache.sling.scripting.sightly.js.impl.rhino;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -30,9 +30,8 @@ import org.mozilla.javascript.Function;
 import org.mozilla.javascript.NativeArray;
 import org.mozilla.javascript.ScriptableObject;
 import org.mozilla.javascript.Wrapper;
-
-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.impl.async.AsyncContainer;
+import org.apache.sling.scripting.sightly.js.impl.async.AsyncExtractor;
 
 /**
  * Converts JS objects to Java objects
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/use/DependencyResolver.java b/src/main/java/org/apache/sling/scripting/sightly/js/impl/use/DependencyResolver.java
similarity index 86%
rename from src/main/java/org/apache/sling/scripting/sightly/js/use/DependencyResolver.java
rename to src/main/java/org/apache/sling/scripting/sightly/js/impl/use/DependencyResolver.java
index 5df0a86..bc43005 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/js/use/DependencyResolver.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/impl/use/DependencyResolver.java
@@ -17,16 +17,15 @@
  * under the License.
  ******************************************************************************/
 
-package org.apache.sling.scripting.sightly.js.use;
+package org.apache.sling.scripting.sightly.js.impl.use;
 
 import javax.script.Bindings;
 
 import org.apache.sling.api.resource.Resource;
-import org.apache.sling.scripting.sightly.api.SightlyUseException;
-
-import org.apache.sling.scripting.sightly.js.JsEnvironment;
-import org.apache.sling.scripting.sightly.js.Utils;
-import org.apache.sling.scripting.sightly.js.async.UnaryCallback;
+import org.apache.sling.scripting.sightly.js.impl.JsEnvironment;
+import org.apache.sling.scripting.sightly.js.impl.Utils;
+import org.apache.sling.scripting.sightly.js.impl.async.UnaryCallback;
+import org.apache.sling.scripting.sightly.use.SightlyUseException;
 
 /**
  * Resolves dependencies specified by the Use function
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/use/UseFunction.java b/src/main/java/org/apache/sling/scripting/sightly/js/impl/use/UseFunction.java
similarity index 93%
rename from src/main/java/org/apache/sling/scripting/sightly/js/use/UseFunction.java
rename to src/main/java/org/apache/sling/scripting/sightly/js/impl/use/UseFunction.java
index 2fe1b22..fbfe132 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/js/use/UseFunction.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/impl/use/UseFunction.java
@@ -17,9 +17,10 @@
  * under the License.
  ******************************************************************************/
 
-package org.apache.sling.scripting.sightly.js.use;
+package org.apache.sling.scripting.sightly.js.impl.use;
 
 import javax.script.Bindings;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -32,11 +33,10 @@ import org.mozilla.javascript.NativeArray;
 import org.mozilla.javascript.NativeObject;
 import org.mozilla.javascript.Scriptable;
 import org.mozilla.javascript.ScriptableObject;
-
-import org.apache.sling.scripting.sightly.js.async.AsyncContainer;
-import org.apache.sling.scripting.sightly.js.async.UnaryCallback;
-import org.apache.sling.scripting.sightly.js.loop.EventLoopInterop;
-import org.apache.sling.scripting.sightly.js.rhino.JsUtils;
+import org.apache.sling.scripting.sightly.js.impl.async.AsyncContainer;
+import org.apache.sling.scripting.sightly.js.impl.async.UnaryCallback;
+import org.apache.sling.scripting.sightly.js.impl.loop.EventLoopInterop;
+import org.apache.sling.scripting.sightly.js.impl.rhino.JsUtils;
 
 /**
  * The JavaScript {@code use} function

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-scripting-sightly-js-provider] 09/18: SLING-4304 Refactor the ResourceResolution class and improve its JavaDoc

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.scripting.sightly.js.provider-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-sightly-js-provider.git

commit c6b94f4a01e2eaf83ec25830ff9bec35b815e341
Author: Felix Meschberger <fm...@apache.org>
AuthorDate: Fri Jan 16 14:04:55 2015 +0000

    SLING-4304 Refactor the ResourceResolution class and improve its JavaDoc
    
    Apply patch by Radu Cotescu (thanks a lot)
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/scripting/sightly/js-use-provider@1652411 13f79535-47bb-0310-9956-ffa450edef68
---
 .../org/apache/sling/scripting/sightly/js/impl/JsEnvironment.java   | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/impl/JsEnvironment.java b/src/main/java/org/apache/sling/scripting/sightly/js/impl/JsEnvironment.java
index ffaeeb8..859accc 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/js/impl/JsEnvironment.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/impl/JsEnvironment.java
@@ -87,12 +87,12 @@ public class JsEnvironment {
     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());
+        Resource componentCaller = ResourceResolution.getResourceForRequest(caller.getResourceResolver(), scriptHelper.getRequest());
         if (scriptResource == null) {
-            scriptResource = ResourceResolution.resolveComponentRelative(caller.getResourceResolver(), componentCaller, path);
+            scriptResource = ResourceResolution.getResourceFromSearchPath(componentCaller, path);
         }
         if (scriptResource == null) {
-            scriptResource = ResourceResolution.resolveComponentRelative(caller.getResourceResolver(), caller, path);
+            scriptResource = ResourceResolution.getResourceFromSearchPath(caller, path);
         }
         if (scriptResource == null) {
             throw new SightlyException("Required script resource could not be located: " + path);

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-scripting-sightly-js-provider] 11/18: SLING-4400 - The Use-API should return a falsy value if no Use-provider was able to solve the requested object

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.scripting.sightly.js.provider-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-sightly-js-provider.git

commit c60ac619b163fcb2a4e9ea7e0fa7e107bcf2ab76
Author: Radu Cotescu <ra...@apache.org>
AuthorDate: Thu Feb 12 13:29:57 2015 +0000

    SLING-4400 - The Use-API should return a falsy value if no Use-provider was able to solve the requested object
    
    * return null when no UseProvider was able to provide an object (an error is logged in this case)
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/scripting/sightly/js-use-provider@1659248 13f79535-47bb-0310-9956-ffa450edef68
---
 .../scripting/sightly/js/impl/JsUseProvider.java   | 53 +++++-----------------
 1 file changed, 12 insertions(+), 41 deletions(-)

diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/impl/JsUseProvider.java b/src/main/java/org/apache/sling/scripting/sightly/js/impl/JsUseProvider.java
index b779c81..665ff4e 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/js/impl/JsUseProvider.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/impl/JsUseProvider.java
@@ -27,11 +27,14 @@ import org.apache.felix.scr.annotations.Properties;
 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.SlingException;
 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.SightlyException;
+import org.apache.sling.scripting.sightly.impl.engine.runtime.RenderContextImpl;
 import org.apache.sling.scripting.sightly.js.impl.async.AsyncContainer;
 import org.apache.sling.scripting.sightly.js.impl.async.AsyncExtractor;
 import org.apache.sling.scripting.sightly.js.impl.jsapi.SlyBindingsValuesProvider;
@@ -73,9 +76,6 @@ public class JsUseProvider implements UseProvider {
     private ScriptEngineManager scriptEngineManager = null;
 
     @Reference
-    private ResourceResolverFactory rrf = null;
-
-    @Reference
     private SlyBindingsValuesProvider slyBindingsValuesProvider = null;
 
     @Override
@@ -85,46 +85,17 @@ public class JsUseProvider implements UseProvider {
         if (!Utils.isJsScript(identifier)) {
             return ProviderOutcome.failure();
         }
-        ScriptEngine jsEngine = obtainEngine();
+        ScriptEngine jsEngine = scriptEngineManager.getEngineByName(JS_ENGINE_NAME);
         if (jsEngine == null) {
-            log.warn("No JavaScript engine defined");
-            return ProviderOutcome.failure();
+            return ProviderOutcome.failure(new SightlyException("No JavaScript engine was defined."));
         }
         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);
+        JsEnvironment environment = new JsEnvironment(jsEngine);
+        environment.initialize();
+        String callerPath = scriptHelper.getScript().getScriptResource().getPath();
+        ResourceResolver adminResolver = renderContext.getScriptResourceResolver();
+        Resource caller = adminResolver.getResource(callerPath);
+        AsyncContainer asyncContainer = environment.run(caller, identifier, globalBindings, arguments);
+        return ProviderOutcome.success(jsValueAdapter.adapt(asyncContainer));
     }
 }

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-scripting-sightly-js-provider] 07/18: SLING-4309 Remove redundant RuntimeExtensionException and SightlyUseException from Sightly's API

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.scripting.sightly.js.provider-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-sightly-js-provider.git

commit c7b48bef6b799e6ba3366af032853ccca0495649
Author: Felix Meschberger <fm...@apache.org>
AuthorDate: Thu Jan 15 14:50:02 2015 +0000

    SLING-4309 Remove redundant RuntimeExtensionException and SightlyUseException from Sightly's API
    
    Applying patch by Radu Cotescu (thank you very much)
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/scripting/sightly/js-use-provider@1652117 13f79535-47bb-0310-9956-ffa450edef68
---
 .../apache/sling/scripting/sightly/js/impl/JsEnvironment.java  | 10 +++++-----
 .../sling/scripting/sightly/js/impl/async/AsyncExtractor.java  |  5 ++---
 .../apache/sling/scripting/sightly/js/impl/loop/EventLoop.java |  4 ++--
 .../scripting/sightly/js/impl/use/DependencyResolver.java      |  4 ++--
 4 files changed, 11 insertions(+), 12 deletions(-)

diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/impl/JsEnvironment.java b/src/main/java/org/apache/sling/scripting/sightly/js/impl/JsEnvironment.java
index f1979fb..ffaeeb8 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/js/impl/JsEnvironment.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/impl/JsEnvironment.java
@@ -34,8 +34,7 @@ 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.ResourceResolution;
-import org.mozilla.javascript.Context;
-import org.slf4j.LoggerFactory;
+import org.apache.sling.scripting.sightly.SightlyException;
 import org.apache.sling.scripting.sightly.js.impl.async.AsyncContainer;
 import org.apache.sling.scripting.sightly.js.impl.async.TimingBindingsValuesProvider;
 import org.apache.sling.scripting.sightly.js.impl.async.UnaryCallback;
@@ -45,7 +44,8 @@ import org.apache.sling.scripting.sightly.js.impl.loop.EventLoopInterop;
 import org.apache.sling.scripting.sightly.js.impl.loop.Task;
 import org.apache.sling.scripting.sightly.js.impl.use.DependencyResolver;
 import org.apache.sling.scripting.sightly.js.impl.use.UseFunction;
-import org.apache.sling.scripting.sightly.use.SightlyUseException;
+import org.mozilla.javascript.Context;
+import org.slf4j.LoggerFactory;
 
 /**
  * Environment for running JS scripts
@@ -95,7 +95,7 @@ public class JsEnvironment {
             scriptResource = ResourceResolution.resolveComponentRelative(caller.getResourceResolver(), caller, path);
         }
         if (scriptResource == null) {
-            throw new SightlyUseException("Required script resource could not be located: " + path);
+            throw new SightlyException("Required script resource could not be located: " + path);
         }
         runResource(scriptResource, globalBindings, arguments, callback);
     }
@@ -163,7 +163,7 @@ public class JsEnvironment {
                         callback.invoke(result);
                     }
                 } catch (ScriptException e) {
-                    throw new SightlyUseException(e);
+                    throw new SightlyException(e);
                 } finally {
                     IOUtils.closeQuietly(reader);
                 }
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/impl/async/AsyncExtractor.java b/src/main/java/org/apache/sling/scripting/sightly/js/impl/async/AsyncExtractor.java
index bf2d933..098bd71 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/js/impl/async/AsyncExtractor.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/impl/async/AsyncExtractor.java
@@ -18,13 +18,13 @@
  ******************************************************************************/
 package org.apache.sling.scripting.sightly.js.impl.async;
 
+import org.apache.sling.scripting.sightly.SightlyException;
 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.impl.loop.EventLoopInterop;
-import org.apache.sling.scripting.sightly.use.SightlyUseException;
 
 /**
  *
@@ -60,8 +60,7 @@ public class AsyncExtractor {
                 }
             });
             if (errorContainer.isCompleted()) {
-                throw new SightlyUseException("Promise has completed with failure: " +
-                        Context.toString(errorContainer.getResult()));
+                throw new SightlyException("Promise has completed with failure: " + Context.toString(errorContainer.getResult()));
             }
         } finally {
             Context.exit();
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/impl/loop/EventLoop.java b/src/main/java/org/apache/sling/scripting/sightly/js/impl/loop/EventLoop.java
index 29480f2..ed565ef 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/js/impl/loop/EventLoop.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/impl/loop/EventLoop.java
@@ -21,7 +21,7 @@ package org.apache.sling.scripting.sightly.js.impl.loop;
 import java.util.LinkedList;
 import java.util.Queue;
 
-import org.apache.sling.scripting.sightly.use.SightlyUseException;
+import org.apache.sling.scripting.sightly.SightlyException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -68,7 +68,7 @@ public class EventLoop {
                 }
             }
             if (thrownException != null) {
-                throw new SightlyUseException(thrownException);
+                throw new SightlyException(thrownException);
             }
         } finally {
             isRunning = false;
diff --git a/src/main/java/org/apache/sling/scripting/sightly/js/impl/use/DependencyResolver.java b/src/main/java/org/apache/sling/scripting/sightly/js/impl/use/DependencyResolver.java
index bc43005..ef24105 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/js/impl/use/DependencyResolver.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/js/impl/use/DependencyResolver.java
@@ -22,10 +22,10 @@ package org.apache.sling.scripting.sightly.js.impl.use;
 import javax.script.Bindings;
 
 import org.apache.sling.api.resource.Resource;
+import org.apache.sling.scripting.sightly.SightlyException;
 import org.apache.sling.scripting.sightly.js.impl.JsEnvironment;
 import org.apache.sling.scripting.sightly.js.impl.Utils;
 import org.apache.sling.scripting.sightly.js.impl.async.UnaryCallback;
-import org.apache.sling.scripting.sightly.use.SightlyUseException;
 
 /**
  * Resolves dependencies specified by the Use function
@@ -49,7 +49,7 @@ public class DependencyResolver {
      */
     public void resolve(String dependency, UnaryCallback callback) {
         if (!Utils.isJsScript(dependency)) {
-            throw new SightlyUseException("Only JS scripts are allowed as dependencies. Invalid dependency: " + dependency);
+            throw new SightlyException("Only JS scripts are allowed as dependencies. Invalid dependency: " + dependency);
         }
         jsEnvironment.run(caller, dependency, globalBindings, Utils.EMPTY_BINDINGS, callback);
     }

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.