README
transform-quadruple-equal
Inspiration
==== ("really strict equals", same as{' '} https://t.co/LMVvSIFdpx)
— getify (@getify) July 22, 2020
Babel Plugin
💡 The Idea
This is something you can't just do with babel transform plugin.
Because the following:
a ==== b
is not a valid JavaScript syntax.
So, we need to first fork the babel parser.
To add support a new operator, we update the tokenizer to recognise one extra =
character:
// filename: https://github.com/babel/babel/tree/master/packages/babel-parser/src/tokenizer/index.js
export default class Tokenizer extends ParserErrors {
// ...
readToken_eq_excl(code: number): void {
// '=!'
const next = this.input.charCodeAt(this.state.pos + 1);
if (next === charCodes.equalsTo) {
this.finishOp(
tt.equality,
- this.input.charCodeAt(this.state.pos + 2) === charCodes.equalsTo ? 3 : 2
+ this.input.charCodeAt(this.state.pos + 2) === charCodes.equalsTo
+ ? this.input.charCodeAt(this.state.pos + 3) === charCodes.equalsTo
+ ? 4
+ : 3
+ : 2
);
return;
}
// ...
}
}
Now as ====
and !===
become a valid token, babel will it treat it the same way as ===
and !==
token.
The Babel plugin itself is straightforward.
a ==== b
will form a binary expression, and we are going to transform it into Object.is(a, b)
.
a ==== b;
c !=== d;
// into
Object.is(a, b);
!Object.is(c, d);
📘 The Code
export default function ({ template }) {
return {
name: 'transform-quadruple-equal',
visitor: {
BinaryExpression(path) {
if (path.node.operator === '====') {
path.replaceWith(
template.expression`Object.is(${path.node.left}, ${path.node.right})`()
);
} else if (path.node.operator === '!===') {
path.replaceWith(
template.expression`!Object.is(${path.node.left}, ${path.node.right})`()
);
}
},
},
};
}
Over here I used babel.template which provides utility functions to create Babel AST using tagged template literal.