| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763 | "use strict";Object.defineProperty(exports, "__esModule", {  value: true});exports.default = void 0;var _helperPluginUtils = require("@babel/helper-plugin-utils");var _tdz = require("./tdz");var _core = require("@babel/core");const DONE = new WeakSet();var _default = (0, _helperPluginUtils.declare)((api, opts) => {  api.assertVersion(7);  const {    throwIfClosureRequired = false,    tdz: tdzEnabled = false  } = opts;  if (typeof throwIfClosureRequired !== "boolean") {    throw new Error(`.throwIfClosureRequired must be a boolean, or undefined`);  }  if (typeof tdzEnabled !== "boolean") {    throw new Error(`.tdz must be a boolean, or undefined`);  }  return {    name: "transform-block-scoping",    visitor: {      VariableDeclaration(path) {        const {          node,          parent,          scope        } = path;        if (!isBlockScoped(node)) return;        convertBlockScopedToVar(path, null, parent, scope, true);        if (node._tdzThis) {          const nodes = [node];          for (let i = 0; i < node.declarations.length; i++) {            const decl = node.declarations[i];            const assign = _core.types.assignmentExpression("=", _core.types.cloneNode(decl.id), decl.init || scope.buildUndefinedNode());            assign._ignoreBlockScopingTDZ = true;            nodes.push(_core.types.expressionStatement(assign));            decl.init = this.addHelper("temporalUndefined");          }          node._blockHoist = 2;          if (path.isCompletionRecord()) {            nodes.push(_core.types.expressionStatement(scope.buildUndefinedNode()));          }          path.replaceWithMultiple(nodes);        }      },      Loop(path, state) {        const {          parent,          scope        } = path;        path.ensureBlock();        const blockScoping = new BlockScoping(path, path.get("body"), parent, scope, throwIfClosureRequired, tdzEnabled, state);        const replace = blockScoping.run();        if (replace) path.replaceWith(replace);      },      CatchClause(path, state) {        const {          parent,          scope        } = path;        const blockScoping = new BlockScoping(null, path.get("body"), parent, scope, throwIfClosureRequired, tdzEnabled, state);        blockScoping.run();      },      "BlockStatement|SwitchStatement|Program"(path, state) {        if (!ignoreBlock(path)) {          const blockScoping = new BlockScoping(null, path, path.parent, path.scope, throwIfClosureRequired, tdzEnabled, state);          blockScoping.run();        }      }    }  };});exports.default = _default;function ignoreBlock(path) {  return _core.types.isLoop(path.parent) || _core.types.isCatchClause(path.parent);}const buildRetCheck = (0, _core.template)(`  if (typeof RETURN === "object") return RETURN.v;`);function isBlockScoped(node) {  if (!_core.types.isVariableDeclaration(node)) return false;  if (node[_core.types.BLOCK_SCOPED_SYMBOL]) return true;  if (node.kind !== "let" && node.kind !== "const") return false;  return true;}function isInLoop(path) {  const loopOrFunctionParent = path.find(path => path.isLoop() || path.isFunction());  return loopOrFunctionParent == null ? void 0 : loopOrFunctionParent.isLoop();}function convertBlockScopedToVar(path, node, parent, scope, moveBindingsToParent = false) {  if (!node) {    node = path.node;  }  if (isInLoop(path) && !_core.types.isFor(parent)) {    for (let i = 0; i < node.declarations.length; i++) {      const declar = node.declarations[i];      declar.init = declar.init || scope.buildUndefinedNode();    }  }  node[_core.types.BLOCK_SCOPED_SYMBOL] = true;  node.kind = "var";  if (moveBindingsToParent) {    const parentScope = scope.getFunctionParent() || scope.getProgramParent();    for (const name of Object.keys(path.getBindingIdentifiers())) {      const binding = scope.getOwnBinding(name);      if (binding) binding.kind = "var";      scope.moveBindingTo(name, parentScope);    }  }}function isVar(node) {  return _core.types.isVariableDeclaration(node, {    kind: "var"  }) && !isBlockScoped(node);}const letReferenceBlockVisitor = _core.traverse.visitors.merge([{  Loop: {    enter(path, state) {      state.loopDepth++;    },    exit(path, state) {      state.loopDepth--;    }  },  FunctionParent(path, state) {    if (state.loopDepth > 0) {      path.traverse(letReferenceFunctionVisitor, state);    } else {      path.traverse(_tdz.visitor, state);    }    return path.skip();  }}, _tdz.visitor]);const letReferenceFunctionVisitor = _core.traverse.visitors.merge([{  ReferencedIdentifier(path, state) {    const ref = state.letReferences.get(path.node.name);    if (!ref) return;    const localBinding = path.scope.getBindingIdentifier(path.node.name);    if (localBinding && localBinding !== ref) return;    state.closurify = true;  }}, _tdz.visitor]);const hoistVarDeclarationsVisitor = {  enter(path, self) {    if (path.isForStatement()) {      const {        node      } = path;      if (isVar(node.init)) {        const nodes = self.pushDeclar(node.init);        if (nodes.length === 1) {          node.init = nodes[0];        } else {          node.init = _core.types.sequenceExpression(nodes);        }      }    } else if (path.isForInStatement() || path.isForOfStatement()) {      const {        node      } = path;      if (isVar(node.left)) {        self.pushDeclar(node.left);        node.left = node.left.declarations[0].id;      }    } else if (isVar(path.node)) {      path.replaceWithMultiple(self.pushDeclar(path.node).map(expr => _core.types.expressionStatement(expr)));    } else if (path.isFunction()) {      return path.skip();    }  }};const loopLabelVisitor = {  LabeledStatement({    node  }, state) {    state.innerLabels.push(node.label.name);  }};const continuationVisitor = {  enter(path, state) {    if (path.isAssignmentExpression() || path.isUpdateExpression()) {      for (const name of Object.keys(path.getBindingIdentifiers())) {        if (state.outsideReferences.get(name) !== path.scope.getBindingIdentifier(name)) {          continue;        }        state.reassignments[name] = true;      }    } else if (path.isReturnStatement()) {      state.returnStatements.push(path);    }  }};function loopNodeTo(node) {  if (_core.types.isBreakStatement(node)) {    return "break";  } else if (_core.types.isContinueStatement(node)) {    return "continue";  }}const loopVisitor = {  Loop(path, state) {    const oldIgnoreLabeless = state.ignoreLabeless;    state.ignoreLabeless = true;    path.traverse(loopVisitor, state);    state.ignoreLabeless = oldIgnoreLabeless;    path.skip();  },  Function(path) {    path.skip();  },  SwitchCase(path, state) {    const oldInSwitchCase = state.inSwitchCase;    state.inSwitchCase = true;    path.traverse(loopVisitor, state);    state.inSwitchCase = oldInSwitchCase;    path.skip();  },  "BreakStatement|ContinueStatement|ReturnStatement"(path, state) {    const {      node,      scope    } = path;    if (node[this.LOOP_IGNORE]) return;    let replace;    let loopText = loopNodeTo(node);    if (loopText) {      if (_core.types.isReturnStatement(node)) {        throw new Error("Internal error: unexpected return statement with `loopText`");      }      if (node.label) {        if (state.innerLabels.indexOf(node.label.name) >= 0) {          return;        }        loopText = `${loopText}|${node.label.name}`;      } else {        if (state.ignoreLabeless) return;        if (_core.types.isBreakStatement(node) && state.inSwitchCase) return;      }      state.hasBreakContinue = true;      state.map[loopText] = node;      replace = _core.types.stringLiteral(loopText);    }    if (_core.types.isReturnStatement(node)) {      state.hasReturn = true;      replace = _core.types.objectExpression([_core.types.objectProperty(_core.types.identifier("v"), node.argument || scope.buildUndefinedNode())]);    }    if (replace) {      replace = _core.types.returnStatement(replace);      replace[this.LOOP_IGNORE] = true;      path.skip();      path.replaceWith(_core.types.inherits(replace, node));    }  }};function isStrict(path) {  return !!path.find(({    node  }) => {    if (_core.types.isProgram(node)) {      if (node.sourceType === "module") return true;    } else if (!_core.types.isBlockStatement(node)) return false;    return node.directives.some(directive => directive.value.value === "use strict");  });}class BlockScoping {  constructor(loopPath, blockPath, parent, scope, throwIfClosureRequired, tdzEnabled, state) {    this.parent = void 0;    this.state = void 0;    this.scope = void 0;    this.throwIfClosureRequired = void 0;    this.tdzEnabled = void 0;    this.blockPath = void 0;    this.block = void 0;    this.outsideLetReferences = void 0;    this.hasLetReferences = void 0;    this.letReferences = void 0;    this.body = void 0;    this.loopParent = void 0;    this.loopLabel = void 0;    this.loopPath = void 0;    this.loop = void 0;    this.has = void 0;    this.parent = parent;    this.scope = scope;    this.state = state;    this.throwIfClosureRequired = throwIfClosureRequired;    this.tdzEnabled = tdzEnabled;    this.blockPath = blockPath;    this.block = blockPath.node;    this.outsideLetReferences = new Map();    this.hasLetReferences = false;    this.letReferences = new Map();    this.body = [];    if (loopPath) {      this.loopParent = loopPath.parent;      this.loopLabel = _core.types.isLabeledStatement(this.loopParent) && this.loopParent.label;      this.loopPath = loopPath;      this.loop = loopPath.node;    }  }  run() {    const block = this.block;    if (DONE.has(block)) return;    DONE.add(block);    const needsClosure = this.getLetReferences();    this.checkConstants();    if (_core.types.isFunction(this.parent) || _core.types.isProgram(this.block)) {      this.updateScopeInfo();      return;    }    if (!this.hasLetReferences) return;    if (needsClosure) {      this.wrapClosure();    } else {      this.remap();    }    this.updateScopeInfo(needsClosure);    if (this.loopLabel && !_core.types.isLabeledStatement(this.loopParent)) {      return _core.types.labeledStatement(this.loopLabel, this.loop);    }  }  checkConstants() {    const scope = this.scope;    const state = this.state;    for (const name of Object.keys(scope.bindings)) {      const binding = scope.bindings[name];      if (binding.kind !== "const") continue;      for (const violation of binding.constantViolations) {        const readOnlyError = state.addHelper("readOnlyError");        const throwNode = _core.types.callExpression(readOnlyError, [_core.types.stringLiteral(name)]);        if (violation.isAssignmentExpression()) {          const {            operator          } = violation.node;          if (operator === "=") {            violation.replaceWith(_core.types.sequenceExpression([violation.get("right").node, throwNode]));          } else if (["&&=", "||=", "??="].includes(operator)) {            violation.replaceWith(_core.types.logicalExpression(operator.slice(0, -1), violation.get("left").node, _core.types.sequenceExpression([violation.get("right").node, throwNode])));          } else {            violation.replaceWith(_core.types.sequenceExpression([_core.types.binaryExpression(operator.slice(0, -1), violation.get("left").node, violation.get("right").node), throwNode]));          }        } else if (violation.isUpdateExpression()) {          violation.replaceWith(_core.types.sequenceExpression([_core.types.unaryExpression("+", violation.get("argument").node), throwNode]));        } else if (violation.isForXStatement()) {          violation.ensureBlock();          violation.get("left").replaceWith(_core.types.variableDeclaration("var", [_core.types.variableDeclarator(violation.scope.generateUidIdentifier(name))]));          violation.node.body.body.unshift(_core.types.expressionStatement(throwNode));        }      }    }  }  updateScopeInfo(wrappedInClosure) {    const blockScope = this.blockPath.scope;    const parentScope = blockScope.getFunctionParent() || blockScope.getProgramParent();    const letRefs = this.letReferences;    for (const key of letRefs.keys()) {      const ref = letRefs.get(key);      const binding = blockScope.getBinding(ref.name);      if (!binding) continue;      if (binding.kind === "let" || binding.kind === "const") {        binding.kind = "var";        if (wrappedInClosure) {          if (blockScope.hasOwnBinding(ref.name)) {            blockScope.removeBinding(ref.name);          }        } else {          blockScope.moveBindingTo(ref.name, parentScope);        }      }    }  }  remap() {    const letRefs = this.letReferences;    const outsideLetRefs = this.outsideLetReferences;    const scope = this.scope;    const blockPathScope = this.blockPath.scope;    for (const key of letRefs.keys()) {      const ref = letRefs.get(key);      if (scope.parentHasBinding(key) || scope.hasGlobal(key)) {        const binding = scope.getOwnBinding(key);        if (binding) {          const parentBinding = scope.parent.getOwnBinding(key);          if (binding.kind === "hoisted" && !binding.path.node.async && !binding.path.node.generator && (!parentBinding || isVar(parentBinding.path.parent)) && !isStrict(binding.path.parentPath)) {            continue;          }          scope.rename(ref.name);        }        if (blockPathScope.hasOwnBinding(key)) {          blockPathScope.rename(ref.name);        }      }    }    for (const key of outsideLetRefs.keys()) {      const ref = letRefs.get(key);      if (isInLoop(this.blockPath) && blockPathScope.hasOwnBinding(key)) {        blockPathScope.rename(ref.name);      }    }  }  wrapClosure() {    if (this.throwIfClosureRequired) {      throw this.blockPath.buildCodeFrameError("Compiling let/const in this block would add a closure " + "(throwIfClosureRequired).");    }    const block = this.block;    const outsideRefs = this.outsideLetReferences;    if (this.loop) {      for (const name of Array.from(outsideRefs.keys())) {        const id = outsideRefs.get(name);        if (this.scope.hasGlobal(id.name) || this.scope.parentHasBinding(id.name)) {          outsideRefs.delete(id.name);          this.letReferences.delete(id.name);          this.scope.rename(id.name);          this.letReferences.set(id.name, id);          outsideRefs.set(id.name, id);        }      }    }    this.has = this.checkLoop();    this.hoistVarDeclarations();    const args = Array.from(outsideRefs.values(), node => _core.types.cloneNode(node));    const params = args.map(id => _core.types.cloneNode(id));    const isSwitch = this.blockPath.isSwitchStatement();    const fn = _core.types.functionExpression(null, params, _core.types.blockStatement(isSwitch ? [block] : block.body));    this.addContinuations(fn);    let call = _core.types.callExpression(_core.types.nullLiteral(), args);    let basePath = ".callee";    const hasYield = _core.traverse.hasType(fn.body, "YieldExpression", _core.types.FUNCTION_TYPES);    if (hasYield) {      fn.generator = true;      call = _core.types.yieldExpression(call, true);      basePath = ".argument" + basePath;    }    const hasAsync = _core.traverse.hasType(fn.body, "AwaitExpression", _core.types.FUNCTION_TYPES);    if (hasAsync) {      fn.async = true;      call = _core.types.awaitExpression(call);      basePath = ".argument" + basePath;    }    let placeholderPath;    let index;    if (this.has.hasReturn || this.has.hasBreakContinue) {      const ret = this.scope.generateUid("ret");      this.body.push(_core.types.variableDeclaration("var", [_core.types.variableDeclarator(_core.types.identifier(ret), call)]));      placeholderPath = "declarations.0.init" + basePath;      index = this.body.length - 1;      this.buildHas(ret);    } else {      this.body.push(_core.types.expressionStatement(call));      placeholderPath = "expression" + basePath;      index = this.body.length - 1;    }    let callPath;    if (isSwitch) {      const {        parentPath,        listKey,        key      } = this.blockPath;      this.blockPath.replaceWithMultiple(this.body);      callPath = parentPath.get(listKey)[key + index];    } else {      block.body = this.body;      callPath = this.blockPath.get("body")[index];    }    const placeholder = callPath.get(placeholderPath);    let fnPath;    if (this.loop) {      const loopId = this.scope.generateUid("loop");      const p = this.loopPath.insertBefore(_core.types.variableDeclaration("var", [_core.types.variableDeclarator(_core.types.identifier(loopId), fn)]));      placeholder.replaceWith(_core.types.identifier(loopId));      fnPath = p[0].get("declarations.0.init");    } else {      placeholder.replaceWith(fn);      fnPath = placeholder;    }    fnPath.unwrapFunctionEnvironment();  }  addContinuations(fn) {    const state = {      reassignments: {},      returnStatements: [],      outsideReferences: this.outsideLetReferences    };    this.scope.traverse(fn, continuationVisitor, state);    for (let i = 0; i < fn.params.length; i++) {      const param = fn.params[i];      if (!state.reassignments[param.name]) continue;      const paramName = param.name;      const newParamName = this.scope.generateUid(param.name);      fn.params[i] = _core.types.identifier(newParamName);      this.scope.rename(paramName, newParamName, fn);      state.returnStatements.forEach(returnStatement => {        returnStatement.insertBefore(_core.types.expressionStatement(_core.types.assignmentExpression("=", _core.types.identifier(paramName), _core.types.identifier(newParamName))));      });      fn.body.body.push(_core.types.expressionStatement(_core.types.assignmentExpression("=", _core.types.identifier(paramName), _core.types.identifier(newParamName))));    }  }  getLetReferences() {    const block = this.block;    const declarators = [];    if (this.loop) {      const init = this.loop.left || this.loop.init;      if (isBlockScoped(init)) {        declarators.push(init);        const names = _core.types.getBindingIdentifiers(init);        for (const name of Object.keys(names)) {          this.outsideLetReferences.set(name, names[name]);        }      }    }    const addDeclarationsFromChild = (path, node) => {      node = node || path.node;      if (_core.types.isClassDeclaration(node) || _core.types.isFunctionDeclaration(node) || isBlockScoped(node)) {        if (isBlockScoped(node)) {          convertBlockScopedToVar(path, node, block, this.scope);        }        if (node.declarations) {          for (let i = 0; i < node.declarations.length; i++) {            declarators.push(node.declarations[i]);          }        } else {          declarators.push(node);        }      }      if (_core.types.isLabeledStatement(node)) {        addDeclarationsFromChild(path.get("body"), node.body);      }    };    if (block.body) {      const declarPaths = this.blockPath.get("body");      for (let i = 0; i < block.body.length; i++) {        addDeclarationsFromChild(declarPaths[i]);      }    }    if (block.cases) {      const declarPaths = this.blockPath.get("cases");      for (let i = 0; i < block.cases.length; i++) {        const consequents = block.cases[i].consequent;        for (let j = 0; j < consequents.length; j++) {          const declar = consequents[j];          addDeclarationsFromChild(declarPaths[i], declar);        }      }    }    for (let i = 0; i < declarators.length; i++) {      const declar = declarators[i];      const keys = _core.types.getBindingIdentifiers(declar, false, true);      for (const key of Object.keys(keys)) {        this.letReferences.set(key, keys[key]);      }      this.hasLetReferences = true;    }    if (!this.hasLetReferences) return;    const state = {      letReferences: this.letReferences,      closurify: false,      loopDepth: 0,      tdzEnabled: this.tdzEnabled,      addHelper: name => this.state.addHelper(name)    };    if (isInLoop(this.blockPath)) {      state.loopDepth++;    }    this.blockPath.traverse(letReferenceBlockVisitor, state);    return state.closurify;  }  checkLoop() {    const state = {      hasBreakContinue: false,      ignoreLabeless: false,      inSwitchCase: false,      innerLabels: [],      hasReturn: false,      isLoop: !!this.loop,      map: {},      LOOP_IGNORE: Symbol()    };    this.blockPath.traverse(loopLabelVisitor, state);    this.blockPath.traverse(loopVisitor, state);    return state;  }  hoistVarDeclarations() {    this.blockPath.traverse(hoistVarDeclarationsVisitor, this);  }  pushDeclar(node) {    const declars = [];    const names = _core.types.getBindingIdentifiers(node);    for (const name of Object.keys(names)) {      declars.push(_core.types.variableDeclarator(names[name]));    }    this.body.push(_core.types.variableDeclaration(node.kind, declars));    const replace = [];    for (let i = 0; i < node.declarations.length; i++) {      const declar = node.declarations[i];      if (!declar.init) continue;      const expr = _core.types.assignmentExpression("=", _core.types.cloneNode(declar.id), _core.types.cloneNode(declar.init));      replace.push(_core.types.inherits(expr, declar));    }    return replace;  }  buildHas(ret) {    const body = this.body;    const has = this.has;    if (has.hasBreakContinue) {      for (const key of Object.keys(has.map)) {        body.push(_core.types.ifStatement(_core.types.binaryExpression("===", _core.types.identifier(ret), _core.types.stringLiteral(key)), has.map[key]));      }    }    if (has.hasReturn) {      body.push(buildRetCheck({        RETURN: _core.types.identifier(ret)      }));    }  }}
 |