a4311d22ec503f936c0b624c13b1349c590a01ea angie Wed Apr 20 12:01:26 2016 -0700 Added an errCatch to cartJsonExecute so that instead of returning invalid JSON where there's an errAbort, we can close out the JSON-in-progress (if any) and add an error message to the JSON response -- then the user will at least see the error message instead of a parser error alert. This required extending jsonWrite's objStack so that in addition to tracking whether a comma is needed, it now tracks whether each stack item is an object or a list. Then, when necessary we can tell jsonWrite to pop up to a certain level (in this case, level 1 so we can include an error string in the response object) by closing out any lists or objects that are deeper than that level. The new flag also allows us to test for errors like ending a list when we need to end an object or vice versa. diff --git src/hg/lib/cartJson.c src/hg/lib/cartJson.c index 7c9bf04..e5a3bdb 100644 --- src/hg/lib/cartJson.c +++ src/hg/lib/cartJson.c @@ -860,34 +860,47 @@ void cartJsonExecute(struct cartJson *cj) /* Get commands from cgi, print Content-type, execute commands, print results as JSON. */ { cartJsonPushErrHandlers(); puts("Content-Type:text/javascript\n"); // Initialize response JSON object: jsonWriteObjectStart(cj->jw, NULL); // Always send back hgsid: jsonWriteString(cj->jw, cartSessionVarName(), cartSessionId(cj->cart)); char *commandJson = cgiOptionalString(CARTJSON_COMMAND); if (commandJson) { + struct errCatch *errCatch = errCatchNew(); + if (errCatchStart(errCatch)) + { struct jsonElement *commandObj = jsonParse(commandJson); struct hash *commandHash = jsonObjectVal(commandObj, "commandObj"); // change* commands need to go first! Really we need an ordered map type here... // for now, just make a list and sort to put change commands at the front. struct slPair *commandList = NULL, *cmd; struct hashCookie cookie = hashFirst(commandHash); struct hashEl *hel; while ((hel = hashNext(&cookie)) != NULL) slAddHead(&commandList, slPairNew(hel->name, hel->val)); slSort(&commandList, commandCmp); for (cmd = commandList; cmd != NULL; cmd = cmd->next) doOneCommand(cj, cmd->name, (struct jsonElement *)cmd->val); } + errCatchEnd(errCatch); + if (errCatch->gotError) + { + jsonWritePopToLevel(cj->jw, 1); + //#*** TODO: move jsonStringEscape inside jsonWriteString + char *encoded = jsonStringEscape(errCatch->message->string); + jsonWriteString(cj->jw, "error", encoded); + } + errCatchFree(&errCatch); + } cartJsonPrintWarnings(cj->jw); jsonWriteObjectEnd(cj->jw); puts(cj->jw->dy->string); cartJsonPopErrHandlers(); }