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 ===
34 p.parentPath.parentPath.node &&
35 !p.parentPath.parentPath.node.alternate
36 ) {
37 p = p.parentPath.parentPath.parentPath;
38 } else if (
39 t.isIfStatement(p.parentPath.parentPath.node) &&
40 p.parentPath.parentPath.node.consequent === p.parentPath.node &&
41 !p.parentPath.parentPath.node.alternate
42 ) {
43 p = path.parentPath.parentPath;
44 } else {
45 break;
46 }
47 }
48
49 p.replaceWith(wrapWithDevCheck({ NODE: p.node }));
50 } else if (name === 'invariant') {
51 path.node[visited] = true;
52 path.node.arguments.length = 1;
53 }
54 },
55 },
56 };
57};
58
59export default plugin;