Anders Kaseorg
2285ee922e
js: Convert _.contains(a, …) to a.includes(…).
...
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-10 14:08:12 -08:00
Anders Kaseorg
ef50346a29
js: Convert _.reject(a, … => …) to a.filter(… => !…).
...
And convert the corresponding function expressions to arrow style
while we’re here.
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-10 14:08:12 -08:00
Anders Kaseorg
4948240619
js: Convert _.filter(a, …) to a.filter(…).
...
And convert the corresponding function expressions to arrow style
while we’re here.
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-10 14:08:12 -08:00
Anders Kaseorg
ac7b09d57e
js: Convert _.map(a, …) to a.map(…).
...
And convert the corresponding function expressions to arrow style
while we’re here.
import * as babelParser from "recast/parsers/babel";
import * as recast from "recast";
import * as tsParser from "recast/parsers/typescript";
import { builders as b, namedTypes as n } from "ast-types";
import K from "ast-types/gen/kinds";
import fs from "fs";
import path from "path";
import process from "process";
const checkExpression = (node: n.Node): node is K.ExpressionKind =>
n.Expression.check(node);
for (const file of process.argv.slice(2)) {
console.log("Parsing", file);
const ast = recast.parse(fs.readFileSync(file, { encoding: "utf8" }), {
parser: path.extname(file) === ".ts" ? tsParser : babelParser,
});
let changed = false;
recast.visit(ast, {
visitCallExpression(path) {
const { callee, arguments: args } = path.node;
if (
n.MemberExpression.check(callee) &&
!callee.computed &&
n.Identifier.check(callee.object) &&
callee.object.name === "_" &&
n.Identifier.check(callee.property) &&
callee.property.name === "map" &&
args.length === 2 &&
checkExpression(args[0]) &&
checkExpression(args[1])
) {
const [arr, fn] = args;
path.replace(
b.callExpression(b.memberExpression(arr, b.identifier("map")), [
n.FunctionExpression.check(fn) ||
n.ArrowFunctionExpression.check(fn)
? b.arrowFunctionExpression(
fn.params,
n.BlockStatement.check(fn.body) &&
fn.body.body.length === 1 &&
n.ReturnStatement.check(fn.body.body[0])
? fn.body.body[0].argument || b.identifier("undefined")
: fn.body
)
: fn,
])
);
changed = true;
}
this.traverse(path);
},
});
if (changed) {
console.log("Writing", file);
fs.writeFileSync(file, recast.print(ast).code, { encoding: "utf8" });
}
}
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-10 14:08:12 -08:00
Anders Kaseorg
719546641f
js: Convert a.indexOf(…) !== -1 to a.includes(…).
...
Babel polyfills this for us for Internet Explorer.
import * as babelParser from "recast/parsers/babel";
import * as recast from "recast";
import * as tsParser from "recast/parsers/typescript";
import { builders as b, namedTypes as n } from "ast-types";
import K from "ast-types/gen/kinds";
import fs from "fs";
import path from "path";
import process from "process";
const checkExpression = (node: n.Node): node is K.ExpressionKind =>
n.Expression.check(node);
for (const file of process.argv.slice(2)) {
console.log("Parsing", file);
const ast = recast.parse(fs.readFileSync(file, { encoding: "utf8" }), {
parser: path.extname(file) === ".ts" ? tsParser : babelParser,
});
let changed = false;
recast.visit(ast, {
visitBinaryExpression(path) {
const { operator, left, right } = path.node;
if (
n.CallExpression.check(left) &&
n.MemberExpression.check(left.callee) &&
!left.callee.computed &&
n.Identifier.check(left.callee.property) &&
left.callee.property.name === "indexOf" &&
left.arguments.length === 1 &&
checkExpression(left.arguments[0]) &&
((["===", "!==", "==", "!=", ">", "<="].includes(operator) &&
n.UnaryExpression.check(right) &&
right.operator == "-" &&
n.Literal.check(right.argument) &&
right.argument.value === 1) ||
([">=", "<"].includes(operator) &&
n.Literal.check(right) &&
right.value === 0))
) {
const test = b.callExpression(
b.memberExpression(left.callee.object, b.identifier("includes")),
[left.arguments[0]]
);
path.replace(
["!==", "!=", ">", ">="].includes(operator)
? test
: b.unaryExpression("!", test)
);
changed = true;
}
this.traverse(path);
},
});
if (changed) {
console.log("Writing", file);
fs.writeFileSync(file, recast.print(ast).code, { encoding: "utf8" });
}
}
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-10 14:08:12 -08:00
Anders Kaseorg
788c5afbcf
js: Convert _.indexOf(a, …) to a.indexOf(…).
...
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-10 14:08:12 -08:00
Anders Kaseorg
29dbf8ec77
schema: Convert _.find used as loop to for…of.
...
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-10 14:08:12 -08:00
Anders Kaseorg
13b8bf830f
message_viewport: Convert _.every used as loop to for…of.
...
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-10 14:08:12 -08:00
Anders Kaseorg
4fbee73d1a
emoji_picker: Convert _.any used as loop to for…of.
...
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-10 14:08:12 -08:00
Anders Kaseorg
2f314a0854
js: Convert _.map on jQuery collections to Array.from.
...
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-10 14:08:12 -08:00
Anders Kaseorg
7b0dea0351
js: Convert jQuery.each to for…of.
...
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-10 14:08:12 -08:00
Anders Kaseorg
22f3ec44bc
blueslip: Use modern spread arguments syntax.
...
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-10 14:08:12 -08:00
Anders Kaseorg
b5bf677717
submessage: Move submessages === undefined check up.
...
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-10 14:08:12 -08:00
Anders Kaseorg
4fa1075840
popovers: Check for undefined message.edit_history.
...
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-10 14:08:12 -08:00
Anders Kaseorg
d671d00cbd
settings_profile_fields: Iterate over field_types with Object.values.
...
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-10 14:08:12 -08:00
Anders Kaseorg
56ab5b4cf4
schema: Iterate over fields with Object.entries.
...
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-10 14:08:12 -08:00
Chris Heald
86faebc2e5
lightbox: Don't blow up for messages not in the message store.
...
This should somewhat reduce the gravity of the failure mode for cases
where the message the user clicked cannot be found (which would be a
significant bug on its own merit in any case).
2020-02-10 14:00:40 -08:00
Chris Heald
c802a1393f
lightbox: Cast zid to an int before looking it up in message_store.
...
The keys for message_store are since the recent Map migration intended
to be integer message IDs, not strings (and likely were always
intended to be integers; the failure mode may simply have shifted).
This may just be a new bug, but this max also fix #9549 ; certainly
we'll want to redo any investigation with this fix in place.
Fixes #9549 .
2020-02-10 13:56:49 -08:00
Steve Howell
fa1059aa2e
stream_data: Remove stream_name param from add_sub().
...
We just get the stream_name from the sub struct now.
This mostly affects node tests.
The only place in real code where we called add_sub()
was when we initialized data from the server.
2020-02-09 22:08:50 -08:00
Vishnu KS
4572be8c27
api: Rename subject_links to topic_links.
...
Fixes #13588
2020-02-07 14:35:22 -08:00
Steve Howell
e9c6653852
node tests: Always enforce blueslip warn/error/fatal.
...
We now require all of our unit tests to handle
blueslip errors for warn/error/fatal. This
simplifies the zblueslip code to not have any
options passed in.
Most of the places changed here fell into two
categories:
- We were just missing a random piece of
setup data in a happy path test.
- We were testing error handling in just
a lazy way to ensure 100% coverage. Often
these error codepaths were fairly
contrived.
The one place where we especially lazy was
the stream_data tests, and those are now
more thorough.
2020-02-07 14:15:44 -08:00
Steve Howell
996d054fe9
messages: Send stream_id for stream messages.
...
This saves a tiny bit of bandwidth, but more
importantly, it protects us against races for
stream name changes. There's some argument that
if the user is thinking they're sending to
old_stream_name, and unbeknownst to them, the
stream has changed to new_stream_name, then we
should fail. But I think 99% of the time the
user just wants the message to go that stream
despite any renames.
In order to verify the blueslip error, we
had to turn on error checking, which required
a tiny fix to a place where we left out
a stream_id for add_sub.
2020-02-07 14:15:44 -08:00
Anders Kaseorg
02511bff1c
js: Automatically convert _.each to for…of.
...
This commit was automatically generated by the following script,
followed by lint --fix and a few small manual lint-related cleanups.
import * as babelParser from "recast/parsers/babel";
import * as recast from "recast";
import * as tsParser from "recast/parsers/typescript";
import { builders as b, namedTypes as n } from "ast-types";
import { Context } from "ast-types/lib/path-visitor";
import K from "ast-types/gen/kinds";
import { NodePath } from "ast-types/lib/node-path";
import assert from "assert";
import fs from "fs";
import path from "path";
import process from "process";
const checkExpression = (node: n.Node): node is K.ExpressionKind =>
n.Expression.check(node);
const checkStatement = (node: n.Node): node is K.StatementKind =>
n.Statement.check(node);
for (const file of process.argv.slice(2)) {
console.log("Parsing", file);
const ast = recast.parse(fs.readFileSync(file, { encoding: "utf8" }), {
parser: path.extname(file) === ".ts" ? tsParser : babelParser,
});
let changed = false;
let inLoop = false;
let replaceReturn = false;
const visitLoop = (...args: string[]) =>
function(this: Context, path: NodePath) {
for (const arg of args) {
this.visit(path.get(arg));
}
const old = { inLoop };
inLoop = true;
this.visit(path.get("body"));
inLoop = old.inLoop;
return false;
};
recast.visit(ast, {
visitDoWhileStatement: visitLoop("test"),
visitExpressionStatement(path) {
const { expression, comments } = path.node;
let valueOnly;
if (
n.CallExpression.check(expression) &&
n.MemberExpression.check(expression.callee) &&
!expression.callee.computed &&
n.Identifier.check(expression.callee.object) &&
expression.callee.object.name === "_" &&
n.Identifier.check(expression.callee.property) &&
["each", "forEach"].includes(expression.callee.property.name) &&
[2, 3].includes(expression.arguments.length) &&
checkExpression(expression.arguments[0]) &&
(n.FunctionExpression.check(expression.arguments[1]) ||
n.ArrowFunctionExpression.check(expression.arguments[1])) &&
[1, 2].includes(expression.arguments[1].params.length) &&
n.Identifier.check(expression.arguments[1].params[0]) &&
((valueOnly = expression.arguments[1].params[1] === undefined) ||
n.Identifier.check(expression.arguments[1].params[1])) &&
(expression.arguments[2] === undefined ||
n.ThisExpression.check(expression.arguments[2]))
) {
const old = { inLoop, replaceReturn };
inLoop = false;
replaceReturn = true;
this.visit(
path
.get("expression")
.get("arguments")
.get(1)
.get("body")
);
inLoop = old.inLoop;
replaceReturn = old.replaceReturn;
const [right, { body, params }] = expression.arguments;
const loop = b.forOfStatement(
b.variableDeclaration("let", [
b.variableDeclarator(
valueOnly ? params[0] : b.arrayPattern([params[1], params[0]])
),
]),
valueOnly
? right
: b.callExpression(
b.memberExpression(right, b.identifier("entries")),
[]
),
checkStatement(body) ? body : b.expressionStatement(body)
);
loop.comments = comments;
path.replace(loop);
changed = true;
}
this.traverse(path);
},
visitForStatement: visitLoop("init", "test", "update"),
visitForInStatement: visitLoop("left", "right"),
visitForOfStatement: visitLoop("left", "right"),
visitFunction(path) {
this.visit(path.get("params"));
const old = { replaceReturn };
replaceReturn = false;
this.visit(path.get("body"));
replaceReturn = old.replaceReturn;
return false;
},
visitReturnStatement(path) {
if (replaceReturn) {
assert(!inLoop); // could use labeled continue if this ever fires
const { argument, comments } = path.node;
if (argument === null) {
const s = b.continueStatement();
s.comments = comments;
path.replace(s);
} else {
const s = b.expressionStatement(argument);
s.comments = comments;
path.replace(s, b.continueStatement());
}
return false;
}
this.traverse(path);
},
visitWhileStatement: visitLoop("test"),
});
if (changed) {
console.log("Writing", file);
fs.writeFileSync(file, recast.print(ast).code, { encoding: "utf8" });
}
}
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-07 14:09:47 -08:00
Anders Kaseorg
b3f63262af
lint: Delegate console.log check to ESLint.
...
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-07 14:09:47 -08:00
Anders Kaseorg
c48eb3d827
extract_people_from_message: Add missing default case.
...
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-07 14:09:47 -08:00
Anders Kaseorg
f912572887
settings_profile_fields: Iterate over field_data with Object.entries.
...
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-07 14:09:47 -08:00
Anders Kaseorg
dd10108c24
user_status: Iterate over page_params.user_status with Object.entries.
...
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-07 14:09:47 -08:00
Anders Kaseorg
91d3d5d9df
settings_org: Iterate over auth_methods with Object.entries.
...
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-07 14:09:47 -08:00
Anders Kaseorg
a9f5730270
drafts: Iterate over drafts with Object.entries.
...
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-07 14:09:47 -08:00
Anders Kaseorg
0d05decbe4
presence: Iterate over presence info with Object.entries.
...
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-07 14:09:47 -08:00
Anders Kaseorg
10edd2d0a1
server_events_dispatch: Iterate over event data with Object.entries.
...
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-07 14:09:47 -08:00
Anders Kaseorg
8bb515dbd9
emoji: Iterate over emoji_codes data with Object.{entries,values}.
...
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-07 14:09:47 -08:00
Anders Kaseorg
5de013b11e
emoji: Iterate over realm_emoji with Object.values.
...
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-07 14:09:47 -08:00
Anders Kaseorg
07602c4aac
message_edit: Convert currently_echoing_messages from object to Map.
...
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-06 17:24:43 -08:00
Anders Kaseorg
b8c8ba544d
message_edit: Convert currently_editing_messages from object to Map.
...
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-06 17:24:43 -08:00
Anders Kaseorg
52a8449a0e
widgetize: Convert widget_contents from object to Map.
...
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-06 17:24:43 -08:00
Anders Kaseorg
56436188a4
widgetize: Convert widgets from object to Map.
...
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-06 17:24:43 -08:00
Anders Kaseorg
88c73602e0
vdom: Convert new_dict, old_dict from object to Map.
...
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-06 17:24:43 -08:00
Anders Kaseorg
737efd1fac
presence: Convert presence_info from object to Map.
...
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-06 17:24:43 -08:00
Anders Kaseorg
cbe476721c
message_store: Convert stored_messages from object to Map.
...
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-06 17:24:43 -08:00
Anders Kaseorg
442ff64836
notifications: Convert notice_memory from object to Map.
...
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-06 17:24:43 -08:00
Anders Kaseorg
44b3b7cf4a
emoji: Convert default_emoji_aliases from object to Map.
...
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-06 17:24:43 -08:00
Anders Kaseorg
362ab8838b
emoji: Convert active_realm_emojis from object to Map.
...
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-06 17:24:43 -08:00
Anders Kaseorg
419666fc31
emoji: Convert all_realm_emojis from object to Map.
...
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-06 17:24:43 -08:00
Anders Kaseorg
ab93385106
emoji: Convert emojis_by_name from object to Map.
...
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-06 17:24:43 -08:00
Steve Howell
58859ab115
unread: Remove topic counts.
...
We no longer use topic counts from unread.get_counts().
The topic list widget instead calls
unread.num_unread_for_topic().
2020-02-05 13:04:16 -08:00
Steve Howell
f0e18b3b3e
topic list: Use vdom techniques.
...
We avoid complicated code to update unread counts
by just using vdom.js.
One small change here is that if click on "more
topics", we replace it with the spinner instead
of putting the spinner after it. This saves us
a redraw under the new scheme.
2020-02-05 13:04:16 -08:00
Steve Howell
3a533dbe8f
vdom: Add replace_content/find parameters.
...
This will give us a bit more flexibility for
updating DOM when we have widgets that
get appended to other containers.
2020-02-05 13:04:16 -08:00
Steve Howell
b8f01f9cda
people: Rename method to get_by_user_id().
...
This name is consistent with:
get_by_email()
get_by_name()
2020-02-05 12:04:56 -08:00
Anders Kaseorg
ea9212a92d
babel: Enable loose mode.
...
Due to try-catch deoptimization, Babel strict mode for…of loops run
about 5× slower in Firefox than Babel loose mode for…of, native
for…of, or forEach (which are all about the same speed). Chrome
doesn’t seem to care.
For some reason we need to explicitly add the core-js Symbol polyfill
near the beginning of the common bundle. Otherwise it gets loaded at
the wrong time and the Casper tests fail.
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-05 11:52:52 -08:00