annex-B_3_3.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.annexB33FunctionsVisitor = void 0;
  6. exports.isVarScope = isVarScope;
  7. var _core = require("@babel/core");
  8. const annexB33FunctionsVisitor = exports.annexB33FunctionsVisitor = {
  9. VariableDeclaration(path) {
  10. if (isStrict(path)) return;
  11. if (path.node.kind !== "var") return;
  12. const varScope = path.scope.getFunctionParent() || path.scope.getProgramParent();
  13. varScope.path.traverse(functionsToVarVisitor, {
  14. names: Object.keys(path.getBindingIdentifiers())
  15. });
  16. },
  17. BlockStatement(path) {
  18. if (isStrict(path)) return;
  19. if (_core.types.isFunction(path.parent, {
  20. body: path.node
  21. })) return;
  22. transformStatementList(path.get("body"));
  23. },
  24. SwitchCase(path) {
  25. if (isStrict(path)) return;
  26. transformStatementList(path.get("consequent"));
  27. }
  28. };
  29. function transformStatementList(paths) {
  30. outer: for (const path of paths) {
  31. if (!path.isFunctionDeclaration()) continue;
  32. if (path.node.async || path.node.generator) return;
  33. const {
  34. scope
  35. } = path.parentPath;
  36. if (isVarScope(scope)) return;
  37. const {
  38. name
  39. } = path.node.id;
  40. let currScope = scope;
  41. do {
  42. if (currScope.parent.hasOwnBinding(name)) continue outer;
  43. currScope = currScope.parent;
  44. } while (!isVarScope(currScope));
  45. maybeTransformBlockScopedFunction(path);
  46. }
  47. }
  48. function maybeTransformBlockScopedFunction(path) {
  49. const {
  50. node,
  51. parentPath: {
  52. scope
  53. }
  54. } = path;
  55. const {
  56. id
  57. } = node;
  58. scope.removeOwnBinding(id.name);
  59. node.id = null;
  60. const varNode = _core.types.variableDeclaration("var", [_core.types.variableDeclarator(id, _core.types.toExpression(node))]);
  61. varNode._blockHoist = 2;
  62. const [varPath] = path.replaceWith(varNode);
  63. scope.registerDeclaration(varPath);
  64. }
  65. const functionsToVarVisitor = {
  66. Scope(path, {
  67. names
  68. }) {
  69. for (const name of names) {
  70. const binding = path.scope.getOwnBinding(name);
  71. if (binding && binding.kind === "hoisted") {
  72. maybeTransformBlockScopedFunction(binding.path);
  73. }
  74. }
  75. },
  76. "Expression|Declaration"(path) {
  77. path.skip();
  78. }
  79. };
  80. function isVarScope(scope) {
  81. return scope.path.isFunctionParent() || scope.path.isProgram();
  82. }
  83. function isStrict(path) {
  84. return !!path.find(({
  85. node
  86. }) => {
  87. var _node$directives;
  88. if (_core.types.isProgram(node)) {
  89. if (node.sourceType === "module") return true;
  90. } else if (_core.types.isClass(node)) {
  91. return true;
  92. } else if (!_core.types.isBlockStatement(node)) {
  93. return false;
  94. }
  95. return (_node$directives = node.directives) == null ? void 0 : _node$directives.some(directive => directive.value.value === "use strict");
  96. });
  97. }
  98. //# sourceMappingURL=annex-B_3_3.js.map