create-expo-cljs-app
Version:
Create a react native application with Expo and Shadow-CLJS!
234 lines (204 loc) • 5.58 kB
JavaScript
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*
* @format
*/
;
function ownKeys(object, enumerableOnly) {
var keys = Object.keys(object);
if (Object.getOwnPropertySymbols) {
var symbols = Object.getOwnPropertySymbols(object);
if (enumerableOnly)
symbols = symbols.filter(function(sym) {
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
});
keys.push.apply(keys, symbols);
}
return keys;
}
function _objectSpread(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i] != null ? arguments[i] : {};
if (i % 2) {
ownKeys(Object(source), true).forEach(function(key) {
_defineProperty(target, key, source[key]);
});
} else if (Object.getOwnPropertyDescriptors) {
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
} else {
ownKeys(Object(source)).forEach(function(key) {
Object.defineProperty(
target,
key,
Object.getOwnPropertyDescriptor(source, key)
);
});
}
}
return target;
}
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
} // This is only a typeof import, no runtime dependency exists
// eslint-disable-next-line import/no-extraneous-dependencies
function constantFoldingPlugin(context) {
const t = context.types;
const isVariableDeclarator = t.isVariableDeclarator;
const evaluate = function(path) {
const state = {
safe: true
};
const unsafe = (path, state) => {
state.safe = false;
};
path.traverse(
{
CallExpression: unsafe,
AssignmentExpression: unsafe
},
state
);
try {
if (!state.safe) {
return {
confident: false,
value: null
};
}
const evaluated = path.evaluate();
return {
confident: evaluated.confident,
value: evaluated.value
};
} catch {
return {
confident: false,
value: null
};
}
};
const FunctionDeclaration = {
exit(path, state) {
const binding =
path.node.id != null && path.scope.getBinding(path.node.id.name);
if (binding && !binding.referenced) {
state.stripped = true;
path.remove();
}
}
};
const FunctionExpression = {
exit(path, state) {
const parentPath = path.parentPath;
const parentNode =
parentPath === null || parentPath === void 0 ? void 0 : parentPath.node;
if (isVariableDeclarator(parentNode) && parentNode.id.name != null) {
const binding =
parentPath === null || parentPath === void 0
? void 0
: parentPath.scope.getBinding(parentNode.id.name);
if (binding && !binding.referenced) {
state.stripped = true;
parentPath === null || parentPath === void 0
? void 0
: parentPath.remove();
}
}
}
};
const Conditional = {
exit(path, state) {
const node = path.node;
const result = evaluate(path.get("test"));
if (result.confident) {
state.stripped = true;
if (result.value || node.alternate) {
// $FlowFixMe Flow error uncovered by typing Babel more strictly
path.replaceWith(result.value ? node.consequent : node.alternate);
} else if (!result.value) {
path.remove();
}
}
}
};
const Expression = {
exit(path) {
const result = evaluate(path);
if (result.confident) {
path.replaceWith(t.valueToNode(result.value));
path.skip();
}
}
};
const LogicalExpression = {
exit(path) {
const node = path.node;
const result = evaluate(path.get("left"));
if (result.confident) {
const value = result.value;
switch (node.operator) {
case "||":
path.replaceWith(value ? node.left : node.right);
break;
case "&&":
path.replaceWith(value ? node.right : node.left);
break;
case "??":
path.replaceWith(value == null ? node.right : node.left);
break;
}
}
}
};
const Program = {
enter(path, state) {
state.stripped = false;
},
exit(path, state) {
path.traverse(
{
ArrowFunctionExpression: FunctionExpression,
ConditionalExpression: Conditional,
FunctionDeclaration,
FunctionExpression,
IfStatement: Conditional
},
state
);
if (state.stripped) {
path.scope.crawl(); // Re-traverse all program, if we removed any blocks. Manually re-call
// enter and exit, because traversing a Program node won't call them.
Program.enter(path, state);
path.traverse(visitor, {
stripped: false
});
Program.exit(path, state);
}
}
};
const visitor = {
BinaryExpression: Expression,
LogicalExpression,
Program: _objectSpread({}, Program),
// Babel mutates objects passed.
UnaryExpression: Expression
};
return {
visitor
};
}
module.exports = constantFoldingPlugin;