Properly serialize non-json values in parser tests (#10858)

This commit is contained in:
Nicolò Ribaudo 2019-12-12 10:20:03 +01:00
parent 25f7e6808e
commit 0b3f883ed1
3 changed files with 68 additions and 79 deletions

View File

@ -91,7 +91,7 @@
}, },
"value": { "value": {
"$$ babel internal serialized type": "BigInt", "$$ babel internal serialized type": "BigInt",
"value": "1n" "value": "1"
}, },
"raw": "1n", "raw": "1n",
"bigint": "1" "bigint": "1"

View File

@ -89,7 +89,11 @@
"column": 13 "column": 13
} }
}, },
"value": "/.*/i", "value": {
"$$ babel internal serialized type": "RegExp",
"source": ".*",
"flags": "i"
},
"raw": "/.*/i", "raw": "/.*/i",
"regex": { "regex": {
"pattern": ".*", "pattern": ".*",

View File

@ -111,41 +111,12 @@ export function runThrowTestsWithEstree(fixturesPath, parseFunction) {
} }
function save(test, ast) { function save(test, ast) {
overrideToJSON(() => fs.writeFileSync(
fs.writeFileSync(test.expect.loc, JSON.stringify(ast, null, 2)), test.expect.loc,
JSON.stringify(ast, (k, v) => serialize(v), 2),
); );
} }
// Ensure that RegExp, BigInt, and Errors are serialized as strings
function overrideToJSON(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() {
if (typeof this === "bigint") {
return { [serialized]: "BigInt", value: serialize(this) };
}
return this.toString();
};
}
const result = cb();
for (const obj of notJSONparseableObj) {
obj.prototype.toJSON = originalToJSONMap.get(obj);
}
return result;
}
function runTest(test, parseFunction) { function runTest(test, parseFunction) {
const opts = test.options; const opts = test.options;
@ -223,20 +194,41 @@ function runTest(test, parseFunction) {
function serialize(value) { function serialize(value) {
if (typeof value === "bigint") { if (typeof value === "bigint") {
return value.toString() + "n"; return {
[serialized]: "BigInt",
value: value.toString(),
};
} else if (value instanceof RegExp) {
return {
[serialized]: "RegExp",
source: value.source,
flags: value.flags,
};
} else if (value instanceof Error) {
// Errors are serialized to a simple string, because are used frequently
return value.toString();
} }
return JSON.stringify(value, null, 2); return value;
} }
function ppJSON(v) { function ppJSON(v) {
if (typeof v === "bigint" || v instanceof Error || v instanceof RegExp) {
return ppJSON(serialize(v));
}
if (v && typeof v === "object" && v[serialized]) { if (v && typeof v === "object" && v[serialized]) {
switch (v[serialized]) { switch (v[serialized]) {
case "BigInt": case "BigInt":
return typeof BigInt === "undefined" ? "null" : v.value; return typeof BigInt === "undefined" ? "null" : v.value + "n";
case "RegExp":
return `/${v.source}/${v.flags}`;
} }
} else if (typeof v === "string" && /^[A-Z][a-z]+Error: /.test(v)) {
// Errors are serialized to a simple string, because are used frequently
return v;
} }
return serialize(v); return JSON.stringify(v, (k, v) => serialize(v), 2);
} }
function addPath(str, pt) { function addPath(str, pt) {
@ -248,7 +240,6 @@ function addPath(str, pt) {
} }
function misMatch(exp, act) { function misMatch(exp, act) {
return overrideToJSON(() => {
if ( if (
act instanceof RegExp || act instanceof RegExp ||
act instanceof Error || act instanceof Error ||
@ -267,12 +258,7 @@ function misMatch(exp, act) {
const mis = misMatch(exp[i], act[i]); const mis = misMatch(exp[i], act[i]);
if (mis) return addPath(mis, i); if (mis) return addPath(mis, i);
} }
} else if ( } else if (!exp || !act || typeof exp != "object" || typeof act != "object") {
!exp ||
!act ||
typeof exp != "object" ||
typeof act != "object"
) {
if (exp !== act && typeof exp != "function") { if (exp !== act && typeof exp != "function") {
return ppJSON(exp) + " !== " + ppJSON(act); return ppJSON(exp) + " !== " + ppJSON(act);
} }
@ -292,5 +278,4 @@ function misMatch(exp, act) {
} }
} }
} }
});
} }