You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
52 lines
1.2 KiB
JavaScript
52 lines
1.2 KiB
JavaScript
"use strict";
|
|
|
|
const assert = require("assert");
|
|
|
|
const acceptableFirstCharacters = /^[a-zA-Z_]$/;
|
|
const acceptableSubsequentCharacters = /^[0-9a-zA-Z_]$/;
|
|
|
|
const reservedWords = new Set([
|
|
"import",
|
|
"const",
|
|
"let",
|
|
"var"
|
|
]);
|
|
|
|
// This function deterministically and statelessly translates a name such that it is guaranteed to be valid in all identifier positions in JS.
|
|
// TODO: This can probably be made more performant...
|
|
|
|
function mangleCharacter(character) {
|
|
return (character === "$")
|
|
? "$$"
|
|
: `$${character.codePointAt(0)}`;
|
|
}
|
|
|
|
module.exports = function mangleName(name) {
|
|
assert(name.length > 0);
|
|
|
|
if (reservedWords.has(name)) {
|
|
return "$" + name;
|
|
} else if (name.startsWith("$")) {
|
|
// FIXME: Tag an identifier of this type with an internal property instead
|
|
return name;
|
|
} else {
|
|
let completedFirstCharacter = false;
|
|
|
|
return Array.from(name)
|
|
.map((character) => {
|
|
if (!completedFirstCharacter) {
|
|
completedFirstCharacter = true;
|
|
|
|
return (acceptableFirstCharacters.test(character))
|
|
? character
|
|
: mangleCharacter(character);
|
|
} else {
|
|
return (acceptableSubsequentCharacters.test(character))
|
|
? character
|
|
: mangleCharacter(character);
|
|
}
|
|
})
|
|
.join("");
|
|
}
|
|
};
|