/**
 * 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 source_patterns_exports = {};
__export(source_patterns_exports, {
  collectCtxAliases: () => collectCtxAliases,
  collectCtxLibMemberCaseMismatches: () => collectCtxLibMemberCaseMismatches,
  collectCtxMemberAccesses: () => collectCtxMemberAccesses,
  collectCtxRenderComponentSignatureCalls: () => collectCtxRenderComponentSignatureCalls,
  collectDirectDomAliases: () => collectDirectDomAliases,
  collectDirectDomWrites: () => collectDirectDomWrites,
  collectFlowResourceAliases: () => collectFlowResourceAliases,
  collectForbiddenBareGlobals: () => collectForbiddenBareGlobals,
  collectInvalidApiResourceCalls: () => collectInvalidApiResourceCalls,
  collectInvalidFlowResourceListCalls: () => collectInvalidFlowResourceListCalls,
  collectInvalidResourceTypeCalls: () => collectInvalidResourceTypeCalls,
  collectReactComponentAliases: () => collectReactComponentAliases,
  collectReactComponentFunctionCalls: () => collectReactComponentFunctionCalls,
  collectReactComponentPropReferences: () => collectReactComponentPropReferences,
  collectReactHookCalls: () => collectReactHookCalls,
  collectResourceCallsInReactHooks: () => collectResourceCallsInReactHooks,
  collectUnboundReactCreateElementCalls: () => collectUnboundReactCreateElementCalls,
  collectWindowDocumentNavigatorAliases: () => collectWindowDocumentNavigatorAliases,
  collectWindowDocumentNavigatorUses: () => collectWindowDocumentNavigatorUses,
  getResourceLikeCtxRunjsEntrypoint: () => getResourceLikeCtxRunjsEntrypoint,
  isResourceLikeCtxRequest: () => isResourceLikeCtxRequest,
  isTopLevelFunctionWrapper: () => isTopLevelFunctionWrapper
});
module.exports = __toCommonJS(source_patterns_exports);
var import_constants = require("../runtime/constants");
var import_bindings = require("../ast/bindings");
var import_source = require("../ast/source");
function collectForbiddenBareGlobals(masked, bindings) {
  const entries = [];
  for (const name of import_constants.FORBIDDEN_BARE_GLOBALS) {
    const pattern = new RegExp(`(?<![.$\\w])${(0, import_source.escapeRegExp)(name)}\\b`, "g");
    for (const match of masked.matchAll(pattern)) {
      if (!(0, import_bindings.isNameBoundAtIndex)(bindings, name, match.index || 0) && !isObjectPropertyKey(masked, match.index || 0, name)) {
        entries.push({ name, index: match.index || 0 });
      }
    }
  }
  return entries.sort((left, right) => left.index - right.index);
}
function collectInvalidApiResourceCalls(source, masked, bindings) {
  var _a, _b, _c, _d, _e, _f, _g, _h;
  const resourceMethods = /* @__PURE__ */ new Set(["list", "get", "create", "update", "destroy"]);
  const entries = [
    ...masked.matchAll(
      /\bctx\s*(?:\?\.|\.)\s*api\s*(?:\?\.|\.)\s*resource\s*(?:\?\.|\.)\s*(list|get|create|update|destroy)\s*(?:\?\.)?\(/g
    )
  ].filter((match) => !(0, import_bindings.isNameBoundAtIndex)(bindings, "ctx", match.index || 0)).map((match) => ({
    index: match.index || 0,
    match: match[0].replace(/\s*(?:\?\.)?\($/, ""),
    method: match[1]
  }));
  for (const match of masked.matchAll(/\bctx\s*(?:\?\.|\.)\s*api\s*(?:\?\.|\.)\s*resource\s*(?:\?\.)?\(/g)) {
    const index = match.index || 0;
    if ((0, import_bindings.isNameBoundAtIndex)(bindings, "ctx", index)) {
      continue;
    }
    const openParen = masked.indexOf("(", index);
    const closeParen = openParen >= 0 ? (0, import_source.findMatchingDelimiter)(masked, openParen) : -1;
    const args = (0, import_source.getCallArgumentSources)(source, masked, index);
    if (args.length >= 2) {
      const method2 = (_b = (0, import_source.readCompleteStringLiteral)(((_a = args[0]) == null ? void 0 : _a.source) || "")) == null ? void 0 : _b.value;
      if (method2 && resourceMethods.has(method2)) {
        entries.push({
          index,
          match: `ctx.api.resource('${method2}')`,
          method: method2
        });
      }
      const resourceName2 = (_d = (0, import_source.readCompleteStringLiteral)(((_c = args[0]) == null ? void 0 : _c.source) || "")) == null ? void 0 : _d.value;
      const action = (_f = (0, import_source.readCompleteStringLiteral)(((_e = args[1]) == null ? void 0 : _e.source) || "")) == null ? void 0 : _f.value;
      if (action && resourceMethods.has(action)) {
        entries.push({
          index,
          match: resourceName2 ? `ctx.api.resource('${resourceName2}', '${action}')` : `ctx.api.resource(..., '${action}')`,
          method: action
        });
      }
    }
    if (closeParen < 0) {
      continue;
    }
    const chainedMethod = masked.slice(closeParen + 1, closeParen + 96).match(/^\s*(?:\?\.|\.)\s*(list|get|create|update|destroy)\s*(?:\?\.)?\(/);
    if (!chainedMethod) {
      continue;
    }
    const method = chainedMethod[1];
    const resourceName = (_h = (0, import_source.readCompleteStringLiteral)(((_g = args[0]) == null ? void 0 : _g.source) || "")) == null ? void 0 : _h.value;
    entries.push({
      index,
      match: resourceName ? `ctx.api.resource('${resourceName}').${method}` : `ctx.api.resource(...).${method}`,
      method
    });
  }
  return (0, import_bindings.dedupeIndexedEntries)(entries).sort((left, right) => left.index - right.index);
}
function collectInvalidResourceTypeCalls(source, masked, stringBindings, bindings) {
  const entries = [];
  for (const match of masked.matchAll(/\bctx\s*(?:\?\.|\.)\s*(makeResource|initResource)\s*(?:\?\.)?\(/g)) {
    const index = match.index || 0;
    if ((0, import_bindings.isNameBoundAtIndex)(bindings, "ctx", index)) {
      continue;
    }
    const method = match[1];
    const capability = `ctx.${method}`;
    const firstArg = (0, import_source.getCallArgumentSources)(source, masked, index)[0];
    if (!firstArg) {
      entries.push({
        capability,
        expression: "",
        index,
        ruleId: "runjs-make-resource-type-unresolved",
        message: `flowSurfaces authoring cannot validate ${capability}(...) without a resource type`
      });
      continue;
    }
    const resolved = resolveResourceTypeExpression(firstArg, stringBindings);
    if (resolved.status === "unresolved") {
      entries.push({
        capability,
        expression: resolved.expression,
        index,
        ruleId: "runjs-make-resource-type-unresolved",
        message: `flowSurfaces authoring cannot validate dynamic ${capability}(...) resource type '${resolved.expression}'`
      });
      continue;
    }
    const allowedResourceTypes = method === "initResource" ? import_constants.INIT_RESOURCE_CLASS_NAMES : import_constants.FLOW_RESOURCE_CLASS_NAMES;
    if (!allowedResourceTypes.has(resolved.value)) {
      entries.push({
        capability,
        index,
        resourceType: resolved.value,
        ruleId: "runjs-make-resource-type-invalid",
        message: `flowSurfaces authoring ${capability}(...) expects a FlowResource class name, not collection '${resolved.value}'`
      });
    }
  }
  return entries;
}
function collectResourceCallsInReactHooks(source, masked, reactHookCalls, bindings) {
  const hookArgumentRanges = reactHookCalls.map((hook) => {
    const firstArg = (0, import_source.getCallArgumentSources)(source, masked, hook.index)[0];
    return firstArg ? { hook: hook.hook, range: firstArg } : null;
  }).filter(Boolean);
  if (!hookArgumentRanges.length) {
    return [];
  }
  const entries = [];
  const pattern = /\bctx\s*(?:\?\.|\.)\s*(?:(makeResource|initResource)\s*(?:\?\.)?\(|resource\b)/g;
  for (const match of masked.matchAll(pattern)) {
    const index = match.index || 0;
    if ((0, import_bindings.isNameBoundAtIndex)(bindings, "ctx", index)) {
      continue;
    }
    const hook = hookArgumentRanges.find((entry) => index >= entry.range.start && index < entry.range.end);
    if (!hook) {
      continue;
    }
    entries.push({
      capability: match[1] ? `ctx.${match[1]}` : "ctx.resource",
      hook: hook.hook,
      index
    });
  }
  return (0, import_bindings.dedupeIndexedEntries)(entries).sort((left, right) => left.index - right.index);
}
function resolveResourceTypeExpression(arg, stringBindings) {
  const expression = arg.source.trim();
  const leadingLength = arg.source.length - arg.source.trimStart().length;
  const expressionIndex = arg.start + leadingLength;
  const literal = (0, import_source.readCompleteStringLiteral)(arg.source);
  if (literal) {
    return { status: "resolved", value: literal.value };
  }
  if (/^[A-Za-z_$][\w$]*$/.test(expression)) {
    const binding = stringBindings.find(
      (entry) => entry.name === expression && expressionIndex >= entry.start && expressionIndex < entry.end
    );
    if (binding) {
      return { status: "resolved", value: binding.value };
    }
  }
  return {
    status: "unresolved",
    expression
  };
}
function collectFlowResourceAliases(masked, bindings) {
  const aliases = [];
  const addAlias = (name, capability, declarationIndex) => {
    const binding = (0, import_bindings.findSourceBindingByDeclaration)(bindings, name, declarationIndex);
    aliases.push({
      name,
      capability,
      declarationStart: declarationIndex,
      start: declarationIndex,
      end: (binding == null ? void 0 : binding.end) ?? masked.length
    });
  };
  for (const match of masked.matchAll(
    /\b(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*ctx\s*(?:\?\.|\.)\s*(makeResource|initResource)\s*(?:\?\.)?\(/g
  )) {
    if ((0, import_bindings.isNameBoundAtIndex)(bindings, "ctx", (match.index || 0) + match[0].lastIndexOf("ctx"))) {
      continue;
    }
    addAlias(match[1], `ctx.${match[2]}`, match.index || 0);
  }
  for (const match of masked.matchAll(
    /\b(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*ctx\s*(?:\?\.|\.)\s*resource\b/g
  )) {
    if ((0, import_bindings.isNameBoundAtIndex)(bindings, "ctx", (match.index || 0) + match[0].lastIndexOf("ctx"))) {
      continue;
    }
    addAlias(match[1], "ctx.resource", match.index || 0);
  }
  return aliases;
}
function collectInvalidFlowResourceListCalls(masked, aliases, bindings) {
  const entries = [];
  for (const match of masked.matchAll(/\bctx\s*(?:\?\.|\.)\s*resource\s*(?:\?\.|\.)\s*list\s*(?:\?\.)?\(/g)) {
    if ((0, import_bindings.isNameBoundAtIndex)(bindings, "ctx", match.index || 0)) {
      continue;
    }
    entries.push({
      index: match.index || 0,
      capability: "ctx.resource.list"
    });
  }
  for (const match of masked.matchAll(
    /\bctx\s*(?:\?\.|\.)\s*(makeResource|initResource)\s*(?:\?\.)?\([^)]*\)\s*(?:\?\.|\.)\s*list\s*(?:\?\.)?\(/g
  )) {
    if ((0, import_bindings.isNameBoundAtIndex)(bindings, "ctx", match.index || 0)) {
      continue;
    }
    entries.push({
      index: match.index || 0,
      capability: `ctx.${match[1]}(...).list`
    });
  }
  aliases.forEach((alias) => {
    const pattern = new RegExp(
      `(?<![.$\\w])${(0, import_source.escapeRegExp)(alias.name)}\\s*(?:\\?\\.|\\.)\\s*list\\s*(?:\\?\\.)?\\(`,
      "g"
    );
    for (const match of masked.matchAll(pattern)) {
      const index = match.index || 0;
      if (index <= alias.start || index >= alias.end) {
        continue;
      }
      if ((0, import_bindings.isSourceAliasShadowedAtIndex)(alias, bindings, index)) {
        continue;
      }
      entries.push({
        index,
        capability: `${alias.name}.list`
      });
    }
  });
  return (0, import_bindings.dedupeIndexedEntries)(entries).sort((left, right) => left.index - right.index);
}
function collectCtxLibMemberCaseMismatches(source, masked, bindings) {
  const entries = [];
  const addEntry = (index, member, accessKind, capability) => {
    const expectedMember = import_constants.CTX_LIB_MEMBER_BY_LOWERCASE.get(member.toLowerCase());
    if (!expectedMember || expectedMember === member) {
      return;
    }
    entries.push({
      accessKind,
      capability: capability || `ctx.libs.${member}`,
      expectedCapability: `ctx.libs.${expectedMember}`,
      expectedMember,
      index,
      member
    });
  };
  for (const match of masked.matchAll(/\bctx\s*(?:\?\.|\.)\s*libs\s*(?:\?\.|\.)\s*([A-Za-z_$][\w$]*)/g)) {
    const index = match.index || 0;
    if ((0, import_bindings.isNameBoundAtIndex)(bindings, "ctx", index)) {
      continue;
    }
    const member = match[1];
    addEntry(index + match[0].lastIndexOf(member), member, "member");
  }
  for (const match of source.matchAll(
    /\bctx\s*(?:\?\.|\.)\s*libs\s*(?:\?\.)?\s*\[\s*(['"])([A-Za-z_$][\w$]*)\1\s*\]/g
  )) {
    const index = match.index || 0;
    if (masked.slice(index, index + 3) !== "ctx" || (0, import_bindings.isNameBoundAtIndex)(bindings, "ctx", index)) {
      continue;
    }
    const quote = match[1];
    const member = match[2];
    addEntry(index + match[0].indexOf(member), member, "bracket", `ctx.libs[${quote}${member}${quote}]`);
  }
  for (const match of masked.matchAll(/\b(?:const|let|var)\s*\{([^}]*)\}\s*=\s*ctx\s*(?:\?\.|\.)\s*libs\b/g)) {
    const declarationIndex = match.index || 0;
    const ctxIndex = declarationIndex + match[0].lastIndexOf("ctx");
    if ((0, import_bindings.isNameBoundAtIndex)(bindings, "ctx", ctxIndex)) {
      continue;
    }
    const bindingPattern = match[1];
    const patternStart = declarationIndex + match[0].indexOf(bindingPattern);
    (0, import_source.splitTopLevelWithRanges)(bindingPattern, ",").forEach((property) => {
      const prop = readObjectBindingPropertyName(property.source);
      if (!prop) {
        return;
      }
      addEntry(patternStart + property.start + prop.offset, prop.name, "destructure", `ctx.libs.${prop.name}`);
    });
  }
  return (0, import_bindings.dedupeIndexedEntries)(entries).sort((left, right) => left.index - right.index);
}
function readObjectBindingPropertyName(element) {
  const trimmed = element.trim();
  if (!trimmed || trimmed.startsWith("...") || trimmed.startsWith("{") || trimmed.startsWith("[")) {
    return void 0;
  }
  const normalized = (0, import_source.trimBindingElement)(trimmed);
  const colon = (0, import_source.findTopLevelChar)(normalized, ":");
  const rawProperty = (colon >= 0 ? normalized.slice(0, colon) : normalized).trim();
  const name = normalizeObjectPropertyName(rawProperty);
  if (!/^[A-Za-z_$][\w$]*$/.test(name)) {
    return void 0;
  }
  const offset = Math.max(0, element.indexOf(name));
  return { name, offset };
}
function collectReactHookCalls(masked, bindings) {
  const entries = [];
  const memberPattern = new RegExp(
    `\\b(?:(?:ctx\\s*(?:\\?\\.|\\.)\\s*(?:libs\\s*(?:\\?\\.|\\.)\\s*)?React)|React)\\s*(?:\\?\\.|\\.)\\s*(${import_constants.REACT_HOOK_PATTERN})\\s*(?:\\?\\.)?\\(`,
    "g"
  );
  for (const match of masked.matchAll(memberPattern)) {
    const index = match.index || 0;
    if (masked.slice(index, index + 3) === "ctx" && (0, import_bindings.isNameBoundAtIndex)(bindings, "ctx", index)) {
      continue;
    }
    entries.push({
      hook: match[1],
      index,
      match: match[0].replace(/\s*(?:\?\.)?\($/, "")
    });
  }
  const barePattern = new RegExp(`(?<![.$\\w])(${import_constants.REACT_HOOK_PATTERN})\\s*(?:\\?\\.)?\\(`, "g");
  for (const match of masked.matchAll(barePattern)) {
    const index = match.index || 0;
    const hook = match[1];
    if ((0, import_source.getPreviousSignificantToken)(masked, index) === "function" || isObjectPropertyKey(masked, index, hook)) {
      continue;
    }
    entries.push({
      hook,
      index,
      match: match[0].replace(/\s*(?:\?\.)?\($/, "")
    });
  }
  return (0, import_bindings.dedupeIndexedEntries)(entries).sort((left, right) => left.index - right.index);
}
function collectUnboundReactCreateElementCalls(masked, bindings) {
  const entries = [];
  for (const match of masked.matchAll(/(?<![.$\w])React\s*(?:\?\.|\.)\s*createElement\s*(?:\?\.)?\(/g)) {
    const index = match.index || 0;
    if (!(0, import_bindings.isNameBoundAtIndex)(bindings, "React", index)) {
      entries.push({ index });
    }
  }
  return entries;
}
function collectReactComponentAliases(masked, bindings) {
  const aliases = [];
  const addAlias = (name, capability, declarationIndex) => {
    if (!/^[A-Z][\w$]*$/.test(name)) {
      return;
    }
    const binding = (0, import_bindings.findSourceBindingByDeclaration)(bindings, name, declarationIndex);
    aliases.push({
      name,
      capability,
      declarationStart: declarationIndex,
      start: declarationIndex,
      end: (binding == null ? void 0 : binding.end) ?? masked.length
    });
  };
  for (const match of masked.matchAll(
    /\b(?:const|let|var)\s*\{([^}]*)\}\s*=\s*ctx\s*(?:\?\.|\.)\s*(?:(libs)\s*(?:\?\.|\.)\s*)?(antdIcons|antd)\b/g
  )) {
    const declarationIndex = match.index || 0;
    const ctxIndex = declarationIndex + match[0].lastIndexOf("ctx");
    if ((0, import_bindings.isNameBoundAtIndex)(bindings, "ctx", ctxIndex)) {
      continue;
    }
    const namespace = `ctx.${match[2] ? "libs." : ""}${match[3]}`;
    collectObjectBindingAliases(match[1]).forEach(
      (alias) => addAlias(alias, `${namespace}.${alias}`, declarationIndex)
    );
  }
  for (const match of masked.matchAll(
    /\b(?:const|let|var)\s+([A-Z][\w$]*)\s*=\s*ctx\s*(?:\?\.|\.)\s*(?:(libs)\s*(?:\?\.|\.)\s*)?(antdIcons|antd)\s*(?:\?\.|\.)\s*([A-Z][\w$]*)\b/g
  )) {
    const ctxIndex = (match.index || 0) + match[0].lastIndexOf("ctx");
    if ((0, import_bindings.isNameBoundAtIndex)(bindings, "ctx", ctxIndex)) {
      continue;
    }
    const namespace = `ctx.${match[2] ? "libs." : ""}${match[3]}`;
    addAlias(match[1], `${namespace}.${match[4]}`, match.index || 0);
  }
  return aliases;
}
function collectReactComponentFunctionCalls(masked, aliases, bindings) {
  const entries = [];
  for (const match of masked.matchAll(
    /\bctx\s*(?:\?\.|\.)\s*(?:(libs)\s*(?:\?\.|\.)\s*)?(antdIcons|antd)\s*(?:\?\.|\.)\s*([A-Z][\w$]*)\s*(?:\?\.)?\(/g
  )) {
    if ((0, import_bindings.isNameBoundAtIndex)(bindings, "ctx", match.index || 0)) {
      continue;
    }
    const namespace = `ctx.${match[1] ? "libs." : ""}${match[2]}`;
    entries.push({
      index: match.index || 0,
      component: match[3],
      capability: `${namespace}.${match[3]}`
    });
  }
  aliases.forEach((alias) => {
    const pattern = new RegExp(`(?<![.$\\w])${(0, import_source.escapeRegExp)(alias.name)}\\s*(?:\\?\\.)?\\(`, "g");
    for (const match of masked.matchAll(pattern)) {
      const index = match.index || 0;
      if (index <= alias.start || index >= alias.end) {
        continue;
      }
      if ((0, import_bindings.isSourceAliasShadowedAtIndex)(alias, bindings, index)) {
        continue;
      }
      const previous = (0, import_source.getPreviousSignificantToken)(masked, index);
      if (previous === "function" || isObjectPropertyKey(masked, index, alias.name)) {
        continue;
      }
      entries.push({
        index,
        component: alias.name,
        capability: alias.capability
      });
    }
  });
  return (0, import_bindings.dedupeIndexedEntries)(entries).sort((left, right) => left.index - right.index);
}
function collectCtxRenderComponentSignatureCalls(source, masked, aliases, bindings) {
  const entries = [];
  for (const match of masked.matchAll(/\bctx\s*(?:\?\.|\.)\s*render\s*(?:\?\.)?\(/g)) {
    const index = match.index || 0;
    if ((0, import_bindings.isNameBoundAtIndex)(bindings, "ctx", index)) {
      continue;
    }
    const firstArg = (0, import_source.getCallArgumentSources)(source, masked, index)[0];
    if (!firstArg) {
      continue;
    }
    const reference = readReactComponentReference(firstArg.source, aliases, firstArg.start, bindings);
    if (reference) {
      entries.push({
        index: firstArg.start,
        ...reference
      });
    }
  }
  return (0, import_bindings.dedupeIndexedEntries)(entries).sort((left, right) => left.index - right.index);
}
function collectReactComponentPropReferences(source, masked, aliases, bindings) {
  var _a, _b;
  const entries = [];
  const inspectPropsArg = (arg) => {
    if (!arg) {
      return;
    }
    collectReactComponentPropReferencesFromObject(arg, aliases, bindings).forEach((entry) => entries.push(entry));
  };
  for (const match of masked.matchAll(
    /\b(?:(?:ctx\s*(?:\?\.|\.)\s*(?:libs\s*(?:\?\.|\.)\s*)?React)|React)\s*(?:\?\.|\.)\s*createElement\s*(?:\?\.)?\(/g
  )) {
    if (masked.slice(match.index || 0, (match.index || 0) + 3) === "ctx" && (0, import_bindings.isNameBoundAtIndex)(bindings, "ctx", match.index || 0)) {
      continue;
    }
    inspectPropsArg((0, import_source.getCallArgumentSources)(source, masked, match.index || 0)[1]);
  }
  for (const match of masked.matchAll(/\bctx\s*(?:\?\.|\.)\s*render\s*(?:\?\.)?\(/g)) {
    if ((0, import_bindings.isNameBoundAtIndex)(bindings, "ctx", match.index || 0)) {
      continue;
    }
    const args = (0, import_source.getCallArgumentSources)(source, masked, match.index || 0);
    if (!readReactComponentReference(((_a = args[0]) == null ? void 0 : _a.source) || "", aliases, ((_b = args[0]) == null ? void 0 : _b.start) || 0, bindings)) {
      continue;
    }
    inspectPropsArg(args[1]);
  }
  return (0, import_bindings.dedupeIndexedEntries)(entries).sort((left, right) => left.index - right.index);
}
function collectReactComponentPropReferencesFromObject(arg, aliases, bindings) {
  const entries = [];
  const localMasked = (0, import_source.maskJavaScriptSource)(arg.source);
  const openOffset = arg.source.search(/\S/);
  if (openOffset < 0 || arg.source[openOffset] !== "{") {
    return entries;
  }
  const closeOffset = (0, import_source.findMatchingDelimiter)(localMasked, openOffset);
  if (closeOffset <= openOffset) {
    return entries;
  }
  const body = arg.source.slice(openOffset + 1, closeOffset);
  const bodyStart = arg.start + openOffset + 1;
  (0, import_source.splitTopLevelWithRanges)(body, ",").forEach((property) => {
    const colon = (0, import_source.findTopLevelChar)(property.source, ":");
    if (colon < 0) {
      return;
    }
    const propName = normalizeObjectPropertyName(property.source.slice(0, colon));
    if (!import_constants.REACT_NODE_COMPONENT_PROP_NAMES.has(propName)) {
      return;
    }
    const rawValue = property.source.slice(colon + 1);
    const leading = rawValue.length - rawValue.trimStart().length;
    const valueStart = bodyStart + property.start + colon + 1 + leading;
    const reference = readReactComponentReference(rawValue, aliases, valueStart, bindings);
    if (!reference) {
      return;
    }
    entries.push({
      index: valueStart,
      prop: propName,
      ...reference
    });
  });
  return entries;
}
function readReactComponentReference(expression, aliases, expressionIndex, bindings) {
  const normalized = (0, import_source.maskJavaScriptComments)(expression).trim();
  const ctxMatch = normalized.match(
    /^ctx\s*(?:\?\.|\.)\s*(?:(libs)\s*(?:\?\.|\.)\s*)?(antdIcons|antd)\s*(?:\?\.|\.)\s*([A-Z][\w$]*)$/
  );
  if (ctxMatch) {
    if ((0, import_bindings.isNameBoundAtIndex)(bindings, "ctx", expressionIndex)) {
      return void 0;
    }
    const namespace = `ctx.${ctxMatch[1] ? "libs." : ""}${ctxMatch[2]}`;
    return {
      component: ctxMatch[3],
      capability: `${namespace}.${ctxMatch[3]}`
    };
  }
  const aliasMatch = normalized.match(/^([A-Z][\w$]*)$/);
  if (!aliasMatch) {
    return void 0;
  }
  const alias = aliases.find(
    (entry) => entry.name === aliasMatch[1] && expressionIndex >= entry.start && expressionIndex < entry.end && !(0, import_bindings.isSourceAliasShadowedAtIndex)(entry, bindings, expressionIndex)
  );
  return alias ? {
    component: alias.name,
    capability: alias.capability
  } : void 0;
}
function normalizeObjectPropertyName(value) {
  return value.trim().replace(/^['"]([A-Za-z_$][\w$]*)['"]$/, "$1");
}
function isObjectPropertyKey(masked, index, name) {
  let cursor = index + name.length;
  while (cursor < masked.length && /\s/.test(masked[cursor])) {
    cursor += 1;
  }
  if (masked[cursor] === ":") {
    return true;
  }
  if (masked[cursor] !== "(") {
    return false;
  }
  const previous = (0, import_source.getPreviousSignificantToken)(masked, index);
  return previous === "{" || previous === ",";
}
function collectDirectDomWrites(source, masked, bindings) {
  const entries = [];
  const commentMasked = (0, import_source.maskJavaScriptComments)(source);
  const pattern = /\b(ctx)\s*(?:\?\.|\.)\s*element\s*(?:\?\.|\.)\s*(innerHTML|insertAdjacentHTML)\b|\b(document)\s*(?:\?\.|\.)\s*(createElement)\b|\b(element)\s*(?:\?\.|\.)\s*(innerHTML|insertAdjacentHTML)\b|(?<![.$\w])(insertAdjacentHTML)\s*(?:\?\.)?\(/g;
  for (const match of masked.matchAll(pattern)) {
    const index = match.index || 0;
    const boundRoot = match[3] || match[5];
    const bareFunction = match[7];
    if (match[1] === "ctx" && (0, import_bindings.isNameBoundAtIndex)(bindings, "ctx", index) || boundRoot && (0, import_bindings.isNameBoundAtIndex)(bindings, boundRoot, index) || bareFunction && (0, import_bindings.isNameBoundAtIndex)(bindings, bareFunction, index)) {
      continue;
    }
    entries.push({ index, match: match[0].replace(/\s*(?:\?\.)?\($/, "") });
  }
  for (const match of commentMasked.matchAll(
    /\b(ctx)\s*(?:\?\.|\.)\s*element\s*(?:\?\.\s*)?\[\s*(?:(['"])([A-Za-z_$][\w$]*)\2|([^\]]+))\s*\]/g
  )) {
    const index = match.index || 0;
    const member = match[3] || "";
    const dynamicMember = Boolean(match[4]);
    if (isCodeTokenAt(masked, index, "ctx") && !(0, import_bindings.isNameBoundAtIndex)(bindings, "ctx", index) && (dynamicMember || isDirectDomMember(member))) {
      entries.push({ index, match: match[0] });
    }
  }
  for (const match of commentMasked.matchAll(
    /\b(document)\s*(?:\?\.\s*)?\[\s*(?:(['"])([A-Za-z_$][\w$]*)\2|([^\]]+))\s*\]/g
  )) {
    const index = match.index || 0;
    const member = match[3] || "";
    const dynamicMember = Boolean(match[4]);
    if (isCodeTokenAt(masked, index, match[1]) && !(0, import_bindings.isNameBoundAtIndex)(bindings, match[1], index) && (dynamicMember || member === "createElement")) {
      entries.push({ index, match: match[0] });
    }
  }
  for (const match of commentMasked.matchAll(
    /\b(element)\s*(?:\?\.\s*)?\[\s*(?:(['"])([A-Za-z_$][\w$]*)\2|([^\]]+))\s*\]/g
  )) {
    const index = match.index || 0;
    const member = match[3] || "";
    const dynamicMember = Boolean(match[4]);
    if (isCodeTokenAt(masked, index, match[1]) && !(0, import_bindings.isNameBoundAtIndex)(bindings, match[1], index) && (dynamicMember || isDirectDomMember(member))) {
      entries.push({ index, match: match[0] });
    }
  }
  return entries;
}
function collectWindowDocumentNavigatorUses(source, masked, bindings) {
  const commentMasked = (0, import_source.maskJavaScriptComments)(source);
  const entries = [...masked.matchAll(/\b(window|document|navigator)\s*(?:\?\.|\.)\s*([A-Za-z_$][\w$]*)/g)].filter((match) => !(0, import_bindings.isNameBoundAtIndex)(bindings, match[1], match.index || 0)).map((match) => ({
    root: match[1],
    member: match[2],
    index: match.index || 0
  }));
  for (const match of commentMasked.matchAll(
    /\b(window|document|navigator)\s*(?:\?\.\s*)?\[\s*(?:(['"])([A-Za-z_$][\w$]*)\2|([^\]]+))\s*\]/g
  )) {
    const index = match.index || 0;
    const root = match[1];
    if (!isCodeTokenAt(masked, index, root) || (0, import_bindings.isNameBoundAtIndex)(bindings, root, index)) {
      continue;
    }
    entries.push({
      root,
      member: match[3] || "[dynamic]",
      index
    });
  }
  return entries.sort((left, right) => left.index - right.index);
}
function collectWindowDocumentNavigatorAliases(masked, bindings) {
  const entries = [];
  collectAliasMatches(
    masked,
    [
      /\b(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*(window|document|navigator)\b/g,
      /(?<![.$\w])([A-Za-z_$][\w$]*)\s*=\s*(window|document|navigator)\b/g
    ],
    (match) => {
      const alias = match[1];
      const root = match[2];
      const rootIndex = (match.index || 0) + match[0].lastIndexOf(root);
      if (alias === root || (0, import_bindings.isNameBoundAtIndex)(bindings, root, rootIndex)) {
        return;
      }
      entries.push({ alias, root, index: rootIndex });
    }
  );
  for (const match of masked.matchAll(
    /\b(?:const|let|var)\s*\{([^}]*)\}\s*=\s*(window|document|navigator)\b(?!\s*(?:\.|\?\.))/g
  )) {
    const root = match[2];
    const rootIndex = (match.index || 0) + match[0].lastIndexOf(root);
    if ((0, import_bindings.isNameBoundAtIndex)(bindings, root, rootIndex)) {
      continue;
    }
    collectObjectBindingAliases(match[1]).forEach((alias) => {
      entries.push({ alias, root, index: rootIndex });
    });
  }
  return dedupeAliasEntries(entries);
}
function collectDirectDomAliases(masked, bindings) {
  const entries = [];
  collectAliasMatches(
    masked,
    [
      /\b(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*ctx\s*(?:\?\.|\.)\s*element\b/g,
      /(?<![.$\w])([A-Za-z_$][\w$]*)\s*=\s*ctx\s*(?:\?\.|\.)\s*element\b/g
    ],
    (match) => {
      const alias = match[1];
      const ctxIndex = (match.index || 0) + match[0].lastIndexOf("ctx");
      if ((0, import_bindings.isNameBoundAtIndex)(bindings, "ctx", ctxIndex)) {
        return;
      }
      entries.push({ alias, index: ctxIndex });
    }
  );
  for (const match of masked.matchAll(/\b(?:const|let|var)\s*\{([^}]*)\}\s*=\s*ctx\b(?!\s*(?:\.|\?\.))/g)) {
    const ctxIndex = (match.index || 0) + match[0].lastIndexOf("ctx");
    if ((0, import_bindings.isNameBoundAtIndex)(bindings, "ctx", ctxIndex)) {
      continue;
    }
    collectObjectBindingAliases(match[1]).filter((alias) => alias === "element").forEach((alias) => {
      entries.push({ alias, index: ctxIndex });
    });
  }
  return dedupeAliasEntries(entries);
}
function collectCtxAliases(masked, bindings) {
  const entries = [];
  collectAliasMatches(
    masked,
    [
      /\b(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*ctx\b(?!\s*(?:\.|\?\.))/g,
      /(?<![.$\w])([A-Za-z_$][\w$]*)\s*=\s*ctx\b(?!\s*(?:\.|\?\.))/g
    ],
    (match) => {
      const alias = match[1];
      const ctxIndex = (match.index || 0) + match[0].lastIndexOf("ctx");
      if (alias === "ctx" || (0, import_bindings.isNameBoundAtIndex)(bindings, "ctx", ctxIndex)) {
        return;
      }
      entries.push({ alias, index: ctxIndex });
    }
  );
  for (const match of masked.matchAll(/\b(?:const|let|var)\s*\{([^}]*)\}\s*=\s*ctx\b(?!\s*(?:\.|\?\.))/g)) {
    const ctxIndex = (match.index || 0) + match[0].lastIndexOf("ctx");
    if ((0, import_bindings.isNameBoundAtIndex)(bindings, "ctx", ctxIndex)) {
      continue;
    }
    collectObjectBindingAliases(match[1]).forEach((alias) => {
      entries.push({ alias, index: ctxIndex });
    });
  }
  return dedupeAliasEntries(entries);
}
function collectAliasMatches(masked, patterns, onMatch) {
  patterns.forEach((pattern) => {
    for (const match of masked.matchAll(pattern)) {
      onMatch(match);
    }
  });
}
function dedupeAliasEntries(entries) {
  const seen = /* @__PURE__ */ new Set();
  return entries.filter((entry) => {
    const key = `${entry.alias}:${entry.index}`;
    if (seen.has(key)) {
      return false;
    }
    seen.add(key);
    return true;
  });
}
function collectObjectBindingAliases(pattern) {
  return (0, import_source.splitTopLevel)(pattern, ",").flatMap((element) => collectObjectBindingElementAliases(element)).filter(Boolean);
}
function collectObjectBindingElementAliases(element) {
  const trimmed = element.trim().replace(/^\.\.\./, "").trim();
  if (!trimmed || trimmed.startsWith("{")) {
    return [];
  }
  const colon = (0, import_source.findTopLevelChar)(trimmed, ":");
  if (colon >= 0) {
    const right = (0, import_source.trimBindingElement)(trimmed.slice(colon + 1));
    const match2 = right.match(/^([A-Za-z_$][\w$]*)\b/);
    return match2 ? [match2[1]] : [];
  }
  const match = trimmed.match(/^([A-Za-z_$][\w$]*)\b/);
  return match ? [match[1]] : [];
}
function isDirectDomMember(member) {
  return member === "innerHTML" || member === "insertAdjacentHTML";
}
function isCodeTokenAt(masked, index, token) {
  return masked.slice(index, index + token.length) === token;
}
function collectCtxMemberAccesses(masked, bindings) {
  return [...masked.matchAll(/\bctx\s*(?:\?\.|\.)\s*([A-Za-z_$][\w$]*)/g)].filter((match) => !(0, import_bindings.isNameBoundAtIndex)(bindings, "ctx", match.index || 0)).map((match) => ({
    member: match[1],
    index: match.index || 0
  }));
}
function isTopLevelFunctionWrapper(masked, functionRanges, topLevelCtxRenderCalls) {
  if (topLevelCtxRenderCalls.length || !functionRanges.length) {
    return false;
  }
  return /^\s*(?:async\s+)?function\b/.test(masked) || /^\s*(?:const|let|var)\s+[A-Za-z_$][\w$]*\s*=/.test(masked);
}
function isResourceLikeCtxRequest(source, masked, index) {
  const args = (0, import_source.getCallArgumentSource)(source, masked, index);
  if (!args) {
    return false;
  }
  const firstArg = (0, import_source.getCallFirstArgumentSource)(source, masked, index);
  const firstArgLiteral = firstArg ? (0, import_source.readLeadingStringLiteral)(firstArg) : void 0;
  if (firstArgLiteral) {
    return isResourceLikeCtxRequestUrl(firstArgLiteral.value.trim());
  }
  const urlMatch = args.match(/\burl\s*:\s*(['"`])([^'"`]+)\1/i) || args.match(/^\s*(['"`])([^'"`]+)\1\s*$/);
  if (urlMatch) {
    return isResourceLikeCtxRequestUrl(urlMatch[2].trim());
  }
  return /\b(?:resource|collectionName|collection)\s*:/i.test(args);
}
function isResourceLikeCtxRequestUrl(url) {
  if (/^(?:https?:)?\/\//i.test(url)) {
    return false;
  }
  const resourceUrl = url.replace(/^\/api\//i, "").replace(/^\//, "");
  return isResourceLikeRequestUrl(resourceUrl);
}
function isResourceLikeRequestUrl(url) {
  return /^(?:[A-Za-z_$][\w$.-]*|\$\{[^}]+\}):(?:list|get)(?:\b|[/?#])/i.test(url);
}
function getResourceLikeCtxRunjsEntrypoint(source, masked, index) {
  const firstArg = (0, import_source.getCallFirstArgumentSource)(source, masked, index);
  if (!firstArg) {
    return "";
  }
  const literal = (0, import_source.readLeadingStringLiteral)(firstArg);
  if (literal) {
    const endpoint = literal.value.trim();
    return isResourceLikeRunjsEntrypoint(endpoint) ? endpoint : "";
  }
  const expression = firstArg.trim();
  return isResourceLikeRunjsEntrypointExpression(expression) ? expression : "";
}
function isResourceLikeRunjsEntrypoint(value) {
  const trimmed = value.trim();
  const action = import_constants.RUNJS_RESOURCE_ACTION_PATTERN;
  return new RegExp(`^(?:resource|collection):${action}(?:$|[/?#])`, "i").test(trimmed) || new RegExp(`^[A-Za-z_$][\\w$.-]*:${action}(?:$|[/?#])`, "i").test(trimmed) || new RegExp(`\\$\\{[^}]+\\}\\s*:${action}(?:$|[/?#])`, "i").test(trimmed);
}
function isResourceLikeRunjsEntrypointExpression(value) {
  const withoutComments = (0, import_source.maskJavaScriptComments)(value);
  return new RegExp(`(['"\`])\\s*:${import_constants.RUNJS_RESOURCE_ACTION_PATTERN}\\1`).test(withoutComments);
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  collectCtxAliases,
  collectCtxLibMemberCaseMismatches,
  collectCtxMemberAccesses,
  collectCtxRenderComponentSignatureCalls,
  collectDirectDomAliases,
  collectDirectDomWrites,
  collectFlowResourceAliases,
  collectForbiddenBareGlobals,
  collectInvalidApiResourceCalls,
  collectInvalidFlowResourceListCalls,
  collectInvalidResourceTypeCalls,
  collectReactComponentAliases,
  collectReactComponentFunctionCalls,
  collectReactComponentPropReferences,
  collectReactHookCalls,
  collectResourceCallsInReactHooks,
  collectUnboundReactCreateElementCalls,
  collectWindowDocumentNavigatorAliases,
  collectWindowDocumentNavigatorUses,
  getResourceLikeCtxRunjsEntrypoint,
  isResourceLikeCtxRequest,
  isTopLevelFunctionWrapper
});
