/**
 * This file is part of the NocoBase (R) project.
 * Copyright (c) 2020-2024 NocoBase Co., Ltd.
 * Authors: NocoBase Team.
 *
 * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
 * For more information, please refer to: https://www.nocobase.com/agreement.
 */

var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var execution_exports = {};
__export(execution_exports, {
  collectAstForOfSourceTargetElementMembers: () => collectAstForOfSourceTargetElementMembers,
  collectAstForOfSourceTargets: () => collectAstForOfSourceTargets,
  collectAstIdentifierWritesFromAst: () => collectAstIdentifierWritesFromAst,
  findAstInnermostSynchronousIifeFunctionAncestorIndex: () => findAstInnermostSynchronousIifeFunctionAncestorIndex,
  getAstLoopPatternTarget: () => getAstLoopPatternTarget,
  getAstWriteExecutionContext: () => getAstWriteExecutionContext,
  hasAstForOfSourceTargets: () => hasAstForOfSourceTargets,
  isAstForOfLoopVariableDeclaratorWithSourceTargets: () => isAstForOfLoopVariableDeclaratorWithSourceTargets
});
module.exports = __toCommonJS(execution_exports);
var import_internal_types = require("../internal-types");
var import_walk = require("./walk");
var import_bindings = require("./bindings");
var import_static_values = require("./static-values");
function collectAstIdentifierWritesFromAst(ast, source) {
  const writes = [];
  const addLoopHeaderWrites = (target, ancestors, fallbackIndex) => {
    const writeContext = getAstWriteExecutionContext(ancestors, source.length);
    (0, import_static_values.collectAstPatternBindingIdentifiers)(target, (name, bindingNode) => {
      writes.push({
        alwaysRunsInExecutionScope: writeContext.alwaysRunsInExecutionScope,
        executionScope: writeContext.executionScope,
        name,
        index: typeof (bindingNode == null ? void 0 : bindingNode.start) === "number" ? bindingNode.start : fallbackIndex
      });
    });
    (0, import_static_values.collectAstPatternMemberExpressions)(target, (memberNode) => {
      const memberWrite = (0, import_static_values.getAstMemberWriteLookup)(memberNode);
      if (!memberWrite) {
        return;
      }
      writes.push({
        alwaysRunsInExecutionScope: writeContext.alwaysRunsInExecutionScope,
        executionScope: writeContext.executionScope,
        name: memberWrite.aliasName,
        index: memberWrite.index
      });
    });
  };
  (0, import_walk.walkAstAncestor)(ast, {
    AssignmentExpression(node, ancestors) {
      if (!(0, import_static_values.isAstDefiniteAssignmentOperator)(node.operator)) {
        return;
      }
      const writeContext = getAstWriteExecutionContext(ancestors, source.length);
      (0, import_static_values.collectAstPatternBindingIdentifiers)(node.left, (name, bindingNode) => {
        writes.push({
          alwaysRunsInExecutionScope: writeContext.alwaysRunsInExecutionScope,
          executionScope: writeContext.executionScope,
          name,
          index: typeof (bindingNode == null ? void 0 : bindingNode.start) === "number" ? bindingNode.start : node.start || 0
        });
      });
      (0, import_static_values.collectAstPatternMemberExpressions)(node.left, (memberNode) => {
        const memberWrite = (0, import_static_values.getAstMemberWriteLookup)(memberNode);
        if (!memberWrite) {
          return;
        }
        writes.push({
          alwaysRunsInExecutionScope: writeContext.alwaysRunsInExecutionScope,
          executionScope: writeContext.executionScope,
          name: memberWrite.aliasName,
          index: memberWrite.index
        });
      });
    },
    VariableDeclarator(node, ancestors) {
      if (!node.init) {
        return;
      }
      const writeContext = getAstWriteExecutionContext(ancestors, source.length);
      (0, import_static_values.collectAstPatternBindingIdentifiers)(node.id, (name, bindingNode) => {
        writes.push({
          alwaysRunsInExecutionScope: writeContext.alwaysRunsInExecutionScope,
          executionScope: writeContext.executionScope,
          name,
          index: typeof (bindingNode == null ? void 0 : bindingNode.start) === "number" ? bindingNode.start : node.start || 0
        });
      });
    },
    UpdateExpression(node, ancestors) {
      var _a;
      const writeContext = getAstWriteExecutionContext(ancestors, source.length);
      if (((_a = node.argument) == null ? void 0 : _a.type) === "Identifier") {
        writes.push({
          alwaysRunsInExecutionScope: writeContext.alwaysRunsInExecutionScope,
          executionScope: writeContext.executionScope,
          name: node.argument.name,
          index: typeof node.argument.start === "number" ? node.argument.start : node.start || 0
        });
      }
      (0, import_static_values.collectAstPatternMemberExpressions)(node.argument, (memberNode) => {
        const memberWrite = (0, import_static_values.getAstMemberWriteLookup)(memberNode);
        if (!memberWrite) {
          return;
        }
        writes.push({
          alwaysRunsInExecutionScope: writeContext.alwaysRunsInExecutionScope,
          executionScope: writeContext.executionScope,
          name: memberWrite.aliasName,
          index: memberWrite.index
        });
      });
    },
    ForInStatement(node, ancestors) {
      var _a, _b;
      if (!(0, import_bindings.isAstDefinitelyNonEmptyForInSource)(node.right) || ((_a = node.left) == null ? void 0 : _a.type) === "VariableDeclaration") {
        return;
      }
      addLoopHeaderWrites(node.left, ancestors, ((_b = node.left) == null ? void 0 : _b.start) || node.start || 0);
    },
    ForOfStatement(node, ancestors) {
      var _a, _b;
      if (!(0, import_bindings.isAstDefinitelyNonEmptyForOfSource)(node.right) || ((_a = node.left) == null ? void 0 : _a.type) === "VariableDeclaration") {
        return;
      }
      addLoopHeaderWrites(node.left, ancestors, ((_b = node.left) == null ? void 0 : _b.start) || node.start || 0);
    }
  });
  return writes;
}
function getAstWriteExecutionContext(ancestors, sourceLength) {
  const iifeFunctionIndex = findAstInnermostSynchronousIifeFunctionAncestorIndex(ancestors);
  if (iifeFunctionIndex > 0) {
    const callAncestors = ancestors.slice(0, iifeFunctionIndex);
    return {
      alwaysRunsInExecutionScope: (0, import_bindings.isAstAlwaysExecutedInCurrentExecutionScope)(callAncestors),
      executionScope: (0, import_bindings.getAstExecutionScopeRange)(callAncestors.slice(0, -1), sourceLength)
    };
  }
  return {
    alwaysRunsInExecutionScope: (0, import_bindings.isAstAlwaysExecutedInCurrentExecutionScope)(ancestors),
    executionScope: (0, import_bindings.getAstExecutionScopeRange)(ancestors, sourceLength)
  };
}
function findAstInnermostSynchronousIifeFunctionAncestorIndex(ancestors) {
  for (let index = ancestors.length - 1; index > 0; index -= 1) {
    const node = ancestors[index];
    if (!(0, import_bindings.isAstFunctionLike)(node) || node.async) {
      continue;
    }
    const parent = ancestors[index - 1];
    if ((parent == null ? void 0 : parent.type) === "CallExpression" && (0, import_bindings.unwrapAstChainExpression)(parent.callee) === node) {
      return index;
    }
  }
  return -1;
}
function getAstLoopPatternTarget(left) {
  var _a, _b;
  if ((left == null ? void 0 : left.type) === "VariableDeclaration") {
    return ((_a = left.declarations) == null ? void 0 : _a.length) === 1 ? (_b = left.declarations[0]) == null ? void 0 : _b.id : void 0;
  }
  return left;
}
function isAstForOfLoopVariableDeclaratorWithSourceTargets(node, ancestors, aliases, identifierBindings) {
  var _a;
  const declaration = ancestors[ancestors.length - 2];
  const loop = ancestors[ancestors.length - 3];
  return (declaration == null ? void 0 : declaration.type) === "VariableDeclaration" && (loop == null ? void 0 : loop.type) === "ForOfStatement" && loop.left === declaration && ((_a = declaration.declarations) == null ? void 0 : _a.length) === 1 && declaration.declarations[0] === node && hasAstForOfSourceTargets(loop.right, aliases, identifierBindings);
}
function hasAstForOfSourceTargets(sourceNode, aliases, identifierBindings) {
  let hasSourceTarget = false;
  collectAstForOfSourceTargets(sourceNode, aliases, identifierBindings, () => {
    hasSourceTarget = true;
  });
  return hasSourceTarget;
}
function collectAstForOfSourceTargets(sourceNode, aliases, identifierBindings, visit) {
  const seenTargets = /* @__PURE__ */ new Set();
  const emitSourceTarget = (sourceTarget) => {
    if (!sourceTarget) {
      return;
    }
    const key = sourceTarget.aliasName ? `${sourceTarget.aliasName}@${sourceTarget.index || 0}` : sourceTarget.node ? `${sourceTarget.node.start || 0}:${sourceTarget.node.end || 0}` : `source:${sourceTarget.index || 0}`;
    if (seenTargets.has(key)) {
      return;
    }
    seenTargets.add(key);
    visit(sourceTarget);
  };
  const collectSourceTargets = (node) => {
    const unwrapped = (0, import_bindings.unwrapAstChainExpression)(node);
    if (!unwrapped) {
      return;
    }
    if (unwrapped.type === "ConditionalExpression") {
      collectSourceTargets(unwrapped.consequent);
      collectSourceTargets(unwrapped.alternate);
      return;
    }
    if (unwrapped.type === "LogicalExpression") {
      collectSourceTargets(unwrapped.left);
      collectSourceTargets(unwrapped.right);
      return;
    }
    if (unwrapped.type === "SequenceExpression") {
      const expressions = unwrapped.expressions || [];
      collectSourceTargets(expressions[expressions.length - 1]);
      return;
    }
    if (unwrapped.type === "AssignmentExpression" && (0, import_static_values.isAstCtxApiAliasAssignmentOperator)(unwrapped.operator)) {
      collectSourceTargets(unwrapped.right);
      return;
    }
    if (unwrapped.type === "ArrayExpression") {
      for (const element of unwrapped.elements || []) {
        if (!element) {
          continue;
        }
        if (element.type === "SpreadElement") {
          collectSourceTargets(element.argument);
          continue;
        }
        emitSourceTarget((0, import_static_values.createAstPatternSourceTarget)(element));
      }
      return;
    }
    const sourceTarget = (0, import_static_values.createAstPatternSourceTarget)(unwrapped);
    collectAstForOfSourceTargetElementMembers(sourceTarget, aliases, identifierBindings).forEach((member) => {
      emitSourceTarget((0, import_static_values.getAstPatternMemberSourceTarget)(sourceTarget, member));
    });
  };
  collectSourceTargets(sourceNode);
}
function collectAstForOfSourceTargetElementMembers(sourceTarget, aliases, identifierBindings) {
  const members = /* @__PURE__ */ new Set();
  (0, import_static_values.collectAstRestCarrierAliasCopies)(sourceTarget, "__forof__", aliases, identifierBindings, (suffix) => {
    const firstMember = suffix.split(".")[0];
    const numericMember = Number(firstMember);
    if (firstMember === import_internal_types.AST_DYNAMIC_MEMBER_ALIAS || Number.isInteger(numericMember) && numericMember >= 0) {
      members.add(firstMember);
    }
  });
  return members;
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  collectAstForOfSourceTargetElementMembers,
  collectAstForOfSourceTargets,
  collectAstIdentifierWritesFromAst,
  findAstInnermostSynchronousIifeFunctionAncestorIndex,
  getAstLoopPatternTarget,
  getAstWriteExecutionContext,
  hasAstForOfSourceTargets,
  isAstForOfLoopVariableDeclaratorWithSourceTargets
});
