Changing front

This commit is contained in:
ewandor committed 2023-01-16 17:49:38 +01:00
1 parent 0b8a93b256
commit 4fe4be7730
48586 files changed
+4725790 -17464

No files matched your search

+201
View File
@@ -0,0 +1,201 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = _default;
var _template = require("@babel/template");
var _t = require("@babel/types");
const {
NOT_LOCAL_BINDING,
cloneNode,
identifier,
isAssignmentExpression,
isAssignmentPattern,
isFunction,
isIdentifier,
isLiteral,
isNullLiteral,
isObjectMethod,
isObjectProperty,
isRegExpLiteral,
isRestElement,
isTemplateLiteral,
isVariableDeclarator,
toBindingIdentifierName
} = _t;
function getFunctionArity(node) {
const count = node.params.findIndex(param => isAssignmentPattern(param) || isRestElement(param));
return count === -1 ? node.params.length : count;
}
const buildPropertyMethodAssignmentWrapper = _template.default.statement(`
(function (FUNCTION_KEY) {
function FUNCTION_ID() {
return FUNCTION_KEY.apply(this, arguments);
}
FUNCTION_ID.toString = function () {
return FUNCTION_KEY.toString();
}
return FUNCTION_ID;
})(FUNCTION)
`);
const buildGeneratorPropertyMethodAssignmentWrapper = _template.default.statement(`
(function (FUNCTION_KEY) {
function* FUNCTION_ID() {
return yield* FUNCTION_KEY.apply(this, arguments);
}
FUNCTION_ID.toString = function () {
return FUNCTION_KEY.toString();
};
return FUNCTION_ID;
})(FUNCTION)
`);
const visitor = {
"ReferencedIdentifier|BindingIdentifier"(path, state) {
if (path.node.name !== state.name) return;
const localDeclar = path.scope.getBindingIdentifier(state.name);
if (localDeclar !== state.outerDeclar) return;
state.selfReference = true;
path.stop();
}
};
function getNameFromLiteralId(id) {
if (isNullLiteral(id)) {
return "null";
}
if (isRegExpLiteral(id)) {
return `_${id.pattern}_${id.flags}`;
}
if (isTemplateLiteral(id)) {
return id.quasis.map(quasi => quasi.value.raw).join("");
}
if (id.value !== undefined) {
return id.value + "";
}
return "";
}
function wrap(state, method, id, scope) {
if (state.selfReference) {
if (scope.hasBinding(id.name) && !scope.hasGlobal(id.name)) {
scope.rename(id.name);
} else {
if (!isFunction(method)) return;
let build = buildPropertyMethodAssignmentWrapper;
if (method.generator) {
build = buildGeneratorPropertyMethodAssignmentWrapper;
}
const template = build({
FUNCTION: method,
FUNCTION_ID: id,
FUNCTION_KEY: scope.generateUidIdentifier(id.name)
}).expression;
const params = template.callee.body.body[0].params;
for (let i = 0, len = getFunctionArity(method); i < len; i++) {
params.push(scope.generateUidIdentifier("x"));
}
return template;
}
}
method.id = id;
scope.getProgramParent().references[id.name] = true;
}
function visit(node, name, scope) {
const state = {
selfAssignment: false,
selfReference: false,
outerDeclar: scope.getBindingIdentifier(name),
name: name
};
const binding = scope.getOwnBinding(name);
if (binding) {
if (binding.kind === "param") {
state.selfReference = true;
} else {}
} else if (state.outerDeclar || scope.hasGlobal(name)) {
scope.traverse(node, visitor, state);
}
return state;
}
function _default({
node,
parent,
scope,
id
}, localBinding = false, supportUnicodeId = false) {
if (node.id) return;
if ((isObjectProperty(parent) || isObjectMethod(parent, {
kind: "method"
})) && (!parent.computed || isLiteral(parent.key))) {
id = parent.key;
} else if (isVariableDeclarator(parent)) {
id = parent.id;
if (isIdentifier(id) && !localBinding) {
const binding = scope.parent.getBinding(id.name);
if (binding && binding.constant && scope.getBinding(id.name) === binding) {
node.id = cloneNode(id);
node.id[NOT_LOCAL_BINDING] = true;
return;
}
}
} else if (isAssignmentExpression(parent, {
operator: "="
})) {
id = parent.left;
} else if (!id) {
return;
}
let name;
if (id && isLiteral(id)) {
name = getNameFromLiteralId(id);
} else if (id && isIdentifier(id)) {
name = id.name;
}
if (name === undefined) {
return;
}
if (!supportUnicodeId && isFunction(node) && /[\uD800-\uDFFF]/.test(name)) {
return;
}
name = toBindingIdentifierName(name);
const newId = identifier(name);
newId[NOT_LOCAL_BINDING] = true;
const state = visit(node, name, scope);
return wrap(state, node, newId, scope) || node;
}
//# sourceMappingURL=index.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"names":["NOT_LOCAL_BINDING","cloneNode","identifier","isAssignmentExpression","isAssignmentPattern","isFunction","isIdentifier","isLiteral","isNullLiteral","isObjectMethod","isObjectProperty","isRegExpLiteral","isRestElement","isTemplateLiteral","isVariableDeclarator","toBindingIdentifierName","getFunctionArity","node","count","params","findIndex","param","length","buildPropertyMethodAssignmentWrapper","template","statement","buildGeneratorPropertyMethodAssignmentWrapper","visitor","path","state","name","localDeclar","scope","getBindingIdentifier","outerDeclar","selfReference","stop","getNameFromLiteralId","id","pattern","flags","quasis","map","quasi","value","raw","join","undefined","wrap","method","hasBinding","hasGlobal","rename","build","generator","FUNCTION","FUNCTION_ID","FUNCTION_KEY","generateUidIdentifier","expression","callee","body","i","len","push","getProgramParent","references","visit","selfAssignment","binding","getOwnBinding","kind","traverse","parent","localBinding","supportUnicodeId","computed","key","getBinding","constant","operator","left","test","newId"],"sources":["../src/index.ts"],"sourcesContent":["import template from \"@babel/template\";\nimport {\n NOT_LOCAL_BINDING,\n cloneNode,\n identifier,\n isAssignmentExpression,\n isAssignmentPattern,\n isFunction,\n isIdentifier,\n isLiteral,\n isNullLiteral,\n isObjectMethod,\n isObjectProperty,\n isRegExpLiteral,\n isRestElement,\n isTemplateLiteral,\n isVariableDeclarator,\n toBindingIdentifierName,\n} from \"@babel/types\";\nimport type * as t from \"@babel/types\";\nimport type { NodePath, Scope, Visitor } from \"@babel/traverse\";\n\nfunction getFunctionArity(node: t.Function): number {\n const count = node.params.findIndex(\n param => isAssignmentPattern(param) || isRestElement(param),\n );\n return count === -1 ? node.params.length : count;\n}\n\nconst buildPropertyMethodAssignmentWrapper = template.statement(`\n (function (FUNCTION_KEY) {\n function FUNCTION_ID() {\n return FUNCTION_KEY.apply(this, arguments);\n }\n\n FUNCTION_ID.toString = function () {\n return FUNCTION_KEY.toString();\n }\n\n return FUNCTION_ID;\n })(FUNCTION)\n`);\n\nconst buildGeneratorPropertyMethodAssignmentWrapper = template.statement(`\n (function (FUNCTION_KEY) {\n function* FUNCTION_ID() {\n return yield* FUNCTION_KEY.apply(this, arguments);\n }\n\n FUNCTION_ID.toString = function () {\n return FUNCTION_KEY.toString();\n };\n\n return FUNCTION_ID;\n })(FUNCTION)\n`);\n\ntype State = {\n name: string;\n outerDeclar: t.Identifier;\n selfAssignment: boolean;\n selfReference: boolean;\n};\n\nconst visitor: Visitor<State> = {\n \"ReferencedIdentifier|BindingIdentifier\"(\n path: NodePath<t.Identifier>,\n state,\n ) {\n // check if this node matches our function id\n if (path.node.name !== state.name) return;\n\n // check that we don't have a local variable declared as that removes the need\n // for the wrapper\n const localDeclar = path.scope.getBindingIdentifier(state.name);\n if (localDeclar !== state.outerDeclar) return;\n\n state.selfReference = true;\n path.stop();\n },\n};\n\nfunction getNameFromLiteralId(id: t.Literal) {\n if (isNullLiteral(id)) {\n return \"null\";\n }\n\n if (isRegExpLiteral(id)) {\n return `_${id.pattern}_${id.flags}`;\n }\n\n if (isTemplateLiteral(id)) {\n return id.quasis.map(quasi => quasi.value.raw).join(\"\");\n }\n\n if (id.value !== undefined) {\n return id.value + \"\";\n }\n\n return \"\";\n}\n\nfunction wrap(\n state: State,\n method: t.FunctionExpression | t.Class,\n id: t.Identifier,\n scope: Scope,\n) {\n if (state.selfReference) {\n if (scope.hasBinding(id.name) && !scope.hasGlobal(id.name)) {\n // we can just munge the local binding\n scope.rename(id.name);\n } else {\n // we don't currently support wrapping class expressions\n if (!isFunction(method)) return;\n\n // need to add a wrapper since we can't change the references\n let build = buildPropertyMethodAssignmentWrapper;\n if (method.generator) {\n build = buildGeneratorPropertyMethodAssignmentWrapper;\n }\n\n const template = (\n build({\n FUNCTION: method,\n FUNCTION_ID: id,\n FUNCTION_KEY: scope.generateUidIdentifier(id.name),\n }) as t.ExpressionStatement\n ).expression as t.CallExpression;\n\n // shim in dummy params to retain function arity, if you try to read the\n // source then you'll get the original since it's proxied so it's all good\n const params = (\n (template.callee as t.FunctionExpression).body\n .body[0] as any as t.FunctionExpression\n ).params;\n\n for (let i = 0, len = getFunctionArity(method); i < len; i++) {\n params.push(scope.generateUidIdentifier(\"x\"));\n }\n\n return template;\n }\n }\n\n method.id = id;\n scope.getLine truncated