annex-B_3_3.js 2.8 KB

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