run_babel_parser_test262_utils.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. "use strict";
  2. const fs = require("graceful-fs");
  3. const promisify = require("util").promisify;
  4. const TestStream = require("test262-stream");
  5. const pfs = {
  6. readFile: promisify(fs.readFile),
  7. writeFile: promisify(fs.writeFile),
  8. readdir: promisify(fs.readdir),
  9. stat: promisify(fs.stat),
  10. };
  11. const parse = require("../../../packages/babel-parser").parse;
  12. const featuresToPlugins = {
  13. BigInt: "bigInt",
  14. "class-fields-public": "classProperties",
  15. "class-fields-private": "classPrivateProperties",
  16. "async-iteration": "asyncGenerators",
  17. "object-rest": "objectRestSpread",
  18. "object-spread": "objectRestSpread",
  19. "optional-catch-binding": "optionalCatchBinding",
  20. "numeric-separator-literal": "numericSeparator",
  21. };
  22. function getPlugins(features) {
  23. return features && features.map(f => featuresToPlugins[f]).filter(Boolean);
  24. }
  25. exports.getTests = function(testDir) {
  26. const stream = new TestStream(testDir, {
  27. omitRuntime: true,
  28. acceptVersion: "3.0.0",
  29. });
  30. const tests = [];
  31. stream.on("data", test => {
  32. // strip test/
  33. const fileName = test.file.substr(5);
  34. tests.push({
  35. contents: test.contents,
  36. fileName,
  37. id: `${fileName}(${test.scenario})`,
  38. sourceType: test.attrs.flags.module ? "module" : "script",
  39. plugins: getPlugins(test.attrs.features),
  40. expectedError:
  41. !!test.attrs.negative &&
  42. (test.attrs.negative.phase === "parse" ||
  43. test.attrs.negative.phase === "early"),
  44. });
  45. });
  46. return new Promise((resolve, reject) => {
  47. stream.on("end", () => resolve(tests));
  48. stream.on("error", reject);
  49. });
  50. };
  51. exports.runTest = function(test) {
  52. try {
  53. parse(test.contents, {
  54. sourceType: test.sourceType,
  55. plugins: test.plugins,
  56. });
  57. test.actualError = false;
  58. } catch (err) {
  59. test.actualError = true;
  60. }
  61. test.result = test.expectedError !== test.actualError ? "fail" : "pass";
  62. return test;
  63. };
  64. exports.getWhitelist = function(filename) {
  65. return pfs.readFile(filename, "utf-8").then(function(contents) {
  66. return contents
  67. .split("\n")
  68. .map(function(line) {
  69. return line.replace(/#.*$/, "").trim();
  70. })
  71. .filter(function(line) {
  72. return line.length > 0;
  73. })
  74. .reduce(function(table, filename) {
  75. table[filename] = true;
  76. return table;
  77. }, Object.create(null));
  78. });
  79. };
  80. exports.updateWhitelist = function(filename, summary) {
  81. return pfs.readFile(filename, "utf-8").then(function(contents) {
  82. const toRemove = summary.disallowed.success
  83. .concat(summary.disallowed.failure)
  84. .map(function(test) {
  85. return test.id;
  86. });
  87. const toAdd = summary.disallowed.falsePositive
  88. .concat(summary.disallowed.falseNegative)
  89. .map(function(test) {
  90. return test.id;
  91. });
  92. const newContents = contents
  93. .split("\n")
  94. .map(function(line) {
  95. const testId = line.replace(/#.*$/, "").trim();
  96. if (toRemove.indexOf(testId) > -1) {
  97. return null;
  98. }
  99. return line;
  100. })
  101. .filter(function(line) {
  102. return line !== null;
  103. })
  104. .concat(toAdd)
  105. .join("\n");
  106. return pfs.writeFile(filename, newContents, "utf-8");
  107. });
  108. };
  109. exports.interpret = function(results, whitelist) {
  110. const summary = {
  111. passed: true,
  112. allowed: {
  113. success: [],
  114. failure: [],
  115. falsePositive: [],
  116. falseNegative: [],
  117. },
  118. disallowed: {
  119. success: [],
  120. failure: [],
  121. falsePositive: [],
  122. falseNegative: [],
  123. },
  124. unrecognized: null,
  125. };
  126. results.forEach(function(result) {
  127. let classification, isAllowed;
  128. const inWhitelist = result.id in whitelist;
  129. delete whitelist[result.id];
  130. if (!result.expectedError) {
  131. if (!result.actualError) {
  132. classification = "success";
  133. isAllowed = !inWhitelist;
  134. } else {
  135. classification = "falseNegative";
  136. isAllowed = inWhitelist;
  137. }
  138. } else {
  139. if (!result.actualError) {
  140. classification = "falsePositive";
  141. isAllowed = inWhitelist;
  142. } else {
  143. classification = "failure";
  144. isAllowed = !inWhitelist;
  145. }
  146. }
  147. summary.passed &= isAllowed;
  148. summary[isAllowed ? "allowed" : "disallowed"][classification].push(result);
  149. });
  150. summary.unrecognized = Object.keys(whitelist);
  151. summary.passed = !!summary.passed && summary.unrecognized.length === 0;
  152. return summary;
  153. };