Skip to content

Instantly share code, notes, and snippets.

@julianburr
Created April 25, 2018 22:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save julianburr/95a0c6f5c5d04e23af7deb16119ea00c to your computer and use it in GitHub Desktop.
Save julianburr/95a0c6f5c5d04e23af7deb16119ea00c to your computer and use it in GitHub Desktop.
Babel plugin for safe reading and setting of deeply nested objects in js
const exceptions = ["console"];
function getExp(node, all) {
let str = all;
let id = "";
if (node.property.type === "Identifier") {
str = `.${node.property.name}${str ? str : ""}`;
} else if (node.property.type === "NumericLiteral") {
str = `.${node.property.value}${str ? str : ""}`;
} else if (node.property.type === "StringLiteral") {
str = `[${node.property.value}]${str ? str : ""}`;
}
if (node.object.type === "MemberExpression") {
const get = getExp(node.object, str);
str = get.str;
id = get.id;
} else if (node.object.type === "Identifier") {
id = node.object.name;
} else if (node.object.type === "ThisExpression") {
id = "this";
}
return { str, id };
}
export default function(babel) {
const { types: t } = babel;
return {
name: "ast-transform", // not required
visitor: {
AssignmentExpression(path) {
console.log("path", path);
if (path.node.left && path.node.left.type === "MemberExpression") {
const exp = getExp(path.node.left);
const newNode = t.callExpression(t.identifier("safeSet"), [
t.identifier(exp.id),
t.stringLiteral(exp.str.substr(1)),
path.node.right
]);
path.replaceWith(newNode);
}
},
MemberExpression(path) {
if (path.parent && path.parent.type === "AssignmentExpression") {
} else {
const exp = getExp(path.node);
const newNode = t.callExpression(t.identifier("safeRead"), [
t.identifier(exp.id),
t.stringLiteral(exp.str.substr(1))
]);
if (!exceptions.includes(exp.id)) {
path.replaceWith(newNode);
}
}
}
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment