SLING-9657 - Same-name JS Use dependencies are not always correctly resolved

* pick the dependency based on the resource type hierarchy, starting from
either the caller or the request driver - whichever is the deepest resource
in the resource type hierarchy
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 121ff77..bc1bee5 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
@@ -29,6 +29,7 @@
 
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.api.resource.ResourceUtil;
@@ -61,45 +62,42 @@
             // attempt to retrieve the dependency directly (as an absolute path or relative to the search paths)
             Resource scriptResource = scriptingResourceResolver.getResource(dependency);
             Resource caller = getCaller(bindings);
-            if (scriptResource == null && caller != null) {
-                Resource requestResource = (Resource) bindings.get(SlingBindings.RESOURCE);
-                String type = requestResource.getResourceType();
-                // look at the resource type hierarchy; a dependency closer to the current resource type has priority
-                while (scriptResource == null && type != null) {
-                    Resource servletResource = null;
-                    if (!type.startsWith("/")) {
-                        for (String searchPath : scriptingResourceResolver.getSearchPath()) {
-                            String normalizedPath = ResourceUtil.normalize(searchPath + "/" + type);
-                            servletResource = resolveResource(normalizedPath);
-                            if (servletResource != null) {
-                                break;
+            if (caller != null) {
+                Resource callerType = caller.getParent();
+                if (scriptResource == null && callerType != null) {
+                    SlingHttpServletRequest request = (SlingHttpServletRequest) bindings.get(SlingBindings.REQUEST);
+                    String driverType = request.getResource().getResourceType();
+                    Resource driver = resolveResource(driverType);
+                    if (driver != null) {
+                        Resource hierarchyResource = getChildResource(callerType, driver);
+                        while (hierarchyResource != null && scriptResource == null) {
+                            if (dependency.startsWith("..")) {
+                                // relative path
+                                String absolutePath = ResourceUtil.normalize(hierarchyResource.getPath() + "/" + dependency);
+                                if (StringUtils.isNotEmpty(absolutePath)) {
+                                    scriptResource = resolveResource(absolutePath);
+                                }
+                            } else {
+                                scriptResource = hierarchyResource.getChild(dependency);
+                            }
+                            String nextType = hierarchyResource.getResourceSuperType();
+                            if (nextType != null) {
+                                hierarchyResource = resolveResource(nextType);
+                            } else {
+                                hierarchyResource = null;
                             }
                         }
-                    } else {
-                        servletResource = resolveResource(type);
                     }
-                    if (servletResource != null) {
-                        scriptResource = servletResource.getChild(dependency);
-                        type = servletResource.getResourceSuperType();
-                    } else {
-                        type = null;
-                    }
-                }
-                // cannot find a dependency relative to the resource type; locate it solely based on the caller
-                if (scriptResource == null) {
-                    if (dependency.startsWith("..")) {
-                        // relative path
-                        String absolutePath = ResourceUtil.normalize(caller.getPath() + "/" + dependency);
-                        if (StringUtils.isNotEmpty(absolutePath)) {
-                            scriptResource = resolveResource(absolutePath);
-                        }
-                        if (scriptResource == null) {
-                            scriptResource = caller.getChild(dependency);
-                        }
-                    } else {
-                        Resource callerParent = caller.getParent();
-                        if (callerParent != null) {
-                            scriptResource = callerParent.getChild(dependency);
+                    // cannot find a dependency relative to the resource type; locate it solely based on the caller
+                    if (scriptResource == null) {
+                        if (dependency.startsWith("..")) {
+                            // relative path
+                            String absolutePath = ResourceUtil.normalize(caller.getPath() + "/" + dependency);
+                            if (StringUtils.isNotEmpty(absolutePath)) {
+                                scriptResource = resolveResource(absolutePath);
+                            }
+                        } else {
+                            scriptResource = callerType.getChild(dependency);
                         }
                     }
                 }
@@ -124,9 +122,25 @@
     }
 
     private Resource resolveResource(String type) {
-        Resource servletResource = scriptingResourceResolver.resolve(type);
-        if (ResourceUtil.isNonExistingResource(servletResource)) {
-            servletResource = scriptingResourceResolver.getResource(type);
+        Resource servletResource = null;
+        if (type.startsWith("/")) {
+            servletResource = scriptingResourceResolver.resolve(type);
+            if (ResourceUtil.isNonExistingResource(servletResource)) {
+                servletResource = scriptingResourceResolver.getResource(type);
+            }
+        } else {
+            for (String searchPath : scriptingResourceResolver.getSearchPath()) {
+                String absolutePath = ResourceUtil.normalize(searchPath + "/" + type);
+                if (absolutePath != null) {
+                    servletResource = scriptingResourceResolver.resolve(absolutePath);
+                    if (ResourceUtil.isNonExistingResource(servletResource)) {
+                        servletResource = scriptingResourceResolver.getResource(type);
+                    }
+                    if (servletResource != null) {
+                        return servletResource;
+                    }
+                }
+            }
         }
         return servletResource;
     }
@@ -146,4 +160,38 @@
         return caller;
     }
 
+    private Resource getChildResource(@NotNull Resource callerType, @NotNull Resource driverType) {
+        if (callerType.getPath().equals(driverType.getPath())) {
+            return callerType;
+        }
+        if (isResourceType(callerType, driverType.getPath())) {
+            return callerType;
+        }
+        if (isResourceType(driverType, callerType.getPath())) {
+            return driverType;
+        }
+        return null;
+    }
+
+    private boolean isResourceType(@NotNull Resource resource, String type) {
+        Resource typeResource = resolveResource(type);
+        if (typeResource != null) {
+            if (typeResource.getPath().equals(resource.getPath())) {
+                return true;
+            }
+            String resourceSuperType = resource.getResourceSuperType();
+            while (resourceSuperType != null) {
+                Resource intermediateType = resolveResource(resourceSuperType);
+                if (intermediateType != null) {
+                    if (intermediateType.getPath().equals(typeResource.getPath())) {
+                        return true;
+                    }
+                    resourceSuperType = intermediateType.getResourceSuperType();
+                } else {
+                    return false;
+                }
+            }
+        }
+        return false;
+    }
 }