diff --git a/web/src/billing/helpers.ts b/web/src/billing/helpers.ts index 00473c1d8e..f4c641c3e3 100644 --- a/web/src/billing/helpers.ts +++ b/web/src/billing/helpers.ts @@ -80,7 +80,7 @@ export function create_ajax_request( }, error(xhr) { $(form_loading).hide(); - $(form_error).show().text(JSON.parse(xhr.responseText).msg); + $(form_error).show().text(xhr.responseJSON.msg); $(form_input_section).show(); $(zulip_limited_section).show(); $(free_trial_alert_message).show(); diff --git a/web/src/channel.js b/web/src/channel.js index d294f1c7c3..2024ed8e99 100644 --- a/web/src/channel.js +++ b/web/src/channel.js @@ -107,7 +107,7 @@ function call(args) { } else if (xhr.status === 403) { try { if ( - JSON.parse(xhr.responseText).code === "CSRF_FAILED" && + xhr.responseJSON.code === "CSRF_FAILED" && reload_state.csrf_failed_handler !== undefined ) { reload_state.csrf_failed_handler(); @@ -192,7 +192,7 @@ export function xhr_error_message(message, xhr) { if (xhr.status.toString().charAt(0) === "4") { // Only display the error response for 4XX, where we've crafted // a nice response. - const server_response_html = _.escape(JSON.parse(xhr.responseText).msg); + const server_response_html = _.escape(xhr.responseJSON.msg); if (message) { message += ": " + server_response_html; } else { diff --git a/web/src/compose.js b/web/src/compose.js index d57bd6e0fe..a203df2472 100644 --- a/web/src/compose.js +++ b/web/src/compose.js @@ -595,7 +595,7 @@ export function initialize() { } function xhr_failure(xhr) { - const error = JSON.parse(xhr.responseText); + const error = xhr.responseJSON; failure(error.msg); } diff --git a/web/src/invite.js b/web/src/invite.js index 4def7e906d..9c5048f041 100644 --- a/web/src/invite.js +++ b/web/src/invite.js @@ -114,16 +114,16 @@ function submit_invitation_form() { } }, error(xhr) { - const arr = JSON.parse(xhr.responseText); - if (arr.errors === undefined) { + if (xhr.responseJSON.errors === undefined) { // There was a fatal error, no partial processing occurred. ui_report.error("", xhr, $invite_status); } else { // Some users were not invited. + const response_body = xhr.responseJSON; const invitee_emails_errored = []; const error_list = []; let is_invitee_deactivated = false; - for (const value of arr.errors) { + for (const value of response_body.errors) { const [email, error_message, deactivated] = value; error_list.push(`${email}: ${error_message}`); if (deactivated) { @@ -133,17 +133,17 @@ function submit_invitation_form() { } const error_response = render_invitation_failed_error({ - error_message: arr.msg, + error_message: response_body.msg, error_list, is_admin: page_params.is_admin, is_invitee_deactivated, - license_limit_reached: arr.license_limit_reached, + license_limit_reached: response_body.license_limit_reached, has_billing_access: page_params.is_owner || page_params.is_billing_admin, - daily_limit_reached: arr.daily_limit_reached, + daily_limit_reached: response_body.daily_limit_reached, }); ui_report.message(error_response, $invite_status, "alert-warning"); - if (arr.sent_invitations) { + if (response_body.sent_invitations) { $invitee_emails.val(invitee_emails_errored.join("\n")); } } diff --git a/web/src/message_edit.js b/web/src/message_edit.js index 27926a38b2..f74c3b62ec 100644 --- a/web/src/message_edit.js +++ b/web/src/message_edit.js @@ -699,8 +699,7 @@ export function toggle_resolve_topic(message_id, old_topic_name, report_errors_i } if (report_errors_in_global_banner) { - const error_msg = JSON.parse(xhr.responseText).msg; - ui_report.generic_embed_error(error_msg, 3500); + ui_report.generic_embed_error(xhr.responseJSON.msg, 3500); } }, }); diff --git a/web/src/server_events.js b/web/src/server_events.js index 5cf410c577..a9b8a29875 100644 --- a/web/src/server_events.js +++ b/web/src/server_events.js @@ -207,10 +207,7 @@ function get_events({dont_block = false} = {}) { get_events_xhr = undefined; // If we're old enough that our message queue has been // garbage collected, immediately reload. - if ( - xhr.status === 400 && - JSON.parse(xhr.responseText).code === "BAD_EVENT_QUEUE_ID" - ) { + if (xhr.status === 400 && xhr.responseJSON.code === "BAD_EVENT_QUEUE_ID") { page_params.event_queue_expired = true; reload.initiate({ immediate: true, diff --git a/web/src/settings_account.js b/web/src/settings_account.js index b7eb4a6f04..c36ae4c389 100644 --- a/web/src/settings_account.js +++ b/web/src/settings_account.js @@ -119,7 +119,7 @@ function upload_avatar($file_input) { $("#user-avatar-source").show(); } const $error = $("#user-avatar-upload-widget .image_file_input_error"); - $error.text(JSON.parse(xhr.responseText).msg); + $error.text(xhr.responseJSON.msg); $error.show(); }, }); @@ -490,7 +490,7 @@ export function set_up() { $("#api_key_value").text(data.api_key); }, error(xhr) { - $("#user_api_key_error").text(JSON.parse(xhr.responseText).msg).show(); + $("#user_api_key_error").text(xhr.responseJSON.msg).show(); }, }); e.preventDefault(); diff --git a/web/src/settings_bots.js b/web/src/settings_bots.js index c45ddb6323..b6286e0745 100644 --- a/web/src/settings_bots.js +++ b/web/src/settings_bots.js @@ -581,7 +581,7 @@ export function set_up() { }, error(xhr) { const $row = $(e.currentTarget).closest("li"); - $row.find(".api_key_error").text(JSON.parse(xhr.responseText).msg).show(); + $row.find(".api_key_error").text(xhr.responseJSON.msg).show(); }, }); }); diff --git a/web/src/settings_linkifiers.js b/web/src/settings_linkifiers.js index dc87b76788..1c58a388ee 100644 --- a/web/src/settings_linkifiers.js +++ b/web/src/settings_linkifiers.js @@ -73,7 +73,7 @@ function open_linkifier_edit_form(linkifier_id) { }, error_continuation(xhr) { $change_linkifier_button.prop("disabled", false); - const response_text = JSON.parse(xhr.responseText); + const response_text = xhr.responseJSON; if (response_text.errors !== undefined) { handle_linkifier_api_error( xhr, @@ -113,17 +113,17 @@ function handle_linkifier_api_error(xhr, pattern_status, template_status, linkif // The endpoint uses the Django ValidationError system for error // handling, which returns somewhat complicated error // dictionaries. This logic parses them. - const errors = JSON.parse(xhr.responseText).errors; + const errors = xhr.responseJSON.errors; if (errors.pattern !== undefined) { - xhr.responseText = JSON.stringify({msg: errors.pattern}); + xhr.responseJSON.msg = errors.pattern; ui_report.error($t_html({defaultMessage: "Failed"}), xhr, pattern_status); } if (errors.url_template !== undefined) { - xhr.responseText = JSON.stringify({msg: errors.url_template}); + xhr.responseJSON.msg = errors.url_template; ui_report.error($t_html({defaultMessage: "Failed"}), xhr, template_status); } if (errors.__all__ !== undefined) { - xhr.responseText = JSON.stringify({msg: errors.__all__}); + xhr.responseJSON.msg = errors.__all__; ui_report.error($t_html({defaultMessage: "Failed"}), xhr, linkifier_status); } } diff --git a/web/src/stats/stats.js b/web/src/stats/stats.js index c31cd438c9..579d453541 100644 --- a/web/src/stats/stats.js +++ b/web/src/stats/stats.js @@ -1101,7 +1101,7 @@ function get_chart_data(data, callback) { update_last_full_update(data.end_times); }, error(xhr) { - $("#id_stats_errors").show().text(JSON.parse(xhr.responseText).msg); + $("#id_stats_errors").show().text(xhr.responseJSON.msg); }, }); } diff --git a/web/src/stream_create.js b/web/src/stream_create.js index 7bd822f8e6..5d9e636ce2 100644 --- a/web/src/stream_create.js +++ b/web/src/stream_create.js @@ -280,7 +280,7 @@ function create_stream() { // The rest of the work is done via the subscribe event we will get }, error(xhr) { - const msg = JSON.parse(xhr.responseText).msg; + const msg = xhr.responseJSON.msg; if (msg.includes("access")) { // If we can't access the stream, we can safely // assume it's a duplicate stream that we are not invited to. diff --git a/web/src/stream_edit_subscribers.js b/web/src/stream_edit_subscribers.js index b97cfac696..0b4d448588 100644 --- a/web/src/stream_edit_subscribers.js +++ b/web/src/stream_edit_subscribers.js @@ -196,7 +196,7 @@ function subscribe_new_users({pill_user_ids}) { } function invite_failure(xhr) { - const error = JSON.parse(xhr.responseText); + const error = xhr.responseJSON; show_stream_subscription_request_result({ message: error.msg, add_class: "text-error", diff --git a/web/src/stream_settings_ui.js b/web/src/stream_settings_ui.js index bcbc3bad1c..a4cebb09b7 100644 --- a/web/src/stream_settings_ui.js +++ b/web/src/stream_settings_ui.js @@ -957,7 +957,7 @@ function ajaxSubscribe(stream, color, $stream_row) { $("#create_stream_name").val(""); } - const res = JSON.parse(xhr.responseText); + const res = xhr.responseJSON; if (!$.isEmptyObject(res.already_subscribed)) { // Display the canonical stream capitalization. true_stream_name = res.already_subscribed[people.my_current_email()][0]; diff --git a/web/src/ui_report.ts b/web/src/ui_report.ts index 5763bdc3db..da21819833 100644 --- a/web/src/ui_report.ts +++ b/web/src/ui_report.ts @@ -41,7 +41,7 @@ export function error( if (xhr && xhr.status >= 400 && xhr.status < 500) { // Only display the error response for 4XX, where we've crafted // a nice response. - const server_response_html = _.escape(JSON.parse(xhr.responseText).msg); + const server_response_html = _.escape(xhr.responseJSON.msg); if (response_html) { response_html += ": " + server_response_html; } else { @@ -79,7 +79,7 @@ export function generic_embed_error(error_html: string, remove_after: number): v export function generic_row_button_error(xhr: JQuery.jqXHR, $btn: JQuery): void { if (xhr.status >= 400 && xhr.status < 500) { - const $error = $("

").addClass("text-error").text(JSON.parse(xhr.responseText).msg); + const $error = $("

").addClass("text-error").text(xhr.responseJSON.msg); $btn.closest("td").empty().append($error); } else { $btn.text($t({defaultMessage: "Failed!"})); diff --git a/web/src/user_group_edit_members.js b/web/src/user_group_edit_members.js index 5bb674f1de..5b836f960a 100644 --- a/web/src/user_group_edit_members.js +++ b/web/src/user_group_edit_members.js @@ -223,7 +223,7 @@ function add_new_members({pill_user_ids}) { } function invite_failure(xhr) { - const error = JSON.parse(xhr.responseText); + const error = xhr.responseJSON; show_user_group_membership_request_result({ message: error.msg, add_class: "text-error", diff --git a/web/tests/billing_helpers.test.js b/web/tests/billing_helpers.test.js index 6cfbee3240..648426ef00 100644 --- a/web/tests/billing_helpers.test.js +++ b/web/tests/billing_helpers.test.js @@ -160,7 +160,7 @@ run_test("create_ajax_request", ({override}) => { assert.equal(state.free_trial_alert_message_show, 0); assert.ok(success_callback_called); - error({responseText: '{"msg": "response_message"}'}); + error({responseJSON: {msg: "response_message"}}); assert.equal(state.form_loading_hide, 2); assert.equal(state.form_error_show, 1); diff --git a/web/tests/channel.test.js b/web/tests/channel.test.js index b0ac3712e8..c2dd86517f 100644 --- a/web/tests/channel.test.js +++ b/web/tests/channel.test.js @@ -9,7 +9,7 @@ const {page_params} = require("./lib/zpage_params"); const xhr_401 = { status: 401, - responseText: '{"msg": "Use cannot access XYZ"}', + responseJSON: {msg: "Use cannot access XYZ"}, }; let login_to_access_shown = false; @@ -294,7 +294,7 @@ test("reload_on_403_error", () => { test_with_mock_ajax({ xhr: { status: 403, - responseText: '{"msg": "CSRF Fehler: etwas", "code": "CSRF_FAILED"}', + responseJSON: {msg: "CSRF Fehler: etwas", code: "CSRF_FAILED"}, }, run_code() { @@ -317,6 +317,7 @@ test("unexpected_403_response", () => { test_with_mock_ajax({ xhr: { status: 403, + responseJSON: undefined, responseText: "unexpected", }, @@ -334,6 +335,7 @@ test("unexpected_403_response", () => { test("xhr_error_message", () => { let xhr = { status: "200", + responseJSON: undefined, responseText: "does not matter", }; let msg = "data added"; @@ -341,7 +343,7 @@ test("xhr_error_message", () => { xhr = { status: "404", - responseText: '{"msg": "file not found"}', + responseJSON: {msg: "file not found"}, }; msg = "some message"; assert.equal(channel.xhr_error_message(msg, xhr), "some message: file not found");