tdz.js 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.visitor = void 0;
  6. var _core = require("@babel/core");
  7. function getTDZStatus(refPath, bindingPath) {
  8. const executionStatus = bindingPath._guessExecutionStatusRelativeTo(refPath);
  9. if (executionStatus === "before") {
  10. return "outside";
  11. } else if (executionStatus === "after") {
  12. return "inside";
  13. } else {
  14. return "maybe";
  15. }
  16. }
  17. function buildTDZAssert(node, state) {
  18. return _core.types.callExpression(state.addHelper("temporalRef"), [
  19. node, _core.types.stringLiteral(node.name)]);
  20. }
  21. function isReference(node, scope, state) {
  22. const declared = state.letReferences.get(node.name);
  23. if (!declared) return false;
  24. return scope.getBindingIdentifier(node.name) === declared;
  25. }
  26. const visitedMaybeTDZNodes = new WeakSet();
  27. const visitor = {
  28. ReferencedIdentifier(path, state) {
  29. if (!state.tdzEnabled) return;
  30. const {
  31. node,
  32. parent,
  33. scope
  34. } = path;
  35. if (path.parentPath.isFor({
  36. left: node
  37. })) return;
  38. if (!isReference(node, scope, state)) return;
  39. const bindingPath = scope.getBinding(node.name).path;
  40. if (bindingPath.isFunctionDeclaration()) return;
  41. const status = getTDZStatus(path, bindingPath);
  42. if (status === "outside") return;
  43. if (status === "maybe") {
  44. if (visitedMaybeTDZNodes.has(node)) {
  45. return;
  46. }
  47. visitedMaybeTDZNodes.add(node);
  48. const assert = buildTDZAssert(node, state);
  49. bindingPath.parent._tdzThis = true;
  50. if (path.parentPath.isUpdateExpression()) {
  51. if (parent._ignoreBlockScopingTDZ) return;
  52. path.parentPath.replaceWith(_core.types.sequenceExpression([assert, parent]));
  53. } else {
  54. path.replaceWith(assert);
  55. }
  56. } else if (status === "inside") {
  57. path.replaceWith(_core.template.ast`${state.addHelper("tdz")}("${node.name}")`);
  58. }
  59. },
  60. AssignmentExpression: {
  61. exit(path, state) {
  62. if (!state.tdzEnabled) return;
  63. const {
  64. node
  65. } = path;
  66. if (node._ignoreBlockScopingTDZ) return;
  67. const nodes = [];
  68. const ids = path.getBindingIdentifiers();
  69. for (const name of Object.keys(ids)) {
  70. const id = ids[name];
  71. if (isReference(id, path.scope, state)) {
  72. nodes.push(id);
  73. }
  74. }
  75. if (nodes.length) {
  76. node._ignoreBlockScopingTDZ = true;
  77. nodes.push(node);
  78. path.replaceWithMultiple(nodes.map(n => _core.types.expressionStatement(n)));
  79. }
  80. }
  81. }
  82. };
  83. exports.visitor = visitor;
  84. //# sourceMappingURL=tdz.js.map