1
0
mirror of https://github.com/misskey-dev/misskey.git synced 2026-05-25 20:13:57 +02:00

Revert "deps: Update vite to v8" (#17283)

Revert "deps: Update vite to v8 (#17238)"

This reverts commit e601fcb729.
This commit is contained in:
かっこかり
2026-04-06 20:15:57 +09:00
committed by GitHub
parent 0b7b59f1e2
commit a18c909ba3
16 changed files with 735 additions and 1553 deletions

View File

@@ -3,16 +3,17 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
import * as estreeWalker from 'estree-walker';
import { generate } from 'astring';
import { walk } from '../node_modules/estree-walker/src/index.js';
import type * as estree from 'estree';
import type * as estreeWalker from 'estree-walker';
import type { Plugin } from 'vite';
import type { ESTree } from 'rolldown/utils';
import { RolldownMagicString } from 'rolldown';
function isFalsyIdentifier(identifier: Extract<ESTree.Node, { type: 'Identifier' }>): boolean {
function isFalsyIdentifier(identifier: estree.Identifier): boolean {
return identifier.name === 'undefined' || identifier.name === 'NaN';
}
function normalizeClassWalker(tree: ESTree.Node, stack: string | undefined): string | null {
function normalizeClassWalker(tree: estree.Node, stack: string | undefined): string | null {
if (tree.type === 'Identifier') return isFalsyIdentifier(tree) ? '' : null;
if (tree.type === 'Literal') return typeof tree.value === 'string' ? tree.value : '';
if (tree.type === 'BinaryExpression') {
@@ -25,7 +26,7 @@ function normalizeClassWalker(tree: ESTree.Node, stack: string | undefined): str
if (tree.type === 'TemplateLiteral') {
if (tree.expressions.some((x) => x.type !== 'Literal' && (x.type !== 'Identifier' || !isFalsyIdentifier(x)))) return null;
return tree.quasis.reduce((a, c, i) => {
const v = i === tree.quasis.length - 1 ? '' : (tree.expressions[i] as Partial<Extract<ESTree.Node, { type: 'Literal' }>>).value;
const v = i === tree.quasis.length - 1 ? '' : (tree.expressions[i] as Partial<estree.Literal>).value;
return a + c.value.raw + (typeof v === 'string' ? v : '');
}, '');
}
@@ -71,144 +72,44 @@ function normalizeClassWalker(tree: ESTree.Node, stack: string | undefined): str
tree.type !== 'ChainExpression' &&
tree.type !== 'ConditionalExpression' &&
tree.type !== 'LogicalExpression' &&
tree.type !== 'MemberExpression'
) {
tree.type !== 'MemberExpression') {
console.error(stack ? `Unexpected node type: ${tree.type} (in ${stack})` : `Unexpected node type: ${tree.type}`);
}
return null;
}
export function normalizeClass(tree: ESTree.Node, stack?: string): string | null {
export function normalizeClass(tree: estree.Node, stack?: string): string | null {
const walked = normalizeClassWalker(tree, stack);
return walked && walked.replace(/^\s+|\s+(?=\s)|\s+$/g, '');
}
function getPropertyName(node: ESTree.Node, computed: boolean): string | null {
if (node.type === 'Identifier') return computed ? null : node.name;
if (node.type === 'Literal' && typeof node.value === 'string') return node.value;
return null;
}
function getMemberPropertyName(node: ESTree.MemberExpression['property'], computed: boolean): string | null {
if (node.type === 'Identifier') return computed ? null : node.name;
if (node.type === 'Literal' && typeof node.value === 'string') return node.value;
return null;
}
function findVariableDeclaration(program: ESTree.Program, name: string): ESTree.VariableDeclaration | null {
return program.body.find((x) => {
if (x.type !== 'VariableDeclaration') return false;
if (x.declarations.length !== 1) return false;
if (x.declarations[0].id.type !== 'Identifier') return false;
return x.declarations[0].id.name === name;
}) as ESTree.VariableDeclaration | null;
}
function resolveObjectExpression(program: ESTree.Program, tree: ESTree.Expression): ESTree.ObjectExpression | null {
if (tree.type === 'ObjectExpression') return tree;
if (tree.type !== 'Identifier') return null;
const declaration = findVariableDeclaration(program, tree.name);
if (declaration?.declarations[0].init?.type !== 'ObjectExpression') return null;
return declaration.declarations[0].init;
}
function resolveComponentOptions(program: ESTree.Program, tree: ESTree.Expression): ESTree.ObjectExpression | null {
const target = tree.type === 'Identifier'
? findVariableDeclaration(program, tree.name)?.declarations[0].init ?? null
: tree;
if (target?.type === 'ObjectExpression') return target;
if (target?.type !== 'CallExpression') return null;
if (target.arguments.length !== 1) return null;
if (target.arguments[0].type !== 'ObjectExpression') return null;
return target.arguments[0];
}
function resolveModuleTree(program: ESTree.Program, tree: ESTree.Expression): Map<string, string> | null {
const objectExpression = resolveObjectExpression(program, tree);
if (objectExpression === null) return null;
return new Map(objectExpression.properties.flatMap((property) => {
if (property.type !== 'Property') return [];
const actualKey = getPropertyName(property.key, property.computed);
if (actualKey === null) return [];
if (property.value.type === 'Literal') {
return typeof property.value.value === 'string' ? [[actualKey, property.value.value]] : [];
}
if (property.value.type === 'Identifier') {
const actualValue = findVariableDeclaration(program, property.value.name);
if (actualValue?.declarations[0].init?.type !== 'Literal') return [];
return typeof actualValue.declarations[0].init.value === 'string' ? [[actualKey, actualValue.declarations[0].init.value]] : [];
}
return [];
}));
}
function resolveModuleForest(program: ESTree.Program, tree: ESTree.Expression): Map<string, Map<string, string>> | null {
const objectExpression = resolveObjectExpression(program, tree);
if (objectExpression === null) return null;
return new Map(objectExpression.properties.flatMap((property) => {
if (property.type !== 'Property') return [];
const actualKey = getPropertyName(property.key, property.computed);
if (actualKey === null) return [];
const moduleTree = resolveModuleTree(program, property.value);
return moduleTree === null ? [] : [[actualKey, moduleTree]];
}));
}
function findRenderArrow(options: ESTree.ObjectExpression): Extract<ESTree.Node, { type: 'ArrowFunctionExpression' }> | null {
const setup = options.properties.find((x) => {
if (x.type !== 'Property') return false;
return getPropertyName(x.key, x.computed) === 'setup';
}) as Extract<ESTree.Node, { type: 'Property' }> | undefined;
if (setup?.value.type !== 'FunctionExpression' && setup?.value.type !== 'ArrowFunctionExpression') return null;
if (setup.value.body == null) return null;
if (setup.value.body.type !== 'BlockStatement') return null;
const render = setup.value.body.body.find((x) => x.type === 'ReturnStatement');
if (render?.type !== 'ReturnStatement') return null;
return render.argument?.type === 'ArrowFunctionExpression' ? render.argument : null;
}
function isCssModuleAccess(node: ESTree.Node, ctxName: string, key: string): node is Extract<ESTree.Node, { type: 'MemberExpression' }> {
if (node.type !== 'MemberExpression') return false;
if (node.object.type !== 'MemberExpression') return false;
if (node.object.object.type !== 'Identifier') return false;
if (node.object.object.name !== ctxName) return false;
return getMemberPropertyName(node.object.property, node.object.computed) === key;
}
function isCssModuleReference(node: ESTree.Node, ctxName: string, key: string): node is Extract<ESTree.Node, { type: 'MemberExpression' }> {
if (!isCssModuleAccess(node, ctxName, key)) return false;
return getMemberPropertyName(node.property, node.computed) !== null;
}
function isClassProperty(node: ESTree.Node | null): node is Extract<ESTree.Node, { type: 'Property' }> {
return node?.type === 'Property' && getPropertyName(node.key, node.computed) === 'class';
}
export function unwindCssModuleClassName(ast: ESTree.Node, magicString: RolldownMagicString): void {
(estreeWalker.walk as any)(ast, {
enter(node: ESTree.Node, parent: ESTree.Node | null): void {
export function unwindCssModuleClassName(ast: estree.Node): void {
(walk as typeof estreeWalker.walk)(ast, {
enter(node, parent): void {
//#region
if (parent?.type !== 'Program') return;
if (ast.type !== 'Program') return;
if (node.type !== 'VariableDeclaration') return;
if (node.declarations.length !== 1) return;
if (node.declarations[0].id.type !== 'Identifier') return;
const name = node.declarations[0].id.name;
if (node.declarations[0].init?.type !== 'CallExpression') return;
if (node.declarations[0].init.callee.type !== 'Identifier') return;
if (node.declarations[0].init.callee.name !== '_export_sfc') return;
if (node.declarations[0].init.arguments.length !== 2) return;
const componentNode = node.declarations[0].init.arguments[0];
if (componentNode.type !== 'Identifier' && componentNode.type !== 'CallExpression' && componentNode.type !== 'ObjectExpression') return;
if (node.declarations[0].init.arguments[0].type !== 'Identifier') return;
const ident = node.declarations[0].init.arguments[0].name;
if (!ident.startsWith('_sfc_main')) return;
if (node.declarations[0].init.arguments[1].type !== 'ArrayExpression') return;
if (node.declarations[0].init.arguments[1].elements.length === 0) return;
const cssModulesEntry = node.declarations[0].init.arguments[1].elements.find((x) => {
const __cssModulesIndex = node.declarations[0].init.arguments[1].elements.findIndex((x) => {
if (x?.type !== 'ArrayExpression') return false;
if (x.elements.length !== 2) return false;
if (x.elements[0]?.type !== 'Literal') return false;
if (x.elements[0].value !== '__cssModules') return false;
if (x.elements[1]?.type !== 'Identifier') return false;
return true;
}) as ESTree.ArrayExpression | undefined;
const __cssModulesIndex = node.declarations[0].init.arguments[1].elements.indexOf(cssModulesEntry ?? null);
if (cssModulesEntry === undefined || __cssModulesIndex < 0) return;
});
if (!~__cssModulesIndex) return;
/* This region assumeed that the entered node looks like the following code.
*
* ```ts
@@ -217,10 +118,21 @@ export function unwindCssModuleClassName(ast: ESTree.Node, magicString: Rolldown
*/
//#endregion
//#region
const cssModuleForest = cssModulesEntry.elements[1];
if (cssModuleForest?.type !== 'Identifier' && cssModuleForest?.type !== 'ObjectExpression') return;
const moduleForest = resolveModuleForest(ast, cssModuleForest);
if (moduleForest === null) return;
const cssModuleForestName = ((node.declarations[0].init.arguments[1].elements[__cssModulesIndex] as estree.ArrayExpression).elements[1] as estree.Identifier).name;
const cssModuleForestNode = parent.body.find((x) => {
if (x.type !== 'VariableDeclaration') return false;
if (x.declarations.length !== 1) return false;
if (x.declarations[0].id.type !== 'Identifier') return false;
if (x.declarations[0].id.name !== cssModuleForestName) return false;
if (x.declarations[0].init?.type !== 'ObjectExpression') return false;
return true;
}) as unknown as estree.VariableDeclaration;
const moduleForest = new Map((cssModuleForestNode.declarations[0].init as estree.ObjectExpression).properties.flatMap((property) => {
if (property.type !== 'Property') return [];
if (property.key.type !== 'Literal') return [];
if (property.value.type !== 'Identifier') return [];
return [[property.key.value as string, property.value.name as string]];
}));
/* This region collected a VariableDeclaration node in the module that looks like the following code.
*
* ```ts
@@ -231,13 +143,35 @@ export function unwindCssModuleClassName(ast: ESTree.Node, magicString: Rolldown
*/
//#endregion
//#region
const options = resolveComponentOptions(ast, componentNode);
if (options === null) return;
const render = findRenderArrow(options);
if (render === null) return;
if (render.params.length !== 2) return;
const ctx = render.params[0];
const sfcMain = parent.body.find((x) => {
if (x.type !== 'VariableDeclaration') return false;
if (x.declarations.length !== 1) return false;
if (x.declarations[0].id.type !== 'Identifier') return false;
if (x.declarations[0].id.name !== ident) return false;
return true;
}) as unknown as estree.VariableDeclaration;
if (sfcMain.declarations[0].init?.type !== 'CallExpression') return;
if (sfcMain.declarations[0].init.callee.type !== 'Identifier') return;
if (sfcMain.declarations[0].init.callee.name !== 'defineComponent') return;
if (sfcMain.declarations[0].init.arguments.length !== 1) return;
if (sfcMain.declarations[0].init.arguments[0].type !== 'ObjectExpression') return;
const setup = sfcMain.declarations[0].init.arguments[0].properties.find((x) => {
if (x.type !== 'Property') return false;
if (x.key.type !== 'Identifier') return false;
if (x.key.name !== 'setup') return false;
return true;
}) as unknown as estree.Property;
if (setup.value.type !== 'FunctionExpression') return;
const render = setup.value.body.body.find((x) => {
if (x.type !== 'ReturnStatement') return false;
return true;
}) as unknown as estree.ReturnStatement;
if (render.argument?.type !== 'ArrowFunctionExpression') return;
if (render.argument.params.length !== 2) return;
const ctx = render.argument.params[0];
if (ctx.type !== 'Identifier') return;
if (ctx.name !== '_ctx') return;
if (render.argument.body.type !== 'BlockStatement') return;
/* This region assumed that `sfcMain` looks like the following code.
*
* ```ts
@@ -252,8 +186,33 @@ export function unwindCssModuleClassName(ast: ESTree.Node, magicString: Rolldown
* ```
*/
//#endregion
for (const [key, moduleTree] of moduleForest) {
for (const [key, value] of moduleForest) {
//#region
const cssModuleTreeNode = parent.body.find((x) => {
if (x.type !== 'VariableDeclaration') return false;
if (x.declarations.length !== 1) return false;
if (x.declarations[0].id.type !== 'Identifier') return false;
if (x.declarations[0].id.name !== value) return false;
return true;
}) as unknown as estree.VariableDeclaration;
if (cssModuleTreeNode.declarations[0].init?.type !== 'ObjectExpression') return;
const moduleTree = new Map(cssModuleTreeNode.declarations[0].init.properties.flatMap((property) => {
if (property.type !== 'Property') return [];
const actualKey = property.key.type === 'Identifier' ? property.key.name : property.key.type === 'Literal' ? property.key.value : null;
if (typeof actualKey !== 'string') return [];
if (property.value.type === 'Literal') return [[actualKey, property.value.value as string]];
if (property.value.type !== 'Identifier') return [];
const labelledValue = property.value.name;
const actualValue = parent.body.find((x) => {
if (x.type !== 'VariableDeclaration') return false;
if (x.declarations.length !== 1) return false;
if (x.declarations[0].id.type !== 'Identifier') return false;
if (x.declarations[0].id.name !== labelledValue) return false;
return true;
}) as unknown as estree.VariableDeclaration;
if (actualValue.declarations[0].init?.type !== 'Literal') return [];
return [[actualKey, actualValue.declarations[0].init.value as string]];
}));
/* This region collected VariableDeclaration nodes in the module that looks like the following code.
*
* ```ts
@@ -267,14 +226,17 @@ export function unwindCssModuleClassName(ast: ESTree.Node, magicString: Rolldown
*/
//#endregion
//#region
(estreeWalker.walk as any)(render.body, {
enter(childNode: ESTree.Node) {
if (!isCssModuleReference(childNode, ctx.name, key)) return;
const actualKey = getMemberPropertyName(childNode.property, childNode.computed);
if (actualKey === null) return;
const actualValue = moduleTree.get(actualKey);
(walk as typeof estreeWalker.walk)(render.argument.body, {
enter(childNode) {
if (childNode.type !== 'MemberExpression') return;
if (childNode.object.type !== 'MemberExpression') return;
if (childNode.object.object.type !== 'Identifier') return;
if (childNode.object.object.name !== ctx.name) return;
if (childNode.object.property.type !== 'Identifier') return;
if (childNode.object.property.name !== key) return;
if (childNode.property.type !== 'Identifier') return;
const actualValue = moduleTree.get(childNode.property.name);
if (actualValue === undefined) return;
magicString.overwrite(childNode.start, childNode.end, JSON.stringify(actualValue));
this.replace({
type: 'Literal',
value: actualValue,
@@ -314,13 +276,20 @@ export function unwindCssModuleClassName(ast: ESTree.Node, magicString: Rolldown
*/
//#endregion
//#region
(estreeWalker.walk as any)(render.body, {
enter(childNode: ESTree.Node) {
if (!isCssModuleReference(childNode, ctx.name, key)) return;
const actualKey = getMemberPropertyName(childNode.property, childNode.computed);
if (actualKey === null) return;
console.error(`Undefined style detected: ${key}.${actualKey} (in ${name})`);
magicString.overwrite(childNode.start, childNode.end, 'undefined');
(walk as typeof estreeWalker.walk)(render.argument.body, {
enter(childNode) {
if (childNode.type !== 'MemberExpression') return;
if (childNode.object.type !== 'MemberExpression') return;
if (childNode.object.object.type !== 'Identifier') return;
if (childNode.object.object.name !== ctx.name) return;
if (childNode.object.property.type !== 'Identifier') return;
if (childNode.object.property.name !== key) return;
if (childNode.property.type !== 'Identifier') return;
console.error(`Undefined style detected: ${key}.${childNode.property.name} (in ${name})`);
this.replace({
type: 'Identifier',
name: 'undefined',
});
},
});
/* This region replaced the reference identifier of missing class names in the render function with `undefined`, as in the following code.
@@ -331,7 +300,7 @@ export function unwindCssModuleClassName(ast: ESTree.Node, magicString: Rolldown
* ...
* return (_ctx, _cache) => {
* ...
* return openBlock(), createElementBlock('div', {
* return openBlock(), createElementBlock("div", {
* class: normalizeClass(_ctx.$style.hoge),
* }, null);
* };
@@ -347,7 +316,7 @@ export function unwindCssModuleClassName(ast: ESTree.Node, magicString: Rolldown
* ...
* return (_ctx, _cache) => {
* ...
* return openBlock(), createElementBlock('div', {
* return openBlock(), createElementBlock("div", {
* class: normalizeClass(undefined),
* }, null);
* };
@@ -357,15 +326,18 @@ export function unwindCssModuleClassName(ast: ESTree.Node, magicString: Rolldown
*/
//#endregion
//#region
(estreeWalker.walk as any)(render.body, {
enter(childNode: ESTree.Node, childParent: ESTree.Node | null) {
(walk as typeof estreeWalker.walk)(render.argument.body, {
enter(childNode) {
if (childNode.type !== 'CallExpression') return;
if (childNode.callee.type !== 'Identifier') return;
if (childNode.callee.name !== 'normalizeClass') return;
if (childNode.arguments.length !== 1) return;
if (childNode.callee.type === 'Identifier' && childNode.callee.name !== 'normalizeClass' && !isClassProperty(childParent)) return;
if (childNode.callee.type !== 'Identifier' && !isClassProperty(childParent)) return;
const normalized = normalizeClass(childNode.arguments[0], name);
if (normalized === null) return;
magicString.overwrite(childNode.start, childNode.end, JSON.stringify(normalized));
this.replace({
type: 'Literal',
value: normalized,
});
},
});
/* This region compiled the `normalizeClass` call into a pseudo-AOT compilation, as in the following code.
@@ -402,34 +374,19 @@ export function unwindCssModuleClassName(ast: ESTree.Node, magicString: Rolldown
*/
//#endregion
}
const hasRemainingCssModuleReference = Array.from(moduleForest.keys()).some((key) => {
let found = false;
(estreeWalker.walk as any)(render.body, {
enter(childNode: ESTree.Node) {
if (!isCssModuleAccess(childNode, ctx.name, key)) return;
found = true;
this.skip();
},
});
return found;
});
if (hasRemainingCssModuleReference) return;
//#region
if (node.declarations[0].init.arguments[1].elements.length === 1) {
if (componentNode.type === 'Identifier') {
(estreeWalker.walk as any)(ast, {
enter(childNode: ESTree.Node) {
if (childNode.type !== 'Identifier') return;
if (childNode.name !== componentNode.name) return;
magicString.overwrite(childNode.start, childNode.end, name);
},
});
magicString.remove(node.start, node.end);
} else {
const removeStart = cssModulesEntry.start;
const removeEnd = node.declarations[0].init.arguments[1].end - 1;
magicString.remove(removeStart, removeEnd);
}
(walk as typeof estreeWalker.walk)(ast, {
enter(childNode) {
if (childNode.type !== 'Identifier') return;
if (childNode.name !== ident) return;
this.replace({
type: 'Identifier',
name: node.declarations[0].id.name,
});
},
});
this.remove();
/* NOTE: The above logic is valid as long as the following two conditions are met.
*
* - the uniqueness of `ident` is kept throughout the module
@@ -454,10 +411,31 @@ export function unwindCssModuleClassName(ast: ESTree.Node, magicString: Rolldown
});
*/
} else {
const nextElement = node.declarations[0].init.arguments[1].elements[__cssModulesIndex + 1];
const removeStart = node.declarations[0].init.arguments[1].elements[__cssModulesIndex]!.start;
const removeEnd = nextElement ? nextElement.start : node.declarations[0].init.arguments[1].end - 1;
magicString.remove(removeStart, removeEnd);
this.replace({
type: 'VariableDeclaration',
declarations: [{
type: 'VariableDeclarator',
id: {
type: 'Identifier',
name: node.declarations[0].id.name,
},
init: {
type: 'CallExpression',
callee: {
type: 'Identifier',
name: '_export_sfc',
},
arguments: [{
type: 'Identifier',
name: ident,
}, {
type: 'ArrayExpression',
elements: node.declarations[0].init.arguments[1].elements.slice(0, __cssModulesIndex).concat(node.declarations[0].init.arguments[1].elements.slice(__cssModulesIndex + 1)),
}],
},
}],
kind: 'const',
});
}
/* This region removed the `__cssModules` reference from the second argument of `_export_sfc`, as in the following code.
*
@@ -496,11 +474,10 @@ export function unwindCssModuleClassName(ast: ESTree.Node, magicString: Rolldown
export default function pluginUnwindCssModuleClassName(): Plugin {
return {
name: 'UnwindCssModuleClassName',
renderChunk(code, _chunk, _options, meta) {
const ast = ('ast' in meta ? meta.ast ?? this.parse(code) : this.parse(code)) as ESTree.Program;
const magicString = meta.magicString ?? new RolldownMagicString(code);
unwindCssModuleClassName(ast, magicString);
return magicString;
renderChunk(code): { code: string } {
const ast = this.parse(code) as unknown as estree.Node;
unwindCssModuleClassName(ast);
return { code: generate(ast) };
},
};
}