Anders Kaseorg
21d432e12c
zjsunit: Deglobalize run_test.
...
Signed-off-by: Anders Kaseorg <anders@zulip.com >
2020-12-01 07:14:00 -05:00
Anders Kaseorg
425f1789e2
zjsunit: Deglobalize namespace.
...
Signed-off-by: Anders Kaseorg <anders@zulip.com >
2020-12-01 07:14:00 -05:00
Anders Kaseorg
7b03d48798
zjsunit: Deglobalize assert.
...
Signed-off-by: Anders Kaseorg <anders@zulip.com >
2020-12-01 07:14:00 -05:00
Anders Kaseorg
6ec808b8df
js: Add "use strict" directive to CommonJS files.
...
ES and TypeScript modules are strict by default and don’t need this
directive. ESLint will remind us to add it to new CommonJS files and
remove it from ES and TypeScript modules.
Signed-off-by: Anders Kaseorg <anders@zulip.com >
2020-07-31 22:09:46 -07:00
Anders Kaseorg
d2520cd7e0
js: Replace underscore with lodash and remove it from globals.
...
Tweaked by tabbott to bump PROVISION_VERSION.
Signed-off-by: Anders Kaseorg <anders@zulip.com >
2020-07-26 16:12:06 -07:00
Anders Kaseorg
96dcc0ce6e
js: Use ES6 object literal shorthand syntax.
...
Generated by ESLint.
Signed-off-by: Anders Kaseorg <anders@zulip.com >
2020-07-21 12:42:22 -07:00
Anders Kaseorg
b65d2e063d
js: Reformat with Prettier.
...
Signed-off-by: Anders Kaseorg <anders@zulip.com >
2020-07-17 14:31:25 -07:00
Anders Kaseorg
f3726db89a
js: Normalize strings to double quotes.
...
Prettier would do this anyway, but it’s separated out for a more
reviewable diff. Generated by ESLint.
Signed-off-by: Anders Kaseorg <anders@zulip.com >
2020-07-17 14:31:24 -07:00
Anders Kaseorg
615b7fcc2c
eslint: Enable arrow-body-style.
...
Signed-off-by: Anders Kaseorg <anders@zulip.com >
2020-07-03 16:55:50 -07:00
Anders Kaseorg
b0253c5a2e
eslint: Enable arrow-parens.
...
Signed-off-by: Anders Kaseorg <anders@zulip.com >
2020-07-03 16:53:39 -07:00
Hashir Sarwar
ee0d4541b4
topic_data: Rename topic_data module to stream_topic_history.
...
`stream_topic_history` is a more appropriate name as this
module will contain information about last message of a
stream in upcoming commits. Function and variable names
are changed accordingly like:
* topic_history() -> per_stream_history()
* get_recent_names() -> get_recent_topic_names()
* name -> topic_name
2020-04-16 20:11:04 -07:00
Steve Howell
b994889315
node tests: Just set i18n every time.
...
Explicitly stubbing i18n in 48 different files
is mostly busy work at this point, and it doesn't
provide much signal, since often it's invoked
only to satisfy transitive dependencies.
2020-02-28 17:11:24 -08:00
Anders Kaseorg
4358d0f364
tests: Convert unread_cnt from object to Map.
...
Signed-off-by: Anders Kaseorg <anders@zulipchat.com >
2020-02-12 10:39:01 -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
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
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
Ryan Rehman
174b2abcfd
settings: Migrate to stream_post_policy structure.
...
This commit includes a new `stream_post_policy` setting,
by replacing the `is_announcement_only` field from the Stream model,
which is done by mirroring the structure of the existing
`create_stream_policy`.
It includes the necessary schema and database migrations to migrate
the is_announcement_only boolean field to stream_post_policy,
a smallPositiveInteger field similar to many other settings.
This change is done to allow organization administrators to restrict
new members from creating and posting to a stream. However, this does
not affect admins who are new members.
With many tweaks by tabbott to documentation under /help, etc.
Fixes #13616 .
2020-02-04 17:08:08 -08:00
Steve Howell
a0712ab798
minor: Consolidate vars for max topics.
...
The two vars here got split apart for temporary
logistical reasons during a recent refactoring.
Now they're just both at the top of
topic_list_data.
2020-01-30 12:15:40 -08:00
Steve Howell
f24de074d4
node tests: Get 100% coverage on topic_list_data.
2020-01-22 14:31:33 -08:00
Steve Howell
fa82d12525
topic list: Extract topic_list_data.js.
...
This is mostly for tactical reasons. It's hard to
get 100% test coverage on topic_list.js, but it
should be easy to get 100% test coverage on this
very important function.
I considered just moving this code into topic_data.js,
but it just didn't feel quite right. I feel like
this is a pretty core piece of code that's nice
to be by itself and not be near other complicated
code that does stuff like build widgets or talk
to servers. (And, again, it's not just the actual
code here, which is pretty small, it's the unit
tests, which are inherently verbose to exercise
all the edge cases.)
2020-01-22 14:31:33 -08:00