| // Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| // use this file except in compliance with the License. You may obtain a copy of |
| // the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| // License for the specific language governing permissions and limitations under |
| // the License. |
| |
| var resolveModule = function(names, parent, current, path) { |
| if (names.length == 0) { |
| if (typeof current != "string") { |
| throw ["error","invalid_require_path", |
| 'Must require a JavaScript string, not: '+(typeof current)]; |
| } |
| return [current, parent, path]; |
| } |
| // 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)]; |
| } |
| path = path.slice(0, path.lastIndexOf('/')); |
| return resolveModule(names, parent.parent.parent, parent.parent, path); |
| } else if (n == '.') { |
| if (!parent) { |
| throw ["error", "invalid_require_path", 'Object has no parent '+JSON.stringify(current)]; |
| } |
| return resolveModule(names, parent.parent, parent, path); |
| } |
| 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; |
| path = path ? path + '/' + n : n; |
| return resolveModule(names, p, current, path); |
| }; |
| |
| 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, ddoc) { |
| if (!source) throw(["error","not_found","missing function"]); |
| try { |
| if (sandbox) { |
| if (ddoc) { |
| var require = function(name, parent) { |
| if (!parent) {parent = {}}; |
| var resolved = resolveModule(name.split('/'), parent.actual, ddoc, parent.id); |
| var s = "function (module, exports, require) { " + resolved[0] + " }"; |
| var module = {id:resolved[2], actual:resolved[1]}; |
| module.exports = {}; |
| try { |
| var func = sandbox ? evalcx(s, sandbox) : eval(s); |
| func.apply(sandbox, [module, module.exports, function(name) {return require(name, module)}]); |
| } catch(e) { |
| throw ["error","compilation_error","Module require('"+name+"') raised error "+e.toSource()]; |
| } |
| return module.exports; |
| } |
| sandbox.require = require; |
| } |
| var functionObject = evalcx(source, sandbox); |
| } else { |
| var functionObject = eval(source); |
| } |
| } catch (err) { |
| throw(["error", "compilation_error", err.toSource() + " (" + source + ")"]); |
| }; |
| if (typeof(functionObject) == "function") { |
| return functionObject; |
| } else { |
| throw(["error","compilation_error", |
| "Expression does not eval to a function. (" + source.toSource() + ")"]); |
| }; |
| }, |
| recursivelySeal : function(obj) { |
| // seal() is broken in current Spidermonkey |
| seal(obj); |
| for (var propname in obj) { |
| if (typeof doc[propname] == "object") { |
| recursivelySeal(doc[propname]); |
| } |
| } |
| } |
| } |
| |
| // prints the object as JSON, and rescues and logs any toJSON() related errors |
| function respond(obj) { |
| try { |
| print(Couch.toJSON(obj)); |
| } catch(e) { |
| log("Error converting object to JSON: " + e.toString()); |
| log("error on obj: "+ obj.toSource()); |
| } |
| }; |
| |
| function log(message) { |
| // idea: query_server_config option for log level |
| if (typeof message != "string") { |
| message = Couch.toJSON(message); |
| } |
| respond(["log", message]); |
| }; |