blob: fc159f4c963f0c0103d00d15e1468439e087a5da [file] [log] [blame]
// 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.
function create_sandbox() {
var sandbox = {};
sandbox.emit = Views.emit;
sandbox.sum = Views.sum;
sandbox.log = log;
sandbox.toJSON = JSON.stringify;
sandbox.JSON = JSON;
sandbox.provides = Mime.provides;
sandbox.registerType = Mime.registerType;
sandbox.start = Render.start;
sandbox.send = Render.send;
sandbox.getRow = Render.getRow;
sandbox.isArray = isArray;
return sandbox;
};
function create_filter_sandbox() {
var sandbox = create_sandbox();
sandbox.emit = Filter.emit;
return sandbox;
};
function create_dreyfus_sandbox() {
var sandbox = create_sandbox();
sandbox.index = Dreyfus.index;
return sandbox;
};
function create_nouveau_sandbox() {
var sandbox = create_sandbox();
sandbox.index = Nouveau.index;
return sandbox;
};
function seal(obj, flag) {
Object.freeze(obj);
};
// This is a copy from loop.js
var DDoc = (function() {
var ddoc_dispatch = {
"lists" : Render.list,
"shows" : Render.show,
"filters" : Filter.filter,
"views" : Filter.filter_view,
"updates" : Render.update,
"validate_doc_update" : Validate.validate,
"rewrites" : Render.rewrite
};
var ddocs = {};
return {
ddoc : function() {
var args = [];
for (var i=0; i < arguments.length; i++) {
args.push(arguments[i]);
};
var ddocId = args.shift();
if (ddocId == "new") {
// get the real ddocId.
ddocId = args.shift();
// store the ddoc, functions are lazily compiled.
ddocs[ddocId] = args.shift();
print("true");
} else {
// Couch makes sure we know this ddoc already.
var ddoc = ddocs[ddocId];
if (!ddoc) throw(["fatal", "query_protocol_error", "uncached design doc: "+ddocId]);
var funPath = args.shift();
var cmd = funPath[0];
// the first member of the fun path determines the type of operation
var funArgs = args.shift();
if (ddoc_dispatch[cmd]) {
// get the function, call the command with it
var point = ddoc;
for (var i=0; i < funPath.length; i++) {
if (i+1 == funPath.length) {
var fun = point[funPath[i]];
if (!fun) {
throw(["error","not_found",
"missing " + funPath[0] + " function " + funPath[i] +
" on design doc " + ddocId]);
}
if (typeof fun != "function") {
// For filter_view we want the emit() function
// to be overridden and just toggle a flag instead of
// accumulating rows
var sandbox = (cmd === "views") ? create_filter_sandbox() : create_sandbox();
fun = Couch.compileFunction(fun, ddoc, funPath.join('.'), sandbox);
// cache the compiled fun on the ddoc
point[funPath[i]] = fun;
};
} else {
point = point[funPath[i]];
}
};
// run the correct responder with the cmd body
ddoc_dispatch[cmd].apply(null, [fun, ddoc, funArgs]);
} else {
// unknown command, quit and hope the restarted version is better
throw(["fatal", "unknown_command", "unknown ddoc command '" + cmd + "'"]);
}
}
}
};
})();
// This mostly a copy from loop.js handleError
function handleError(e) {
if (e === null) {
// internal error, another possibility when out of memory
// nothing to do except rethrow and let main.c catch it and exit(1)
throw(null);
}
const type = e[0];
if (type == "fatal") {
e[0] = "error"; // we tell the client it was a fatal error by dying
respond(e);
return false;
} else if (type == "error") {
respond(e);
return true;
} else if (e.name == "InternalError") {
// If the internal error is caught by handleViewError it will be
// re-thrown as a ["fatal", ...] error, and we already handle that above.
// Here we handle the case when the error is thrown outside of
// handleViewError, for instance when serializing the rows to be sent
// back to the user
respond(["error", e.name, e.message]);
return false;
} else if (e.error && e.reason) {
// compatibility with old error format
respond(["error", e.error, e.reason]);
return true;
} else if (e.name) {
respond(["error", e.name, e]);
return true;
} else {
respond(["error","unnamed_error", e.stack]);
return true;
}
};
globalThis.dispatch = function(line) {
const cmd = JSON.parse(line);
State.line_length = line.length;
try {
switch (cmd.shift()) {
case "ddoc":
DDoc.ddoc.apply(null, cmd);
break;
case "reset":
State.reset.apply(null, cmd);
break;
case "add_fun":
State.addFun.apply(null, cmd);
break;
case "add_lib":
State.addLib.apply(null, cmd);
break;
case "map_doc":
Views.mapDoc.apply(null, cmd);
break;
case "index_doc":
Dreyfus.indexDoc.apply(null, cmd);
break;
case "nouveau_index_doc":
Nouveau.indexDoc.apply(null, cmd);
break;
case "reduce":
Views.reduce.apply(null, cmd);
break;
case "rereduce":
Views.rereduce.apply(null, cmd);
break;
default:
// unknown command, quit and hope the restarted version is better
throw(["fatal", "unknown_command", "unknown command '" + cmdkey + "'"]);
}
} catch(e) {
return handleError(e);
};
return true;
};