134 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			134 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
"use strict";
 | 
						|
 | 
						|
Object.defineProperty(exports, "__esModule", {
 | 
						|
  value: true
 | 
						|
});
 | 
						|
exports.validateUsage = validateUsage;
 | 
						|
var _core = require("@babel/core");
 | 
						|
function validateUsage(path, state, tdzEnabled) {
 | 
						|
  const dynamicTDZNames = [];
 | 
						|
  for (const name of Object.keys(path.getBindingIdentifiers())) {
 | 
						|
    const binding = path.scope.getBinding(name);
 | 
						|
    if (!binding) continue;
 | 
						|
    if (tdzEnabled) {
 | 
						|
      if (injectTDZChecks(binding, state)) dynamicTDZNames.push(name);
 | 
						|
    }
 | 
						|
    if (path.node.kind === "const") {
 | 
						|
      disallowConstantViolations(name, binding, state);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return dynamicTDZNames;
 | 
						|
}
 | 
						|
function disallowConstantViolations(name, binding, state) {
 | 
						|
  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,
 | 
						|
        left,
 | 
						|
        right
 | 
						|
      } = violation.node;
 | 
						|
      if (operator === "=") {
 | 
						|
        const exprs = [right];
 | 
						|
        exprs.push(throwNode);
 | 
						|
        violation.replaceWith(_core.types.sequenceExpression(exprs));
 | 
						|
      } else if (["&&=", "||=", "??="].includes(operator)) {
 | 
						|
        violation.replaceWith(_core.types.logicalExpression(operator.slice(0, -1), left, _core.types.sequenceExpression([right, throwNode])));
 | 
						|
      } else {
 | 
						|
        violation.replaceWith(_core.types.sequenceExpression([_core.types.binaryExpression(operator.slice(0, -1), left, right), 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));
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
function getTDZStatus(refPath, bindingPath) {
 | 
						|
  const executionStatus = bindingPath._guessExecutionStatusRelativeTo(refPath);
 | 
						|
  if (executionStatus === "before") {
 | 
						|
    return "outside";
 | 
						|
  } else if (executionStatus === "after") {
 | 
						|
    return "inside";
 | 
						|
  } else {
 | 
						|
    return "maybe";
 | 
						|
  }
 | 
						|
}
 | 
						|
const skipTDZChecks = new WeakSet();
 | 
						|
function buildTDZAssert(status, node, state) {
 | 
						|
  if (status === "maybe") {
 | 
						|
    const clone = _core.types.cloneNode(node);
 | 
						|
    skipTDZChecks.add(clone);
 | 
						|
    return _core.types.callExpression(state.addHelper("temporalRef"), [clone, _core.types.stringLiteral(node.name)]);
 | 
						|
  } else {
 | 
						|
    return _core.types.callExpression(state.addHelper("tdz"), [_core.types.stringLiteral(node.name)]);
 | 
						|
  }
 | 
						|
}
 | 
						|
function getTDZReplacement(path, state, id = path.node) {
 | 
						|
  var _path$scope$getBindin;
 | 
						|
  if (skipTDZChecks.has(id)) return;
 | 
						|
  skipTDZChecks.add(id);
 | 
						|
  const bindingPath = (_path$scope$getBindin = path.scope.getBinding(id.name)) == null ? void 0 : _path$scope$getBindin.path;
 | 
						|
  if (!bindingPath || bindingPath.isFunctionDeclaration()) return;
 | 
						|
  const status = getTDZStatus(path, bindingPath);
 | 
						|
  if (status === "outside") return;
 | 
						|
  if (status === "maybe") {
 | 
						|
    bindingPath.parent._tdzThis = true;
 | 
						|
  }
 | 
						|
  return {
 | 
						|
    status,
 | 
						|
    node: buildTDZAssert(status, id, state)
 | 
						|
  };
 | 
						|
}
 | 
						|
function injectTDZChecks(binding, state) {
 | 
						|
  const allUsages = new Set(binding.referencePaths);
 | 
						|
  binding.constantViolations.forEach(allUsages.add, allUsages);
 | 
						|
  let dynamicTdz = false;
 | 
						|
  for (const path of binding.constantViolations) {
 | 
						|
    const {
 | 
						|
      node
 | 
						|
    } = path;
 | 
						|
    if (skipTDZChecks.has(node)) continue;
 | 
						|
    skipTDZChecks.add(node);
 | 
						|
    if (path.isUpdateExpression()) {
 | 
						|
      const arg = path.get("argument");
 | 
						|
      const replacement = getTDZReplacement(path, state, arg.node);
 | 
						|
      if (!replacement) continue;
 | 
						|
      if (replacement.status === "maybe") {
 | 
						|
        dynamicTdz = true;
 | 
						|
        path.insertBefore(replacement.node);
 | 
						|
      } else {
 | 
						|
        path.replaceWith(replacement.node);
 | 
						|
      }
 | 
						|
    } else if (path.isAssignmentExpression()) {
 | 
						|
      const nodes = [];
 | 
						|
      const ids = path.getBindingIdentifiers();
 | 
						|
      for (const name of Object.keys(ids)) {
 | 
						|
        const replacement = getTDZReplacement(path, state, ids[name]);
 | 
						|
        if (replacement) {
 | 
						|
          nodes.push(_core.types.expressionStatement(replacement.node));
 | 
						|
          if (replacement.status === "inside") break;
 | 
						|
          if (replacement.status === "maybe") dynamicTdz = true;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      if (nodes.length > 0) path.insertBefore(nodes);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  for (const path of binding.referencePaths) {
 | 
						|
    if (path.parentPath.isUpdateExpression()) continue;
 | 
						|
    if (path.parentPath.isFor({
 | 
						|
      left: path.node
 | 
						|
    })) continue;
 | 
						|
    const replacement = getTDZReplacement(path, state);
 | 
						|
    if (!replacement) continue;
 | 
						|
    if (replacement.status === "maybe") dynamicTdz = true;
 | 
						|
    path.replaceWith(replacement.node);
 | 
						|
  }
 | 
						|
  return dynamicTdz;
 | 
						|
}
 | 
						|
 | 
						|
//# sourceMappingURL=validation.js.map
 |