Skip to content

Commit

Permalink
Update test helpers to handle BigInt serializing
Browse files Browse the repository at this point in the history
  • Loading branch information
kaicataldo committed Dec 6, 2019
1 parent 6016d16 commit fe20f14
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 67 deletions.
Expand Up @@ -89,7 +89,7 @@
"column": 12
}
},
"value": null,
"value": "1",
"raw": "1n",
"bigint": "1"
}
Expand Down
147 changes: 81 additions & 66 deletions packages/babel-parser/test/helpers/runFixtureTests.js
@@ -1,3 +1,5 @@
/* global BigInt */

import { multiple as getFixtures } from "@babel/helper-fixtures";
import { codeFrameColumns } from "@babel/code-frame";
import fs from "fs";
Expand Down Expand Up @@ -41,11 +43,6 @@ class FixtureError extends Error {
}
}

// https://github.com/estree/estree/blob/master/es2020.md#bigintliteral
function bigIntReplacer(key, value) {
return typeof value === "bigint" ? null : value;
}

export function runFixtureTests(fixturesPath, parseFunction) {
const fixtures = getFixtures(fixturesPath);

Expand All @@ -66,10 +63,7 @@ export function runFixtureTests(fixturesPath, parseFunction) {
/^.*Got error message: /,
"",
);
fs.writeFileSync(
fn,
JSON.stringify(task.options, bigIntReplacer, " "),
);
fs.writeFileSync(fn, JSON.stringify(task.options, null, 2));
}
}

Expand Down Expand Up @@ -115,22 +109,43 @@ export function runThrowTestsWithEstree(fixturesPath, parseFunction) {
}

function save(test, ast) {
// Ensure that RegExp and Errors are serialized as strings
forceToString(RegExp, () =>
forceToString(Error, () =>
fs.writeFileSync(
test.expect.loc,
JSON.stringify(ast, bigIntReplacer, " "),
),
),
forceToString(() =>
fs.writeFileSync(test.expect.loc, JSON.stringify(ast, null, 2)),
);
}

function forceToString(obj, cb) {
const { toJSON } = obj.prototype;
obj.prototype.toJSON = obj.prototype.toString;
// Ensure that RegExp, BigInt, and Errors are serialized as strings
function forceToString(cb) {
const originalToJSONMap = new Map();
const notJSONparseableObj = [RegExp, Error];

if (typeof BigInt !== "undefined") {
notJSONparseableObj.push(BigInt);
}

for (const obj of notJSONparseableObj) {
const { toJSON } = obj.prototype;
originalToJSONMap.set(obj, toJSON);
obj.prototype.toJSON = function(...args) {
let isBigInt = false;

try {
isBigInt = typeof obj("1") === "bigint";
} catch (e) {}

if (isBigInt) {
return this.toString();
}

return this.toString(...args);
};
}

cb();
obj.prototype.toJSON = toJSON;

for (const obj of notJSONparseableObj) {
obj.prototype.toJSON = originalToJSONMap.get(obj);
}
}

function runTest(test, parseFunction) {
Expand All @@ -154,10 +169,7 @@ function runTest(test, parseFunction) {
const fn = path.dirname(test.expect.loc) + "/options.json";
test.options = test.options || {};
test.options.throws = err.message;
fs.writeFileSync(
fn,
JSON.stringify(test.options, bigIntReplacer, " "),
);
fs.writeFileSync(fn, JSON.stringify(test.options, null, 2));
return;
}

Expand Down Expand Up @@ -186,14 +198,11 @@ function runTest(test, parseFunction) {
const fn = path.dirname(test.expect.loc) + "/options.json";
test.options = test.options || {};
delete test.options.throws;
const contents = JSON.stringify(test.options, bigIntReplacer, " ");
const contents = JSON.stringify(test.options, null, 2);
if (contents === "{}") {
fs.unlinkSync(fn);
} else {
fs.writeFileSync(
fn,
JSON.stringify(test.options, bigIntReplacer, " "),
);
fs.writeFileSync(fn, JSON.stringify(test.options, null, 2));
}
test.expect.loc += "on";
return save(test, ast);
Expand All @@ -215,8 +224,7 @@ function runTest(test, parseFunction) {
}

function ppJSON(v) {
v = v instanceof RegExp || v instanceof Error ? v.toString() : v;
return JSON.stringify(v, bigIntReplacer, 2);
return JSON.stringify(v, null, 2);
}

function addPath(str, pt) {
Expand All @@ -228,42 +236,49 @@ function addPath(str, pt) {
}

function misMatch(exp, act) {
if (
exp instanceof RegExp ||
act instanceof RegExp ||
exp instanceof Error ||
act instanceof Error
) {
const left = ppJSON(exp);
const right = ppJSON(act);
if (left !== right) return left + " !== " + right;
} else if (Array.isArray(exp)) {
if (!Array.isArray(act)) return ppJSON(exp) + " != " + ppJSON(act);
if (act.length != exp.length) {
return "array length mismatch " + exp.length + " != " + act.length;
}
for (let i = 0; i < act.length; ++i) {
const mis = misMatch(exp[i], act[i]);
if (mis) return addPath(mis, i);
}
} else if (!exp || !act || typeof exp != "object" || typeof act != "object") {
if (exp !== act && typeof exp != "function") {
return ppJSON(exp) + " !== " + ppJSON(act);
}
} else {
for (const prop of Object.keys(exp)) {
const mis = misMatch(exp[prop], act[prop]);
if (mis) return addPath(mis, prop);
}

for (const prop of Object.keys(act)) {
if (typeof act[prop] === "function") {
continue;
forceToString(() => {
if (
exp instanceof RegExp ||
act instanceof RegExp ||
exp instanceof Error ||
act instanceof Error
) {
const left = ppJSON(exp);
const right = ppJSON(act);
if (left !== right) return left + " !== " + right;
} else if (Array.isArray(exp)) {
if (!Array.isArray(act)) return ppJSON(exp) + " != " + ppJSON(act);
if (act.length != exp.length) {
return "array length mismatch " + exp.length + " != " + act.length;
}
for (let i = 0; i < act.length; ++i) {
const mis = misMatch(exp[i], act[i]);
if (mis) return addPath(mis, i);
}
} else if (
!exp ||
!act ||
typeof exp != "object" ||
typeof act != "object"
) {
if (exp !== act && typeof exp != "function") {
return ppJSON(exp) + " !== " + ppJSON(act);
}
} else {
for (const prop of Object.keys(exp)) {
const mis = misMatch(exp[prop], act[prop]);
if (mis) return addPath(mis, prop);
}

for (const prop of Object.keys(act)) {
if (typeof act[prop] === "function") {
continue;
}

if (!(prop in exp) && act[prop] !== undefined) {
return `Did not expect a property '${prop}'`;
if (!(prop in exp) && act[prop] !== undefined) {
return `Did not expect a property '${prop}'`;
}
}
}
}
});
}

0 comments on commit fe20f14

Please sign in to comment.