diff options
Diffstat (limited to 'share/server')
-rw-r--r-- | share/server/loop.js | 2 | ||||
-rw-r--r-- | share/server/render.js | 7 | ||||
-rw-r--r-- | share/server/util.js | 55 |
3 files changed, 60 insertions, 4 deletions
diff --git a/share/server/loop.js b/share/server/loop.js index 800d4440..300151e9 100644 --- a/share/server/loop.js +++ b/share/server/loop.js @@ -74,7 +74,7 @@ var DDoc = (function() { if (i+1 == funPath.length) { fun = point[funPath[i]] if (typeof fun != "function") { - fun = Couch.compileFunction(fun); + fun = Couch.compileFunction(fun, ddoc); // cache the compiled fun on the ddoc point[funPath[i]] = fun }; diff --git a/share/server/render.js b/share/server/render.js index 1e341ec7..9dcfbcd6 100644 --- a/share/server/render.js +++ b/share/server/render.js @@ -210,6 +210,11 @@ var Render = (function() { return s; }; + function isDocRequestPath(info) { + var path = info.path; + return path.length > 5; + }; + function runShow(fun, ddoc, args) { try { resetList(); @@ -239,7 +244,7 @@ var Render = (function() { throw(["error", "render_error", "undefined response from show function"]); } } catch(e) { - if(args[0] === null) { + if (args[0] === null && isDocRequestPath(args[1])) { throw(["error", "not_found", "document not found"]); } else { renderError(e, fun.toSource()); diff --git a/share/server/util.js b/share/server/util.js index c2e6600f..d017b094 100644 --- a/share/server/util.js +++ b/share/server/util.js @@ -10,15 +10,66 @@ // License for the specific language governing permissions and limitations under // the License. +var resolveModule = function(names, parent, current) { + if (names.length == 0) { + if (typeof current != "string") { + throw ["error","invalid_require_path", + 'Must require a JavaScript string, not: '+(typeof current)]; + } + return [current, parent]; + } + // we need to traverse the path + var n = names.shift(); + if (n == '..') { + if (!(parent && parent.parent)) { + throw ["error", "invalid_require_path", 'Object has no parent '+JSON.stringify(current)]; + } + return resolveModule(names, parent.parent.parent, parent.parent); + } else if (n == '.') { + if (!parent) { + throw ["error", "invalid_require_path", 'Object has no parent '+JSON.stringify(current)]; + } + return resolveModule(names, parent.parent, parent); + } + if (!current[n]) { + throw ["error", "invalid_require_path", 'Object has no property "'+n+'". '+JSON.stringify(current)]; + } + var p = current + current = current[n]; + current.parent = p; + return resolveModule(names, p, current) +} + var Couch = { // moving this away from global so we can move to json2.js later toJSON : function (val) { return JSON.stringify(val); }, - compileFunction : function(source) { + compileFunction : function(source, ddoc) { if (!source) throw(["error","not_found","missing function"]); try { - var functionObject = sandbox ? evalcx(source, sandbox) : eval(source); + if (sandbox) { + if (ddoc) { + var require = function(name, parent) { + var exports = {}; + var resolved = resolveModule(name.split('/'), parent, ddoc); + var source = resolved[0]; + parent = resolved[1]; + var s = "function (exports, require) { " + source + " }"; + try { + var func = sandbox ? evalcx(s, sandbox) : eval(s); + func.apply(sandbox, [exports, function(name) {return require(name, parent, source)}]); + } catch(e) { + throw ["error","compilation_error","Module require('"+name+"') raised error "+e.toSource()]; + } + return exports; + } + sandbox.require = require; + } + var functionObject = evalcx(source, sandbox); + } else { + var functionObject = eval(source); + } } catch (err) { throw(["error", "compilation_error", err.toSource() + " (" + source + ")"]); }; |