mirror of https://github.com/zulip/zulip.git
ts: Convert blueslip module to TypeScript.
We turn off the eslint no-use-before-define for TypeScript files because it does not work correctly for types. There is already a typescript-eslint version of it that is enabled for TS. We also update the error handler on window to use instanceof check for ErrorEvent instead of checking the error property.
This commit is contained in:
parent
f7235912ff
commit
c862c673af
|
@ -145,6 +145,7 @@
|
|||
"no-duplicate-imports": "off",
|
||||
"no-unused-vars": "off",
|
||||
"no-useless-constructor": "off",
|
||||
"no-use-before-define": "off",
|
||||
|
||||
"@typescript-eslint/array-type": "error",
|
||||
"@typescript-eslint/await-thenable": "error",
|
||||
|
|
|
@ -16,12 +16,12 @@ if (Error.stackTraceLimit !== undefined) {
|
|||
Error.stackTraceLimit = 100000;
|
||||
}
|
||||
|
||||
function pad(num, width) {
|
||||
function pad(num: number, width: number): string {
|
||||
return num.toString().padStart(width, "0");
|
||||
}
|
||||
|
||||
function make_logger_func(name) {
|
||||
return function Logger_func(...args) {
|
||||
function make_logger_func(name: "debug" | "log" | "info" | "warn" | "error") {
|
||||
return function Logger_func(this: Logger, ...args: unknown[]) {
|
||||
const now = new Date();
|
||||
const date_str =
|
||||
now.getUTCFullYear() +
|
||||
|
@ -62,27 +62,26 @@ class Logger {
|
|||
warn = make_logger_func("warn");
|
||||
error = make_logger_func("error");
|
||||
|
||||
_memory_log = [];
|
||||
|
||||
get_log() {
|
||||
_memory_log: string[] = [];
|
||||
get_log(): string[] {
|
||||
return this._memory_log;
|
||||
}
|
||||
}
|
||||
|
||||
const logger = new Logger();
|
||||
|
||||
export function get_log() {
|
||||
export function get_log(): string[] {
|
||||
return logger.get_log();
|
||||
}
|
||||
|
||||
const reported_errors = new Set();
|
||||
const last_report_attempt = new Map();
|
||||
const reported_errors = new Set<string>();
|
||||
const last_report_attempt = new Map<string, number>();
|
||||
|
||||
function report_error(
|
||||
msg,
|
||||
msg: string,
|
||||
stack = "No stacktrace available",
|
||||
{show_ui_msg = false, more_info} = {},
|
||||
) {
|
||||
{show_ui_msg = false, more_info}: {show_ui_msg?: boolean; more_info?: unknown} = {},
|
||||
): void {
|
||||
if (page_params.development_environment) {
|
||||
// In development, we display blueslip errors in the web UI,
|
||||
// to make them hard to miss.
|
||||
|
@ -176,8 +175,8 @@ function report_error(
|
|||
|
||||
class BlueslipError extends Error {
|
||||
name = "BlueslipError";
|
||||
|
||||
constructor(msg, more_info) {
|
||||
more_info?: unknown;
|
||||
constructor(msg: string, more_info: unknown) {
|
||||
super(msg);
|
||||
if (more_info !== undefined) {
|
||||
this.more_info = more_info;
|
||||
|
@ -185,7 +184,13 @@ class BlueslipError extends Error {
|
|||
}
|
||||
}
|
||||
|
||||
export function exception_msg(ex) {
|
||||
export function exception_msg(
|
||||
ex: Error & {
|
||||
// Unsupported properties avaliable on some browsers
|
||||
fileName?: string;
|
||||
lineNumber?: number;
|
||||
},
|
||||
): string {
|
||||
let message = ex.message;
|
||||
if (ex.fileName !== undefined) {
|
||||
message += " at " + ex.fileName;
|
||||
|
@ -197,38 +202,44 @@ export function exception_msg(ex) {
|
|||
}
|
||||
|
||||
$(window).on("error", (event) => {
|
||||
const ex = event.originalEvent.error;
|
||||
const {originalEvent} = event;
|
||||
if (!(originalEvent instanceof ErrorEvent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const ex = originalEvent.error;
|
||||
if (!ex || ex instanceof BlueslipError) {
|
||||
return;
|
||||
}
|
||||
|
||||
const message = exception_msg(ex);
|
||||
report_error(message, ex.stack);
|
||||
});
|
||||
|
||||
function build_arg_list(msg, more_info) {
|
||||
const args = [msg];
|
||||
function build_arg_list(msg: string, more_info: unknown): [string, string?, unknown?] {
|
||||
const args: [string, string?, unknown?] = [msg];
|
||||
if (more_info !== undefined) {
|
||||
args.push("\nAdditional information: ", more_info);
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
export function debug(msg, more_info) {
|
||||
export function debug(msg: string, more_info: unknown): void {
|
||||
const args = build_arg_list(msg, more_info);
|
||||
logger.debug(...args);
|
||||
}
|
||||
|
||||
export function log(msg, more_info) {
|
||||
export function log(msg: string, more_info: unknown): void {
|
||||
const args = build_arg_list(msg, more_info);
|
||||
logger.log(...args);
|
||||
}
|
||||
|
||||
export function info(msg, more_info) {
|
||||
export function info(msg: string, more_info: unknown): void {
|
||||
const args = build_arg_list(msg, more_info);
|
||||
logger.info(...args);
|
||||
}
|
||||
|
||||
export function warn(msg, more_info) {
|
||||
export function warn(msg: string, more_info: unknown): void {
|
||||
const args = build_arg_list(msg, more_info);
|
||||
logger.warn(...args);
|
||||
if (page_params.development_environment) {
|
||||
|
@ -236,7 +247,7 @@ export function warn(msg, more_info) {
|
|||
}
|
||||
}
|
||||
|
||||
export function error(msg, more_info, stack = new Error("dummy").stack) {
|
||||
export function error(msg: string, more_info: unknown, stack = new Error("dummy").stack): void {
|
||||
const args = build_arg_list(msg, more_info);
|
||||
logger.error(...args);
|
||||
report_error(msg, stack, {more_info});
|
||||
|
@ -251,7 +262,7 @@ export function error(msg, more_info, stack = new Error("dummy").stack) {
|
|||
|
||||
export const timings = new Map();
|
||||
|
||||
export function measure_time(label, f) {
|
||||
export function measure_time<T>(label: string, f: () => T): T {
|
||||
const t1 = performance.now();
|
||||
const ret = f();
|
||||
const t2 = performance.now();
|
||||
|
@ -264,8 +275,8 @@ export function measure_time(label, f) {
|
|||
// only used for including in error report emails; be sure to discuss
|
||||
// with other developers before using it in a user-facing context
|
||||
// because it is not XSS-safe.
|
||||
export function preview_node(node) {
|
||||
if (node instanceof $) {
|
||||
export function preview_node(node: JQuery | HTMLElement): string {
|
||||
if (!(node instanceof HTMLElement)) {
|
||||
node = node[0];
|
||||
}
|
||||
|
|
@ -10,5 +10,6 @@ interface JQuery {
|
|||
}
|
||||
|
||||
interface Window {
|
||||
last_stacktrace: string;
|
||||
page_params_parse_time: number;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,9 @@ export const page_params: {
|
|||
name: string;
|
||||
percent_translated: number | undefined;
|
||||
}[];
|
||||
development_environment: boolean;
|
||||
request_language: string;
|
||||
save_stacktraces: boolean;
|
||||
translation_data: Record<string, string>;
|
||||
} = $("#page-params").remove().data("params");
|
||||
const t2 = performance.now();
|
||||
|
|
|
@ -190,7 +190,7 @@ js_rules = RuleList(
|
|||
"description": "Use channel module for AJAX calls",
|
||||
"exclude": {
|
||||
# Internal modules can do direct network calls
|
||||
"static/js/blueslip.js",
|
||||
"static/js/blueslip.ts",
|
||||
"static/js/channel.js",
|
||||
# External modules that don't include channel.js
|
||||
"static/js/stats/",
|
||||
|
|
|
@ -42,7 +42,7 @@ EXEMPT_FILES = {
|
|||
"static/js/attachments_ui.js",
|
||||
"static/js/avatar.js",
|
||||
"static/js/billing/helpers.js",
|
||||
"static/js/blueslip.js",
|
||||
"static/js/blueslip.ts",
|
||||
"static/js/blueslip_stacktrace.ts",
|
||||
"static/js/click_handlers.js",
|
||||
"static/js/compose_actions.js",
|
||||
|
|
Loading…
Reference in New Issue