@Override public synchronized Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { Transaction previousTransaction = Transaction.currentTransaction(); Transaction.startTransaction(); String filename = (String) args[0]; if (filename.startsWith(".")) filename = currentJslibPath + filename; filename = Pattern.compile("\\.\\./[^.]*/").matcher(filename).replaceAll("/"); filename = filename.replace("./", ""); InputStream inStream; ScriptableObject exportObject; String oldJsLibPath = currentJslibPath; try { File jslibFile = jslibFiles.get(filename); if (jslibFile == null && !filename.endsWith(".js")) { filename += ".js"; jslibFile = jslibFiles.get(filename); } if (jslibFile == null) throw ScriptRuntime.constructError("Error", "File not found " + filename); exportObject = exports.get(filename); Long lastTimeStamp = lastTimeStamps.get(filename); if (lastTimeStamp == null || lastTimeStamp < jslibFile.lastModified()) { lastTimeStamps.put(filename, jslibFile.lastModified()); inStream = new FileInputStream(jslibFile); exportObject = new NativeObject(); ScriptRuntime.setObjectProtoAndParent((ScriptableObject) exportObject, global); // setup the module scope ScriptableObject moduleScope = new NativeObject(); moduleScope.setParentScope(global); int lastSlash = filename.lastIndexOf('/'); currentJslibPath = lastSlash == -1 ? "" : filename.substring(0, lastSlash + 1); moduleScope.put("exports", moduleScope, exportObject); // memoize exports.put(filename, exportObject); // evaluate the script try { cx.evaluateString(moduleScope, IOUtils.toString(inStream, "UTF-8"), filename, 1, null); } catch (RuntimeException e) { // revert exports.remove(filename); jslibFiles.put(filename, jslibFile); throw e; } // re-retrieve it in case the library changed it exportObject = (ScriptableObject) moduleScope.get("exports", moduleScope); exports.put(filename, exportObject); if ("jsgi-app.js".equals(filename)) { // handle jackconfig.js, setting up the app if it is there global.put("app", global, exportObject.get("app", exportObject)); } // freeze it // exportObject.sealObject(); } Transaction.currentTransaction().commit(); } catch (IOException e) { throw ScriptRuntime.constructError("Error", e.getMessage()); } finally { currentJslibPath = oldJsLibPath; previousTransaction.enterTransaction(); } return exportObject; }