Mirror: The small sibling of the graphql package, slimmed down for client-side libraries.
1const visited = 'visitedByTransformDevAssert';
2
3const warningDevCheckTemplate = `
4 if (false) {
5 NODE;
6 }
7`.trim();
8
9const plugin = ({ template, types: t }) => {
10 const wrapWithDevCheck = template(warningDevCheckTemplate, {
11 placeholderPattern: /^NODE$/,
12 });
13
14 return {
15 visitor: {
16 CallExpression(path) {
17 const { name } = path.node.callee;
18 if (path.node[visited]) return;
19
20 if (name === 'devAssert') {
21 path.node[visited] = true;
22
23 // The production-check may be hoisted if the parent
24 // is already an if-statement only containing the
25 // warn call
26 let p = path;
27 while (t.isExpressionStatement(p.parentPath.node)) {
28 if (
29 t.isBlockStatement(p.parentPath.parentPath.node) &&
30 p.parentPath.parentPath.node.body.length === 1 &&
31 p.parentPath.parentPath.node.body[0] === path.parentPath.node &&
32 t.isIfStatement(p.parentPath.parentPath.parentPath.node) &&
33 p.parentPath.parentPath.parentPath.node.consequent === p.parentPath.parentPath.node &&
34 !p.parentPath.parentPath.node.alternate
35 ) {
36 p = p.parentPath.parentPath.parentPath;
37 } else if (
38 t.isIfStatement(p.parentPath.parentPath.node) &&
39 p.parentPath.parentPath.node.consequent === p.parentPath.node &&
40 !p.parentPath.parentPath.node.alternate
41 ) {
42 p = path.parentPath.parentPath;
43 } else {
44 break;
45 }
46 }
47
48 p.replaceWith(wrapWithDevCheck({ NODE: p.node }));
49 } else if (name === 'invariant') {
50 path.node[visited] = true;
51 path.node.arguments.length = 1;
52 }
53 },
54 },
55 };
56};
57
58export default plugin;