_walkIIFE(functionExpression, options, currentThis) {
		/**
		 * @param {Expression | SpreadElement} argOrThis arg or this
		 * @returns {string | VariableInfo | undefined} var info
		 */
		const getVarInfo = argOrThis => {
			const renameIdentifier = this.getRenameIdentifier(argOrThis);
			if (
				renameIdentifier &&
				this.callHooksForInfo(
					this.hooks.canRename,
					renameIdentifier,
					/** @type {Expression} */
					(argOrThis)
				) &&
				!this.callHooksForInfo(
					this.hooks.rename,
					renameIdentifier,
					/** @type {Expression} */
					(argOrThis)
				)
			) {
				return typeof renameIdentifier === "string"
					? /** @type {string} */ (this.getVariableInfo(renameIdentifier))
					: renameIdentifier;
			}
			this.walkExpression(argOrThis);
		};
		const { params, type } = functionExpression;
		const arrow = type === "ArrowFunctionExpression";
		const renameThis = currentThis ? getVarInfo(currentThis) : null;
		const varInfoForArgs = options.map(getVarInfo);
		const wasTopLevel = this.scope.topLevelScope;
		this.scope.topLevelScope = wasTopLevel && arrow ? "arrow" : false;
		const scopeParams =
			/** @type {(Identifier | string)[]} */
			(params.filter((identifier, idx) => !varInfoForArgs[idx]));

		// Add function name in scope for recursive calls
		if (
			functionExpression.type === "FunctionExpression" &&
			functionExpression.id
		) {
			scopeParams.push(functionExpression.id.name);
		}

		this.inFunctionScope(true, scopeParams, () => {
			if (renameThis && !arrow) {
				this.setVariable("this", renameThis);
			}
			for (let i = 0; i < varInfoForArgs.length; i++) {
				const varInfo = varInfoForArgs[i];
				if (!varInfo) continue;
				if (!params[i] || params[i].type !== "Identifier") continue;
				this.setVariable(/** @type {Identifier} */ (params[i]).name, varInfo);
			}
			if (functionExpression.body.type === "BlockStatement") {
				this.detectMode(functionExpression.body.body);
				const prev = this.prevStatement;
				this.preWalkStatement(functionExpression.body);
				this.prevStatement = prev;
				this.walkStatement(functionExpression.body);
			} else {
				this.walkExpression(functionExpression.body);
			}
		});
		this.scope.topLevelScope = wasTopLevel;
	}
@private
@param {FunctionExpression | ArrowFunctionExpression} functionExpression function expression
@param {(Expression | SpreadElement)[]} options options
@param {Expression | SpreadElement | null} currentThis current this