summaryrefslogtreecommitdiff
path: root/share/server/util.js
diff options
context:
space:
mode:
Diffstat (limited to 'share/server/util.js')
-rw-r--r--share/server/util.js150
1 files changed, 84 insertions, 66 deletions
diff --git a/share/server/util.js b/share/server/util.js
index bd4abc1d..b55480b9 100644
--- a/share/server/util.js
+++ b/share/server/util.js
@@ -10,22 +10,80 @@
// License for the specific language governing permissions and limitations under
// the License.
+var resolveModule = function(names, mod, root) {
+ if (names.length == 0) {
+ if (typeof mod.current != "string") {
+ throw ["error","invalid_require_path",
+ 'Must require a JavaScript string, not: '+(typeof mod.current)];
+ }
+ return {
+ current : mod.current,
+ parent : mod.parent,
+ id : mod.id,
+ exports : {}
+ }
+ }
+ // we need to traverse the path
+ var n = names.shift();
+ if (n == '..') {
+ if (!(mod.parent && mod.parent.parent)) {
+ throw ["error", "invalid_require_path", 'Object has no parent '+JSON.stringify(mod.current)];
+ }
+ return resolveModule(names, {
+ id : mod.id.slice(0, mod.id.lastIndexOf('/')),
+ parent : mod.parent.parent.parent,
+ current : mod.parent.parent.current
+ });
+ } else if (n == '.') {
+ if (!mod.parent) {
+ throw ["error", "invalid_require_path", 'Object has no parent '+JSON.stringify(mod.current)];
+ }
+ return resolveModule(names, {
+ parent : mod.parent.parent,
+ current : mod.parent.current,
+ id : mod.id
+ });
+ } else if (root) {
+ mod = {current : root};
+ }
+ if (!mod.current[n]) {
+ throw ["error", "invalid_require_path", 'Object has no property "'+n+'". '+JSON.stringify(mod.current)];
+ }
+ return resolveModule(names, {
+ current : mod.current[n],
+ parent : mod,
+ id : mod.id ? mod.id + '/' + n : n
+ });
+};
+
var Couch = {
// moving this away from global so we can move to json2.js later
toJSON : function (val) {
- if (typeof(val) == "undefined") {
- throw "Cannot encode 'undefined' value as JSON";
- }
- if (typeof(val) == "xml") { // E4X support
- val = val.toXMLString();
- }
- if (val === null) { return "null"; }
- return (Couch.toJSON.dispatcher[val.constructor.name])(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, module) {
+ module = module || {};
+ var newModule = resolveModule(name.split('/'), module, ddoc);
+ var s = "function (module, exports, require) { " + newModule.current + " }";
+ try {
+ var func = sandbox ? evalcx(s, sandbox) : eval(s);
+ func.apply(sandbox, [newModule, newModule.exports, function(name) {return require(name, newModule)}]);
+ } catch(e) {
+ throw ["error","compilation_error","Module require('"+name+"') raised error "+e.toSource()];
+ }
+ return newModule.exports;
+ }
+ sandbox.require = require;
+ }
+ var functionObject = evalcx(source, sandbox);
+ } else {
+ var functionObject = eval(source);
+ }
} catch (err) {
throw(["error", "compilation_error", err.toSource() + " (" + source + ")"]);
};
@@ -38,64 +96,20 @@ var Couch = {
},
recursivelySeal : function(obj) {
// seal() is broken in current Spidermonkey
- seal(obj);
+ try {
+ seal(obj);
+ } catch (x) {
+ // Sealing of arrays broken in some SpiderMonkey versions.
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=449657
+ }
for (var propname in obj) {
- if (typeof doc[propname] == "object") {
- recursivelySeal(doc[propname]);
+ if (typeof obj[propname] == "object") {
+ arguments.callee(obj[propname]);
}
}
}
}
-Couch.toJSON.subs = {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f',
- '\r': '\\r', '"' : '\\"', '\\': '\\\\'};
-Couch.toJSON.dispatcher = {
- "Array": function(v) {
- var buf = [];
- for (var i = 0; i < v.length; i++) {
- buf.push(Couch.toJSON(v[i]));
- }
- return "[" + buf.join(",") + "]";
- },
- "Boolean": function(v) {
- return v.toString();
- },
- "Date": function(v) {
- var f = function(n) { return n < 10 ? '0' + n : n };
- return '"' + v.getUTCFullYear() + '-' +
- f(v.getUTCMonth() + 1) + '-' +
- f(v.getUTCDate()) + 'T' +
- f(v.getUTCHours()) + ':' +
- f(v.getUTCMinutes()) + ':' +
- f(v.getUTCSeconds()) + 'Z"';
- },
- "Number": function(v) {
- return isFinite(v) ? v.toString() : "null";
- },
- "Object": function(v) {
- //if (v === null) return "null";
- var buf = [];
- for (var k in v) {
- if (!v.hasOwnProperty(k) || typeof(k) !== "string" || v[k] === undefined) {
- continue;
- }
- buf.push(Couch.toJSON(k) + ": " + Couch.toJSON(v[k]));
- }
- return "{" + buf.join(",") + "}";
- },
- "String": function(v) {
- if (/["\\\x00-\x1f]/.test(v)) {
- v = v.replace(/([\x00-\x1f\\"])/g, function(a, b) {
- var c = Couch.toJSON.subs[b];
- if (c) return c;
- c = b.charCodeAt();
- return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
- });
- }
- return '"' + v + '"';
- }
-};
-
// prints the object as JSON, and rescues and logs any toJSON() related errors
function respond(obj) {
try {
@@ -107,11 +121,15 @@ function respond(obj) {
};
function log(message) {
- // return; // idea: query_server_config option for log level
- if (typeof message == "undefined") {
- message = "Error: attempting to log message of 'undefined'.";
+ // idea: query_server_config option for log level
+ if (typeof message == "xml") {
+ message = message.toXMLString();
} else if (typeof message != "string") {
message = Couch.toJSON(message);
}
- respond(["log", message]);
+ respond(["log", String(message)]);
};
+
+function isArray(obj) {
+ return toString.call(obj) === "[object Array]";
+}