From 6bfee30b10fb0498f3d70f383814a669939bb1c7 Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Sun, 3 Jul 2011 23:30:30 -0600 Subject: [PATCH] Allowing for module loading from jar URI. Thanks @groldan for the fix. --- .../provider/UrlModuleSourceProvider.java | 2 +- .../tests/commonjs/module/RequireJarTest.java | 113 ++++++++++++++++++ .../tests/commonjs/module/modules.jar | Bin 0 -> 30850 bytes 3 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 testsrc/org/mozilla/javascript/tests/commonjs/module/RequireJarTest.java create mode 100644 testsrc/org/mozilla/javascript/tests/commonjs/module/modules.jar diff --git a/src/org/mozilla/javascript/commonjs/module/provider/UrlModuleSourceProvider.java b/src/org/mozilla/javascript/commonjs/module/provider/UrlModuleSourceProvider.java index 2df6eeb347..b1b6ff2f17 100644 --- a/src/org/mozilla/javascript/commonjs/module/provider/UrlModuleSourceProvider.java +++ b/src/org/mozilla/javascript/commonjs/module/provider/UrlModuleSourceProvider.java @@ -130,7 +130,7 @@ protected ModuleSource loadFromUri(URI uri, URI base, Object validator) protected ModuleSource loadFromActualUri(URI uri, URI base, Object validator) throws IOException { - final URL url = uri.toURL(); + final URL url = new URL(base.toURL(), uri.toString()); final long request_time = System.currentTimeMillis(); final URLConnection urlConnection = openUrlConnection(url); final URLValidator applicableValidator; diff --git a/testsrc/org/mozilla/javascript/tests/commonjs/module/RequireJarTest.java b/testsrc/org/mozilla/javascript/tests/commonjs/module/RequireJarTest.java new file mode 100644 index 0000000000..c4d45efaaa --- /dev/null +++ b/testsrc/org/mozilla/javascript/tests/commonjs/module/RequireJarTest.java @@ -0,0 +1,113 @@ +package org.mozilla.javascript.tests.commonjs.module; + +import java.io.InputStreamReader; +import java.io.Reader; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Collections; + +import org.mozilla.javascript.Context; +import org.mozilla.javascript.Scriptable; +import org.mozilla.javascript.ScriptableObject; +import org.mozilla.javascript.commonjs.module.Require; +import org.mozilla.javascript.commonjs.module.provider.StrongCachingModuleScriptProvider; +import org.mozilla.javascript.commonjs.module.provider.UrlModuleSourceProvider; + +/** + * @author Attila Szegedi + * @version $Id: RequireTest.java,v 1.1 2011/04/07 22:24:37 hannes%helma.at Exp $ + */ +public class RequireJarTest extends RequireTest +{ + public void testSandboxed() throws Exception + { + final Context cx = createContext(); + final Require require = getSandboxedRequire(cx); + require.requireMain(cx, "testSandboxed"); + // Also, test idempotent double-require of same main: + require.requireMain(cx, "testSandboxed"); + // Also, test failed require of different main: + try { + require.requireMain(cx, "blah"); + fail(); + } + catch(IllegalStateException e) { + // Expected, success + } + } + + private Context createContext() + { + final Context cx = Context.enter(); + cx.setOptimizationLevel(-1); + return cx; + } + + public void testNonSandboxed() throws Exception + { + final Context cx = createContext(); + final Scriptable scope = cx.initStandardObjects(); + final Require require = getSandboxedRequire(cx, scope, false); + final String jsFile = getClass().getResource("testNonSandboxed.js").toExternalForm(); + ScriptableObject.putProperty(scope, "moduleUri", jsFile); + require.requireMain(cx, "testNonSandboxed"); + } + + public void testVariousUsageErrors() throws Exception { + testWithSandboxedRequire("testNoArgsRequire"); + } + + public void testRelativeId() throws Exception { + final Context cx = createContext(); + final Scriptable scope = cx.initStandardObjects(); + final Require require = getSandboxedRequire(cx, scope, false); + require.install(scope); + cx.evaluateReader(scope, getReader("testRelativeId.js"), + "testRelativeId.js", 1, null); + } + + public void testSetMainForAlreadyLoadedModule() throws Exception { + final Context cx = createContext(); + final Scriptable scope = cx.initStandardObjects(); + final Require require = getSandboxedRequire(cx, scope, false); + require.install(scope); + cx.evaluateReader(scope, getReader("testSetMainForAlreadyLoadedModule.js"), + "testSetMainForAlreadyLoadedModule.js", 1, null); + try { + require.requireMain(cx, "assert"); + fail(); + } + catch(IllegalStateException e) { + assertEquals(e.getMessage(), "Attempt to set main module after it was loaded"); + } + } + + private Reader getReader(String name) { + return new InputStreamReader(getClass().getResourceAsStream(name)); + } + + private void testWithSandboxedRequire(String moduleId) throws Exception { + final Context cx = createContext(); + getSandboxedRequire(cx).requireMain(cx, moduleId); + } + + private Require getSandboxedRequire(final Context cx) + throws URISyntaxException { + return getSandboxedRequire(cx, cx.initStandardObjects(), true); + } + + private Require getSandboxedRequire(Context cx, Scriptable scope, boolean sandboxed) + throws URISyntaxException + { + return new Require(cx, cx.initStandardObjects(), + new StrongCachingModuleScriptProvider( + new UrlModuleSourceProvider(Collections.singleton( + getDirectory()), null)), null, null, true); + } + + private URI getDirectory() throws URISyntaxException { + final String jarFileLoc = getClass().getResource("modules.jar").toURI().toString(); + String jarParent = "jar:" + jarFileLoc + "!/"; + return new URI(jarParent); + } +} diff --git a/testsrc/org/mozilla/javascript/tests/commonjs/module/modules.jar b/testsrc/org/mozilla/javascript/tests/commonjs/module/modules.jar new file mode 100644 index 0000000000000000000000000000000000000000..0dab4857e3cf2b8d7debca5785d67e015ee899e9 GIT binary patch literal 30850 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 literal 0 HcmV?d00001