123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399 |
- import Printer from "../lib/printer";
- import generate, { CodeGenerator } from "../lib";
- import { parse } from "@babel/parser";
- import * as t from "@babel/types";
- import fs from "fs";
- import path from "path";
- import fixtures from "@babel/helper-fixtures";
- describe("generation", function() {
- it("completeness", function() {
- Object.keys(t.VISITOR_KEYS).forEach(function(type) {
- expect(Printer.prototype[type]).toBeTruthy();
- });
- Object.keys(Printer.prototype).forEach(function(type) {
- if (!/[A-Z]/.test(type[0])) return;
- expect(t.VISITOR_KEYS[type]).toBeTruthy();
- });
- });
- it("multiple sources", function() {
- const sources = {
- "a.js": "function hi (msg) { console.log(msg); }\n",
- "b.js": "hi('hello');\n",
- };
- const parsed = Object.keys(sources).reduce(function(_parsed, filename) {
- _parsed[filename] = parse(sources[filename], {
- sourceFilename: filename,
- });
- return _parsed;
- }, {});
- const combinedAst = {
- type: "File",
- program: {
- type: "Program",
- sourceType: "module",
- body: [].concat(
- parsed["a.js"].program.body,
- parsed["b.js"].program.body,
- ),
- },
- };
- const generated = generate(combinedAst, { sourceMaps: true }, sources);
- expect(generated.map).toEqual(
- {
- version: 3,
- sources: ["a.js", "b.js"],
- mappings:
- "AAAA,SAASA,EAAT,CAAaC,GAAb,EAAkB;AAAEC,UAAQC,GAAR,CAAYF,GAAZ;AAAmB;;ACAvCD,GAAG,OAAH",
- names: ["hi", "msg", "console", "log"],
- sourcesContent: [
- "function hi (msg) { console.log(msg); }\n",
- "hi('hello');\n",
- ],
- },
- "sourcemap was incorrectly generated",
- );
- expect(generated.rawMappings).toEqual(
- [
- {
- name: undefined,
- generated: { line: 1, column: 0 },
- source: "a.js",
- original: { line: 1, column: 0 },
- },
- {
- name: "hi",
- generated: { line: 1, column: 9 },
- source: "a.js",
- original: { line: 1, column: 9 },
- },
- {
- name: undefined,
- generated: { line: 1, column: 11 },
- source: "a.js",
- original: { line: 1, column: 0 },
- },
- {
- name: "msg",
- generated: { line: 1, column: 12 },
- source: "a.js",
- original: { line: 1, column: 13 },
- },
- {
- name: undefined,
- generated: { line: 1, column: 15 },
- source: "a.js",
- original: { line: 1, column: 0 },
- },
- {
- name: undefined,
- generated: { line: 1, column: 17 },
- source: "a.js",
- original: { line: 1, column: 18 },
- },
- {
- name: "console",
- generated: { line: 2, column: 0 },
- source: "a.js",
- original: { line: 1, column: 20 },
- },
- {
- name: "log",
- generated: { line: 2, column: 10 },
- source: "a.js",
- original: { line: 1, column: 28 },
- },
- {
- name: undefined,
- generated: { line: 2, column: 13 },
- source: "a.js",
- original: { line: 1, column: 20 },
- },
- {
- name: "msg",
- generated: { line: 2, column: 14 },
- source: "a.js",
- original: { line: 1, column: 32 },
- },
- {
- name: undefined,
- generated: { line: 2, column: 17 },
- source: "a.js",
- original: { line: 1, column: 20 },
- },
- {
- name: undefined,
- generated: { line: 3, column: 0 },
- source: "a.js",
- original: { line: 1, column: 39 },
- },
- {
- name: "hi",
- generated: { line: 5, column: 0 },
- source: "b.js",
- original: { line: 1, column: 0 },
- },
- {
- name: undefined,
- generated: { line: 5, column: 3 },
- source: "b.js",
- original: { line: 1, column: 3 },
- },
- {
- name: undefined,
- generated: { line: 5, column: 10 },
- source: "b.js",
- original: { line: 1, column: 0 },
- },
- ],
- "raw mappings were incorrectly generated",
- );
- expect(generated.code).toBe(
- "function hi(msg) {\n console.log(msg);\n}\n\nhi('hello');",
- );
- });
- it("identifierName", function() {
- const code = "function foo() { bar; }\n";
- const ast = parse(code, { filename: "inline" }).program;
- const fn = ast.body[0];
- const id = fn.id;
- id.name += "2";
- id.loc.identifierName = "foo";
- const id2 = fn.body.body[0].expression;
- id2.name += "2";
- id2.loc.identiferName = "bar";
- const generated = generate(
- ast,
- {
- filename: "inline",
- sourceFileName: "inline",
- sourceMaps: true,
- },
- code,
- );
- expect(generated.map).toEqual(
- {
- version: 3,
- sources: ["inline"],
- names: ["foo", "bar"],
- mappings: "AAAA,SAASA,IAAT,GAAe;AAAEC;AAAM",
- sourcesContent: ["function foo() { bar; }\n"],
- },
- "sourcemap was incorrectly generated",
- );
- expect(generated.rawMappings).toEqual(
- [
- {
- name: undefined,
- generated: { line: 1, column: 0 },
- source: "inline",
- original: { line: 1, column: 0 },
- },
- {
- name: "foo",
- generated: { line: 1, column: 9 },
- source: "inline",
- original: { line: 1, column: 9 },
- },
- {
- name: undefined,
- generated: { line: 1, column: 13 },
- source: "inline",
- original: { line: 1, column: 0 },
- },
- {
- name: undefined,
- generated: { line: 1, column: 16 },
- source: "inline",
- original: { line: 1, column: 15 },
- },
- {
- name: "bar",
- generated: { line: 2, column: 0 },
- source: "inline",
- original: { line: 1, column: 17 },
- },
- {
- name: undefined,
- generated: { line: 3, column: 0 },
- source: "inline",
- original: { line: 1, column: 23 },
- },
- ],
- "raw mappings were incorrectly generated",
- );
- expect(generated.code).toBe("function foo2() {\n bar2;\n}");
- });
- it("lazy source map generation", function() {
- const code = "function hi (msg) { console.log(msg); }\n";
- const ast = parse(code, { filename: "a.js" }).program;
- const generated = generate(ast, {
- sourceFileName: "a.js",
- sourceMaps: true,
- });
- expect(Array.isArray(generated.rawMappings)).toBe(true);
- expect(
- Object.getOwnPropertyDescriptor(generated, "map"),
- ).not.toHaveProperty("value");
- expect(generated).toHaveProperty("map");
- expect(typeof generated.map).toBe("object");
- });
- });
- describe("programmatic generation", function() {
- it("numeric member expression", function() {
- // Should not generate `0.foo`
- const mem = t.memberExpression(
- t.numericLiteral(60702),
- t.identifier("foo"),
- );
- new Function(generate(mem).code);
- });
- it("nested if statements needs block", function() {
- const ifStatement = t.ifStatement(
- t.stringLiteral("top cond"),
- t.whileStatement(
- t.stringLiteral("while cond"),
- t.ifStatement(
- t.stringLiteral("nested"),
- t.expressionStatement(t.numericLiteral(1)),
- ),
- ),
- t.expressionStatement(t.stringLiteral("alt")),
- );
- const ast = parse(generate(ifStatement).code);
- expect(ast.program.body[0].consequent.type).toBe("BlockStatement");
- });
- it("prints directives in block with empty body", function() {
- const blockStatement = t.blockStatement(
- [],
- [t.directive(t.directiveLiteral("use strict"))],
- );
- const output = generate(blockStatement).code;
- expect(output).toBe(`{
- "use strict";
- }`);
- });
- it("flow object indentation", function() {
- const objectStatement = t.objectTypeAnnotation(
- [t.objectTypeProperty(t.identifier("bar"), t.stringTypeAnnotation())],
- null,
- null,
- null,
- );
- const output = generate(objectStatement).code;
- expect(output).toBe(`{
- bar: string
- }`);
- });
- it("flow object exact", function() {
- const objectStatement = t.objectTypeAnnotation(
- [t.objectTypeProperty(t.identifier("bar"), t.stringTypeAnnotation())],
- null,
- null,
- null,
- true,
- );
- const output = generate(objectStatement).code;
- expect(output).toBe(`{|
- bar: string
- |}`);
- });
- it("flow object indentation with empty leading ObjectTypeProperty", function() {
- const objectStatement = t.objectTypeAnnotation(
- [],
- [
- t.objectTypeIndexer(
- t.identifier("key"),
- t.anyTypeAnnotation(),
- t.numberTypeAnnotation(),
- ),
- ],
- null,
- );
- const output = generate(objectStatement).code;
- expect(output).toBe(`{
- [key: any]: number
- }`);
- });
- });
- describe("CodeGenerator", function() {
- it("generate", function() {
- const codeGen = new CodeGenerator(t.numericLiteral(123));
- const code = codeGen.generate().code;
- expect(parse(code).program.body[0].expression.value).toBe(123);
- });
- });
- const suites = fixtures(`${__dirname}/fixtures`);
- suites.forEach(function(testSuite) {
- describe("generation/" + testSuite.title, function() {
- testSuite.tests.forEach(function(task) {
- it(
- task.title,
- !task.disabled &&
- function() {
- const expected = task.expect;
- const actual = task.actual;
- const actualCode = actual.code;
- if (actualCode) {
- const actualAst = parse(actualCode, {
- filename: actual.loc,
- plugins: task.options.plugins || [],
- strictMode: false,
- sourceType: "module",
- });
- const result = generate(actualAst, task.options, actualCode);
- if (
- !expected.code &&
- result.code &&
- fs.statSync(path.dirname(expected.loc)).isDirectory() &&
- !process.env.CI
- ) {
- console.log(`New test file created: ${expected.loc}`);
- fs.writeFileSync(expected.loc, result.code);
- } else {
- expect(result.code).toBe(expected.code);
- }
- }
- },
- );
- });
- });
- });
|