swc/node-swc/__tests__/plugin_test.mjs
강동윤 211e208219
fix(node-swc): Fix visitor (#1890)
node/binding:
 - Fix visitor methods for array elements. (#1819, #1888)
 - Fix for const assertion. (#1625)
 - Verify object properties. (#906)
2021-07-04 12:35:25 +00:00

163 lines
4.0 KiB
JavaScript

import swc from "../..";
import Visitor from "../../Visitor";
function assertAllObjectHasTypeFiled(obj, desc = '') {
if (Array.isArray(obj)) {
for (const item of obj) {
assertAllObjectHasTypeFiled(item, `${desc} -> array`);
}
return
}
if (!obj) {
return
}
if (typeof obj === 'object') {
if (typeof obj.start !== 'undefined' && typeof obj.end !== 'undefined') {
return;
}
if ("spread" in obj) {
return;
}
if ("params" in obj && "span" in obj && "body" in obj) {
return;
}
if (!obj.type) {
throw new Error(`${desc}: ${JSON.stringify(obj)} should have field 'type'`)
}
for (const key in obj) {
if (Object.hasOwnProperty.call(obj, key)) {
assertAllObjectHasTypeFiled(obj[key], `${desc} -> ${key}`)
}
}
}
}
class BaseVisitor extends Visitor.default {
visitExpression(n) {
const e = super.visitExpression(n);
assertAllObjectHasTypeFiled(e);
return e;
}
visitPattern(n) {
const e = super.visitPattern(n);
assertAllObjectHasTypeFiled(e);
return e;
}
visitStatement(n) {
const e = super.visitStatement(n);
assertAllObjectHasTypeFiled(e);
return e;
}
visitFunctionDeclaration(n) {
const e = super.visitFunctionDeclaration(n);
assertAllObjectHasTypeFiled(e);
return e;
}
visitClassMember(n) {
const e = super.visitClassMember(n);
assertAllObjectHasTypeFiled(e);
return e;
}
visitClassMethod(n) {
assertAllObjectHasTypeFiled(n, 'BEFORE');
const e = super.visitClassMethod(n);
assertAllObjectHasTypeFiled(e);
return e;
}
}
const testCodes = [
{
input: `const arr = [1, 2, 3]`,
output: `const arr = [1, 2, 3];`
},
{
input: `export default {
foo: 'foo',
} as const;`,
output: `export default {
foo: 'foo'
};`
},
{
input: `const obj = { a: 1, b: 2 };
const { a, b } = obj;`,
output: `const obj = { a: 1, b: 2 };
const { a, b } = obj;`
}
];
test.each(testCodes)(`code($s)`, async ({ input, output }) => {
const { code } = await swc.transform(input, {
jsc: {
parser: {
syntax: 'typescript',
},
target: 'es2021'
},
isModule: true,
plugin: (ast) => {
const visitor = new BaseVisitor();
const after = visitor.visitProgram(ast);
assertAllObjectHasTypeFiled(after);
return after
},
});
expect(code.replace(/[\n\t ]/g, '')).toEqual(output.replace(/[\n\t ]/g, ''))
})
// test.each(files)('test262(%s)', async (file) => {
// if (!file.endsWith('.js')) {
// console.log(`Ignoring ${file}`)
// return
// }
// console.log(`Validating $${file}`)
// let astNode;
// const { code } = await swc.transformFile(file, {
// jsc: {
// parser: {
// syntax: 'ecmascript',
// },
// target: 'es2021'
// },
// isModule: file.includes('module.'),
// plugin: (ast) => {
// // console.debug(ast);
// const visitor = new BaseVisitor();
// const after = visitor.visitProgram(ast);
// // console.debug(after);
// assertAllObjectHasTypeFiled(after);
// astNode = ast;
// return after
// },
// });
// const filename = path.basename(file);
// try {
// await swc.print(astNode);
// } catch (e) {
// throw new Error(`${e}: ${JSON.stringify(astNode, null, 4)}`)
// }
// const expected = await fs.promises.readFile(`./ecmascript/codegen/tests/references/${filename}`, { encoding: 'utf8' });
// expect(code.trim()).toEqual(expected.trim());
// })