8040078: Avoid repeated reading of source for cached loads
Reviewed-by: jlaskey, lagergren
This commit is contained in:
parent
8fb1f303f7
commit
60a0f257df
@ -27,16 +27,14 @@ package jdk.nashorn.api.scripting;
|
||||
|
||||
import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError;
|
||||
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
|
||||
import static jdk.nashorn.internal.runtime.Source.sourceFor;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
import java.security.Permissions;
|
||||
@ -124,21 +122,21 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
|
||||
}
|
||||
}
|
||||
|
||||
// load engine.js and return content as a char[]
|
||||
// load engine.js
|
||||
@SuppressWarnings("resource")
|
||||
private static char[] loadEngineJSSource() {
|
||||
private static Source loadEngineJSSource() {
|
||||
final String script = "resources/engine.js";
|
||||
try {
|
||||
final InputStream is = AccessController.doPrivileged(
|
||||
new PrivilegedExceptionAction<InputStream>() {
|
||||
return AccessController.doPrivileged(
|
||||
new PrivilegedExceptionAction<Source>() {
|
||||
@Override
|
||||
public InputStream run() throws Exception {
|
||||
public Source run() throws IOException {
|
||||
final URL url = NashornScriptEngine.class.getResource(script);
|
||||
return url.openStream();
|
||||
return sourceFor(NashornException.ENGINE_SCRIPT_SOURCE_NAME, url);
|
||||
}
|
||||
});
|
||||
return Source.readFully(new InputStreamReader(is));
|
||||
} catch (final PrivilegedActionException | IOException e) {
|
||||
}
|
||||
);
|
||||
} catch (final PrivilegedActionException e) {
|
||||
if (Context.DEBUG) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@ -147,7 +145,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
|
||||
}
|
||||
|
||||
// Source object for engine.js
|
||||
private static final Source ENGINE_SCRIPT_SRC = new Source(NashornException.ENGINE_SCRIPT_SOURCE_NAME, loadEngineJSSource());
|
||||
private static final Source ENGINE_SCRIPT_SRC = loadEngineJSSource();
|
||||
|
||||
NashornScriptEngine(final NashornScriptEngineFactory factory, final ClassLoader appLoader) {
|
||||
this(factory, DEFAULT_OPTIONS, appLoader);
|
||||
@ -282,19 +280,14 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
|
||||
|
||||
private static Source makeSource(final Reader reader, final ScriptContext ctxt) throws ScriptException {
|
||||
try {
|
||||
if (reader instanceof URLReader) {
|
||||
final URL url = ((URLReader)reader).getURL();
|
||||
final Charset cs = ((URLReader)reader).getCharset();
|
||||
return new Source(url.toString(), url, cs);
|
||||
}
|
||||
return new Source(getScriptName(ctxt), Source.readFully(reader));
|
||||
} catch (final IOException e) {
|
||||
return sourceFor(getScriptName(ctxt), reader);
|
||||
} catch (IOException e) {
|
||||
throw new ScriptException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static Source makeSource(final String src, final ScriptContext ctxt) {
|
||||
return new Source(getScriptName(ctxt), src);
|
||||
return sourceFor(getScriptName(ctxt), src);
|
||||
}
|
||||
|
||||
private static String getScriptName(final ScriptContext ctxt) {
|
||||
|
@ -25,6 +25,8 @@
|
||||
|
||||
package jdk.nashorn.internal.ir.debug;
|
||||
|
||||
import static jdk.nashorn.internal.runtime.Source.sourceFor;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
@ -88,7 +90,7 @@ public final class JSONWriter extends NodeVisitor<LexicalContext> {
|
||||
* @return JSON string representation of AST of the supplied code
|
||||
*/
|
||||
public static String parse(final ScriptEnvironment env, final String code, final String name, final boolean includeLoc) {
|
||||
final Parser parser = new Parser(env, new Source(name, code), new Context.ThrowErrorManager(), env._strict);
|
||||
final Parser parser = new Parser(env, sourceFor(name, code), new Context.ThrowErrorManager(), env._strict);
|
||||
final JSONWriter jsonWriter = new JSONWriter(includeLoc);
|
||||
try {
|
||||
final FunctionNode functionNode = parser.parse(CompilerConstants.RUN_SCRIPT.symbolName());
|
||||
|
@ -27,6 +27,7 @@ package jdk.nashorn.internal.objects;
|
||||
|
||||
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
|
||||
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
|
||||
import static jdk.nashorn.internal.runtime.Source.sourceFor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -257,7 +258,7 @@ public final class NativeFunction {
|
||||
}
|
||||
|
||||
private static void checkFunctionParameters(final String params) {
|
||||
final Source src = new Source("<function>", params);
|
||||
final Source src = sourceFor("<function>", params);
|
||||
final Parser parser = new Parser(Global.getEnv(), src, new Context.ThrowErrorManager());
|
||||
try {
|
||||
parser.parseFormalParameterList();
|
||||
@ -267,7 +268,7 @@ public final class NativeFunction {
|
||||
}
|
||||
|
||||
private static void checkFunctionBody(final String funcBody) {
|
||||
final Source src = new Source("<function>", funcBody);
|
||||
final Source src = sourceFor("<function>", funcBody);
|
||||
final Parser parser = new Parser(Global.getEnv(), src, new Context.ThrowErrorManager());
|
||||
try {
|
||||
parser.parseFunctionBody();
|
||||
|
@ -32,6 +32,7 @@ import static jdk.nashorn.internal.codegen.CompilerConstants.STRICT_MODE;
|
||||
import static jdk.nashorn.internal.lookup.Lookup.MH;
|
||||
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
|
||||
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
|
||||
import static jdk.nashorn.internal.runtime.Source.sourceFor;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@ -501,7 +502,7 @@ public final class Context {
|
||||
*/
|
||||
public Object eval(final ScriptObject initialScope, final String string, final Object callThis, final Object location, final boolean strict) {
|
||||
final String file = (location == UNDEFINED || location == null) ? "<eval>" : location.toString();
|
||||
final Source source = new Source(file, string);
|
||||
final Source source = sourceFor(file, string);
|
||||
final boolean directEval = location != UNDEFINED; // is this direct 'eval' call or indirectly invoked eval?
|
||||
final Global global = Context.getGlobal();
|
||||
|
||||
@ -568,7 +569,7 @@ public final class Context {
|
||||
public Source run() {
|
||||
try {
|
||||
final URL resURL = Context.class.getResource(resource);
|
||||
return (resURL != null)? new Source(srcStr, resURL) : null;
|
||||
return (resURL != null)? sourceFor(srcStr, resURL) : null;
|
||||
} catch (final IOException exp) {
|
||||
return null;
|
||||
}
|
||||
@ -600,7 +601,7 @@ public final class Context {
|
||||
final String srcStr = (String)src;
|
||||
if (srcStr.startsWith(LOAD_CLASSPATH)) {
|
||||
URL url = getResourceURL(srcStr.substring(LOAD_CLASSPATH.length()));
|
||||
source = (url != null)? new Source(url.toString(), url) : null;
|
||||
source = (url != null)? sourceFor(url.toString(), url) : null;
|
||||
} else {
|
||||
final File file = new File(srcStr);
|
||||
if (srcStr.indexOf(':') != -1) {
|
||||
@ -613,31 +614,31 @@ public final class Context {
|
||||
} catch (final MalformedURLException e) {
|
||||
url = file.toURI().toURL();
|
||||
}
|
||||
source = new Source(url.toString(), url);
|
||||
source = sourceFor(url.toString(), url);
|
||||
}
|
||||
} else if (file.isFile()) {
|
||||
source = new Source(srcStr, file);
|
||||
source = sourceFor(srcStr, file);
|
||||
}
|
||||
}
|
||||
} else if (src instanceof File && ((File)src).isFile()) {
|
||||
final File file = (File)src;
|
||||
source = new Source(file.getName(), file);
|
||||
source = sourceFor(file.getName(), file);
|
||||
} else if (src instanceof URL) {
|
||||
final URL url = (URL)src;
|
||||
source = new Source(url.toString(), url);
|
||||
source = sourceFor(url.toString(), url);
|
||||
} else if (src instanceof ScriptObject) {
|
||||
final ScriptObject sobj = (ScriptObject)src;
|
||||
if (sobj.has("script") && sobj.has("name")) {
|
||||
final String script = JSType.toString(sobj.get("script"));
|
||||
final String name = JSType.toString(sobj.get("name"));
|
||||
source = new Source(name, script);
|
||||
source = sourceFor(name, script);
|
||||
}
|
||||
} else if (src instanceof Map) {
|
||||
final Map<?,?> map = (Map<?,?>)src;
|
||||
if (map.containsKey("script") && map.containsKey("name")) {
|
||||
final String script = JSType.toString(map.get("script"));
|
||||
final String name = JSType.toString(map.get("name"));
|
||||
source = new Source(name, script);
|
||||
source = sourceFor(name, script);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,8 @@ import jdk.nashorn.internal.parser.TokenType;
|
||||
import jdk.nashorn.internal.runtime.arrays.ArrayIndex;
|
||||
import jdk.nashorn.internal.runtime.linker.Bootstrap;
|
||||
|
||||
import static jdk.nashorn.internal.runtime.Source.sourceFor;
|
||||
|
||||
/**
|
||||
* Utilities used by "JSON" object implementation.
|
||||
*/
|
||||
@ -77,9 +79,7 @@ public final class JSONFunctions {
|
||||
*/
|
||||
public static Object parse(final Object text, final Object reviver) {
|
||||
final String str = JSType.toString(text);
|
||||
final JSONParser parser = new JSONParser(
|
||||
new Source("<json>", str),
|
||||
new Context.ThrowErrorManager());
|
||||
final JSONParser parser = new JSONParser(sourceFor("<json>", str), new Context.ThrowErrorManager());
|
||||
|
||||
Node node;
|
||||
|
||||
|
@ -27,13 +27,16 @@ package jdk.nashorn.internal.runtime;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOError;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
@ -43,13 +46,19 @@ import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.util.WeakHashMap;
|
||||
import jdk.nashorn.api.scripting.URLReader;
|
||||
import jdk.nashorn.internal.parser.Token;
|
||||
|
||||
/**
|
||||
* Source objects track the origin of JavaScript entities.
|
||||
*
|
||||
*/
|
||||
public final class Source {
|
||||
|
||||
private static final DebugLogger DEBUG = new DebugLogger("source");
|
||||
private static final int BUF_SIZE = 8 * 1024;
|
||||
private static final Cache CACHE = new Cache();
|
||||
|
||||
/**
|
||||
* Descriptive name of the source as supplied by the user. Used for error
|
||||
* reporting to the user. For example, SyntaxError will use this to print message.
|
||||
@ -64,11 +73,8 @@ public final class Source {
|
||||
*/
|
||||
private final String base;
|
||||
|
||||
/** Cached source content. */
|
||||
private final char[] content;
|
||||
|
||||
/** Length of source content. */
|
||||
private final int length;
|
||||
/** Source content */
|
||||
private final Data data;
|
||||
|
||||
/** Cached hash code */
|
||||
private int hash;
|
||||
@ -76,40 +82,297 @@ public final class Source {
|
||||
/** Message digest */
|
||||
private byte[] digest;
|
||||
|
||||
/** Source URL if available */
|
||||
private final URL url;
|
||||
// Do *not* make this public, ever! Trusts the URL and content.
|
||||
private Source(final String name, final String base, final Data data) {
|
||||
this.name = name;
|
||||
this.base = base;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
private static final int BUFSIZE = 8 * 1024;
|
||||
private static synchronized Source sourceFor(final String name, final String base, final URLData data) throws IOException {
|
||||
try {
|
||||
final Source newSource = new Source(name, base, data);
|
||||
final Source existingSource = CACHE.get(newSource);
|
||||
if (existingSource != null) {
|
||||
// Force any access errors
|
||||
data.checkPermissionAndClose();
|
||||
return existingSource;
|
||||
} else {
|
||||
// All sources in cache must be fully loaded
|
||||
data.load();
|
||||
CACHE.put(newSource, newSource);
|
||||
return newSource;
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
final Throwable cause = e.getCause();
|
||||
if (cause instanceof IOException) {
|
||||
throw (IOException) cause;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
// Do *not* make this public ever! Trusts the URL and content. So has to be called
|
||||
// from other public constructors. Note that this can not be some init method as
|
||||
// we initialize final fields from here.
|
||||
private Source(final String name, final String base, final char[] content, final URL url) {
|
||||
this.name = name;
|
||||
this.base = base;
|
||||
this.content = content;
|
||||
this.length = content.length;
|
||||
this.url = url;
|
||||
private static class Cache extends WeakHashMap<Source, WeakReference<Source>> {
|
||||
public Source get(final Source key) {
|
||||
final WeakReference<Source> ref = super.get(key);
|
||||
return ref == null ? null : ref.get();
|
||||
}
|
||||
|
||||
public void put(final Source key, final Source value) {
|
||||
assert !(value.data instanceof RawData);
|
||||
put(key, new WeakReference<>(value));
|
||||
}
|
||||
}
|
||||
|
||||
// Wrapper to manage lazy loading
|
||||
private static interface Data {
|
||||
|
||||
URL url();
|
||||
|
||||
int length();
|
||||
|
||||
long lastModified();
|
||||
|
||||
char[] array();
|
||||
}
|
||||
|
||||
private static class RawData implements Data {
|
||||
private final char[] array;
|
||||
private int hash;
|
||||
|
||||
private RawData(final char[] array) {
|
||||
this.array = Objects.requireNonNull(array);
|
||||
}
|
||||
|
||||
private RawData(final String source) {
|
||||
this.array = Objects.requireNonNull(source).toCharArray();
|
||||
}
|
||||
|
||||
private RawData(final Reader reader) throws IOException {
|
||||
this(readFully(reader));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int h = hash;
|
||||
if (h == 0) {
|
||||
h = hash = Arrays.hashCode(array);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof RawData) {
|
||||
return Arrays.equals(array, ((RawData)obj).array);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new String(array());
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL url() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int length() {
|
||||
return array.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long lastModified() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char[] array() {
|
||||
return array;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private static class URLData implements Data {
|
||||
private final URL url;
|
||||
protected final Charset cs;
|
||||
private int hash;
|
||||
protected char[] array;
|
||||
protected int length;
|
||||
protected long lastModified;
|
||||
|
||||
private URLData(final URL url, final Charset cs) {
|
||||
this.url = Objects.requireNonNull(url);
|
||||
this.cs = cs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int h = hash;
|
||||
if (h == 0) {
|
||||
h = hash = url.hashCode();
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof URLData)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
URLData otherData = (URLData) other;
|
||||
|
||||
if (url.equals(otherData.url)) {
|
||||
// Make sure both have meta data loaded
|
||||
try {
|
||||
if (isDeferred()) {
|
||||
// Data in cache is always loaded, and we only compare to cached data.
|
||||
assert !otherData.isDeferred();
|
||||
loadMeta();
|
||||
} else if (otherData.isDeferred()) {
|
||||
otherData.loadMeta();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
// Compare meta data
|
||||
return this.length == otherData.length && this.lastModified == otherData.lastModified;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new String(array());
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL url() {
|
||||
return url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int length() {
|
||||
return length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long lastModified() {
|
||||
return lastModified;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char[] array() {
|
||||
assert !isDeferred();
|
||||
return array;
|
||||
}
|
||||
|
||||
boolean isDeferred() {
|
||||
return array == null;
|
||||
}
|
||||
|
||||
protected void checkPermissionAndClose() throws IOException {
|
||||
try (InputStream in = url.openStream()) {}
|
||||
debug("permission checked for ", url);
|
||||
}
|
||||
|
||||
protected void load() throws IOException {
|
||||
if (array == null) {
|
||||
final URLConnection c = url.openConnection();
|
||||
try (InputStream in = c.getInputStream()) {
|
||||
array = cs == null ? readFully(in) : readFully(in, cs);
|
||||
length = array.length;
|
||||
lastModified = c.getLastModified();
|
||||
debug("loaded content for ", url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void loadMeta() throws IOException {
|
||||
if (length == 0 && lastModified == 0) {
|
||||
final URLConnection c = url.openConnection();
|
||||
length = c.getContentLength();
|
||||
lastModified = c.getLastModified();
|
||||
debug("loaded metadata for ", url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class FileData extends URLData {
|
||||
private final File file;
|
||||
|
||||
private FileData(final File file, final Charset cs) {
|
||||
super(getURLFromFile(file), cs);
|
||||
this.file = file;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void checkPermissionAndClose() throws IOException {
|
||||
if (!file.canRead()) {
|
||||
throw new FileNotFoundException(file + " (Permission Denied)");
|
||||
}
|
||||
debug("permission checked for ", file);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadMeta() {
|
||||
if (length == 0 && lastModified == 0) {
|
||||
length = (int) file.length();
|
||||
lastModified = file.lastModified();
|
||||
debug("loaded metadata for ", file);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void load() throws IOException {
|
||||
if (array == null) {
|
||||
array = cs == null ? readFully(file) : readFully(file, cs);
|
||||
length = array.length;
|
||||
lastModified = file.lastModified();
|
||||
debug("loaded content for ", file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void debug(final Object... msg) {
|
||||
DEBUG.info(msg);
|
||||
}
|
||||
|
||||
private char[] data() {
|
||||
return data.array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* Returns an instance
|
||||
*
|
||||
* @param name source name
|
||||
* @param content contents as char array
|
||||
*/
|
||||
public Source(final String name, final char[] content) {
|
||||
this(name, baseName(name, null), content, null);
|
||||
public static Source sourceFor(final String name, final char[] content) {
|
||||
return new Source(name, baseName(name), new RawData(content));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* Returns an instance
|
||||
*
|
||||
* @param name source name
|
||||
* @param content contents as string
|
||||
*/
|
||||
public Source(final String name, final String content) {
|
||||
this(name, content.toCharArray());
|
||||
public static Source sourceFor(final String name, final String content) {
|
||||
return new Source(name, baseName(name), new RawData(content));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -120,8 +383,8 @@ public final class Source {
|
||||
*
|
||||
* @throws IOException if source cannot be loaded
|
||||
*/
|
||||
public Source(final String name, final URL url) throws IOException {
|
||||
this(name, baseURL(url, null), readFully(url), url);
|
||||
public static Source sourceFor(final String name, final URL url) throws IOException {
|
||||
return sourceFor(name, url, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -133,8 +396,8 @@ public final class Source {
|
||||
*
|
||||
* @throws IOException if source cannot be loaded
|
||||
*/
|
||||
public Source(final String name, final URL url, final Charset cs) throws IOException {
|
||||
this(name, baseURL(url, null), readFully(url, cs), url);
|
||||
public static Source sourceFor(final String name, final URL url, final Charset cs) throws IOException {
|
||||
return sourceFor(name, baseURL(url), new URLData(url, cs));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -145,8 +408,8 @@ public final class Source {
|
||||
*
|
||||
* @throws IOException if source cannot be loaded
|
||||
*/
|
||||
public Source(final String name, final File file) throws IOException {
|
||||
this(name, dirName(file, null), readFully(file), getURLFromFile(file));
|
||||
public static Source sourceFor(final String name, final File file) throws IOException {
|
||||
return sourceFor(name, file, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -158,8 +421,25 @@ public final class Source {
|
||||
*
|
||||
* @throws IOException if source cannot be loaded
|
||||
*/
|
||||
public Source(final String name, final File file, final Charset cs) throws IOException {
|
||||
this(name, dirName(file, null), readFully(file, cs), getURLFromFile(file));
|
||||
public static Source sourceFor(final String name, final File file, final Charset cs) throws IOException {
|
||||
final File absFile = file.getAbsoluteFile();
|
||||
return sourceFor(name, dirName(absFile, null), new FileData(file, cs));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an instance
|
||||
*
|
||||
* @param name source name
|
||||
* @param reader reader from which source can be loaded
|
||||
* @throws IOException if source cannot be loaded
|
||||
*/
|
||||
public static Source sourceFor(final String name, final Reader reader) throws IOException {
|
||||
// Extract URL from URLReader to defer loading and reuse cached data if available.
|
||||
if (reader instanceof URLReader) {
|
||||
final URLReader urlReader = (URLReader) reader;
|
||||
return sourceFor(name, urlReader.getURL(), urlReader.getCharset());
|
||||
}
|
||||
return new Source(name, baseName(name), new RawData(reader));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -167,21 +447,18 @@ public final class Source {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(obj instanceof Source)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final Source src = (Source)obj;
|
||||
// Only compare content as a last resort measure
|
||||
return length == src.length && Objects.equals(url, src.url) && Objects.equals(name, src.name) && Arrays.equals(content, src.content);
|
||||
final Source other = (Source) obj;
|
||||
return Objects.equals(name, other.name) && data.equals(other.data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int h = hash;
|
||||
if (h == 0) {
|
||||
h = hash = Arrays.hashCode(content) ^ Objects.hashCode(name);
|
||||
h = hash = data.hashCode() ^ Objects.hashCode(name);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
@ -191,7 +468,7 @@ public final class Source {
|
||||
* @return Source content.
|
||||
*/
|
||||
public String getString() {
|
||||
return new String(content, 0, length);
|
||||
return data.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -202,6 +479,14 @@ public final class Source {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last modified time of this script.
|
||||
* @return Last modified time.
|
||||
*/
|
||||
public long getLastModified() {
|
||||
return data.lastModified();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the "directory" part of the file or "base" of the URL.
|
||||
* @return base of file or URL.
|
||||
@ -217,7 +502,7 @@ public final class Source {
|
||||
* @return Source content portion.
|
||||
*/
|
||||
public String getString(final int start, final int len) {
|
||||
return new String(content, start, len);
|
||||
return new String(data(), start, len);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -228,7 +513,7 @@ public final class Source {
|
||||
public String getString(final long token) {
|
||||
final int start = Token.descPosition(token);
|
||||
final int len = Token.descLength(token);
|
||||
return new String(content, start, len);
|
||||
return new String(data(), start, len);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -238,7 +523,7 @@ public final class Source {
|
||||
* @return URL source or null
|
||||
*/
|
||||
public URL getURL() {
|
||||
return url;
|
||||
return data.url();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -247,8 +532,9 @@ public final class Source {
|
||||
* @return Index of first character of line.
|
||||
*/
|
||||
private int findBOLN(final int position) {
|
||||
final char[] data = data();
|
||||
for (int i = position - 1; i > 0; i--) {
|
||||
final char ch = content[i];
|
||||
final char ch = data[i];
|
||||
|
||||
if (ch == '\n' || ch == '\r') {
|
||||
return i + 1;
|
||||
@ -264,8 +550,10 @@ public final class Source {
|
||||
* @return Index of last character of line.
|
||||
*/
|
||||
private int findEOLN(final int position) {
|
||||
for (int i = position; i < length; i++) {
|
||||
final char ch = content[i];
|
||||
final char[] data = data();
|
||||
final int length = data.length;
|
||||
for (int i = position; i < length; i++) {
|
||||
final char ch = data[i];
|
||||
|
||||
if (ch == '\n' || ch == '\r') {
|
||||
return i - 1;
|
||||
@ -285,11 +573,12 @@ public final class Source {
|
||||
* @return Line number.
|
||||
*/
|
||||
public int getLine(final int position) {
|
||||
final char[] data = data();
|
||||
// Line count starts at 1.
|
||||
int line = 1;
|
||||
|
||||
for (int i = 0; i < position; i++) {
|
||||
final char ch = content[i];
|
||||
final char ch = data[i];
|
||||
// Works for both \n and \r\n.
|
||||
if (ch == '\n') {
|
||||
line++;
|
||||
@ -320,7 +609,7 @@ public final class Source {
|
||||
// Find end of this line.
|
||||
final int last = findEOLN(position);
|
||||
|
||||
return new String(content, first, last - first + 1);
|
||||
return new String(data(), first, last - first + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -328,7 +617,7 @@ public final class Source {
|
||||
* @return content
|
||||
*/
|
||||
public char[] getContent() {
|
||||
return content.clone();
|
||||
return data().clone();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -336,19 +625,18 @@ public final class Source {
|
||||
* @return length
|
||||
*/
|
||||
public int getLength() {
|
||||
return length;
|
||||
return data.length();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read all of the source until end of file. Return it as char array
|
||||
*
|
||||
* @param reader reader opened to source stream
|
||||
* @param reader reader opened to source stream
|
||||
* @return source as content
|
||||
*
|
||||
* @throws IOException if source could not be read
|
||||
*/
|
||||
public static char[] readFully(final Reader reader) throws IOException {
|
||||
final char[] arr = new char[BUFSIZE];
|
||||
final char[] arr = new char[BUF_SIZE];
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
|
||||
try {
|
||||
@ -366,9 +654,8 @@ public final class Source {
|
||||
/**
|
||||
* Read all of the source until end of file. Return it as char array
|
||||
*
|
||||
* @param file source file
|
||||
* @param file source file
|
||||
* @return source as content
|
||||
*
|
||||
* @throws IOException if source could not be read
|
||||
*/
|
||||
public static char[] readFully(final File file) throws IOException {
|
||||
@ -381,10 +668,9 @@ public final class Source {
|
||||
/**
|
||||
* Read all of the source until end of file. Return it as char array
|
||||
*
|
||||
* @param file source file
|
||||
* @param file source file
|
||||
* @param cs Charset used to convert bytes to chars
|
||||
* @return source as content
|
||||
*
|
||||
* @throws IOException if source could not be read
|
||||
*/
|
||||
public static char[] readFully(final File file, final Charset cs) throws IOException {
|
||||
@ -393,7 +679,7 @@ public final class Source {
|
||||
}
|
||||
|
||||
final byte[] buf = Files.readAllBytes(file.toPath());
|
||||
return (cs != null)? new String(buf, cs).toCharArray() : byteToCharArray(buf);
|
||||
return (cs != null) ? new String(buf, cs).toCharArray() : byteToCharArray(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -401,7 +687,6 @@ public final class Source {
|
||||
*
|
||||
* @param url URL to read content from
|
||||
* @return source as content
|
||||
*
|
||||
* @throws IOException if source could not be read
|
||||
*/
|
||||
public static char[] readFully(final URL url) throws IOException {
|
||||
@ -414,7 +699,6 @@ public final class Source {
|
||||
* @param url URL to read content from
|
||||
* @param cs Charset used to convert bytes to chars
|
||||
* @return source as content
|
||||
*
|
||||
* @throws IOException if source could not be read
|
||||
*/
|
||||
public static char[] readFully(final URL url, final Charset cs) throws IOException {
|
||||
@ -428,7 +712,7 @@ public final class Source {
|
||||
*/
|
||||
public synchronized byte[] getDigest() {
|
||||
if (digest == null) {
|
||||
|
||||
final char[] content = data();
|
||||
final byte[] bytes = new byte[content.length * 2];
|
||||
|
||||
for (int i = 0; i < content.length; i++) {
|
||||
@ -444,8 +728,8 @@ public final class Source {
|
||||
if (base != null) {
|
||||
md.update(base.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
if (url != null) {
|
||||
md.update(url.toString().getBytes(StandardCharsets.UTF_8));
|
||||
if (getURL() != null) {
|
||||
md.update(getURL().toString().getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
digest = md.digest(bytes);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
@ -461,50 +745,46 @@ public final class Source {
|
||||
* @return base URL for url
|
||||
*/
|
||||
public static String baseURL(final URL url) {
|
||||
return baseURL(url, null);
|
||||
}
|
||||
|
||||
private static String baseURL(final URL url, final String defaultValue) {
|
||||
if (url.getProtocol().equals("file")) {
|
||||
try {
|
||||
final Path path = Paths.get(url.toURI());
|
||||
final Path parent = path.getParent();
|
||||
return (parent != null) ? (parent + File.separator) : defaultValue;
|
||||
return (parent != null) ? (parent + File.separator) : null;
|
||||
} catch (final SecurityException | URISyntaxException | IOError e) {
|
||||
return defaultValue;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: is there a better way to find 'base' URL of a given URL?
|
||||
String path = url.getPath();
|
||||
if (path.isEmpty()) {
|
||||
return defaultValue;
|
||||
return null;
|
||||
}
|
||||
path = path.substring(0, path.lastIndexOf('/') + 1);
|
||||
final int port = url.getPort();
|
||||
try {
|
||||
return new URL(url.getProtocol(), url.getHost(), port, path).toString();
|
||||
} catch (final MalformedURLException e) {
|
||||
return defaultValue;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static String dirName(final File file, final String defaultValue) {
|
||||
private static String dirName(final File file, final String DEFAULT_BASE_NAME) {
|
||||
final String res = file.getParent();
|
||||
return (res != null)? (res + File.separator) : defaultValue;
|
||||
return (res != null) ? (res + File.separator) : DEFAULT_BASE_NAME;
|
||||
}
|
||||
|
||||
// fake directory like name
|
||||
private static String baseName(final String name, final String defaultValue) {
|
||||
private static String baseName(final String name) {
|
||||
int idx = name.lastIndexOf('/');
|
||||
if (idx == -1) {
|
||||
idx = name.lastIndexOf('\\');
|
||||
}
|
||||
return (idx != -1)? name.substring(0, idx + 1) : defaultValue;
|
||||
return (idx != -1) ? name.substring(0, idx + 1) : null;
|
||||
}
|
||||
|
||||
private static char[] readFully(final InputStream is, final Charset cs) throws IOException {
|
||||
return (cs != null)? new String(readBytes(is), cs).toCharArray() : readFully(is);
|
||||
return (cs != null) ? new String(readBytes(is), cs).toCharArray() : readFully(is);
|
||||
}
|
||||
|
||||
private static char[] readFully(final InputStream is) throws IOException {
|
||||
@ -515,19 +795,19 @@ public final class Source {
|
||||
Charset cs = StandardCharsets.UTF_8;
|
||||
int start = 0;
|
||||
// BOM detection.
|
||||
if (bytes.length > 1 && bytes[0] == (byte)0xFE && bytes[1] == (byte)0xFF) {
|
||||
if (bytes.length > 1 && bytes[0] == (byte) 0xFE && bytes[1] == (byte) 0xFF) {
|
||||
start = 2;
|
||||
cs = StandardCharsets.UTF_16BE;
|
||||
} else if (bytes.length > 1 && bytes[0] == (byte)0xFF && bytes[1] == (byte)0xFE) {
|
||||
} else if (bytes.length > 1 && bytes[0] == (byte) 0xFF && bytes[1] == (byte) 0xFE) {
|
||||
start = 2;
|
||||
cs = StandardCharsets.UTF_16LE;
|
||||
} else if (bytes.length > 2 && bytes[0] == (byte)0xEF && bytes[1] == (byte)0xBB && bytes[2] == (byte)0xBF) {
|
||||
} else if (bytes.length > 2 && bytes[0] == (byte) 0xEF && bytes[1] == (byte) 0xBB && bytes[2] == (byte) 0xBF) {
|
||||
start = 3;
|
||||
cs = StandardCharsets.UTF_8;
|
||||
} else if (bytes.length > 3 && bytes[0] == (byte)0xFF && bytes[1] == (byte)0xFE && bytes[2] == 0 && bytes[3] == 0) {
|
||||
} else if (bytes.length > 3 && bytes[0] == (byte) 0xFF && bytes[1] == (byte) 0xFE && bytes[2] == 0 && bytes[3] == 0) {
|
||||
start = 4;
|
||||
cs = Charset.forName("UTF-32LE");
|
||||
} else if (bytes.length > 3 && bytes[0] == 0 && bytes[1] == 0 && bytes[2] == (byte)0xFE && bytes[3] == (byte)0xFF) {
|
||||
} else if (bytes.length > 3 && bytes[0] == 0 && bytes[1] == 0 && bytes[2] == (byte) 0xFE && bytes[3] == (byte) 0xFF) {
|
||||
start = 4;
|
||||
cs = Charset.forName("UTF-32BE");
|
||||
}
|
||||
@ -536,7 +816,7 @@ public final class Source {
|
||||
}
|
||||
|
||||
static byte[] readBytes(final InputStream is) throws IOException {
|
||||
final byte[] arr = new byte[BUFSIZE];
|
||||
final byte[] arr = new byte[BUF_SIZE];
|
||||
try {
|
||||
try (ByteArrayOutputStream buf = new ByteArrayOutputStream()) {
|
||||
int numBytes;
|
||||
|
@ -25,6 +25,8 @@
|
||||
|
||||
package jdk.nashorn.tools;
|
||||
|
||||
import static jdk.nashorn.internal.runtime.Source.sourceFor;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
@ -50,7 +52,6 @@ import jdk.nashorn.internal.runtime.JSType;
|
||||
import jdk.nashorn.internal.runtime.Property;
|
||||
import jdk.nashorn.internal.runtime.ScriptEnvironment;
|
||||
import jdk.nashorn.internal.runtime.ScriptFunction;
|
||||
import jdk.nashorn.internal.runtime.ScriptObject;
|
||||
import jdk.nashorn.internal.runtime.ScriptRuntime;
|
||||
import jdk.nashorn.internal.runtime.Source;
|
||||
import jdk.nashorn.internal.runtime.options.Options;
|
||||
@ -244,7 +245,7 @@ public class Shell {
|
||||
|
||||
// For each file on the command line.
|
||||
for (final String fileName : files) {
|
||||
final FunctionNode functionNode = new Parser(env, new Source(fileName, new File(fileName)), errors).parse();
|
||||
final FunctionNode functionNode = new Parser(env, sourceFor(fileName, new File(fileName)), errors).parse();
|
||||
|
||||
if (errors.getNumberOfErrors() != 0) {
|
||||
return COMPILATION_ERROR;
|
||||
@ -302,7 +303,7 @@ public class Shell {
|
||||
}
|
||||
|
||||
final File file = new File(fileName);
|
||||
final ScriptFunction script = context.compileScript(new Source(fileName, file.toURI().toURL()), global);
|
||||
final ScriptFunction script = context.compileScript(sourceFor(fileName, file), global);
|
||||
if (script == null || errors.getNumberOfErrors() != 0) {
|
||||
return COMPILATION_ERROR;
|
||||
}
|
||||
@ -405,7 +406,7 @@ public class Shell {
|
||||
|
||||
// initialize with "shell.js" script
|
||||
try {
|
||||
final Source source = new Source("<shell.js>", Shell.class.getResource("resources/shell.js"));
|
||||
final Source source = sourceFor("<shell.js>", Shell.class.getResource("resources/shell.js"));
|
||||
context.eval(global, source.getString(), global, "<shell.js>", false);
|
||||
} catch (final Exception e) {
|
||||
err.println(e);
|
||||
|
@ -113,7 +113,7 @@ function findFunction(node) {
|
||||
var getContextMethod = Context.class.getMethod("getContext")
|
||||
var getEnvMethod = Context.class.getMethod("getEnv")
|
||||
|
||||
var SourceConstructor = Source.class.getConstructor(java.lang.String.class, java.lang.String.class)
|
||||
var sourceForMethod = Source.class.getMethod("sourceFor", java.lang.String.class, java.lang.String.class)
|
||||
var ParserConstructor = Parser.class.getConstructor(ScriptEnvironment.class, Source.class, ErrorManager.class)
|
||||
var CompilerConstructor = Compiler.class.getConstructor(ScriptEnvironment.class)
|
||||
|
||||
@ -121,7 +121,7 @@ var CompilerConstructor = Compiler.class.getConstructor(ScriptEnvironment.class)
|
||||
// source code, returns a jdk.nashorn.internal.ir.FunctionNode object
|
||||
// representing it.
|
||||
function compile(source) {
|
||||
var source = SourceConstructor.newInstance("<no name>", source);
|
||||
var source = sourceForMethod.invoke(null, "<no name>", source);
|
||||
|
||||
var env = getEnvMethod.invoke(getContextMethod.invoke(null))
|
||||
|
||||
|
@ -25,6 +25,9 @@
|
||||
|
||||
package jdk.nashorn.internal.codegen;
|
||||
|
||||
import static jdk.nashorn.internal.runtime.Source.sourceFor;
|
||||
import static jdk.nashorn.internal.runtime.Source.readFully;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
@ -32,7 +35,6 @@ import jdk.nashorn.internal.objects.Global;
|
||||
import jdk.nashorn.internal.runtime.Context;
|
||||
import jdk.nashorn.internal.runtime.ErrorManager;
|
||||
import jdk.nashorn.internal.runtime.ScriptFunction;
|
||||
import jdk.nashorn.internal.runtime.ScriptObject;
|
||||
import jdk.nashorn.internal.runtime.Source;
|
||||
import jdk.nashorn.internal.runtime.options.Options;
|
||||
import org.testng.Assert;
|
||||
@ -151,7 +153,7 @@ public class CompilerTest {
|
||||
final boolean globalChanged = (oldGlobal != global);
|
||||
|
||||
try {
|
||||
final char[] buffer = Source.readFully(file);
|
||||
final char[] buffer = readFully(file);
|
||||
boolean excluded = false;
|
||||
|
||||
if (filter != null) {
|
||||
@ -170,7 +172,7 @@ public class CompilerTest {
|
||||
if (globalChanged) {
|
||||
Context.setGlobal(global);
|
||||
}
|
||||
final Source source = new Source(file.getAbsolutePath(), buffer);
|
||||
final Source source = sourceFor(file.getAbsolutePath(), buffer);
|
||||
final ScriptFunction script = context.compileScript(source, global);
|
||||
if (script == null || context.getErrorManager().getNumberOfErrors() > 0) {
|
||||
log("Compile failed: " + file.getAbsolutePath());
|
||||
|
@ -25,6 +25,9 @@
|
||||
|
||||
package jdk.nashorn.internal.parser;
|
||||
|
||||
import static jdk.nashorn.internal.runtime.Source.sourceFor;
|
||||
import static jdk.nashorn.internal.runtime.Source.readFully;
|
||||
|
||||
import java.io.File;
|
||||
import jdk.nashorn.internal.runtime.Context;
|
||||
import jdk.nashorn.internal.runtime.ErrorManager;
|
||||
@ -131,7 +134,7 @@ public class ParserTest {
|
||||
}
|
||||
|
||||
try {
|
||||
final char[] buffer = Source.readFully(file);
|
||||
final char[] buffer = readFully(file);
|
||||
boolean excluded = false;
|
||||
if (filter != null) {
|
||||
final String content = new String(buffer);
|
||||
@ -153,7 +156,7 @@ public class ParserTest {
|
||||
}
|
||||
};
|
||||
errors.setLimit(0);
|
||||
final Source source = new Source(file.getAbsolutePath(), buffer);
|
||||
final Source source = sourceFor(file.getAbsolutePath(), buffer);
|
||||
new Parser(context.getEnv(), source, errors).parse();
|
||||
if (errors.getNumberOfErrors() > 0) {
|
||||
log("Parse failed: " + file.getAbsolutePath());
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
package jdk.nashorn.internal.runtime;
|
||||
|
||||
import static jdk.nashorn.internal.runtime.Source.sourceFor;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
@ -107,7 +108,7 @@ public class ContextTest {
|
||||
}
|
||||
|
||||
private Object eval(final Context cx, final String name, final String code) {
|
||||
final Source source = new Source(name, code);
|
||||
final Source source = sourceFor(name, code);
|
||||
final ScriptObject global = Context.getGlobal();
|
||||
final ScriptFunction func = cx.compileScript(source, global);
|
||||
return func != null ? ScriptRuntime.apply(func, global) : null;
|
||||
|
128
nashorn/test/src/jdk/nashorn/internal/runtime/SourceTest.java
Normal file
128
nashorn/test/src/jdk/nashorn/internal/runtime/SourceTest.java
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package jdk.nashorn.internal.runtime;
|
||||
|
||||
import jdk.nashorn.api.scripting.URLReader;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static jdk.nashorn.internal.runtime.Source.sourceFor;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
import static org.testng.Assert.fail;
|
||||
|
||||
/**
|
||||
* Tests different Source representations.
|
||||
*/
|
||||
public class SourceTest {
|
||||
|
||||
final private static String SOURCE_NAME = "source.js";
|
||||
final private static String SOURCE_STRING = "var x = 1;";
|
||||
final private static char[] SOURCE_CHARS = SOURCE_STRING.toCharArray();
|
||||
final private static String RESOURCE_PATH = "resources/load_test.js";
|
||||
final private static File SOURCE_FILE = new File("build/test/classes/jdk/nashorn/internal/runtime/" + RESOURCE_PATH);
|
||||
final private static URL SOURCE_URL = SourceTest.class.getResource(RESOURCE_PATH);
|
||||
|
||||
|
||||
@Test
|
||||
public void testStringSource() {
|
||||
testSources(sourceFor(SOURCE_NAME, SOURCE_STRING), sourceFor(SOURCE_NAME, SOURCE_STRING));
|
||||
testSources(sourceFor(SOURCE_NAME, SOURCE_STRING), sourceFor(SOURCE_NAME, SOURCE_CHARS));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCharArraySource() {
|
||||
testSources(sourceFor(SOURCE_NAME, SOURCE_CHARS), sourceFor(SOURCE_NAME, SOURCE_CHARS));
|
||||
testSources(sourceFor(SOURCE_NAME, SOURCE_CHARS), sourceFor(SOURCE_NAME, SOURCE_STRING));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testURLSource() {
|
||||
try {
|
||||
testSources(sourceFor(SOURCE_NAME, SOURCE_URL), sourceFor(SOURCE_NAME, SOURCE_URL));
|
||||
testSources(sourceFor(SOURCE_NAME, SOURCE_URL), sourceFor(SOURCE_NAME, new URLReader(SOURCE_URL)));
|
||||
|
||||
} catch (final IOException e) {
|
||||
fail(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testURLReaderSource() {
|
||||
try {
|
||||
System.err.println(SourceTest.class.getResource(""));
|
||||
testSources(sourceFor(SOURCE_NAME, new URLReader(SOURCE_URL)), sourceFor(SOURCE_NAME, new URLReader(SOURCE_URL)));
|
||||
testSources(sourceFor(SOURCE_NAME, new URLReader(SOURCE_URL)), sourceFor(SOURCE_NAME, SOURCE_URL));
|
||||
} catch (final IOException e) {
|
||||
fail(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReaderSource() {
|
||||
try {
|
||||
testSources(sourceFor(SOURCE_NAME, getReader(RESOURCE_PATH)), sourceFor(SOURCE_NAME, getReader(RESOURCE_PATH)));
|
||||
} catch (final IOException e) {
|
||||
fail(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFileSource() {
|
||||
try {
|
||||
testSources(sourceFor(SOURCE_NAME, SOURCE_FILE), sourceFor(SOURCE_NAME, SOURCE_FILE));
|
||||
} catch (final IOException e) {
|
||||
fail(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private Reader getReader(final String path) {
|
||||
return new InputStreamReader(SourceTest.class.getResourceAsStream(path));
|
||||
}
|
||||
|
||||
private void testSources(final Source source1, final Source source2) {
|
||||
final char[] chars1 = source1.getContent();
|
||||
final char[] chars2 = source2.getContent();
|
||||
final String str1 = source1.getString();
|
||||
final String str2 = source2.getString();
|
||||
assertTrue(Arrays.equals(chars1, chars2));
|
||||
assertEquals(str1, str2);
|
||||
assertEquals(source1.hashCode(), source2.hashCode());
|
||||
assertTrue(source1.equals(source2));
|
||||
// Test for immutability
|
||||
Arrays.fill(source1.getContent(), (char)0);
|
||||
Arrays.fill(source2.getContent(), (char)1);
|
||||
assertTrue(Arrays.equals(source1.getContent(), str1.toCharArray()));
|
||||
assertTrue(Arrays.equals(source1.getContent(), chars1));
|
||||
assertTrue(Arrays.equals(source1.getContent(), source2.getContent()));
|
||||
}
|
||||
}
|
@ -25,6 +25,7 @@
|
||||
|
||||
package jdk.nashorn.internal.test.framework;
|
||||
|
||||
import static jdk.nashorn.internal.runtime.Source.sourceFor;
|
||||
import static jdk.nashorn.tools.Shell.COMPILATION_ERROR;
|
||||
import static jdk.nashorn.tools.Shell.RUNTIME_ERROR;
|
||||
import static jdk.nashorn.tools.Shell.SUCCESS;
|
||||
@ -39,7 +40,6 @@ import jdk.nashorn.internal.runtime.Context;
|
||||
import jdk.nashorn.internal.runtime.ErrorManager;
|
||||
import jdk.nashorn.internal.runtime.ScriptFunction;
|
||||
import jdk.nashorn.internal.runtime.ScriptRuntime;
|
||||
import jdk.nashorn.internal.runtime.Source;
|
||||
import jdk.nashorn.internal.runtime.options.Options;
|
||||
|
||||
/**
|
||||
@ -125,7 +125,7 @@ public final class SharedContextEvaluator implements ScriptEvaluator {
|
||||
continue;
|
||||
}
|
||||
final File file = new File(fileName);
|
||||
ScriptFunction script = context.compileScript(new Source(fileName, file.toURI().toURL()), global);
|
||||
ScriptFunction script = context.compileScript(sourceFor(fileName, file.toURI().toURL()), global);
|
||||
|
||||
if (script == null || errors.getNumberOfErrors() != 0) {
|
||||
return COMPILATION_ERROR;
|
||||
|
@ -46,7 +46,7 @@ public final class SourceHelper {
|
||||
}
|
||||
|
||||
public static String readFully(final URL url) throws IOException {
|
||||
return new Source(url.toString(), url).getString();
|
||||
return Source.sourceFor(url.toString(), url).getString();
|
||||
}
|
||||
|
||||
public static String readFully(final Reader reader) throws IOException {
|
||||
|
Loading…
x
Reference in New Issue
Block a user