import { I as IGNORABLE_RUNTIME_WARNINGS, N as NAMESPACE_SVG, d as NAMESPACE_MATHML, m as PROPS_IS_BINDABLE, o as PROPS_IS_IMMUTABLE, n as PROPS_IS_RUNES, P as PROPS_IS_UPDATED, p as PROPS_IS_LAZY_INITIAL, E as ELEMENT_IS_NAMESPACED, q as ELEMENT_PRESERVE_ATTRIBUTE_CASE, r as ELEMENT_IS_INPUT, s as EACH_INDEX_REACTIVE, t as EACH_ITEM_REACTIVE, u as EACH_ITEM_IMMUTABLE, v as EACH_IS_ANIMATED, w as EACH_IS_CONTROLLED, e as TEMPLATE_USE_SVG, f as TEMPLATE_USE_MATHML, c as TEMPLATE_USE_IMPORT_NODE, T as TEMPLATE_FRAGMENT, j as TRANSITION_GLOBAL, k as TRANSITION_IN, l as TRANSITION_OUT } from './constants-CdtLqJ9y.js';
import { s as sanitize_location, i as is_void, e as is_reserved, f as is_rune, g as cannot_be_set_statically, d as can_delegate_event, h as is_svg, j as is_content_editable_binding, k as is_state_creation_rune, l as is_mathml, m as hash, o as is_load_error_element, p as is_boolean_attribute, c as is_capture_event, a as is_passive_event, q as is_dom_property, n as normalize_attribute } from './utils-Bmu7F6be.js';
import { c as closing_tag_omitted, i as is_tag_valid_with_parent, a as is_tag_valid_with_ancestor, B as BLOCK_OPEN_ELSE, b as BLOCK_CLOSE, d as BLOCK_OPEN, E as EMPTY_COMMENT } from './hydration-2IdOHHtJ.js';
import { V as VERSION } from './version-Cd0FSyXd.js';
import { g as getDefaultExportFromCjs } from './_commonjsHelpers-B85MJLTf.js';
import { e as escape_html } from './escaping-CBnpiEl5.js';

/** @import { Context, Visitor, Visitors } from './types.js' */

/**
 * @template {{ type: string }} T
 * @template {Record<string, any> | null} U
 * @param {T} node
 * @param {U} state
 * @param {Visitors<T, U>} visitors
 */
function walk$1(node, state, visitors) {
	const universal = visitors._;

	let stopped = false;

	/** @type {Visitor<T, U, T>} _ */
	function default_visitor(_, { next, state }) {
		next(state);
	}

	/**
	 * @param {T} node
	 * @param {T[]} path
	 * @param {U} state
	 * @returns {T | undefined}
	 */
	function visit(node, path, state) {
		// Don't return the node here or it could lead to false-positive mutation detection
		if (stopped) return;
		if (!node.type) return;

		/** @type {T | void} */
		let result;

		/** @type {Record<string, any>} */
		const mutations = {};

		/** @type {Context<T, U>} */
		const context = {
			path,
			state,
			next: (next_state = state) => {
				path.push(node);
				for (const key in node) {
					if (key === 'type') continue;

					const child_node = node[key];
					if (child_node && typeof child_node === 'object') {
						if (Array.isArray(child_node)) {
							/** @type {Record<number, T>} */
							const array_mutations = {};
							const len = child_node.length;

							let mutated = false;

							for (let i = 0; i < len; i++) {
								const node = child_node[i];
								if (node && typeof node === 'object') {
									const result = visit(node, path, next_state);
									if (result) {
										array_mutations[i] = result;
										mutated = true;
									}
								}
							}

							if (mutated) {
								mutations[key] = child_node.map(
									(node, i) => array_mutations[i] ?? node
								);
							}
						} else {
							const result = visit(
								/** @type {T} */ (child_node),
								path,
								next_state
							);

							// @ts-ignore
							if (result) {
								mutations[key] = result;
							}
						}
					}
				}
				path.pop();

				if (Object.keys(mutations).length > 0) {
					return apply_mutations(node, mutations);
				}
			},
			stop: () => {
				stopped = true;
			},
			visit: (next_node, next_state = state) => {
				path.push(node);
				const result = visit(next_node, path, next_state) ?? next_node;
				path.pop();
				return result;
			}
		};

		let visitor = /** @type {Visitor<T, U, T>} */ (
			visitors[/** @type {T['type']} */ (node.type)] ?? default_visitor
		);

		if (universal) {
			/** @type {T | void} */
			let inner_result;

			result = universal(node, {
				...context,
				/** @param {U} next_state */
				next: (next_state = state) => {
					state = next_state; // make it the default for subsequent specialised visitors

					inner_result = visitor(node, {
						...context,
						state: next_state
					});

					return inner_result;
				}
			});

			// @ts-expect-error TypeScript doesn't understand that `context.next(...)` is called immediately
			if (!result && inner_result) {
				result = inner_result;
			}
		} else {
			result = visitor(node, context);
		}

		if (!result) {
			if (Object.keys(mutations).length > 0) {
				result = apply_mutations(node, mutations);
			}
		}

		if (result) {
			return result;
		}
	}

	return visit(node, [], state) ?? node;
}

/**
 * @template {Record<string, any>} T
 * @param {T} node
 * @param {Record<string, any>} mutations
 * @returns {T}
 */
function apply_mutations(node, mutations) {
	/** @type {Record<string, any>} */
	const obj = {};

	const descriptors = Object.getOwnPropertyDescriptors(node);

	for (const key in descriptors) {
		Object.defineProperty(obj, key, descriptors[key]);
	}

	for (const key in mutations) {
		obj[key] = mutations[key];
	}

	return /** @type {T} */ (obj);
}

const regex_whitespace = /\s/;
const regex_whitespaces = /\s+/;
const regex_starts_with_newline = /^\r?\n/;
const regex_starts_with_whitespace = /^\s/;
const regex_starts_with_whitespaces = /^[ \t\r\n]+/;
const regex_ends_with_whitespace = /\s$/;
const regex_ends_with_whitespaces = /[ \t\r\n]+$/;
/** Not \S because that also removes explicit whitespace defined through things like `&nbsp;` */
const regex_not_whitespace = /[^ \t\r\n]/;
/** Not \s+ because that also includes explicit whitespace defined through things like `&nbsp;` */
const regex_whitespaces_strict = /[ \t\n\r\f]+/g;

const regex_only_whitespaces = /^[ \t\n\r\f]+$/;

const regex_not_newline_characters = /[^\n]/g;

const regex_is_valid_identifier = /^[a-zA-Z_$][a-zA-Z_$0-9]*$/;
// used in replace all to remove all invalid chars from a literal identifier
const regex_invalid_identifier_chars = /(^[^a-zA-Z_$]|[^a-zA-Z0-9_$])/g;

const regex_starts_with_vowel = /^[aeiou]/;
const regex_heading_tags = /^h[1-6]$/;
const regex_illegal_attribute_character = /(^[0-9-.])|[\^$@%&#?!|()[\]{}^*+~;]/;
const regex_bidirectional_control_characters =
	/[\u202a\u202b\u202c\u202d\u202e\u2066\u2067\u2068\u2069]+/g;
const regex_js_prefix = /^\W*javascript:/i;
const regex_redundant_img_alt = /\b(image|picture|photo)\b/i;

/**
 * @param {string} name
 * @param {string[]} names
 * @returns {string | null}
 */
function fuzzymatch(name, names) {
	if (names.length === 0) return null;

	const set = new FuzzySet(names);
	const matches = set.get(name);

	return matches && matches[0][0] > 0.7 ? matches[0][1] : null;
}

// adapted from https://github.com/Glench/fuzzyset.js/blob/master/lib/fuzzyset.js in 2016
// BSD Licensed (see https://github.com/Glench/fuzzyset.js/issues/10)

const GRAM_SIZE_LOWER = 2;
const GRAM_SIZE_UPPER = 3;

// return an edit distance from 0 to 1

/**
 * @param {string} str1
 * @param {string} str2
 */
function _distance(str1, str2) {
	if (str1 === null && str2 === null) {
		throw 'Trying to compare two null values';
	}
	if (str1 === null || str2 === null) return 0;
	str1 = String(str1);
	str2 = String(str2);

	const distance = levenshtein(str1, str2);
	return 1 - distance / Math.max(str1.length, str2.length);
}

// helper functions

/**
 * @param {string} str1
 * @param {string} str2
 */
function levenshtein(str1, str2) {
	/** @type {number[]} */
	const current = [];
	let prev = 0;
	let value = 0;

	for (let i = 0; i <= str2.length; i++) {
		for (let j = 0; j <= str1.length; j++) {
			if (i && j) {
				if (str1.charAt(j - 1) === str2.charAt(i - 1)) {
					value = prev;
				} else {
					value = Math.min(current[j], current[j - 1], prev) + 1;
				}
			} else {
				value = i + j;
			}

			prev = current[j];
			current[j] = value;
		}
	}

	return /** @type {number} */ (current.pop());
}

const non_word_regex = /[^\w, ]+/;

/**
 * @param {string} value
 * @param {any} gram_size
 */
function iterate_grams(value, gram_size = 2) {
	const simplified = '-' + value.toLowerCase().replace(non_word_regex, '') + '-';
	const len_diff = gram_size - simplified.length;
	const results = [];

	if (len_diff > 0) {
		for (let i = 0; i < len_diff; ++i) {
			value += '-';
		}
	}
	for (let i = 0; i < simplified.length - gram_size + 1; ++i) {
		results.push(simplified.slice(i, i + gram_size));
	}
	return results;
}

/**
 * @param {string} value
 * @param {any} gram_size
 */
function gram_counter(value, gram_size = 2) {
	// return an object where key=gram, value=number of occurrences

	/** @type {Record<string, number>} */
	const result = {};
	const grams = iterate_grams(value, gram_size);
	let i = 0;

	for (i; i < grams.length; ++i) {
		if (grams[i] in result) {
			result[grams[i]] += 1;
		} else {
			result[grams[i]] = 1;
		}
	}
	return result;
}

/**
 * @param {MatchTuple} a
 * @param {MatchTuple} b
 */
function sort_descending(a, b) {
	return b[0] - a[0];
}

class FuzzySet {
	/** @type {Record<string, string>} */
	exact_set = {};

	/** @type {Record<string, [number, number][]>} */
	match_dict = {};

	/** @type {Record<string, number[]>} */
	items = {};

	/** @param {string[]} arr */
	constructor(arr) {
		// initialisation
		for (let i = GRAM_SIZE_LOWER; i < GRAM_SIZE_UPPER + 1; ++i) {
			this.items[i] = [];
		}

		// add all the items to the set
		for (let i = 0; i < arr.length; ++i) {
			this.add(arr[i]);
		}
	}

	/** @param {string} value */
	add(value) {
		const normalized_value = value.toLowerCase();
		if (normalized_value in this.exact_set) {
			return false;
		}

		let i = GRAM_SIZE_LOWER;
		for (i; i < GRAM_SIZE_UPPER + 1; ++i) {
			this._add(value, i);
		}
	}

	/**
	 * @param {string} value
	 * @param {number} gram_size
	 */
	_add(value, gram_size) {
		const normalized_value = value.toLowerCase();
		const items = this.items[gram_size] || [];
		const index = items.length;

		items.push(0);
		const gram_counts = gram_counter(normalized_value, gram_size);
		let sum_of_square_gram_counts = 0;
		let gram;
		let gram_count;

		for (gram in gram_counts) {
			gram_count = gram_counts[gram];
			sum_of_square_gram_counts += Math.pow(gram_count, 2);
			if (gram in this.match_dict) {
				this.match_dict[gram].push([index, gram_count]);
			} else {
				this.match_dict[gram] = [[index, gram_count]];
			}
		}
		const vector_normal = Math.sqrt(sum_of_square_gram_counts);
		// @ts-ignore no idea what this code is doing
		items[index] = [vector_normal, normalized_value];
		this.items[gram_size] = items;
		this.exact_set[normalized_value] = value;
	}

	/** @param {string} value */
	get(value) {
		const normalized_value = value.toLowerCase();
		const result = this.exact_set[normalized_value];

		if (result) {
			return /** @type {MatchTuple[]} */ ([[1, result]]);
		}

		// start with high gram size and if there are no results, go to lower gram sizes
		for (let gram_size = GRAM_SIZE_UPPER; gram_size >= GRAM_SIZE_LOWER; --gram_size) {
			const results = this.__get(value, gram_size);
			if (results.length > 0) return results;
		}
		return null;
	}

	/**
	 * @param {string} value
	 * @param {number} gram_size
	 * @returns {MatchTuple[]}
	 */
	__get(value, gram_size) {
		const normalized_value = value.toLowerCase();

		/** @type {Record<string, number>} */
		const matches = {};
		const gram_counts = gram_counter(normalized_value, gram_size);
		const items = this.items[gram_size];
		let sum_of_square_gram_counts = 0;
		let gram;
		let gram_count;
		let i;
		let index;
		let other_gram_count;

		for (gram in gram_counts) {
			gram_count = gram_counts[gram];
			sum_of_square_gram_counts += Math.pow(gram_count, 2);
			if (gram in this.match_dict) {
				for (i = 0; i < this.match_dict[gram].length; ++i) {
					index = this.match_dict[gram][i][0];
					other_gram_count = this.match_dict[gram][i][1];
					if (index in matches) {
						matches[index] += gram_count * other_gram_count;
					} else {
						matches[index] = gram_count * other_gram_count;
					}
				}
			}
		}

		const vector_normal = Math.sqrt(sum_of_square_gram_counts);

		/** @type {MatchTuple[]} */
		let results = [];
		let match_score;

		// build a results list of [score, str]
		for (const match_index in matches) {
			match_score = matches[match_index];
			// @ts-ignore no idea what this code is doing
			results.push([match_score / (vector_normal * items[match_index][0]), items[match_index][1]]);
		}

		results.sort(sort_descending);

		/** @type {MatchTuple[]} */
		let new_results = [];
		const end_index = Math.min(50, results.length);
		// truncate somewhat arbitrarily to 50
		for (let i = 0; i < end_index; ++i) {
			// @ts-ignore no idea what this code is doing
			new_results.push([_distance(results[i][1], normalized_value), results[i][1]]);
		}
		results = new_results;
		results.sort(sort_descending);

		new_results = [];
		for (let i = 0; i < results.length; ++i) {
			if (results[i][0] === results[0][0]) {
				// @ts-ignore no idea what this code is doing
				new_results.push([results[i][0], this.exact_set[results[i][1]]]);
			}
		}

		return new_results;
	}
}

/** @typedef {[score: number, match: string]} MatchTuple */

/** @typedef {import('./types').Location} Location */

/**
 * @param {import('./types').Range} range
 * @param {number} index
 */
function rangeContains(range, index) {
	return range.start <= index && index < range.end;
}

/**
 * @param {string} source
 * @param {import('./types').Options} [options]
 */
function getLocator$1(source, options = {}) {
	const { offsetLine = 0, offsetColumn = 0 } = options;

	let start = 0;
	const ranges = source.split('\n').map((line, i) => {
		const end = start + line.length + 1;

		/** @type {import('./types').Range} */
		const range = { start, end, line: i };

		start = end;
		return range;
	});

	let i = 0;

	/**
	 * @param {string | number} search
	 * @param {number} [index]
	 * @returns {Location | undefined}
	 */
	function locator(search, index) {
		if (typeof search === 'string') {
			search = source.indexOf(search, index ?? 0);
		}

		if (search === -1) return undefined;

		let range = ranges[i];

		const d = search >= range.end ? 1 : -1;

		while (range) {
			if (rangeContains(range, search)) {
				return {
					line: offsetLine + range.line,
					column: offsetColumn + search - range.start,
					character: search
				};
			}

			i += d;
			range = ranges[i];
		}
	}

	return locator;
}

/** @import { Location } from 'locate-character' */
/** @import { CompileOptions } from './types' */
/** @import { AST, Warning } from '#compiler' */

/** @typedef {{ start?: number, end?: number }} NodeLike */

/** @type {Warning[]} */
let warnings = [];

/**
 * The filename relative to the rootDir (if specified).
 * This should not be used in the compiler output except in dev mode
 * @type {string}
 */
let filename;

/**
 * This is the fallback used when no filename is specified.
 */
const UNKNOWN_FILENAME = '(unknown)';

/**
 * The name of the component that is used in the `export default function ...` statement.
 */
let component_name = '<unknown>';

/**
 * The original source code
 * @type {string}
 */
let source;

/**
 * True if compiling with `dev: true`
 * @type {boolean}
 */
let dev;

let locator = getLocator$1('', { offsetLine: 1 });

/** @param {string} value */
function set_source(value) {
	source = value;
	locator = getLocator$1(source, { offsetLine: 1 });
}

/**
 * @param {AST.SvelteNode & { start?: number | undefined }} node
 */
function locate_node(node) {
	const loc = /** @type {Location} */ (locator(/** @type {number} */ (node.start)));
	return `${sanitize_location(filename)}:${loc?.line}:${loc.column}`;
}

/** @type {NonNullable<CompileOptions['warningFilter']>} */
let warning_filter;

/**
 * The current stack of ignored warnings
 * @type {Set<string>[]}
 */
let ignore_stack = [];

/**
 * For each node the list of warnings that should be ignored for that node.
 * Exists in addition to `ignore_stack` because not all warnings are emitted
 * while the stack is being built.
 * @type {Map<AST.SvelteNode | NodeLike, Set<string>[]>}
 */
let ignore_map = new Map();

/**
 * @param {string[]} ignores
 */
function push_ignore(ignores) {
	const next = new Set([...(ignore_stack.at(-1) || []), ...ignores]);
	ignore_stack.push(next);
}

function pop_ignore() {
	ignore_stack.pop();
}

/**
 * @param {AST.SvelteNode | NodeLike} node
 * @param {typeof import('../constants.js').IGNORABLE_RUNTIME_WARNINGS[number]} code
 * @returns
 */
function is_ignored(node, code) {
	return dev && !!ignore_map.get(node)?.some((codes) => codes.has(code));
}

/**
 * Call this to reset the compiler state. Should be called before each compilation.
 * @param {{ warning?: (warning: Warning) => boolean; filename: string | undefined }} state
 */
function reset(state) {
	dev = false;
	component_name = UNKNOWN_FILENAME;
	source = '';
	locator = () => undefined;
	filename = (state.filename ?? UNKNOWN_FILENAME).replace(/\\/g, '/');
	warning_filter = state.warning ?? (() => true);
	warnings = [];
}

/**
 * Adjust the compiler state based on the provided state object.
 * Call this after parsing and basic analysis happened.
 * @param {{
 *   dev: boolean;
 *   component_name?: string;
 *   rootDir?: string;
 *   runes: boolean;
 * }} state
 */
function adjust(state) {
	const root_dir = state.rootDir?.replace(/\\/g, '/');

	dev = state.dev;
	state.runes;
	component_name = state.component_name ?? UNKNOWN_FILENAME;

	if (typeof root_dir === 'string' && filename.startsWith(root_dir)) {
		// make filename relative to rootDir
		filename = filename.replace(root_dir, '').replace(/^[/\\]/, '');
	}

	ignore_stack = [];
	ignore_map.clear();
}

/** @import { Location } from 'locate-character' */

const regex_tabs = /^\t+/;

/**
 * @param {string} str
 */
function tabs_to_spaces(str) {
	return str.replace(regex_tabs, (match) => match.split('\t').join('  '));
}

/**
 * @param {string} source
 * @param {number} line
 * @param {number} column
 */
function get_code_frame(source, line, column) {
	const lines = source.split('\n');
	const frame_start = Math.max(0, line - 2);
	const frame_end = Math.min(line + 3, lines.length);
	const digits = String(frame_end + 1).length;
	return lines
		.slice(frame_start, frame_end)
		.map((str, i) => {
			const is_error_line = frame_start + i === line;
			const line_num = String(i + frame_start + 1).padStart(digits, ' ');
			if (is_error_line) {
				const indicator =
					' '.repeat(digits + 2 + tabs_to_spaces(str.slice(0, column)).length) + '^';
				return `${line_num}: ${tabs_to_spaces(str)}\n${indicator}`;
			}
			return `${line_num}: ${tabs_to_spaces(str)}`;
		})
		.join('\n');
}

/**
 * @typedef {{
 * 	code: string;
 * 	message: string;
 *  stack?: string;
 * 	filename?: string;
 * 	start?: Location;
 * 	end?: Location;
 * 	position?: [number, number];
 * 	frame?: string;
 * }} ICompileDiagnostic
 */

/** @implements {ICompileDiagnostic} */
class CompileDiagnostic {
	name = 'CompileDiagnostic';

	/**
	 * @param {string} code
	 * @param {string} message
	 * @param {[number, number] | undefined} position
	 */
	constructor(code, message, position) {
		this.code = code;
		this.message = message;

		if (filename !== UNKNOWN_FILENAME) {
			this.filename = filename;
		}

		if (position) {
			this.position = position;
			this.start = locator(position[0]);
			this.end = locator(position[1]);
			if (this.start && this.end) {
				this.frame = get_code_frame(source, this.start.line - 1, this.end.column);
			}
		}
	}

	toString() {
		let out = `${this.code}: ${this.message}`;

		if (this.filename) {
			out += `\n${this.filename}`;

			if (this.start) {
				out += `:${this.start.line}:${this.start.column}`;
			}
		}

		if (this.frame) {
			out += `\n${this.frame}`;
		}

		return out;
	}

	toJSON() {
		return {
			code: this.code,
			message: this.message,
			filename: this.filename,
			start: this.start,
			end: this.end,
			position: this.position,
			frame: this.frame
		};
	}
}

/* This file is generated by scripts/process-messages/index.js. Do not edit! */


/** @typedef {{ start?: number, end?: number }} NodeLike */
class InternalCompileWarning extends CompileDiagnostic {
	name = 'CompileWarning';

	/**
	 * @param {string} code
	 * @param {string} message
	 * @param {[number, number] | undefined} position
	 */
	constructor(code, message, position) {
		super(code, message, position);
	}
}

/**
 * @param {null | NodeLike} node
 * @param {string} code
 * @param {string} message
 */
function w(node, code, message) {
	let stack = ignore_stack;

	if (node) {
		stack = ignore_map.get(node) ?? ignore_stack;
	}

	if (stack && stack.at(-1)?.has(code)) return;

	const warning = new InternalCompileWarning(code, message, node && node.start !== undefined ? [node.start, node.end ?? node.start] : undefined);

	if (!warning_filter(warning)) return;

	warnings.push(warning);
}

const codes$1 = [
	'a11y_accesskey',
	'a11y_aria_activedescendant_has_tabindex',
	'a11y_aria_attributes',
	'a11y_autocomplete_valid',
	'a11y_autofocus',
	'a11y_click_events_have_key_events',
	'a11y_consider_explicit_label',
	'a11y_distracting_elements',
	'a11y_figcaption_index',
	'a11y_figcaption_parent',
	'a11y_hidden',
	'a11y_img_redundant_alt',
	'a11y_incorrect_aria_attribute_type',
	'a11y_incorrect_aria_attribute_type_boolean',
	'a11y_incorrect_aria_attribute_type_id',
	'a11y_incorrect_aria_attribute_type_idlist',
	'a11y_incorrect_aria_attribute_type_integer',
	'a11y_incorrect_aria_attribute_type_token',
	'a11y_incorrect_aria_attribute_type_tokenlist',
	'a11y_incorrect_aria_attribute_type_tristate',
	'a11y_interactive_supports_focus',
	'a11y_invalid_attribute',
	'a11y_label_has_associated_control',
	'a11y_media_has_caption',
	'a11y_misplaced_role',
	'a11y_misplaced_scope',
	'a11y_missing_attribute',
	'a11y_missing_content',
	'a11y_mouse_events_have_key_events',
	'a11y_no_abstract_role',
	'a11y_no_interactive_element_to_noninteractive_role',
	'a11y_no_noninteractive_element_interactions',
	'a11y_no_noninteractive_element_to_interactive_role',
	'a11y_no_noninteractive_tabindex',
	'a11y_no_redundant_roles',
	'a11y_no_static_element_interactions',
	'a11y_positive_tabindex',
	'a11y_role_has_required_aria_props',
	'a11y_role_supports_aria_props',
	'a11y_role_supports_aria_props_implicit',
	'a11y_unknown_aria_attribute',
	'a11y_unknown_role',
	'bidirectional_control_characters',
	'legacy_code',
	'unknown_code',
	'options_deprecated_accessors',
	'options_deprecated_immutable',
	'options_missing_custom_element',
	'options_removed_enable_sourcemap',
	'options_removed_hydratable',
	'options_removed_loop_guard_timeout',
	'options_renamed_ssr_dom',
	'custom_element_props_identifier',
	'export_let_unused',
	'legacy_component_creation',
	'non_reactive_update',
	'perf_avoid_inline_class',
	'perf_avoid_nested_class',
	'reactive_declaration_invalid_placement',
	'reactive_declaration_module_script_dependency',
	'state_referenced_locally',
	'store_rune_conflict',
	'css_unused_selector',
	'attribute_avoid_is',
	'attribute_global_event_reference',
	'attribute_illegal_colon',
	'attribute_invalid_property_name',
	'attribute_quoted',
	'bind_invalid_each_rest',
	'block_empty',
	'component_name_lowercase',
	'element_implicitly_closed',
	'element_invalid_self_closing_tag',
	'event_directive_deprecated',
	'node_invalid_placement_ssr',
	'script_context_deprecated',
	'script_unknown_attribute',
	'slot_element_deprecated',
	'svelte_component_deprecated',
	'svelte_element_invalid_this',
	'svelte_self_deprecated'
];

/**
 * Avoid using accesskey
 * @param {null | NodeLike} node
 */
function a11y_accesskey(node) {
	w(node, 'a11y_accesskey', `Avoid using accesskey\nhttps://svelte.dev/e/a11y_accesskey`);
}

/**
 * An element with an aria-activedescendant attribute should have a tabindex value
 * @param {null | NodeLike} node
 */
function a11y_aria_activedescendant_has_tabindex(node) {
	w(node, 'a11y_aria_activedescendant_has_tabindex', `An element with an aria-activedescendant attribute should have a tabindex value\nhttps://svelte.dev/e/a11y_aria_activedescendant_has_tabindex`);
}

/**
 * `<%name%>` should not have aria-* attributes
 * @param {null | NodeLike} node
 * @param {string} name
 */
function a11y_aria_attributes(node, name) {
	w(node, 'a11y_aria_attributes', `\`<${name}>\` should not have aria-* attributes\nhttps://svelte.dev/e/a11y_aria_attributes`);
}

/**
 * '%value%' is an invalid value for 'autocomplete' on `<input type="%type%">`
 * @param {null | NodeLike} node
 * @param {string} value
 * @param {string} type
 */
function a11y_autocomplete_valid(node, value, type) {
	w(node, 'a11y_autocomplete_valid', `'${value}' is an invalid value for 'autocomplete' on \`<input type="${type}">\`\nhttps://svelte.dev/e/a11y_autocomplete_valid`);
}

/**
 * Avoid using autofocus
 * @param {null | NodeLike} node
 */
function a11y_autofocus(node) {
	w(node, 'a11y_autofocus', `Avoid using autofocus\nhttps://svelte.dev/e/a11y_autofocus`);
}

/**
 * Visible, non-interactive elements with a click event must be accompanied by a keyboard event handler. Consider whether an interactive element such as `<button type="button">` or `<a>` might be more appropriate
 * @param {null | NodeLike} node
 */
function a11y_click_events_have_key_events(node) {
	w(node, 'a11y_click_events_have_key_events', `Visible, non-interactive elements with a click event must be accompanied by a keyboard event handler. Consider whether an interactive element such as \`<button type="button">\` or \`<a>\` might be more appropriate\nhttps://svelte.dev/e/a11y_click_events_have_key_events`);
}

/**
 * Buttons and links should either contain text or have an `aria-label`, `aria-labelledby` or `title` attribute
 * @param {null | NodeLike} node
 */
function a11y_consider_explicit_label(node) {
	w(node, 'a11y_consider_explicit_label', `Buttons and links should either contain text or have an \`aria-label\`, \`aria-labelledby\` or \`title\` attribute\nhttps://svelte.dev/e/a11y_consider_explicit_label`);
}

/**
 * Avoid `<%name%>` elements
 * @param {null | NodeLike} node
 * @param {string} name
 */
function a11y_distracting_elements$1(node, name) {
	w(node, 'a11y_distracting_elements', `Avoid \`<${name}>\` elements\nhttps://svelte.dev/e/a11y_distracting_elements`);
}

/**
 * `<figcaption>` must be first or last child of `<figure>`
 * @param {null | NodeLike} node
 */
function a11y_figcaption_index(node) {
	w(node, 'a11y_figcaption_index', `\`<figcaption>\` must be first or last child of \`<figure>\`\nhttps://svelte.dev/e/a11y_figcaption_index`);
}

/**
 * `<figcaption>` must be an immediate child of `<figure>`
 * @param {null | NodeLike} node
 */
function a11y_figcaption_parent(node) {
	w(node, 'a11y_figcaption_parent', `\`<figcaption>\` must be an immediate child of \`<figure>\`\nhttps://svelte.dev/e/a11y_figcaption_parent`);
}

/**
 * `<%name%>` element should not be hidden
 * @param {null | NodeLike} node
 * @param {string} name
 */
function a11y_hidden(node, name) {
	w(node, 'a11y_hidden', `\`<${name}>\` element should not be hidden\nhttps://svelte.dev/e/a11y_hidden`);
}

/**
 * Screenreaders already announce `<img>` elements as an image
 * @param {null | NodeLike} node
 */
function a11y_img_redundant_alt(node) {
	w(node, 'a11y_img_redundant_alt', `Screenreaders already announce \`<img>\` elements as an image\nhttps://svelte.dev/e/a11y_img_redundant_alt`);
}

/**
 * The value of '%attribute%' must be a %type%
 * @param {null | NodeLike} node
 * @param {string} attribute
 * @param {string} type
 */
function a11y_incorrect_aria_attribute_type(node, attribute, type) {
	w(node, 'a11y_incorrect_aria_attribute_type', `The value of '${attribute}' must be a ${type}\nhttps://svelte.dev/e/a11y_incorrect_aria_attribute_type`);
}

/**
 * The value of '%attribute%' must be either 'true' or 'false'. It cannot be empty
 * @param {null | NodeLike} node
 * @param {string} attribute
 */
function a11y_incorrect_aria_attribute_type_boolean(node, attribute) {
	w(node, 'a11y_incorrect_aria_attribute_type_boolean', `The value of '${attribute}' must be either 'true' or 'false'. It cannot be empty\nhttps://svelte.dev/e/a11y_incorrect_aria_attribute_type_boolean`);
}

/**
 * The value of '%attribute%' must be a space-separated list of strings that represent DOM element IDs
 * @param {null | NodeLike} node
 * @param {string} attribute
 */
function a11y_incorrect_aria_attribute_type_idlist(node, attribute) {
	w(node, 'a11y_incorrect_aria_attribute_type_idlist', `The value of '${attribute}' must be a space-separated list of strings that represent DOM element IDs\nhttps://svelte.dev/e/a11y_incorrect_aria_attribute_type_idlist`);
}

/**
 * The value of '%attribute%' must be an integer
 * @param {null | NodeLike} node
 * @param {string} attribute
 */
function a11y_incorrect_aria_attribute_type_integer(node, attribute) {
	w(node, 'a11y_incorrect_aria_attribute_type_integer', `The value of '${attribute}' must be an integer\nhttps://svelte.dev/e/a11y_incorrect_aria_attribute_type_integer`);
}

/**
 * The value of '%attribute%' must be exactly one of %values%
 * @param {null | NodeLike} node
 * @param {string} attribute
 * @param {string} values
 */
function a11y_incorrect_aria_attribute_type_token(node, attribute, values) {
	w(node, 'a11y_incorrect_aria_attribute_type_token', `The value of '${attribute}' must be exactly one of ${values}\nhttps://svelte.dev/e/a11y_incorrect_aria_attribute_type_token`);
}

/**
 * The value of '%attribute%' must be a space-separated list of one or more of %values%
 * @param {null | NodeLike} node
 * @param {string} attribute
 * @param {string} values
 */
function a11y_incorrect_aria_attribute_type_tokenlist(node, attribute, values) {
	w(node, 'a11y_incorrect_aria_attribute_type_tokenlist', `The value of '${attribute}' must be a space-separated list of one or more of ${values}\nhttps://svelte.dev/e/a11y_incorrect_aria_attribute_type_tokenlist`);
}

/**
 * The value of '%attribute%' must be exactly one of true, false, or mixed
 * @param {null | NodeLike} node
 * @param {string} attribute
 */
function a11y_incorrect_aria_attribute_type_tristate(node, attribute) {
	w(node, 'a11y_incorrect_aria_attribute_type_tristate', `The value of '${attribute}' must be exactly one of true, false, or mixed\nhttps://svelte.dev/e/a11y_incorrect_aria_attribute_type_tristate`);
}

/**
 * Elements with the '%role%' interactive role must have a tabindex value
 * @param {null | NodeLike} node
 * @param {string} role
 */
function a11y_interactive_supports_focus(node, role) {
	w(node, 'a11y_interactive_supports_focus', `Elements with the '${role}' interactive role must have a tabindex value\nhttps://svelte.dev/e/a11y_interactive_supports_focus`);
}

/**
 * '%href_value%' is not a valid %href_attribute% attribute
 * @param {null | NodeLike} node
 * @param {string} href_value
 * @param {string} href_attribute
 */
function a11y_invalid_attribute(node, href_value, href_attribute) {
	w(node, 'a11y_invalid_attribute', `'${href_value}' is not a valid ${href_attribute} attribute\nhttps://svelte.dev/e/a11y_invalid_attribute`);
}

/**
 * A form label must be associated with a control
 * @param {null | NodeLike} node
 */
function a11y_label_has_associated_control(node) {
	w(node, 'a11y_label_has_associated_control', `A form label must be associated with a control\nhttps://svelte.dev/e/a11y_label_has_associated_control`);
}

/**
 * `<video>` elements must have a `<track kind="captions">`
 * @param {null | NodeLike} node
 */
function a11y_media_has_caption(node) {
	w(node, 'a11y_media_has_caption', `\`<video>\` elements must have a \`<track kind="captions">\`\nhttps://svelte.dev/e/a11y_media_has_caption`);
}

/**
 * `<%name%>` should not have role attribute
 * @param {null | NodeLike} node
 * @param {string} name
 */
function a11y_misplaced_role(node, name) {
	w(node, 'a11y_misplaced_role', `\`<${name}>\` should not have role attribute\nhttps://svelte.dev/e/a11y_misplaced_role`);
}

/**
 * The scope attribute should only be used with `<th>` elements
 * @param {null | NodeLike} node
 */
function a11y_misplaced_scope(node) {
	w(node, 'a11y_misplaced_scope', `The scope attribute should only be used with \`<th>\` elements\nhttps://svelte.dev/e/a11y_misplaced_scope`);
}

/**
 * `<%name%>` element should have %article% %sequence% attribute
 * @param {null | NodeLike} node
 * @param {string} name
 * @param {string} article
 * @param {string} sequence
 */
function a11y_missing_attribute(node, name, article, sequence) {
	w(node, 'a11y_missing_attribute', `\`<${name}>\` element should have ${article} ${sequence} attribute\nhttps://svelte.dev/e/a11y_missing_attribute`);
}

/**
 * `<%name%>` element should contain text
 * @param {null | NodeLike} node
 * @param {string} name
 */
function a11y_missing_content(node, name) {
	w(node, 'a11y_missing_content', `\`<${name}>\` element should contain text\nhttps://svelte.dev/e/a11y_missing_content`);
}

/**
 * '%event%' event must be accompanied by '%accompanied_by%' event
 * @param {null | NodeLike} node
 * @param {string} event
 * @param {string} accompanied_by
 */
function a11y_mouse_events_have_key_events(node, event, accompanied_by) {
	w(node, 'a11y_mouse_events_have_key_events', `'${event}' event must be accompanied by '${accompanied_by}' event\nhttps://svelte.dev/e/a11y_mouse_events_have_key_events`);
}

/**
 * Abstract role '%role%' is forbidden
 * @param {null | NodeLike} node
 * @param {string} role
 */
function a11y_no_abstract_role(node, role) {
	w(node, 'a11y_no_abstract_role', `Abstract role '${role}' is forbidden\nhttps://svelte.dev/e/a11y_no_abstract_role`);
}

/**
 * `<%element%>` cannot have role '%role%'
 * @param {null | NodeLike} node
 * @param {string} element
 * @param {string} role
 */
function a11y_no_interactive_element_to_noninteractive_role(node, element, role) {
	w(node, 'a11y_no_interactive_element_to_noninteractive_role', `\`<${element}>\` cannot have role '${role}'\nhttps://svelte.dev/e/a11y_no_interactive_element_to_noninteractive_role`);
}

/**
 * Non-interactive element `<%element%>` should not be assigned mouse or keyboard event listeners
 * @param {null | NodeLike} node
 * @param {string} element
 */
function a11y_no_noninteractive_element_interactions(node, element) {
	w(node, 'a11y_no_noninteractive_element_interactions', `Non-interactive element \`<${element}>\` should not be assigned mouse or keyboard event listeners\nhttps://svelte.dev/e/a11y_no_noninteractive_element_interactions`);
}

/**
 * Non-interactive element `<%element%>` cannot have interactive role '%role%'
 * @param {null | NodeLike} node
 * @param {string} element
 * @param {string} role
 */
function a11y_no_noninteractive_element_to_interactive_role(node, element, role) {
	w(node, 'a11y_no_noninteractive_element_to_interactive_role', `Non-interactive element \`<${element}>\` cannot have interactive role '${role}'\nhttps://svelte.dev/e/a11y_no_noninteractive_element_to_interactive_role`);
}

/**
 * noninteractive element cannot have nonnegative tabIndex value
 * @param {null | NodeLike} node
 */
function a11y_no_noninteractive_tabindex(node) {
	w(node, 'a11y_no_noninteractive_tabindex', `noninteractive element cannot have nonnegative tabIndex value\nhttps://svelte.dev/e/a11y_no_noninteractive_tabindex`);
}

/**
 * Redundant role '%role%'
 * @param {null | NodeLike} node
 * @param {string} role
 */
function a11y_no_redundant_roles(node, role) {
	w(node, 'a11y_no_redundant_roles', `Redundant role '${role}'\nhttps://svelte.dev/e/a11y_no_redundant_roles`);
}

/**
 * `<%element%>` with a %handler% handler must have an ARIA role
 * @param {null | NodeLike} node
 * @param {string} element
 * @param {string} handler
 */
function a11y_no_static_element_interactions(node, element, handler) {
	w(node, 'a11y_no_static_element_interactions', `\`<${element}>\` with a ${handler} handler must have an ARIA role\nhttps://svelte.dev/e/a11y_no_static_element_interactions`);
}

/**
 * Avoid tabindex values above zero
 * @param {null | NodeLike} node
 */
function a11y_positive_tabindex(node) {
	w(node, 'a11y_positive_tabindex', `Avoid tabindex values above zero\nhttps://svelte.dev/e/a11y_positive_tabindex`);
}

/**
 * Elements with the ARIA role "%role%" must have the following attributes defined: %props%
 * @param {null | NodeLike} node
 * @param {string} role
 * @param {string} props
 */
function a11y_role_has_required_aria_props(node, role, props) {
	w(node, 'a11y_role_has_required_aria_props', `Elements with the ARIA role "${role}" must have the following attributes defined: ${props}\nhttps://svelte.dev/e/a11y_role_has_required_aria_props`);
}

/**
 * The attribute '%attribute%' is not supported by the role '%role%'
 * @param {null | NodeLike} node
 * @param {string} attribute
 * @param {string} role
 */
function a11y_role_supports_aria_props(node, attribute, role) {
	w(node, 'a11y_role_supports_aria_props', `The attribute '${attribute}' is not supported by the role '${role}'\nhttps://svelte.dev/e/a11y_role_supports_aria_props`);
}

/**
 * The attribute '%attribute%' is not supported by the role '%role%'. This role is implicit on the element `<%name%>`
 * @param {null | NodeLike} node
 * @param {string} attribute
 * @param {string} role
 * @param {string} name
 */
function a11y_role_supports_aria_props_implicit(node, attribute, role, name) {
	w(node, 'a11y_role_supports_aria_props_implicit', `The attribute '${attribute}' is not supported by the role '${role}'. This role is implicit on the element \`<${name}>\`\nhttps://svelte.dev/e/a11y_role_supports_aria_props_implicit`);
}

/**
 * Unknown aria attribute 'aria-%attribute%'. Did you mean '%suggestion%'?
 * @param {null | NodeLike} node
 * @param {string} attribute
 * @param {string | undefined | null} [suggestion]
 */
function a11y_unknown_aria_attribute(node, attribute, suggestion) {
	w(node, 'a11y_unknown_aria_attribute', `${suggestion
		? `Unknown aria attribute 'aria-${attribute}'. Did you mean '${suggestion}'?`
		: `Unknown aria attribute 'aria-${attribute}'`}\nhttps://svelte.dev/e/a11y_unknown_aria_attribute`);
}

/**
 * Unknown role '%role%'. Did you mean '%suggestion%'?
 * @param {null | NodeLike} node
 * @param {string} role
 * @param {string | undefined | null} [suggestion]
 */
function a11y_unknown_role(node, role, suggestion) {
	w(node, 'a11y_unknown_role', `${suggestion
		? `Unknown role '${role}'. Did you mean '${suggestion}'?`
		: `Unknown role '${role}'`}\nhttps://svelte.dev/e/a11y_unknown_role`);
}

/**
 * A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences
 * @param {null | NodeLike} node
 */
function bidirectional_control_characters(node) {
	w(node, 'bidirectional_control_characters', `A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences\nhttps://svelte.dev/e/bidirectional_control_characters`);
}

/**
 * `%code%` is no longer valid — please use `%suggestion%` instead
 * @param {null | NodeLike} node
 * @param {string} code
 * @param {string} suggestion
 */
function legacy_code(node, code, suggestion) {
	w(node, 'legacy_code', `\`${code}\` is no longer valid — please use \`${suggestion}\` instead\nhttps://svelte.dev/e/legacy_code`);
}

/**
 * `%code%` is not a recognised code (did you mean `%suggestion%`?)
 * @param {null | NodeLike} node
 * @param {string} code
 * @param {string | undefined | null} [suggestion]
 */
function unknown_code(node, code, suggestion) {
	w(node, 'unknown_code', `${suggestion
		? `\`${code}\` is not a recognised code (did you mean \`${suggestion}\`?)`
		: `\`${code}\` is not a recognised code`}\nhttps://svelte.dev/e/unknown_code`);
}

/**
 * The `accessors` option has been deprecated. It will have no effect in runes mode
 * @param {null | NodeLike} node
 */
function options_deprecated_accessors(node) {
	w(node, 'options_deprecated_accessors', `The \`accessors\` option has been deprecated. It will have no effect in runes mode\nhttps://svelte.dev/e/options_deprecated_accessors`);
}

/**
 * The `immutable` option has been deprecated. It will have no effect in runes mode
 * @param {null | NodeLike} node
 */
function options_deprecated_immutable(node) {
	w(node, 'options_deprecated_immutable', `The \`immutable\` option has been deprecated. It will have no effect in runes mode\nhttps://svelte.dev/e/options_deprecated_immutable`);
}

/**
 * The `customElement` option is used when generating a custom element. Did you forget the `customElement: true` compile option?
 * @param {null | NodeLike} node
 */
function options_missing_custom_element(node) {
	w(node, 'options_missing_custom_element', `The \`customElement\` option is used when generating a custom element. Did you forget the \`customElement: true\` compile option?\nhttps://svelte.dev/e/options_missing_custom_element`);
}

/**
 * The `enableSourcemap` option has been removed. Source maps are always generated now, and tooling can choose to ignore them
 * @param {null | NodeLike} node
 */
function options_removed_enable_sourcemap(node) {
	w(node, 'options_removed_enable_sourcemap', `The \`enableSourcemap\` option has been removed. Source maps are always generated now, and tooling can choose to ignore them\nhttps://svelte.dev/e/options_removed_enable_sourcemap`);
}

/**
 * The `hydratable` option has been removed. Svelte components are always hydratable now
 * @param {null | NodeLike} node
 */
function options_removed_hydratable(node) {
	w(node, 'options_removed_hydratable', `The \`hydratable\` option has been removed. Svelte components are always hydratable now\nhttps://svelte.dev/e/options_removed_hydratable`);
}

/**
 * The `loopGuardTimeout` option has been removed
 * @param {null | NodeLike} node
 */
function options_removed_loop_guard_timeout(node) {
	w(node, 'options_removed_loop_guard_timeout', `The \`loopGuardTimeout\` option has been removed\nhttps://svelte.dev/e/options_removed_loop_guard_timeout`);
}

/**
 * `generate: "dom"` and `generate: "ssr"` options have been renamed to "client" and "server" respectively
 * @param {null | NodeLike} node
 */
function options_renamed_ssr_dom(node) {
	w(node, 'options_renamed_ssr_dom', `\`generate: "dom"\` and \`generate: "ssr"\` options have been renamed to "client" and "server" respectively\nhttps://svelte.dev/e/options_renamed_ssr_dom`);
}

/**
 * Using a rest element or a non-destructured declaration with `$props()` means that Svelte can't infer what properties to expose when creating a custom element. Consider destructuring all the props or explicitly specifying the `customElement.props` option.
 * @param {null | NodeLike} node
 */
function custom_element_props_identifier(node) {
	w(node, 'custom_element_props_identifier', `Using a rest element or a non-destructured declaration with \`$props()\` means that Svelte can't infer what properties to expose when creating a custom element. Consider destructuring all the props or explicitly specifying the \`customElement.props\` option.\nhttps://svelte.dev/e/custom_element_props_identifier`);
}

/**
 * Component has unused export property '%name%'. If it is for external reference only, please consider using `export const %name%`
 * @param {null | NodeLike} node
 * @param {string} name
 */
function export_let_unused(node, name) {
	w(node, 'export_let_unused', `Component has unused export property '${name}'. If it is for external reference only, please consider using \`export const ${name}\`\nhttps://svelte.dev/e/export_let_unused`);
}

/**
 * Svelte 5 components are no longer classes. Instantiate them using `mount` or `hydrate` (imported from 'svelte') instead.
 * @param {null | NodeLike} node
 */
function legacy_component_creation(node) {
	w(node, 'legacy_component_creation', `Svelte 5 components are no longer classes. Instantiate them using \`mount\` or \`hydrate\` (imported from 'svelte') instead.\nhttps://svelte.dev/e/legacy_component_creation`);
}

/**
 * `%name%` is updated, but is not declared with `$state(...)`. Changing its value will not correctly trigger updates
 * @param {null | NodeLike} node
 * @param {string} name
 */
function non_reactive_update(node, name) {
	w(node, 'non_reactive_update', `\`${name}\` is updated, but is not declared with \`$state(...)\`. Changing its value will not correctly trigger updates\nhttps://svelte.dev/e/non_reactive_update`);
}

/**
 * Avoid 'new class' — instead, declare the class at the top level scope
 * @param {null | NodeLike} node
 */
function perf_avoid_inline_class(node) {
	w(node, 'perf_avoid_inline_class', `Avoid 'new class' — instead, declare the class at the top level scope\nhttps://svelte.dev/e/perf_avoid_inline_class`);
}

/**
 * Avoid declaring classes below the top level scope
 * @param {null | NodeLike} node
 */
function perf_avoid_nested_class(node) {
	w(node, 'perf_avoid_nested_class', `Avoid declaring classes below the top level scope\nhttps://svelte.dev/e/perf_avoid_nested_class`);
}

/**
 * Reactive declarations only exist at the top level of the instance script
 * @param {null | NodeLike} node
 */
function reactive_declaration_invalid_placement(node) {
	w(node, 'reactive_declaration_invalid_placement', `Reactive declarations only exist at the top level of the instance script\nhttps://svelte.dev/e/reactive_declaration_invalid_placement`);
}

/**
 * Reassignments of module-level declarations will not cause reactive statements to update
 * @param {null | NodeLike} node
 */
function reactive_declaration_module_script_dependency(node) {
	w(node, 'reactive_declaration_module_script_dependency', `Reassignments of module-level declarations will not cause reactive statements to update\nhttps://svelte.dev/e/reactive_declaration_module_script_dependency`);
}

/**
 * This reference only captures the initial value of `%name%`. Did you mean to reference it inside a %type% instead?
 * @param {null | NodeLike} node
 * @param {string} name
 * @param {string} type
 */
function state_referenced_locally(node, name, type) {
	w(node, 'state_referenced_locally', `This reference only captures the initial value of \`${name}\`. Did you mean to reference it inside a ${type} instead?\nhttps://svelte.dev/e/state_referenced_locally`);
}

/**
 * It looks like you're using the `$%name%` rune, but there is a local binding called `%name%`. Referencing a local variable with a `$` prefix will create a store subscription. Please rename `%name%` to avoid the ambiguity
 * @param {null | NodeLike} node
 * @param {string} name
 */
function store_rune_conflict(node, name) {
	w(node, 'store_rune_conflict', `It looks like you're using the \`$${name}\` rune, but there is a local binding called \`${name}\`. Referencing a local variable with a \`$\` prefix will create a store subscription. Please rename \`${name}\` to avoid the ambiguity\nhttps://svelte.dev/e/store_rune_conflict`);
}

/**
 * Unused CSS selector "%name%"
 * @param {null | NodeLike} node
 * @param {string} name
 */
function css_unused_selector(node, name) {
	w(node, 'css_unused_selector', `Unused CSS selector "${name}"\nhttps://svelte.dev/e/css_unused_selector`);
}

/**
 * The "is" attribute is not supported cross-browser and should be avoided
 * @param {null | NodeLike} node
 */
function attribute_avoid_is(node) {
	w(node, 'attribute_avoid_is', `The "is" attribute is not supported cross-browser and should be avoided\nhttps://svelte.dev/e/attribute_avoid_is`);
}

/**
 * You are referencing `globalThis.%name%`. Did you forget to declare a variable with that name?
 * @param {null | NodeLike} node
 * @param {string} name
 */
function attribute_global_event_reference(node, name) {
	w(node, 'attribute_global_event_reference', `You are referencing \`globalThis.${name}\`. Did you forget to declare a variable with that name?\nhttps://svelte.dev/e/attribute_global_event_reference`);
}

/**
 * Attributes should not contain ':' characters to prevent ambiguity with Svelte directives
 * @param {null | NodeLike} node
 */
function attribute_illegal_colon(node) {
	w(node, 'attribute_illegal_colon', `Attributes should not contain ':' characters to prevent ambiguity with Svelte directives\nhttps://svelte.dev/e/attribute_illegal_colon`);
}

/**
 * '%wrong%' is not a valid HTML attribute. Did you mean '%right%'?
 * @param {null | NodeLike} node
 * @param {string} wrong
 * @param {string} right
 */
function attribute_invalid_property_name(node, wrong, right) {
	w(node, 'attribute_invalid_property_name', `'${wrong}' is not a valid HTML attribute. Did you mean '${right}'?\nhttps://svelte.dev/e/attribute_invalid_property_name`);
}

/**
 * Quoted attributes on components and custom elements will be stringified in a future version of Svelte. If this isn't what you want, remove the quotes
 * @param {null | NodeLike} node
 */
function attribute_quoted(node) {
	w(node, 'attribute_quoted', `Quoted attributes on components and custom elements will be stringified in a future version of Svelte. If this isn't what you want, remove the quotes\nhttps://svelte.dev/e/attribute_quoted`);
}

/**
 * The rest operator (...) will create a new object and binding '%name%' with the original object will not work
 * @param {null | NodeLike} node
 * @param {string} name
 */
function bind_invalid_each_rest(node, name) {
	w(node, 'bind_invalid_each_rest', `The rest operator (...) will create a new object and binding '${name}' with the original object will not work\nhttps://svelte.dev/e/bind_invalid_each_rest`);
}

/**
 * Empty block
 * @param {null | NodeLike} node
 */
function block_empty(node) {
	w(node, 'block_empty', `Empty block\nhttps://svelte.dev/e/block_empty`);
}

/**
 * `<%name%>` will be treated as an HTML element unless it begins with a capital letter
 * @param {null | NodeLike} node
 * @param {string} name
 */
function component_name_lowercase(node, name) {
	w(node, 'component_name_lowercase', `\`<${name}>\` will be treated as an HTML element unless it begins with a capital letter\nhttps://svelte.dev/e/component_name_lowercase`);
}

/**
 * This element is implicitly closed by the following `%tag%`, which can cause an unexpected DOM structure. Add an explicit `%closing%` to avoid surprises.
 * @param {null | NodeLike} node
 * @param {string} tag
 * @param {string} closing
 */
function element_implicitly_closed(node, tag, closing) {
	w(node, 'element_implicitly_closed', `This element is implicitly closed by the following \`${tag}\`, which can cause an unexpected DOM structure. Add an explicit \`${closing}\` to avoid surprises.\nhttps://svelte.dev/e/element_implicitly_closed`);
}

/**
 * Self-closing HTML tags for non-void elements are ambiguous — use `<%name% ...></%name%>` rather than `<%name% ... />`
 * @param {null | NodeLike} node
 * @param {string} name
 */
function element_invalid_self_closing_tag(node, name) {
	w(node, 'element_invalid_self_closing_tag', `Self-closing HTML tags for non-void elements are ambiguous — use \`<${name} ...></${name}>\` rather than \`<${name} ... />\`\nhttps://svelte.dev/e/element_invalid_self_closing_tag`);
}

/**
 * Using `on:%name%` to listen to the %name% event is deprecated. Use the event attribute `on%name%` instead
 * @param {null | NodeLike} node
 * @param {string} name
 */
function event_directive_deprecated(node, name) {
	w(node, 'event_directive_deprecated', `Using \`on:${name}\` to listen to the ${name} event is deprecated. Use the event attribute \`on${name}\` instead\nhttps://svelte.dev/e/event_directive_deprecated`);
}

/**
 * %message%. When rendering this component on the server, the resulting HTML will be modified by the browser (by moving, removing, or inserting elements), likely resulting in a `hydration_mismatch` warning
 * @param {null | NodeLike} node
 * @param {string} message
 */
function node_invalid_placement_ssr(node, message) {
	w(node, 'node_invalid_placement_ssr', `${message}. When rendering this component on the server, the resulting HTML will be modified by the browser (by moving, removing, or inserting elements), likely resulting in a \`hydration_mismatch\` warning\nhttps://svelte.dev/e/node_invalid_placement_ssr`);
}

/**
 * `context="module"` is deprecated, use the `module` attribute instead
 * @param {null | NodeLike} node
 */
function script_context_deprecated(node) {
	w(node, 'script_context_deprecated', `\`context="module"\` is deprecated, use the \`module\` attribute instead\nhttps://svelte.dev/e/script_context_deprecated`);
}

/**
 * Unrecognized attribute — should be one of `generics`, `lang` or `module`. If this exists for a preprocessor, ensure that the preprocessor removes it
 * @param {null | NodeLike} node
 */
function script_unknown_attribute(node) {
	w(node, 'script_unknown_attribute', `Unrecognized attribute — should be one of \`generics\`, \`lang\` or \`module\`. If this exists for a preprocessor, ensure that the preprocessor removes it\nhttps://svelte.dev/e/script_unknown_attribute`);
}

/**
 * Using `<slot>` to render parent content is deprecated. Use `{@render ...}` tags instead
 * @param {null | NodeLike} node
 */
function slot_element_deprecated(node) {
	w(node, 'slot_element_deprecated', `Using \`<slot>\` to render parent content is deprecated. Use \`{@render ...}\` tags instead\nhttps://svelte.dev/e/slot_element_deprecated`);
}

/**
 * `<svelte:component>` is deprecated in runes mode — components are dynamic by default
 * @param {null | NodeLike} node
 */
function svelte_component_deprecated(node) {
	w(node, 'svelte_component_deprecated', `\`<svelte:component>\` is deprecated in runes mode — components are dynamic by default\nhttps://svelte.dev/e/svelte_component_deprecated`);
}

/**
 * `this` should be an `{expression}`. Using a string attribute value will cause an error in future versions of Svelte
 * @param {null | NodeLike} node
 */
function svelte_element_invalid_this(node) {
	w(node, 'svelte_element_invalid_this', `\`this\` should be an \`{expression}\`. Using a string attribute value will cause an error in future versions of Svelte\nhttps://svelte.dev/e/svelte_element_invalid_this`);
}

/**
 * `<svelte:self>` is deprecated — use self-imports (e.g. `import %name% from './%basename%'`) instead
 * @param {null | NodeLike} node
 * @param {string} name
 * @param {string} basename
 */
function svelte_self_deprecated(node, name, basename) {
	w(node, 'svelte_self_deprecated', `\`<svelte:self>\` is deprecated — use self-imports (e.g. \`import ${name} from './${basename}'\`) instead\nhttps://svelte.dev/e/svelte_self_deprecated`);
}

const regex_svelte_ignore = /^\s*svelte-ignore\s/;

/** @type {Record<string, string>} Map of legacy code -> new code */
const replacements = {
	'non-top-level-reactive-declaration': 'reactive_declaration_invalid_placement',
	'module-script-reactive-declaration': 'reactive_declaration_module_script',
	'empty-block': 'block_empty',
	'avoid-is': 'attribute_avoid_is',
	'invalid-html-attribute': 'attribute_invalid_property_name',
	'a11y-structure': 'a11y_figcaption_parent',
	'illegal-attribute-character': 'attribute_illegal_colon',
	'invalid-rest-eachblock-binding': 'bind_invalid_each_rest',
	'unused-export-let': 'export_let_unused'
};

const codes = codes$1.concat(IGNORABLE_RUNTIME_WARNINGS);

/**
 * @param {number} offset
 * @param {string} text
 * @param {boolean} runes
 * @returns {string[]}
 */
function extract_svelte_ignore(offset, text, runes) {
	const match = regex_svelte_ignore.exec(text);
	if (!match) return [];

	let length = match[0].length;
	offset += length;

	/** @type {string[]} */
	const ignores = [];

	if (runes) {
		// Warnings have to be separated by commas, everything after is interpreted as prose
		for (const match of text.slice(length).matchAll(/([\w$-]+)(,)?/gm)) {
			const code = match[1];

			if (codes.includes(code)) {
				ignores.push(code);
			} else {
				const replacement = replacements[code] ?? code.replace(/-/g, '_');

				// The type cast is for some reason necessary to pass the type check in CI
				const start = offset + /** @type {number} */ (match.index);
				const end = start + code.length;

				if (codes.includes(replacement)) {
					legacy_code({ start, end }, code, replacement);
				} else {
					const suggestion = fuzzymatch(code, codes);
					unknown_code({ start, end }, code, suggestion);
				}
			}

			if (!match[2]) {
				break;
			}
		}
	} else {
		// Non-runes mode: lax parsing, backwards compat with old codes
		for (const match of text.slice(length).matchAll(/[\w$-]+/gm)) {
			const code = match[0];

			ignores.push(code);

			if (!codes.includes(code)) {
				const replacement = replacements[code] ?? code.replace(/-/g, '_');

				if (codes.includes(replacement)) {
					ignores.push(replacement);
				}
			}
		}
	}

	return ignores;
}

/**
 * Replaces legacy svelte-ignore codes with new codes.
 * @param {string} text
 * @returns {string}
 */
function migrate_svelte_ignore(text) {
	const match = regex_svelte_ignore.exec(text);
	if (!match) return text;

	const length = match[0].length;
	return (
		text.substring(0, length) +
		text.substring(length).replace(/\w+-\w+(-\w+)*/g, (code, _, idx) => {
			let replacement = replacements[code] ?? code.replace(/-/g, '_');
			if (/\w+-\w+/.test(text.substring(length + idx + code.length))) {
				replacement += ',';
			}
			return replacement;
		})
	);
}

/** @import { Expression } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import * as Legacy from './types/legacy-nodes.js' */

/**
 * Some of the legacy Svelte AST nodes remove whitespace from the start and end of their children.
 * @param {AST.TemplateNode[]} nodes
 */
function remove_surrounding_whitespace_nodes(nodes) {
	const first = nodes.at(0);
	const last = nodes.at(-1);

	if (first?.type === 'Text') {
		if (!regex_not_whitespace.test(first.data)) {
			nodes.shift();
		} else {
			first.data = first.data.replace(regex_starts_with_whitespaces, '');
		}
	}
	if (last?.type === 'Text') {
		if (!regex_not_whitespace.test(last.data)) {
			nodes.pop();
		} else {
			last.data = last.data.replace(regex_ends_with_whitespaces, '');
		}
	}
}

/**
 * Transform our nice modern AST into the monstrosity emitted by Svelte 4
 * @param {string} source
 * @param {AST.Root} ast
 * @returns {Legacy.LegacyRoot}
 */
function convert(source, ast) {
	const root = /** @type {AST.SvelteNode | Legacy.LegacySvelteNode} */ (ast);

	return /** @type {Legacy.LegacyRoot} */ (
		walk$1(root, null, {
			_(node, { next }) {
				// @ts-ignore
				delete node.metadata;
				next();
			},
			// @ts-ignore
			Root(node, { visit }) {
				const { instance, module, options } = node;

				// Insert svelte:options back into the root nodes
				if (/** @type {any} */ (options)?.__raw__) {
					let idx = node.fragment.nodes.findIndex(
						(node) => /** @type {any} */ (options).end <= node.start
					);
					if (idx === -1) {
						idx = node.fragment.nodes.length;
					}

					node.fragment.nodes.splice(idx, 0, /** @type {any} */ (options).__raw__);
				}

				/** @type {number | null} */
				let start = null;

				/** @type {number | null} */
				let end = null;

				if (node.fragment.nodes.length > 0) {
					const first = /** @type {AST.BaseNode} */ (node.fragment.nodes.at(0));
					const last = /** @type {AST.BaseNode} */ (node.fragment.nodes.at(-1));

					start = first.start;
					end = last.end;

					while (/\s/.test(source[start])) start += 1;
					while (/\s/.test(source[end - 1])) end -= 1;
				}

				if (instance) {
					// @ts-ignore
					delete instance.attributes;
				}

				if (module) {
					// @ts-ignore
					delete module.attributes;
				}

				return {
					html: {
						type: 'Fragment',
						start,
						end,
						children: node.fragment.nodes.map((child) => visit(child))
					},
					instance,
					module,
					css: ast.css ? visit(ast.css) : undefined
				};
			},
			AnimateDirective(node) {
				return { ...node, type: 'Animation' };
			},
			// @ts-ignore
			AwaitBlock(node, { visit }) {
				let pendingblock = {
					type: 'PendingBlock',
					/** @type {number | null} */
					start: null,
					/** @type {number | null} */
					end: null,
					children: node.pending?.nodes.map((child) => visit(child)) ?? [],
					skip: true
				};

				let thenblock = {
					type: 'ThenBlock',
					/** @type {number | null} */
					start: null,
					/** @type {number | null} */
					end: null,
					children: node.then?.nodes.map((child) => visit(child)) ?? [],
					skip: true
				};

				let catchblock = {
					type: 'CatchBlock',
					/** @type {number | null} */
					start: null,
					/** @type {number | null} */
					end: null,
					children: node.catch?.nodes.map((child) => visit(child)) ?? [],
					skip: true
				};

				if (node.pending) {
					const first = node.pending.nodes.at(0);
					const last = node.pending.nodes.at(-1);

					pendingblock.start = first?.start ?? source.indexOf('}', node.expression.end) + 1;
					pendingblock.end = last?.end ?? pendingblock.start;
					pendingblock.skip = false;
				}

				if (node.then) {
					const first = node.then.nodes.at(0);
					const last = node.then.nodes.at(-1);

					thenblock.start =
						pendingblock.end ?? first?.start ?? source.indexOf('}', node.expression.end) + 1;
					thenblock.end =
						last?.end ?? source.lastIndexOf('}', pendingblock.end ?? node.expression.end) + 1;
					thenblock.skip = false;
				}

				if (node.catch) {
					const first = node.catch.nodes.at(0);
					const last = node.catch.nodes.at(-1);

					catchblock.start =
						thenblock.end ??
						pendingblock.end ??
						first?.start ??
						source.indexOf('}', node.expression.end) + 1;
					catchblock.end =
						last?.end ??
						source.lastIndexOf('}', thenblock.end ?? pendingblock.end ?? node.expression.end) + 1;
					catchblock.skip = false;
				}

				return {
					type: 'AwaitBlock',
					start: node.start,
					end: node.end,
					expression: node.expression,
					value: node.value,
					error: node.error,
					pending: pendingblock,
					then: thenblock,
					catch: catchblock
				};
			},
			BindDirective(node) {
				return { ...node, type: 'Binding' };
			},
			ClassDirective(node) {
				return { ...node, type: 'Class' };
			},
			Comment(node) {
				return {
					...node,
					ignores: extract_svelte_ignore(node.start, node.data, false)
				};
			},
			ComplexSelector(node, { next }) {
				next(); // delete inner metadata/parent properties

				const children = [];

				for (const child of node.children) {
					if (child.combinator) {
						children.push(child.combinator);
					}

					children.push(...child.selectors);
				}

				return {
					type: 'Selector',
					start: node.start,
					end: node.end,
					children
				};
			},
			Component(node, { visit }) {
				return {
					type: 'InlineComponent',
					start: node.start,
					end: node.end,
					name: node.name,
					attributes: node.attributes.map(
						(child) => /** @type {Legacy.LegacyAttributeLike} */ (visit(child))
					),
					children: node.fragment.nodes.map(
						(child) => /** @type {Legacy.LegacyElementLike} */ (visit(child))
					)
				};
			},
			// @ts-ignore
			ConstTag(node) {
				if (/** @type {Legacy.LegacyConstTag} */ (node).expression !== undefined) {
					return node;
				}

				const modern_node = /** @type {AST.ConstTag} */ (node);
				const { id: left } = { ...modern_node.declaration.declarations[0] };
				// @ts-ignore
				delete left.typeAnnotation;
				return {
					type: 'ConstTag',
					start: modern_node.start,
					end: node.end,
					expression: {
						type: 'AssignmentExpression',
						start: (modern_node.declaration.start ?? 0) + 'const '.length,
						end: modern_node.declaration.end ?? 0,
						operator: '=',
						left,
						right: modern_node.declaration.declarations[0].init
					}
				};
			},
			// @ts-ignore
			KeyBlock(node, { visit }) {
				remove_surrounding_whitespace_nodes(node.fragment.nodes);
				return {
					type: 'KeyBlock',
					start: node.start,
					end: node.end,
					expression: node.expression,
					children: node.fragment.nodes.map(
						(child) => /** @type {Legacy.LegacyElementLike} */ (visit(child))
					)
				};
			},
			// @ts-ignore
			EachBlock(node, { visit }) {
				let elseblock = undefined;

				if (node.fallback) {
					const first = node.fallback.nodes.at(0);
					const end = source.lastIndexOf('{', /** @type {number} */ (node.end) - 1);
					const start = first?.start ?? end;

					remove_surrounding_whitespace_nodes(node.fallback.nodes);

					elseblock = {
						type: 'ElseBlock',
						start,
						end,
						children: node.fallback.nodes.map((child) => visit(child))
					};
				}

				remove_surrounding_whitespace_nodes(node.body.nodes);

				return {
					type: 'EachBlock',
					start: node.start,
					end: node.end,
					children: node.body.nodes.map((child) => visit(child)),
					context: node.context,
					expression: node.expression,
					index: node.index,
					key: node.key,
					else: elseblock
				};
			},
			ExpressionTag(node, { path }) {
				const parent = path.at(-1);
				if (parent?.type === 'Attribute') {
					if (source[parent.start] === '{') {
						return {
							type: 'AttributeShorthand',
							start: node.start,
							end: node.end,
							expression: node.expression
						};
					}
				}

				return {
					type: 'MustacheTag',
					start: node.start,
					end: node.end,
					expression: node.expression
				};
			},
			HtmlTag(node) {
				return { ...node, type: 'RawMustacheTag' };
			},
			// @ts-ignore
			IfBlock(node, { visit }) {
				let elseblock = undefined;
				if (node.alternate) {
					let nodes = node.alternate.nodes;
					if (nodes.length === 1 && nodes[0].type === 'IfBlock' && nodes[0].elseif) {
						nodes = nodes[0].consequent.nodes;
					}

					const end = source.lastIndexOf('{', /** @type {number} */ (node.end) - 1);
					const start = nodes.at(0)?.start ?? end;

					remove_surrounding_whitespace_nodes(node.alternate.nodes);

					elseblock = {
						type: 'ElseBlock',
						start,
						end: end,
						children: node.alternate.nodes.map(
							(child) => /** @type {Legacy.LegacyElementLike} */ (visit(child))
						)
					};
				}

				const start = node.elseif
					? node.consequent.nodes[0]?.start ??
						source.lastIndexOf('{', /** @type {number} */ (node.end) - 1)
					: node.start;

				remove_surrounding_whitespace_nodes(node.consequent.nodes);

				return {
					type: 'IfBlock',
					start,
					end: node.end,
					expression: node.test,
					children: node.consequent.nodes.map(
						(child) => /** @type {Legacy.LegacyElementLike} */ (visit(child))
					),
					else: elseblock,
					elseif: node.elseif ? true : undefined
				};
			},
			OnDirective(node) {
				return { ...node, type: 'EventHandler' };
			},
			// @ts-expect-error
			SnippetBlock(node, { visit }) {
				remove_surrounding_whitespace_nodes(node.body.nodes);
				return {
					type: 'SnippetBlock',
					start: node.start,
					end: node.end,
					expression: node.expression,
					parameters: node.parameters,
					children: node.body.nodes.map((child) => visit(child)),
					typeParams: node.typeParams
				};
			},
			// @ts-expect-error
			SvelteBoundary(node, { visit }) {
				remove_surrounding_whitespace_nodes(node.fragment.nodes);
				return {
					type: 'SvelteBoundary',
					name: 'svelte:boundary',
					start: node.start,
					end: node.end,
					attributes: node.attributes.map(
						(child) => /** @type {Legacy.LegacyAttributeLike} */ (visit(child))
					),
					children: node.fragment.nodes.map((child) => visit(child))
				};
			},
			RegularElement(node, { visit }) {
				return {
					type: 'Element',
					start: node.start,
					end: node.end,
					name: node.name,
					attributes: node.attributes.map((child) => visit(child)),
					children: node.fragment.nodes.map((child) => visit(child))
				};
			},
			SlotElement(node, { visit }) {
				return {
					type: 'Slot',
					start: node.start,
					end: node.end,
					name: node.name,
					attributes: node.attributes.map(
						(child) => /** @type {Legacy.LegacyAttributeLike} */ (visit(child))
					),
					children: node.fragment.nodes.map(
						(child) => /** @type {Legacy.LegacyElementLike} */ (visit(child))
					)
				};
			},
			Attribute(node, { visit, next, path }) {
				if (node.value !== true && !Array.isArray(node.value)) {
					path.push(node);
					const value = /** @type {Legacy.LegacyAttribute['value']} */ ([visit(node.value)]);
					path.pop();

					return {
						...node,
						value
					};
				} else {
					return next();
				}
			},
			StyleDirective(node, { visit, next, path }) {
				if (node.value !== true && !Array.isArray(node.value)) {
					path.push(node);
					const value = /** @type {Legacy.LegacyStyleDirective['value']} */ ([visit(node.value)]);
					path.pop();

					return {
						...node,
						value
					};
				} else {
					return next();
				}
			},
			SpreadAttribute(node) {
				return { ...node, type: 'Spread' };
			},
			// @ts-ignore
			StyleSheet(node, context) {
				return {
					...node,
					...context.next(),
					type: 'Style'
				};
			},
			SvelteBody(node, { visit }) {
				return {
					type: 'Body',
					name: 'svelte:body',
					start: node.start,
					end: node.end,
					attributes: node.attributes.map(
						(child) => /** @type {Legacy.LegacyAttributeLike} */ (visit(child))
					),
					children: node.fragment.nodes.map(
						(child) => /** @type {Legacy.LegacyElementLike} */ (visit(child))
					)
				};
			},
			SvelteComponent(node, { visit }) {
				return {
					type: 'InlineComponent',
					name: 'svelte:component',
					start: node.start,
					end: node.end,
					expression: node.expression,
					attributes: node.attributes.map(
						(child) => /** @type {Legacy.LegacyAttributeLike} */ (visit(child))
					),
					children: node.fragment.nodes.map(
						(child) => /** @type {Legacy.LegacyElementLike} */ (visit(child))
					)
				};
			},
			SvelteDocument(node, { visit }) {
				return {
					type: 'Document',
					name: 'svelte:document',
					start: node.start,
					end: node.end,
					attributes: node.attributes.map(
						(child) => /** @type {Legacy.LegacyAttributeLike} */ (visit(child))
					),
					children: node.fragment.nodes.map(
						(child) => /** @type {Legacy.LegacyElementLike} */ (visit(child))
					)
				};
			},
			SvelteElement(node, { visit }) {
				/** @type {Expression | string} */
				let tag = node.tag;
				if (
					tag.type === 'Literal' &&
					typeof tag.value === 'string' &&
					source[/** @type {number} */ (node.tag.start) - 1] !== '{'
				) {
					tag = tag.value;
				}

				return {
					type: 'Element',
					name: 'svelte:element',
					start: node.start,
					end: node.end,
					tag,
					attributes: node.attributes.map((child) => visit(child)),
					children: node.fragment.nodes.map((child) => visit(child))
				};
			},
			SvelteFragment(node, { visit }) {
				return {
					type: 'SlotTemplate',
					name: 'svelte:fragment',
					start: node.start,
					end: node.end,
					attributes: node.attributes.map(
						(a) => /** @type {Legacy.LegacyAttributeLike} */ (visit(a))
					),
					children: node.fragment.nodes.map(
						(child) => /** @type {Legacy.LegacyElementLike} */ (visit(child))
					)
				};
			},
			SvelteHead(node, { visit }) {
				return {
					type: 'Head',
					name: 'svelte:head',
					start: node.start,
					end: node.end,
					attributes: node.attributes.map(
						(child) => /** @type {Legacy.LegacyAttributeLike} */ (visit(child))
					),
					children: node.fragment.nodes.map(
						(child) => /** @type {Legacy.LegacyElementLike} */ (visit(child))
					)
				};
			},
			SvelteOptions(node, { visit }) {
				return {
					type: 'Options',
					name: 'svelte:options',
					start: node.start,
					end: node.end,
					attributes: node.attributes.map(
						(child) => /** @type {Legacy.LegacyAttributeLike} */ (visit(child))
					)
				};
			},
			SvelteSelf(node, { visit }) {
				return {
					type: 'InlineComponent',
					name: 'svelte:self',
					start: node.start,
					end: node.end,
					attributes: node.attributes.map(
						(child) => /** @type {Legacy.LegacyAttributeLike} */ (visit(child))
					),
					children: node.fragment.nodes.map(
						(child) => /** @type {Legacy.LegacyElementLike} */ (visit(child))
					)
				};
			},
			SvelteWindow(node, { visit }) {
				return {
					type: 'Window',
					name: 'svelte:window',
					start: node.start,
					end: node.end,
					attributes: node.attributes.map(
						(child) => /** @type {Legacy.LegacyAttributeLike} */ (visit(child))
					),
					children: node.fragment.nodes.map(
						(child) => /** @type {Legacy.LegacyElementLike} */ (visit(child))
					)
				};
			},
			Text(node, { path }) {
				const parent = path.at(-1);
				if (parent?.type === 'RegularElement' && parent.name === 'style') {
					// these text nodes are missing `raw` for some dumb reason
					return /** @type {AST.Text} */ ({
						type: 'Text',
						start: node.start,
						end: node.end,
						data: node.data
					});
				}
			},
			TitleElement(node, { visit }) {
				return {
					type: 'Title',
					name: 'title',
					start: node.start,
					end: node.end,
					attributes: node.attributes.map(
						(child) => /** @type {Legacy.LegacyAttributeLike} */ (visit(child))
					),
					children: node.fragment.nodes.map(
						(child) => /** @type {Legacy.LegacyElementLike} */ (visit(child))
					)
				};
			},
			TransitionDirective(node) {
				return { ...node, type: 'Transition' };
			},
			UseDirective(node) {
				return { ...node, type: 'Action' };
			},
			LetDirective(node) {
				return { ...node, type: 'Let' };
			}
		})
	);
}

// This file was generated. Do not modify manually!
var astralIdentifierCodes = [509, 0, 227, 0, 150, 4, 294, 9, 1368, 2, 2, 1, 6, 3, 41, 2, 5, 0, 166, 1, 574, 3, 9, 9, 7, 9, 32, 4, 318, 1, 80, 3, 71, 10, 50, 3, 123, 2, 54, 14, 32, 10, 3, 1, 11, 3, 46, 10, 8, 0, 46, 9, 7, 2, 37, 13, 2, 9, 6, 1, 45, 0, 13, 2, 49, 13, 9, 3, 2, 11, 83, 11, 7, 0, 3, 0, 158, 11, 6, 9, 7, 3, 56, 1, 2, 6, 3, 1, 3, 2, 10, 0, 11, 1, 3, 6, 4, 4, 68, 8, 2, 0, 3, 0, 2, 3, 2, 4, 2, 0, 15, 1, 83, 17, 10, 9, 5, 0, 82, 19, 13, 9, 214, 6, 3, 8, 28, 1, 83, 16, 16, 9, 82, 12, 9, 9, 7, 19, 58, 14, 5, 9, 243, 14, 166, 9, 71, 5, 2, 1, 3, 3, 2, 0, 2, 1, 13, 9, 120, 6, 3, 6, 4, 0, 29, 9, 41, 6, 2, 3, 9, 0, 10, 10, 47, 15, 343, 9, 54, 7, 2, 7, 17, 9, 57, 21, 2, 13, 123, 5, 4, 0, 2, 1, 2, 6, 2, 0, 9, 9, 49, 4, 2, 1, 2, 4, 9, 9, 330, 3, 10, 1, 2, 0, 49, 6, 4, 4, 14, 10, 5350, 0, 7, 14, 11465, 27, 2343, 9, 87, 9, 39, 4, 60, 6, 26, 9, 535, 9, 470, 0, 2, 54, 8, 3, 82, 0, 12, 1, 19628, 1, 4178, 9, 519, 45, 3, 22, 543, 4, 4, 5, 9, 7, 3, 6, 31, 3, 149, 2, 1418, 49, 513, 54, 5, 49, 9, 0, 15, 0, 23, 4, 2, 14, 1361, 6, 2, 16, 3, 6, 2, 1, 2, 4, 101, 0, 161, 6, 10, 9, 357, 0, 62, 13, 499, 13, 245, 1, 2, 9, 726, 6, 110, 6, 6, 9, 4759, 9, 787719, 239];

// This file was generated. Do not modify manually!
var astralIdentifierStartCodes = [0, 11, 2, 25, 2, 18, 2, 1, 2, 14, 3, 13, 35, 122, 70, 52, 268, 28, 4, 48, 48, 31, 14, 29, 6, 37, 11, 29, 3, 35, 5, 7, 2, 4, 43, 157, 19, 35, 5, 35, 5, 39, 9, 51, 13, 10, 2, 14, 2, 6, 2, 1, 2, 10, 2, 14, 2, 6, 2, 1, 4, 51, 13, 310, 10, 21, 11, 7, 25, 5, 2, 41, 2, 8, 70, 5, 3, 0, 2, 43, 2, 1, 4, 0, 3, 22, 11, 22, 10, 30, 66, 18, 2, 1, 11, 21, 11, 25, 71, 55, 7, 1, 65, 0, 16, 3, 2, 2, 2, 28, 43, 28, 4, 28, 36, 7, 2, 27, 28, 53, 11, 21, 11, 18, 14, 17, 111, 72, 56, 50, 14, 50, 14, 35, 39, 27, 10, 22, 251, 41, 7, 1, 17, 2, 60, 28, 11, 0, 9, 21, 43, 17, 47, 20, 28, 22, 13, 52, 58, 1, 3, 0, 14, 44, 33, 24, 27, 35, 30, 0, 3, 0, 9, 34, 4, 0, 13, 47, 15, 3, 22, 0, 2, 0, 36, 17, 2, 24, 20, 1, 64, 6, 2, 0, 2, 3, 2, 14, 2, 9, 8, 46, 39, 7, 3, 1, 3, 21, 2, 6, 2, 1, 2, 4, 4, 0, 19, 0, 13, 4, 31, 9, 2, 0, 3, 0, 2, 37, 2, 0, 26, 0, 2, 0, 45, 52, 19, 3, 21, 2, 31, 47, 21, 1, 2, 0, 185, 46, 42, 3, 37, 47, 21, 0, 60, 42, 14, 0, 72, 26, 38, 6, 186, 43, 117, 63, 32, 7, 3, 0, 3, 7, 2, 1, 2, 23, 16, 0, 2, 0, 95, 7, 3, 38, 17, 0, 2, 0, 29, 0, 11, 39, 8, 0, 22, 0, 12, 45, 20, 0, 19, 72, 200, 32, 32, 8, 2, 36, 18, 0, 50, 29, 113, 6, 2, 1, 2, 37, 22, 0, 26, 5, 2, 1, 2, 31, 15, 0, 328, 18, 16, 0, 2, 12, 2, 33, 125, 0, 80, 921, 103, 110, 18, 195, 2637, 96, 16, 1071, 18, 5, 26, 3994, 6, 582, 6842, 29, 1763, 568, 8, 30, 18, 78, 18, 29, 19, 47, 17, 3, 32, 20, 6, 18, 433, 44, 212, 63, 129, 74, 6, 0, 67, 12, 65, 1, 2, 0, 29, 6135, 9, 1237, 42, 9, 8936, 3, 2, 6, 2, 1, 2, 290, 16, 0, 30, 2, 3, 0, 15, 3, 9, 395, 2309, 106, 6, 12, 4, 8, 8, 9, 5991, 84, 2, 70, 2, 1, 3, 0, 3, 1, 3, 3, 2, 11, 2, 0, 2, 6, 2, 64, 2, 3, 3, 7, 2, 6, 2, 27, 2, 3, 2, 4, 2, 0, 4, 6, 2, 339, 3, 24, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 7, 1845, 30, 7, 5, 262, 61, 147, 44, 11, 6, 17, 0, 322, 29, 19, 43, 485, 27, 229, 29, 3, 0, 496, 6, 2, 3, 2, 1, 2, 14, 2, 196, 60, 67, 8, 0, 1205, 3, 2, 26, 2, 1, 2, 0, 3, 0, 2, 9, 2, 3, 2, 0, 2, 0, 7, 0, 5, 0, 2, 0, 2, 0, 2, 2, 2, 1, 2, 0, 3, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 3, 3, 2, 6, 2, 3, 2, 3, 2, 0, 2, 9, 2, 16, 6, 2, 2, 4, 2, 16, 4421, 42719, 33, 4153, 7, 221, 3, 5761, 15, 7472, 16, 621, 2467, 541, 1507, 4938, 6, 4191];

// This file was generated. Do not modify manually!
var nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u0897-\u089f\u08ca-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u09fe\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b55-\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c04\u0c3c\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0cf3\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d81-\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0ebc\u0ec8-\u0ece\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1715\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u180f-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1abf-\u1ace\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf4\u1cf7-\u1cf9\u1dc0-\u1dff\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\u30fb\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua82c\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua8ff-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f\uff65";

// This file was generated. Do not modify manually!
var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u05d0-\u05ea\u05ef-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u0870-\u0887\u0889-\u088e\u08a0-\u08c9\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u09fc\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c5d\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cdd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d04-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u1711\u171f-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1878\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4c\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c8a\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5\u1cf6\u1cfa\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31bf\u31f0-\u31ff\u3400-\u4dbf\u4e00-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7cd\ua7d0\ua7d1\ua7d3\ua7d5-\ua7dc\ua7f2-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab69\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc";

// These are a run-length and offset encoded representation of the
// >0xffff code points that are a valid part of identifiers. The
// offset starts at 0x10000, and each pair of numbers represents an
// offset to the next range, and then a size of the range.

// Reserved word lists for various dialects of the language

var reservedWords = {
  3: "abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile",
  5: "class enum extends super const export import",
  6: "enum",
  strict: "implements interface let package private protected public static yield",
  strictBind: "eval arguments"
};

// And the keywords

var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this";

var keywords$1 = {
  5: ecma5AndLessKeywords,
  "5module": ecma5AndLessKeywords + " export import",
  6: ecma5AndLessKeywords + " const class extends export import super"
};

var keywordRelationalOperator = /^in(stanceof)?$/;

// ## Character categories

var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]");
var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]");

// This has a complexity linear to the value of the code. The
// assumption is that looking up astral identifier characters is
// rare.
function isInAstralSet(code, set) {
  var pos = 0x10000;
  for (var i = 0; i < set.length; i += 2) {
    pos += set[i];
    if (pos > code) { return false }
    pos += set[i + 1];
    if (pos >= code) { return true }
  }
  return false
}

// Test whether a given character code starts an identifier.

function isIdentifierStart(code, astral) {
  if (code < 65) { return code === 36 }
  if (code < 91) { return true }
  if (code < 97) { return code === 95 }
  if (code < 123) { return true }
  if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)) }
  if (astral === false) { return false }
  return isInAstralSet(code, astralIdentifierStartCodes)
}

// Test whether a given character is part of an identifier.

function isIdentifierChar(code, astral) {
  if (code < 48) { return code === 36 }
  if (code < 58) { return true }
  if (code < 65) { return false }
  if (code < 91) { return true }
  if (code < 97) { return code === 95 }
  if (code < 123) { return true }
  if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)) }
  if (astral === false) { return false }
  return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes)
}

// ## Token types

// The assignment of fine-grained, information-carrying type objects
// allows the tokenizer to store the information it has about a
// token in a way that is very cheap for the parser to look up.

// All token type variables start with an underscore, to make them
// easy to recognize.

// The `beforeExpr` property is used to disambiguate between regular
// expressions and divisions. It is set on all token types that can
// be followed by an expression (thus, a slash after them would be a
// regular expression).
//
// The `startsExpr` property is used to check if the token ends a
// `yield` expression. It is set on all token types that either can
// directly start an expression (like a quotation mark) or can
// continue an expression (like the body of a string).
//
// `isLoop` marks a keyword as starting a loop, which is important
// to know when parsing a label, in order to allow or disallow
// continue jumps to that label.

var TokenType = function TokenType(label, conf) {
  if ( conf === void 0 ) conf = {};

  this.label = label;
  this.keyword = conf.keyword;
  this.beforeExpr = !!conf.beforeExpr;
  this.startsExpr = !!conf.startsExpr;
  this.isLoop = !!conf.isLoop;
  this.isAssign = !!conf.isAssign;
  this.prefix = !!conf.prefix;
  this.postfix = !!conf.postfix;
  this.binop = conf.binop || null;
  this.updateContext = null;
};

function binop(name, prec) {
  return new TokenType(name, {beforeExpr: true, binop: prec})
}
var beforeExpr = {beforeExpr: true}, startsExpr$1 = {startsExpr: true};

// Map keyword names to token types.

var keywords = {};

// Succinct definitions of keyword token types
function kw(name, options) {
  if ( options === void 0 ) options = {};

  options.keyword = name;
  return keywords[name] = new TokenType(name, options)
}

var types$1 = {
  num: new TokenType("num", startsExpr$1),
  regexp: new TokenType("regexp", startsExpr$1),
  string: new TokenType("string", startsExpr$1),
  name: new TokenType("name", startsExpr$1),
  privateId: new TokenType("privateId", startsExpr$1),
  eof: new TokenType("eof"),

  // Punctuation token types.
  bracketL: new TokenType("[", {beforeExpr: true, startsExpr: true}),
  bracketR: new TokenType("]"),
  braceL: new TokenType("{", {beforeExpr: true, startsExpr: true}),
  braceR: new TokenType("}"),
  parenL: new TokenType("(", {beforeExpr: true, startsExpr: true}),
  parenR: new TokenType(")"),
  comma: new TokenType(",", beforeExpr),
  semi: new TokenType(";", beforeExpr),
  colon: new TokenType(":", beforeExpr),
  dot: new TokenType("."),
  question: new TokenType("?", beforeExpr),
  questionDot: new TokenType("?."),
  arrow: new TokenType("=>", beforeExpr),
  template: new TokenType("template"),
  invalidTemplate: new TokenType("invalidTemplate"),
  ellipsis: new TokenType("...", beforeExpr),
  backQuote: new TokenType("`", startsExpr$1),
  dollarBraceL: new TokenType("${", {beforeExpr: true, startsExpr: true}),

  // Operators. These carry several kinds of properties to help the
  // parser use them properly (the presence of these properties is
  // what categorizes them as operators).
  //
  // `binop`, when present, specifies that this operator is a binary
  // operator, and will refer to its precedence.
  //
  // `prefix` and `postfix` mark the operator as a prefix or postfix
  // unary operator.
  //
  // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as
  // binary operators with a very low precedence, that should result
  // in AssignmentExpression nodes.

  eq: new TokenType("=", {beforeExpr: true, isAssign: true}),
  assign: new TokenType("_=", {beforeExpr: true, isAssign: true}),
  incDec: new TokenType("++/--", {prefix: true, postfix: true, startsExpr: true}),
  prefix: new TokenType("!/~", {beforeExpr: true, prefix: true, startsExpr: true}),
  logicalOR: binop("||", 1),
  logicalAND: binop("&&", 2),
  bitwiseOR: binop("|", 3),
  bitwiseXOR: binop("^", 4),
  bitwiseAND: binop("&", 5),
  equality: binop("==/!=/===/!==", 6),
  relational: binop("</>/<=/>=", 7),
  bitShift: binop("<</>>/>>>", 8),
  plusMin: new TokenType("+/-", {beforeExpr: true, binop: 9, prefix: true, startsExpr: true}),
  modulo: binop("%", 10),
  star: binop("*", 10),
  slash: binop("/", 10),
  starstar: new TokenType("**", {beforeExpr: true}),
  coalesce: binop("??", 1),

  // Keyword token types.
  _break: kw("break"),
  _case: kw("case", beforeExpr),
  _catch: kw("catch"),
  _continue: kw("continue"),
  _debugger: kw("debugger"),
  _default: kw("default", beforeExpr),
  _do: kw("do", {isLoop: true, beforeExpr: true}),
  _else: kw("else", beforeExpr),
  _finally: kw("finally"),
  _for: kw("for", {isLoop: true}),
  _function: kw("function", startsExpr$1),
  _if: kw("if"),
  _return: kw("return", beforeExpr),
  _switch: kw("switch"),
  _throw: kw("throw", beforeExpr),
  _try: kw("try"),
  _var: kw("var"),
  _const: kw("const"),
  _while: kw("while", {isLoop: true}),
  _with: kw("with"),
  _new: kw("new", {beforeExpr: true, startsExpr: true}),
  _this: kw("this", startsExpr$1),
  _super: kw("super", startsExpr$1),
  _class: kw("class", startsExpr$1),
  _extends: kw("extends", beforeExpr),
  _export: kw("export"),
  _import: kw("import", startsExpr$1),
  _null: kw("null", startsExpr$1),
  _true: kw("true", startsExpr$1),
  _false: kw("false", startsExpr$1),
  _in: kw("in", {beforeExpr: true, binop: 7}),
  _instanceof: kw("instanceof", {beforeExpr: true, binop: 7}),
  _typeof: kw("typeof", {beforeExpr: true, prefix: true, startsExpr: true}),
  _void: kw("void", {beforeExpr: true, prefix: true, startsExpr: true}),
  _delete: kw("delete", {beforeExpr: true, prefix: true, startsExpr: true})
};

// Matches a whole line break (where CRLF is considered a single
// line break). Used to count lines.

var lineBreak = /\r\n?|\n|\u2028|\u2029/;
var lineBreakG = new RegExp(lineBreak.source, "g");

function isNewLine(code) {
  return code === 10 || code === 13 || code === 0x2028 || code === 0x2029
}

function nextLineBreak(code, from, end) {
  if ( end === void 0 ) end = code.length;

  for (var i = from; i < end; i++) {
    var next = code.charCodeAt(i);
    if (isNewLine(next))
      { return i < end - 1 && next === 13 && code.charCodeAt(i + 1) === 10 ? i + 2 : i + 1 }
  }
  return -1
}

var nonASCIIwhitespace = /[\u1680\u2000-\u200a\u202f\u205f\u3000\ufeff]/;

var skipWhiteSpace$1 = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g;

var ref = Object.prototype;
var hasOwnProperty = ref.hasOwnProperty;
var toString$1 = ref.toString;

var hasOwn = Object.hasOwn || (function (obj, propName) { return (
  hasOwnProperty.call(obj, propName)
); });

var isArray = Array.isArray || (function (obj) { return (
  toString$1.call(obj) === "[object Array]"
); });

var regexpCache = Object.create(null);

function wordsRegexp(words) {
  return regexpCache[words] || (regexpCache[words] = new RegExp("^(?:" + words.replace(/ /g, "|") + ")$"))
}

function codePointToString(code) {
  // UTF-16 Decoding
  if (code <= 0xFFFF) { return String.fromCharCode(code) }
  code -= 0x10000;
  return String.fromCharCode((code >> 10) + 0xD800, (code & 1023) + 0xDC00)
}

var loneSurrogate = /(?:[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])/;

// These are used when `options.locations` is on, for the
// `startLoc` and `endLoc` properties.

var Position = function Position(line, col) {
  this.line = line;
  this.column = col;
};

Position.prototype.offset = function offset (n) {
  return new Position(this.line, this.column + n)
};

var SourceLocation = function SourceLocation(p, start, end) {
  this.start = start;
  this.end = end;
  if (p.sourceFile !== null) { this.source = p.sourceFile; }
};

// The `getLineInfo` function is mostly useful when the
// `locations` option is off (for performance reasons) and you
// want to find the line/column position for a given character
// offset. `input` should be the code string that the offset refers
// into.

function getLineInfo(input, offset) {
  for (var line = 1, cur = 0;;) {
    var nextBreak = nextLineBreak(input, cur, offset);
    if (nextBreak < 0) { return new Position(line, offset - cur) }
    ++line;
    cur = nextBreak;
  }
}

// A second argument must be given to configure the parser process.
// These options are recognized (only `ecmaVersion` is required):

var defaultOptions = {
  // `ecmaVersion` indicates the ECMAScript version to parse. Must be
  // either 3, 5, 6 (or 2015), 7 (2016), 8 (2017), 9 (2018), 10
  // (2019), 11 (2020), 12 (2021), 13 (2022), 14 (2023), or `"latest"`
  // (the latest version the library supports). This influences
  // support for strict mode, the set of reserved words, and support
  // for new syntax features.
  ecmaVersion: null,
  // `sourceType` indicates the mode the code should be parsed in.
  // Can be either `"script"` or `"module"`. This influences global
  // strict mode and parsing of `import` and `export` declarations.
  sourceType: "script",
  // `onInsertedSemicolon` can be a callback that will be called when
  // a semicolon is automatically inserted. It will be passed the
  // position of the inserted semicolon as an offset, and if
  // `locations` is enabled, it is given the location as a `{line,
  // column}` object as second argument.
  onInsertedSemicolon: null,
  // `onTrailingComma` is similar to `onInsertedSemicolon`, but for
  // trailing commas.
  onTrailingComma: null,
  // By default, reserved words are only enforced if ecmaVersion >= 5.
  // Set `allowReserved` to a boolean value to explicitly turn this on
  // an off. When this option has the value "never", reserved words
  // and keywords can also not be used as property names.
  allowReserved: null,
  // When enabled, a return at the top level is not considered an
  // error.
  allowReturnOutsideFunction: false,
  // When enabled, import/export statements are not constrained to
  // appearing at the top of the program, and an import.meta expression
  // in a script isn't considered an error.
  allowImportExportEverywhere: false,
  // By default, await identifiers are allowed to appear at the top-level scope only if ecmaVersion >= 2022.
  // When enabled, await identifiers are allowed to appear at the top-level scope,
  // but they are still not allowed in non-async functions.
  allowAwaitOutsideFunction: null,
  // When enabled, super identifiers are not constrained to
  // appearing in methods and do not raise an error when they appear elsewhere.
  allowSuperOutsideMethod: null,
  // When enabled, hashbang directive in the beginning of file is
  // allowed and treated as a line comment. Enabled by default when
  // `ecmaVersion` >= 2023.
  allowHashBang: false,
  // By default, the parser will verify that private properties are
  // only used in places where they are valid and have been declared.
  // Set this to false to turn such checks off.
  checkPrivateFields: true,
  // When `locations` is on, `loc` properties holding objects with
  // `start` and `end` properties in `{line, column}` form (with
  // line being 1-based and column 0-based) will be attached to the
  // nodes.
  locations: false,
  // A function can be passed as `onToken` option, which will
  // cause Acorn to call that function with object in the same
  // format as tokens returned from `tokenizer().getToken()`. Note
  // that you are not allowed to call the parser from the
  // callback—that will corrupt its internal state.
  onToken: null,
  // A function can be passed as `onComment` option, which will
  // cause Acorn to call that function with `(block, text, start,
  // end)` parameters whenever a comment is skipped. `block` is a
  // boolean indicating whether this is a block (`/* */`) comment,
  // `text` is the content of the comment, and `start` and `end` are
  // character offsets that denote the start and end of the comment.
  // When the `locations` option is on, two more parameters are
  // passed, the full `{line, column}` locations of the start and
  // end of the comments. Note that you are not allowed to call the
  // parser from the callback—that will corrupt its internal state.
  // When this option has an array as value, objects representing the
  // comments are pushed to it.
  onComment: null,
  // Nodes have their start and end characters offsets recorded in
  // `start` and `end` properties (directly on the node, rather than
  // the `loc` object, which holds line/column data. To also add a
  // [semi-standardized][range] `range` property holding a `[start,
  // end]` array with the same numbers, set the `ranges` option to
  // `true`.
  //
  // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678
  ranges: false,
  // It is possible to parse multiple files into a single AST by
  // passing the tree produced by parsing the first file as
  // `program` option in subsequent parses. This will add the
  // toplevel forms of the parsed file to the `Program` (top) node
  // of an existing parse tree.
  program: null,
  // When `locations` is on, you can pass this to record the source
  // file in every node's `loc` object.
  sourceFile: null,
  // This value, if given, is stored in every node, whether
  // `locations` is on or off.
  directSourceFile: null,
  // When enabled, parenthesized expressions are represented by
  // (non-standard) ParenthesizedExpression nodes
  preserveParens: false
};

// Interpret and default an options object

var warnedAboutEcmaVersion = false;

function getOptions(opts) {
  var options = {};

  for (var opt in defaultOptions)
    { options[opt] = opts && hasOwn(opts, opt) ? opts[opt] : defaultOptions[opt]; }

  if (options.ecmaVersion === "latest") {
    options.ecmaVersion = 1e8;
  } else if (options.ecmaVersion == null) {
    if (!warnedAboutEcmaVersion && typeof console === "object" && console.warn) {
      warnedAboutEcmaVersion = true;
      console.warn("Since Acorn 8.0.0, options.ecmaVersion is required.\nDefaulting to 2020, but this will stop working in the future.");
    }
    options.ecmaVersion = 11;
  } else if (options.ecmaVersion >= 2015) {
    options.ecmaVersion -= 2009;
  }

  if (options.allowReserved == null)
    { options.allowReserved = options.ecmaVersion < 5; }

  if (!opts || opts.allowHashBang == null)
    { options.allowHashBang = options.ecmaVersion >= 14; }

  if (isArray(options.onToken)) {
    var tokens = options.onToken;
    options.onToken = function (token) { return tokens.push(token); };
  }
  if (isArray(options.onComment))
    { options.onComment = pushComment(options, options.onComment); }

  return options
}

function pushComment(options, array) {
  return function(block, text, start, end, startLoc, endLoc) {
    var comment = {
      type: block ? "Block" : "Line",
      value: text,
      start: start,
      end: end
    };
    if (options.locations)
      { comment.loc = new SourceLocation(this, startLoc, endLoc); }
    if (options.ranges)
      { comment.range = [start, end]; }
    array.push(comment);
  }
}

// Each scope gets a bitset that may contain these flags
var
    SCOPE_TOP = 1,
    SCOPE_FUNCTION = 2,
    SCOPE_ASYNC = 4,
    SCOPE_GENERATOR = 8,
    SCOPE_ARROW = 16,
    SCOPE_SIMPLE_CATCH = 32,
    SCOPE_SUPER = 64,
    SCOPE_DIRECT_SUPER = 128,
    SCOPE_CLASS_STATIC_BLOCK = 256,
    SCOPE_CLASS_FIELD_INIT = 512,
    SCOPE_VAR = SCOPE_TOP | SCOPE_FUNCTION | SCOPE_CLASS_STATIC_BLOCK;

function functionFlags$1(async, generator) {
  return SCOPE_FUNCTION | (async ? SCOPE_ASYNC : 0) | (generator ? SCOPE_GENERATOR : 0)
}

// Used in checkLVal* and declareName to determine the type of a binding
var
    BIND_NONE = 0, // Not a binding
    BIND_VAR = 1, // Var-style binding
    BIND_LEXICAL = 2, // Let- or const-style binding
    BIND_FUNCTION = 3, // Function declaration
    BIND_SIMPLE_CATCH = 4, // Simple (identifier pattern) catch binding
    BIND_OUTSIDE = 5; // Special case for function names as bound inside the function

var Parser$1 = function Parser(options, input, startPos) {
  this.options = options = getOptions(options);
  this.sourceFile = options.sourceFile;
  this.keywords = wordsRegexp(keywords$1[options.ecmaVersion >= 6 ? 6 : options.sourceType === "module" ? "5module" : 5]);
  var reserved = "";
  if (options.allowReserved !== true) {
    reserved = reservedWords[options.ecmaVersion >= 6 ? 6 : options.ecmaVersion === 5 ? 5 : 3];
    if (options.sourceType === "module") { reserved += " await"; }
  }
  this.reservedWords = wordsRegexp(reserved);
  var reservedStrict = (reserved ? reserved + " " : "") + reservedWords.strict;
  this.reservedWordsStrict = wordsRegexp(reservedStrict);
  this.reservedWordsStrictBind = wordsRegexp(reservedStrict + " " + reservedWords.strictBind);
  this.input = String(input);

  // Used to signal to callers of `readWord1` whether the word
  // contained any escape sequences. This is needed because words with
  // escape sequences must not be interpreted as keywords.
  this.containsEsc = false;

  // Set up token state

  // The current position of the tokenizer in the input.
  if (startPos) {
    this.pos = startPos;
    this.lineStart = this.input.lastIndexOf("\n", startPos - 1) + 1;
    this.curLine = this.input.slice(0, this.lineStart).split(lineBreak).length;
  } else {
    this.pos = this.lineStart = 0;
    this.curLine = 1;
  }

  // Properties of the current token:
  // Its type
  this.type = types$1.eof;
  // For tokens that include more information than their type, the value
  this.value = null;
  // Its start and end offset
  this.start = this.end = this.pos;
  // And, if locations are used, the {line, column} object
  // corresponding to those offsets
  this.startLoc = this.endLoc = this.curPosition();

  // Position information for the previous token
  this.lastTokEndLoc = this.lastTokStartLoc = null;
  this.lastTokStart = this.lastTokEnd = this.pos;

  // The context stack is used to superficially track syntactic
  // context to predict whether a regular expression is allowed in a
  // given position.
  this.context = this.initialContext();
  this.exprAllowed = true;

  // Figure out if it's a module code.
  this.inModule = options.sourceType === "module";
  this.strict = this.inModule || this.strictDirective(this.pos);

  // Used to signify the start of a potential arrow function
  this.potentialArrowAt = -1;
  this.potentialArrowInForAwait = false;

  // Positions to delayed-check that yield/await does not exist in default parameters.
  this.yieldPos = this.awaitPos = this.awaitIdentPos = 0;
  // Labels in scope.
  this.labels = [];
  // Thus-far undefined exports.
  this.undefinedExports = Object.create(null);

  // If enabled, skip leading hashbang line.
  if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === "#!")
    { this.skipLineComment(2); }

  // Scope tracking for duplicate variable names (see scope.js)
  this.scopeStack = [];
  this.enterScope(SCOPE_TOP);

  // For RegExp validation
  this.regexpState = null;

  // The stack of private names.
  // Each element has two properties: 'declared' and 'used'.
  // When it exited from the outermost class definition, all used private names must be declared.
  this.privateNameStack = [];
};

var prototypeAccessors = { inFunction: { configurable: true },inGenerator: { configurable: true },inAsync: { configurable: true },canAwait: { configurable: true },allowSuper: { configurable: true },allowDirectSuper: { configurable: true },treatFunctionsAsVar: { configurable: true },allowNewDotTarget: { configurable: true },inClassStaticBlock: { configurable: true } };

Parser$1.prototype.parse = function parse () {
  var node = this.options.program || this.startNode();
  this.nextToken();
  return this.parseTopLevel(node)
};

prototypeAccessors.inFunction.get = function () { return (this.currentVarScope().flags & SCOPE_FUNCTION) > 0 };

prototypeAccessors.inGenerator.get = function () { return (this.currentVarScope().flags & SCOPE_GENERATOR) > 0 };

prototypeAccessors.inAsync.get = function () { return (this.currentVarScope().flags & SCOPE_ASYNC) > 0 };

prototypeAccessors.canAwait.get = function () {
  for (var i = this.scopeStack.length - 1; i >= 0; i--) {
    var ref = this.scopeStack[i];
      var flags = ref.flags;
    if (flags & (SCOPE_CLASS_STATIC_BLOCK | SCOPE_CLASS_FIELD_INIT)) { return false }
    if (flags & SCOPE_FUNCTION) { return (flags & SCOPE_ASYNC) > 0 }
  }
  return (this.inModule && this.options.ecmaVersion >= 13) || this.options.allowAwaitOutsideFunction
};

prototypeAccessors.allowSuper.get = function () {
  var ref = this.currentThisScope();
    var flags = ref.flags;
  return (flags & SCOPE_SUPER) > 0 || this.options.allowSuperOutsideMethod
};

prototypeAccessors.allowDirectSuper.get = function () { return (this.currentThisScope().flags & SCOPE_DIRECT_SUPER) > 0 };

prototypeAccessors.treatFunctionsAsVar.get = function () { return this.treatFunctionsAsVarInScope(this.currentScope()) };

prototypeAccessors.allowNewDotTarget.get = function () {
  for (var i = this.scopeStack.length - 1; i >= 0; i--) {
    var ref = this.scopeStack[i];
      var flags = ref.flags;
    if (flags & (SCOPE_CLASS_STATIC_BLOCK | SCOPE_CLASS_FIELD_INIT) ||
        ((flags & SCOPE_FUNCTION) && !(flags & SCOPE_ARROW))) { return true }
  }
  return false
};

prototypeAccessors.inClassStaticBlock.get = function () {
  return (this.currentVarScope().flags & SCOPE_CLASS_STATIC_BLOCK) > 0
};

Parser$1.extend = function extend () {
    var plugins = [], len = arguments.length;
    while ( len-- ) plugins[ len ] = arguments[ len ];

  var cls = this;
  for (var i = 0; i < plugins.length; i++) { cls = plugins[i](cls); }
  return cls
};

Parser$1.parse = function parse (input, options) {
  return new this(options, input).parse()
};

Parser$1.parseExpressionAt = function parseExpressionAt (input, pos, options) {
  var parser = new this(options, input, pos);
  parser.nextToken();
  return parser.parseExpression()
};

Parser$1.tokenizer = function tokenizer (input, options) {
  return new this(options, input)
};

Object.defineProperties( Parser$1.prototype, prototypeAccessors );

var pp$9 = Parser$1.prototype;

// ## Parser utilities

var literal$1 = /^(?:'((?:\\[^]|[^'\\])*?)'|"((?:\\[^]|[^"\\])*?)")/;
pp$9.strictDirective = function(start) {
  if (this.options.ecmaVersion < 5) { return false }
  for (;;) {
    // Try to find string literal.
    skipWhiteSpace$1.lastIndex = start;
    start += skipWhiteSpace$1.exec(this.input)[0].length;
    var match = literal$1.exec(this.input.slice(start));
    if (!match) { return false }
    if ((match[1] || match[2]) === "use strict") {
      skipWhiteSpace$1.lastIndex = start + match[0].length;
      var spaceAfter = skipWhiteSpace$1.exec(this.input), end = spaceAfter.index + spaceAfter[0].length;
      var next = this.input.charAt(end);
      return next === ";" || next === "}" ||
        (lineBreak.test(spaceAfter[0]) &&
         !(/[(`.[+\-/*%<>=,?^&]/.test(next) || next === "!" && this.input.charAt(end + 1) === "="))
    }
    start += match[0].length;

    // Skip semicolon, if any.
    skipWhiteSpace$1.lastIndex = start;
    start += skipWhiteSpace$1.exec(this.input)[0].length;
    if (this.input[start] === ";")
      { start++; }
  }
};

// Predicate that tests whether the next token is of the given
// type, and if yes, consumes it as a side effect.

pp$9.eat = function(type) {
  if (this.type === type) {
    this.next();
    return true
  } else {
    return false
  }
};

// Tests whether parsed token is a contextual keyword.

pp$9.isContextual = function(name) {
  return this.type === types$1.name && this.value === name && !this.containsEsc
};

// Consumes contextual keyword if possible.

pp$9.eatContextual = function(name) {
  if (!this.isContextual(name)) { return false }
  this.next();
  return true
};

// Asserts that following token is given contextual keyword.

pp$9.expectContextual = function(name) {
  if (!this.eatContextual(name)) { this.unexpected(); }
};

// Test whether a semicolon can be inserted at the current position.

pp$9.canInsertSemicolon = function() {
  return this.type === types$1.eof ||
    this.type === types$1.braceR ||
    lineBreak.test(this.input.slice(this.lastTokEnd, this.start))
};

pp$9.insertSemicolon = function() {
  if (this.canInsertSemicolon()) {
    if (this.options.onInsertedSemicolon)
      { this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc); }
    return true
  }
};

// Consume a semicolon, or, failing that, see if we are allowed to
// pretend that there is a semicolon at this position.

pp$9.semicolon = function() {
  if (!this.eat(types$1.semi) && !this.insertSemicolon()) { this.unexpected(); }
};

pp$9.afterTrailingComma = function(tokType, notNext) {
  if (this.type === tokType) {
    if (this.options.onTrailingComma)
      { this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc); }
    if (!notNext)
      { this.next(); }
    return true
  }
};

// Expect a token of a given type. If found, consume it, otherwise,
// raise an unexpected token error.

pp$9.expect = function(type) {
  this.eat(type) || this.unexpected();
};

// Raise an unexpected token error.

pp$9.unexpected = function(pos) {
  this.raise(pos != null ? pos : this.start, "Unexpected token");
};

var DestructuringErrors$1 = function DestructuringErrors() {
  this.shorthandAssign =
  this.trailingComma =
  this.parenthesizedAssign =
  this.parenthesizedBind =
  this.doubleProto =
    -1;
};

pp$9.checkPatternErrors = function(refDestructuringErrors, isAssign) {
  if (!refDestructuringErrors) { return }
  if (refDestructuringErrors.trailingComma > -1)
    { this.raiseRecoverable(refDestructuringErrors.trailingComma, "Comma is not permitted after the rest element"); }
  var parens = isAssign ? refDestructuringErrors.parenthesizedAssign : refDestructuringErrors.parenthesizedBind;
  if (parens > -1) { this.raiseRecoverable(parens, isAssign ? "Assigning to rvalue" : "Parenthesized pattern"); }
};

pp$9.checkExpressionErrors = function(refDestructuringErrors, andThrow) {
  if (!refDestructuringErrors) { return false }
  var shorthandAssign = refDestructuringErrors.shorthandAssign;
  var doubleProto = refDestructuringErrors.doubleProto;
  if (!andThrow) { return shorthandAssign >= 0 || doubleProto >= 0 }
  if (shorthandAssign >= 0)
    { this.raise(shorthandAssign, "Shorthand property assignments are valid only in destructuring patterns"); }
  if (doubleProto >= 0)
    { this.raiseRecoverable(doubleProto, "Redefinition of __proto__ property"); }
};

pp$9.checkYieldAwaitInDefaultParams = function() {
  if (this.yieldPos && (!this.awaitPos || this.yieldPos < this.awaitPos))
    { this.raise(this.yieldPos, "Yield expression cannot be a default value"); }
  if (this.awaitPos)
    { this.raise(this.awaitPos, "Await expression cannot be a default value"); }
};

pp$9.isSimpleAssignTarget = function(expr) {
  if (expr.type === "ParenthesizedExpression")
    { return this.isSimpleAssignTarget(expr.expression) }
  return expr.type === "Identifier" || expr.type === "MemberExpression"
};

var pp$8 = Parser$1.prototype;

// ### Statement parsing

// Parse a program. Initializes the parser, reads any number of
// statements, and wraps them in a Program node.  Optionally takes a
// `program` argument.  If present, the statements will be appended
// to its body instead of creating a new node.

pp$8.parseTopLevel = function(node) {
  var exports$1 = Object.create(null);
  if (!node.body) { node.body = []; }
  while (this.type !== types$1.eof) {
    var stmt = this.parseStatement(null, true, exports$1);
    node.body.push(stmt);
  }
  if (this.inModule)
    { for (var i = 0, list = Object.keys(this.undefinedExports); i < list.length; i += 1)
      {
        var name = list[i];

        this.raiseRecoverable(this.undefinedExports[name].start, ("Export '" + name + "' is not defined"));
      } }
  this.adaptDirectivePrologue(node.body);
  this.next();
  node.sourceType = this.options.sourceType;
  return this.finishNode(node, "Program")
};

var loopLabel = {kind: "loop"}, switchLabel = {kind: "switch"};

pp$8.isLet = function(context) {
  if (this.options.ecmaVersion < 6 || !this.isContextual("let")) { return false }
  skipWhiteSpace$1.lastIndex = this.pos;
  var skip = skipWhiteSpace$1.exec(this.input);
  var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next);
  // For ambiguous cases, determine if a LexicalDeclaration (or only a
  // Statement) is allowed here. If context is not empty then only a Statement
  // is allowed. However, `let [` is an explicit negative lookahead for
  // ExpressionStatement, so special-case it first.
  if (nextCh === 91 || nextCh === 92) { return true } // '[', '\'
  if (context) { return false }

  if (nextCh === 123 || nextCh > 0xd7ff && nextCh < 0xdc00) { return true } // '{', astral
  if (isIdentifierStart(nextCh, true)) {
    var pos = next + 1;
    while (isIdentifierChar(nextCh = this.input.charCodeAt(pos), true)) { ++pos; }
    if (nextCh === 92 || nextCh > 0xd7ff && nextCh < 0xdc00) { return true }
    var ident = this.input.slice(next, pos);
    if (!keywordRelationalOperator.test(ident)) { return true }
  }
  return false
};

// check 'async [no LineTerminator here] function'
// - 'async /*foo*/ function' is OK.
// - 'async /*\n*/ function' is invalid.
pp$8.isAsyncFunction = function() {
  if (this.options.ecmaVersion < 8 || !this.isContextual("async"))
    { return false }

  skipWhiteSpace$1.lastIndex = this.pos;
  var skip = skipWhiteSpace$1.exec(this.input);
  var next = this.pos + skip[0].length, after;
  return !lineBreak.test(this.input.slice(this.pos, next)) &&
    this.input.slice(next, next + 8) === "function" &&
    (next + 8 === this.input.length ||
     !(isIdentifierChar(after = this.input.charCodeAt(next + 8)) || after > 0xd7ff && after < 0xdc00))
};

pp$8.isUsingKeyword = function(isAwaitUsing, isFor) {
  if (this.options.ecmaVersion < 17 || !this.isContextual(isAwaitUsing ? "await" : "using"))
    { return false }

  skipWhiteSpace$1.lastIndex = this.pos;
  var skip = skipWhiteSpace$1.exec(this.input);
  var next = this.pos + skip[0].length;

  if (lineBreak.test(this.input.slice(this.pos, next))) { return false }

  if (isAwaitUsing) {
    var awaitEndPos = next + 5 /* await */, after;
    if (this.input.slice(next, awaitEndPos) !== "using" ||
      awaitEndPos === this.input.length ||
      isIdentifierChar(after = this.input.charCodeAt(awaitEndPos)) ||
      (after > 0xd7ff && after < 0xdc00)
    ) { return false }

    skipWhiteSpace$1.lastIndex = awaitEndPos;
    var skipAfterUsing = skipWhiteSpace$1.exec(this.input);
    if (skipAfterUsing && lineBreak.test(this.input.slice(awaitEndPos, awaitEndPos + skipAfterUsing[0].length))) { return false }
  }

  if (isFor) {
    var ofEndPos = next + 2 /* of */, after$1;
    if (this.input.slice(next, ofEndPos) === "of") {
      if (ofEndPos === this.input.length ||
        (!isIdentifierChar(after$1 = this.input.charCodeAt(ofEndPos)) && !(after$1 > 0xd7ff && after$1 < 0xdc00))) { return false }
    }
  }

  var ch = this.input.charCodeAt(next);
  return isIdentifierStart(ch, true) || ch === 92 // '\'
};

pp$8.isAwaitUsing = function(isFor) {
  return this.isUsingKeyword(true, isFor)
};

pp$8.isUsing = function(isFor) {
  return this.isUsingKeyword(false, isFor)
};

// Parse a single statement.
//
// If expecting a statement and finding a slash operator, parse a
// regular expression literal. This is to handle cases like
// `if (foo) /blah/.exec(foo)`, where looking at the previous token
// does not help.

pp$8.parseStatement = function(context, topLevel, exports$1) {
  var starttype = this.type, node = this.startNode(), kind;

  if (this.isLet(context)) {
    starttype = types$1._var;
    kind = "let";
  }

  // Most types of statements are recognized by the keyword they
  // start with. Many are trivial to parse, some require a bit of
  // complexity.

  switch (starttype) {
  case types$1._break: case types$1._continue: return this.parseBreakContinueStatement(node, starttype.keyword)
  case types$1._debugger: return this.parseDebuggerStatement(node)
  case types$1._do: return this.parseDoStatement(node)
  case types$1._for: return this.parseForStatement(node)
  case types$1._function:
    // Function as sole body of either an if statement or a labeled statement
    // works, but not when it is part of a labeled statement that is the sole
    // body of an if statement.
    if ((context && (this.strict || context !== "if" && context !== "label")) && this.options.ecmaVersion >= 6) { this.unexpected(); }
    return this.parseFunctionStatement(node, false, !context)
  case types$1._class:
    if (context) { this.unexpected(); }
    return this.parseClass(node, true)
  case types$1._if: return this.parseIfStatement(node)
  case types$1._return: return this.parseReturnStatement(node)
  case types$1._switch: return this.parseSwitchStatement(node)
  case types$1._throw: return this.parseThrowStatement(node)
  case types$1._try: return this.parseTryStatement(node)
  case types$1._const: case types$1._var:
    kind = kind || this.value;
    if (context && kind !== "var") { this.unexpected(); }
    return this.parseVarStatement(node, kind)
  case types$1._while: return this.parseWhileStatement(node)
  case types$1._with: return this.parseWithStatement(node)
  case types$1.braceL: return this.parseBlock(true, node)
  case types$1.semi: return this.parseEmptyStatement(node)
  case types$1._export:
  case types$1._import:
    if (this.options.ecmaVersion > 10 && starttype === types$1._import) {
      skipWhiteSpace$1.lastIndex = this.pos;
      var skip = skipWhiteSpace$1.exec(this.input);
      var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next);
      if (nextCh === 40 || nextCh === 46) // '(' or '.'
        { return this.parseExpressionStatement(node, this.parseExpression()) }
    }

    if (!this.options.allowImportExportEverywhere) {
      if (!topLevel)
        { this.raise(this.start, "'import' and 'export' may only appear at the top level"); }
      if (!this.inModule)
        { this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'"); }
    }
    return starttype === types$1._import ? this.parseImport(node) : this.parseExport(node, exports$1)

    // If the statement does not start with a statement keyword or a
    // brace, it's an ExpressionStatement or LabeledStatement. We
    // simply start parsing an expression, and afterwards, if the
    // next token is a colon and the expression was a simple
    // Identifier node, we switch to interpreting it as a label.
  default:
    if (this.isAsyncFunction()) {
      if (context) { this.unexpected(); }
      this.next();
      return this.parseFunctionStatement(node, true, !context)
    }

    var usingKind = this.isAwaitUsing(false) ? "await using" : this.isUsing(false) ? "using" : null;
    if (usingKind) {
      if (topLevel && this.options.sourceType === "script") {
        this.raise(this.start, "Using declaration cannot appear in the top level when source type is `script`");
      }
      if (usingKind === "await using") {
        if (!this.canAwait) {
          this.raise(this.start, "Await using cannot appear outside of async function");
        }
        this.next();
      }
      this.next();
      this.parseVar(node, false, usingKind);
      this.semicolon();
      return this.finishNode(node, "VariableDeclaration")
    }

    var maybeName = this.value, expr = this.parseExpression();
    if (starttype === types$1.name && expr.type === "Identifier" && this.eat(types$1.colon))
      { return this.parseLabeledStatement(node, maybeName, expr, context) }
    else { return this.parseExpressionStatement(node, expr) }
  }
};

pp$8.parseBreakContinueStatement = function(node, keyword) {
  var isBreak = keyword === "break";
  this.next();
  if (this.eat(types$1.semi) || this.insertSemicolon()) { node.label = null; }
  else if (this.type !== types$1.name) { this.unexpected(); }
  else {
    node.label = this.parseIdent();
    this.semicolon();
  }

  // Verify that there is an actual destination to break or
  // continue to.
  var i = 0;
  for (; i < this.labels.length; ++i) {
    var lab = this.labels[i];
    if (node.label == null || lab.name === node.label.name) {
      if (lab.kind != null && (isBreak || lab.kind === "loop")) { break }
      if (node.label && isBreak) { break }
    }
  }
  if (i === this.labels.length) { this.raise(node.start, "Unsyntactic " + keyword); }
  return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement")
};

pp$8.parseDebuggerStatement = function(node) {
  this.next();
  this.semicolon();
  return this.finishNode(node, "DebuggerStatement")
};

pp$8.parseDoStatement = function(node) {
  this.next();
  this.labels.push(loopLabel);
  node.body = this.parseStatement("do");
  this.labels.pop();
  this.expect(types$1._while);
  node.test = this.parseParenExpression();
  if (this.options.ecmaVersion >= 6)
    { this.eat(types$1.semi); }
  else
    { this.semicolon(); }
  return this.finishNode(node, "DoWhileStatement")
};

// Disambiguating between a `for` and a `for`/`in` or `for`/`of`
// loop is non-trivial. Basically, we have to parse the init `var`
// statement or expression, disallowing the `in` operator (see
// the second parameter to `parseExpression`), and then check
// whether the next token is `in` or `of`. When there is no init
// part (semicolon immediately after the opening parenthesis), it
// is a regular `for` loop.

pp$8.parseForStatement = function(node) {
  this.next();
  var awaitAt = (this.options.ecmaVersion >= 9 && this.canAwait && this.eatContextual("await")) ? this.lastTokStart : -1;
  this.labels.push(loopLabel);
  this.enterScope(0);
  this.expect(types$1.parenL);
  if (this.type === types$1.semi) {
    if (awaitAt > -1) { this.unexpected(awaitAt); }
    return this.parseFor(node, null)
  }
  var isLet = this.isLet();
  if (this.type === types$1._var || this.type === types$1._const || isLet) {
    var init$1 = this.startNode(), kind = isLet ? "let" : this.value;
    this.next();
    this.parseVar(init$1, true, kind);
    this.finishNode(init$1, "VariableDeclaration");
    return this.parseForAfterInit(node, init$1, awaitAt)
  }
  var startsWithLet = this.isContextual("let"), isForOf = false;

  var usingKind = this.isUsing(true) ? "using" : this.isAwaitUsing(true) ? "await using" : null;
  if (usingKind) {
    var init$2 = this.startNode();
    this.next();
    if (usingKind === "await using") { this.next(); }
    this.parseVar(init$2, true, usingKind);
    this.finishNode(init$2, "VariableDeclaration");
    return this.parseForAfterInit(node, init$2, awaitAt)
  }
  var containsEsc = this.containsEsc;
  var refDestructuringErrors = new DestructuringErrors$1;
  var initPos = this.start;
  var init = awaitAt > -1
    ? this.parseExprSubscripts(refDestructuringErrors, "await")
    : this.parseExpression(true, refDestructuringErrors);
  if (this.type === types$1._in || (isForOf = this.options.ecmaVersion >= 6 && this.isContextual("of"))) {
    if (awaitAt > -1) { // implies `ecmaVersion >= 9` (see declaration of awaitAt)
      if (this.type === types$1._in) { this.unexpected(awaitAt); }
      node.await = true;
    } else if (isForOf && this.options.ecmaVersion >= 8) {
      if (init.start === initPos && !containsEsc && init.type === "Identifier" && init.name === "async") { this.unexpected(); }
      else if (this.options.ecmaVersion >= 9) { node.await = false; }
    }
    if (startsWithLet && isForOf) { this.raise(init.start, "The left-hand side of a for-of loop may not start with 'let'."); }
    this.toAssignable(init, false, refDestructuringErrors);
    this.checkLValPattern(init);
    return this.parseForIn(node, init)
  } else {
    this.checkExpressionErrors(refDestructuringErrors, true);
  }
  if (awaitAt > -1) { this.unexpected(awaitAt); }
  return this.parseFor(node, init)
};

// Helper method to parse for loop after variable initialization
pp$8.parseForAfterInit = function(node, init, awaitAt) {
  if ((this.type === types$1._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) && init.declarations.length === 1) {
    if (this.options.ecmaVersion >= 9) {
      if (this.type === types$1._in) {
        if (awaitAt > -1) { this.unexpected(awaitAt); }
      } else { node.await = awaitAt > -1; }
    }
    return this.parseForIn(node, init)
  }
  if (awaitAt > -1) { this.unexpected(awaitAt); }
  return this.parseFor(node, init)
};

pp$8.parseFunctionStatement = function(node, isAsync, declarationPosition) {
  this.next();
  return this.parseFunction(node, FUNC_STATEMENT$1 | (declarationPosition ? 0 : FUNC_HANGING_STATEMENT$1), false, isAsync)
};

pp$8.parseIfStatement = function(node) {
  this.next();
  node.test = this.parseParenExpression();
  // allow function declarations in branches, but only in non-strict mode
  node.consequent = this.parseStatement("if");
  node.alternate = this.eat(types$1._else) ? this.parseStatement("if") : null;
  return this.finishNode(node, "IfStatement")
};

pp$8.parseReturnStatement = function(node) {
  if (!this.inFunction && !this.options.allowReturnOutsideFunction)
    { this.raise(this.start, "'return' outside of function"); }
  this.next();

  // In `return` (and `break`/`continue`), the keywords with
  // optional arguments, we eagerly look for a semicolon or the
  // possibility to insert one.

  if (this.eat(types$1.semi) || this.insertSemicolon()) { node.argument = null; }
  else { node.argument = this.parseExpression(); this.semicolon(); }
  return this.finishNode(node, "ReturnStatement")
};

pp$8.parseSwitchStatement = function(node) {
  this.next();
  node.discriminant = this.parseParenExpression();
  node.cases = [];
  this.expect(types$1.braceL);
  this.labels.push(switchLabel);
  this.enterScope(0);

  // Statements under must be grouped (by label) in SwitchCase
  // nodes. `cur` is used to keep the node that we are currently
  // adding statements to.

  var cur;
  for (var sawDefault = false; this.type !== types$1.braceR;) {
    if (this.type === types$1._case || this.type === types$1._default) {
      var isCase = this.type === types$1._case;
      if (cur) { this.finishNode(cur, "SwitchCase"); }
      node.cases.push(cur = this.startNode());
      cur.consequent = [];
      this.next();
      if (isCase) {
        cur.test = this.parseExpression();
      } else {
        if (sawDefault) { this.raiseRecoverable(this.lastTokStart, "Multiple default clauses"); }
        sawDefault = true;
        cur.test = null;
      }
      this.expect(types$1.colon);
    } else {
      if (!cur) { this.unexpected(); }
      cur.consequent.push(this.parseStatement(null));
    }
  }
  this.exitScope();
  if (cur) { this.finishNode(cur, "SwitchCase"); }
  this.next(); // Closing brace
  this.labels.pop();
  return this.finishNode(node, "SwitchStatement")
};

pp$8.parseThrowStatement = function(node) {
  this.next();
  if (lineBreak.test(this.input.slice(this.lastTokEnd, this.start)))
    { this.raise(this.lastTokEnd, "Illegal newline after throw"); }
  node.argument = this.parseExpression();
  this.semicolon();
  return this.finishNode(node, "ThrowStatement")
};

// Reused empty array added for node fields that are always empty.

var empty$1 = [];

pp$8.parseCatchClauseParam = function() {
  var param = this.parseBindingAtom();
  var simple = param.type === "Identifier";
  this.enterScope(simple ? SCOPE_SIMPLE_CATCH : 0);
  this.checkLValPattern(param, simple ? BIND_SIMPLE_CATCH : BIND_LEXICAL);
  this.expect(types$1.parenR);

  return param
};

pp$8.parseTryStatement = function(node) {
  this.next();
  node.block = this.parseBlock();
  node.handler = null;
  if (this.type === types$1._catch) {
    var clause = this.startNode();
    this.next();
    if (this.eat(types$1.parenL)) {
      clause.param = this.parseCatchClauseParam();
    } else {
      if (this.options.ecmaVersion < 10) { this.unexpected(); }
      clause.param = null;
      this.enterScope(0);
    }
    clause.body = this.parseBlock(false);
    this.exitScope();
    node.handler = this.finishNode(clause, "CatchClause");
  }
  node.finalizer = this.eat(types$1._finally) ? this.parseBlock() : null;
  if (!node.handler && !node.finalizer)
    { this.raise(node.start, "Missing catch or finally clause"); }
  return this.finishNode(node, "TryStatement")
};

pp$8.parseVarStatement = function(node, kind, allowMissingInitializer) {
  this.next();
  this.parseVar(node, false, kind, allowMissingInitializer);
  this.semicolon();
  return this.finishNode(node, "VariableDeclaration")
};

pp$8.parseWhileStatement = function(node) {
  this.next();
  node.test = this.parseParenExpression();
  this.labels.push(loopLabel);
  node.body = this.parseStatement("while");
  this.labels.pop();
  return this.finishNode(node, "WhileStatement")
};

pp$8.parseWithStatement = function(node) {
  if (this.strict) { this.raise(this.start, "'with' in strict mode"); }
  this.next();
  node.object = this.parseParenExpression();
  node.body = this.parseStatement("with");
  return this.finishNode(node, "WithStatement")
};

pp$8.parseEmptyStatement = function(node) {
  this.next();
  return this.finishNode(node, "EmptyStatement")
};

pp$8.parseLabeledStatement = function(node, maybeName, expr, context) {
  for (var i$1 = 0, list = this.labels; i$1 < list.length; i$1 += 1)
    {
    var label = list[i$1];

    if (label.name === maybeName)
      { this.raise(expr.start, "Label '" + maybeName + "' is already declared");
  } }
  var kind = this.type.isLoop ? "loop" : this.type === types$1._switch ? "switch" : null;
  for (var i = this.labels.length - 1; i >= 0; i--) {
    var label$1 = this.labels[i];
    if (label$1.statementStart === node.start) {
      // Update information about previous labels on this node
      label$1.statementStart = this.start;
      label$1.kind = kind;
    } else { break }
  }
  this.labels.push({name: maybeName, kind: kind, statementStart: this.start});
  node.body = this.parseStatement(context ? context.indexOf("label") === -1 ? context + "label" : context : "label");
  this.labels.pop();
  node.label = expr;
  return this.finishNode(node, "LabeledStatement")
};

pp$8.parseExpressionStatement = function(node, expr) {
  node.expression = expr;
  this.semicolon();
  return this.finishNode(node, "ExpressionStatement")
};

// Parse a semicolon-enclosed block of statements, handling `"use
// strict"` declarations when `allowStrict` is true (used for
// function bodies).

pp$8.parseBlock = function(createNewLexicalScope, node, exitStrict) {
  if ( createNewLexicalScope === void 0 ) createNewLexicalScope = true;
  if ( node === void 0 ) node = this.startNode();

  node.body = [];
  this.expect(types$1.braceL);
  if (createNewLexicalScope) { this.enterScope(0); }
  while (this.type !== types$1.braceR) {
    var stmt = this.parseStatement(null);
    node.body.push(stmt);
  }
  if (exitStrict) { this.strict = false; }
  this.next();
  if (createNewLexicalScope) { this.exitScope(); }
  return this.finishNode(node, "BlockStatement")
};

// Parse a regular `for` loop. The disambiguation code in
// `parseStatement` will already have parsed the init statement or
// expression.

pp$8.parseFor = function(node, init) {
  node.init = init;
  this.expect(types$1.semi);
  node.test = this.type === types$1.semi ? null : this.parseExpression();
  this.expect(types$1.semi);
  node.update = this.type === types$1.parenR ? null : this.parseExpression();
  this.expect(types$1.parenR);
  node.body = this.parseStatement("for");
  this.exitScope();
  this.labels.pop();
  return this.finishNode(node, "ForStatement")
};

// Parse a `for`/`in` and `for`/`of` loop, which are almost
// same from parser's perspective.

pp$8.parseForIn = function(node, init) {
  var isForIn = this.type === types$1._in;
  this.next();

  if (
    init.type === "VariableDeclaration" &&
    init.declarations[0].init != null &&
    (
      !isForIn ||
      this.options.ecmaVersion < 8 ||
      this.strict ||
      init.kind !== "var" ||
      init.declarations[0].id.type !== "Identifier"
    )
  ) {
    this.raise(
      init.start,
      ((isForIn ? "for-in" : "for-of") + " loop variable declaration may not have an initializer")
    );
  }
  node.left = init;
  node.right = isForIn ? this.parseExpression() : this.parseMaybeAssign();
  this.expect(types$1.parenR);
  node.body = this.parseStatement("for");
  this.exitScope();
  this.labels.pop();
  return this.finishNode(node, isForIn ? "ForInStatement" : "ForOfStatement")
};

// Parse a list of variable declarations.

pp$8.parseVar = function(node, isFor, kind, allowMissingInitializer) {
  node.declarations = [];
  node.kind = kind;
  for (;;) {
    var decl = this.startNode();
    this.parseVarId(decl, kind);
    if (this.eat(types$1.eq)) {
      decl.init = this.parseMaybeAssign(isFor);
    } else if (!allowMissingInitializer && kind === "const" && !(this.type === types$1._in || (this.options.ecmaVersion >= 6 && this.isContextual("of")))) {
      this.unexpected();
    } else if (!allowMissingInitializer && (kind === "using" || kind === "await using") && this.options.ecmaVersion >= 17 && this.type !== types$1._in && !this.isContextual("of")) {
      this.raise(this.lastTokEnd, ("Missing initializer in " + kind + " declaration"));
    } else if (!allowMissingInitializer && decl.id.type !== "Identifier" && !(isFor && (this.type === types$1._in || this.isContextual("of")))) {
      this.raise(this.lastTokEnd, "Complex binding patterns require an initialization value");
    } else {
      decl.init = null;
    }
    node.declarations.push(this.finishNode(decl, "VariableDeclarator"));
    if (!this.eat(types$1.comma)) { break }
  }
  return node
};

pp$8.parseVarId = function(decl, kind) {
  decl.id = kind === "using" || kind === "await using"
    ? this.parseIdent()
    : this.parseBindingAtom();

  this.checkLValPattern(decl.id, kind === "var" ? BIND_VAR : BIND_LEXICAL, false);
};

var FUNC_STATEMENT$1 = 1, FUNC_HANGING_STATEMENT$1 = 2, FUNC_NULLABLE_ID$1 = 4;

// Parse a function declaration or literal (depending on the
// `statement & FUNC_STATEMENT`).

// Remove `allowExpressionBody` for 7.0.0, as it is only called with false
pp$8.parseFunction = function(node, statement, allowExpressionBody, isAsync, forInit) {
  this.initFunction(node);
  if (this.options.ecmaVersion >= 9 || this.options.ecmaVersion >= 6 && !isAsync) {
    if (this.type === types$1.star && (statement & FUNC_HANGING_STATEMENT$1))
      { this.unexpected(); }
    node.generator = this.eat(types$1.star);
  }
  if (this.options.ecmaVersion >= 8)
    { node.async = !!isAsync; }

  if (statement & FUNC_STATEMENT$1) {
    node.id = (statement & FUNC_NULLABLE_ID$1) && this.type !== types$1.name ? null : this.parseIdent();
    if (node.id && !(statement & FUNC_HANGING_STATEMENT$1))
      // If it is a regular function declaration in sloppy mode, then it is
      // subject to Annex B semantics (BIND_FUNCTION). Otherwise, the binding
      // mode depends on properties of the current scope (see
      // treatFunctionsAsVar).
      { this.checkLValSimple(node.id, (this.strict || node.generator || node.async) ? this.treatFunctionsAsVar ? BIND_VAR : BIND_LEXICAL : BIND_FUNCTION); }
  }

  var oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos;
  this.yieldPos = 0;
  this.awaitPos = 0;
  this.awaitIdentPos = 0;
  this.enterScope(functionFlags$1(node.async, node.generator));

  if (!(statement & FUNC_STATEMENT$1))
    { node.id = this.type === types$1.name ? this.parseIdent() : null; }

  this.parseFunctionParams(node);
  this.parseFunctionBody(node, allowExpressionBody, false, forInit);

  this.yieldPos = oldYieldPos;
  this.awaitPos = oldAwaitPos;
  this.awaitIdentPos = oldAwaitIdentPos;
  return this.finishNode(node, (statement & FUNC_STATEMENT$1) ? "FunctionDeclaration" : "FunctionExpression")
};

pp$8.parseFunctionParams = function(node) {
  this.expect(types$1.parenL);
  node.params = this.parseBindingList(types$1.parenR, false, this.options.ecmaVersion >= 8);
  this.checkYieldAwaitInDefaultParams();
};

// Parse a class declaration or literal (depending on the
// `isStatement` parameter).

pp$8.parseClass = function(node, isStatement) {
  this.next();

  // ecma-262 14.6 Class Definitions
  // A class definition is always strict mode code.
  var oldStrict = this.strict;
  this.strict = true;

  this.parseClassId(node, isStatement);
  this.parseClassSuper(node);
  var privateNameMap = this.enterClassBody();
  var classBody = this.startNode();
  var hadConstructor = false;
  classBody.body = [];
  this.expect(types$1.braceL);
  while (this.type !== types$1.braceR) {
    var element = this.parseClassElement(node.superClass !== null);
    if (element) {
      classBody.body.push(element);
      if (element.type === "MethodDefinition" && element.kind === "constructor") {
        if (hadConstructor) { this.raiseRecoverable(element.start, "Duplicate constructor in the same class"); }
        hadConstructor = true;
      } else if (element.key && element.key.type === "PrivateIdentifier" && isPrivateNameConflicted$1(privateNameMap, element)) {
        this.raiseRecoverable(element.key.start, ("Identifier '#" + (element.key.name) + "' has already been declared"));
      }
    }
  }
  this.strict = oldStrict;
  this.next();
  node.body = this.finishNode(classBody, "ClassBody");
  this.exitClassBody();
  return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression")
};

pp$8.parseClassElement = function(constructorAllowsSuper) {
  if (this.eat(types$1.semi)) { return null }

  var ecmaVersion = this.options.ecmaVersion;
  var node = this.startNode();
  var keyName = "";
  var isGenerator = false;
  var isAsync = false;
  var kind = "method";
  var isStatic = false;

  if (this.eatContextual("static")) {
    // Parse static init block
    if (ecmaVersion >= 13 && this.eat(types$1.braceL)) {
      this.parseClassStaticBlock(node);
      return node
    }
    if (this.isClassElementNameStart() || this.type === types$1.star) {
      isStatic = true;
    } else {
      keyName = "static";
    }
  }
  node.static = isStatic;
  if (!keyName && ecmaVersion >= 8 && this.eatContextual("async")) {
    if ((this.isClassElementNameStart() || this.type === types$1.star) && !this.canInsertSemicolon()) {
      isAsync = true;
    } else {
      keyName = "async";
    }
  }
  if (!keyName && (ecmaVersion >= 9 || !isAsync) && this.eat(types$1.star)) {
    isGenerator = true;
  }
  if (!keyName && !isAsync && !isGenerator) {
    var lastValue = this.value;
    if (this.eatContextual("get") || this.eatContextual("set")) {
      if (this.isClassElementNameStart()) {
        kind = lastValue;
      } else {
        keyName = lastValue;
      }
    }
  }

  // Parse element name
  if (keyName) {
    // 'async', 'get', 'set', or 'static' were not a keyword contextually.
    // The last token is any of those. Make it the element name.
    node.computed = false;
    node.key = this.startNodeAt(this.lastTokStart, this.lastTokStartLoc);
    node.key.name = keyName;
    this.finishNode(node.key, "Identifier");
  } else {
    this.parseClassElementName(node);
  }

  // Parse element value
  if (ecmaVersion < 13 || this.type === types$1.parenL || kind !== "method" || isGenerator || isAsync) {
    var isConstructor = !node.static && checkKeyName$1(node, "constructor");
    var allowsDirectSuper = isConstructor && constructorAllowsSuper;
    // Couldn't move this check into the 'parseClassMethod' method for backward compatibility.
    if (isConstructor && kind !== "method") { this.raise(node.key.start, "Constructor can't have get/set modifier"); }
    node.kind = isConstructor ? "constructor" : kind;
    this.parseClassMethod(node, isGenerator, isAsync, allowsDirectSuper);
  } else {
    this.parseClassField(node);
  }

  return node
};

pp$8.isClassElementNameStart = function() {
  return (
    this.type === types$1.name ||
    this.type === types$1.privateId ||
    this.type === types$1.num ||
    this.type === types$1.string ||
    this.type === types$1.bracketL ||
    this.type.keyword
  )
};

pp$8.parseClassElementName = function(element) {
  if (this.type === types$1.privateId) {
    if (this.value === "constructor") {
      this.raise(this.start, "Classes can't have an element named '#constructor'");
    }
    element.computed = false;
    element.key = this.parsePrivateIdent();
  } else {
    this.parsePropertyName(element);
  }
};

pp$8.parseClassMethod = function(method, isGenerator, isAsync, allowsDirectSuper) {
  // Check key and flags
  var key = method.key;
  if (method.kind === "constructor") {
    if (isGenerator) { this.raise(key.start, "Constructor can't be a generator"); }
    if (isAsync) { this.raise(key.start, "Constructor can't be an async method"); }
  } else if (method.static && checkKeyName$1(method, "prototype")) {
    this.raise(key.start, "Classes may not have a static property named prototype");
  }

  // Parse value
  var value = method.value = this.parseMethod(isGenerator, isAsync, allowsDirectSuper);

  // Check value
  if (method.kind === "get" && value.params.length !== 0)
    { this.raiseRecoverable(value.start, "getter should have no params"); }
  if (method.kind === "set" && value.params.length !== 1)
    { this.raiseRecoverable(value.start, "setter should have exactly one param"); }
  if (method.kind === "set" && value.params[0].type === "RestElement")
    { this.raiseRecoverable(value.params[0].start, "Setter cannot use rest params"); }

  return this.finishNode(method, "MethodDefinition")
};

pp$8.parseClassField = function(field) {
  if (checkKeyName$1(field, "constructor")) {
    this.raise(field.key.start, "Classes can't have a field named 'constructor'");
  } else if (field.static && checkKeyName$1(field, "prototype")) {
    this.raise(field.key.start, "Classes can't have a static field named 'prototype'");
  }

  if (this.eat(types$1.eq)) {
    // To raise SyntaxError if 'arguments' exists in the initializer.
    this.enterScope(SCOPE_CLASS_FIELD_INIT | SCOPE_SUPER);
    field.value = this.parseMaybeAssign();
    this.exitScope();
  } else {
    field.value = null;
  }
  this.semicolon();

  return this.finishNode(field, "PropertyDefinition")
};

pp$8.parseClassStaticBlock = function(node) {
  node.body = [];

  var oldLabels = this.labels;
  this.labels = [];
  this.enterScope(SCOPE_CLASS_STATIC_BLOCK | SCOPE_SUPER);
  while (this.type !== types$1.braceR) {
    var stmt = this.parseStatement(null);
    node.body.push(stmt);
  }
  this.next();
  this.exitScope();
  this.labels = oldLabels;

  return this.finishNode(node, "StaticBlock")
};

pp$8.parseClassId = function(node, isStatement) {
  if (this.type === types$1.name) {
    node.id = this.parseIdent();
    if (isStatement)
      { this.checkLValSimple(node.id, BIND_LEXICAL, false); }
  } else {
    if (isStatement === true)
      { this.unexpected(); }
    node.id = null;
  }
};

pp$8.parseClassSuper = function(node) {
  node.superClass = this.eat(types$1._extends) ? this.parseExprSubscripts(null, false) : null;
};

pp$8.enterClassBody = function() {
  var element = {declared: Object.create(null), used: []};
  this.privateNameStack.push(element);
  return element.declared
};

pp$8.exitClassBody = function() {
  var ref = this.privateNameStack.pop();
  var declared = ref.declared;
  var used = ref.used;
  if (!this.options.checkPrivateFields) { return }
  var len = this.privateNameStack.length;
  var parent = len === 0 ? null : this.privateNameStack[len - 1];
  for (var i = 0; i < used.length; ++i) {
    var id = used[i];
    if (!hasOwn(declared, id.name)) {
      if (parent) {
        parent.used.push(id);
      } else {
        this.raiseRecoverable(id.start, ("Private field '#" + (id.name) + "' must be declared in an enclosing class"));
      }
    }
  }
};

function isPrivateNameConflicted$1(privateNameMap, element) {
  var name = element.key.name;
  var curr = privateNameMap[name];

  var next = "true";
  if (element.type === "MethodDefinition" && (element.kind === "get" || element.kind === "set")) {
    next = (element.static ? "s" : "i") + element.kind;
  }

  // `class { get #a(){}; static set #a(_){} }` is also conflict.
  if (
    curr === "iget" && next === "iset" ||
    curr === "iset" && next === "iget" ||
    curr === "sget" && next === "sset" ||
    curr === "sset" && next === "sget"
  ) {
    privateNameMap[name] = "true";
    return false
  } else if (!curr) {
    privateNameMap[name] = next;
    return false
  } else {
    return true
  }
}

function checkKeyName$1(node, name) {
  var computed = node.computed;
  var key = node.key;
  return !computed && (
    key.type === "Identifier" && key.name === name ||
    key.type === "Literal" && key.value === name
  )
}

// Parses module export declaration.

pp$8.parseExportAllDeclaration = function(node, exports$1) {
  if (this.options.ecmaVersion >= 11) {
    if (this.eatContextual("as")) {
      node.exported = this.parseModuleExportName();
      this.checkExport(exports$1, node.exported, this.lastTokStart);
    } else {
      node.exported = null;
    }
  }
  this.expectContextual("from");
  if (this.type !== types$1.string) { this.unexpected(); }
  node.source = this.parseExprAtom();
  if (this.options.ecmaVersion >= 16)
    { node.attributes = this.parseWithClause(); }
  this.semicolon();
  return this.finishNode(node, "ExportAllDeclaration")
};

pp$8.parseExport = function(node, exports$1) {
  this.next();
  // export * from '...'
  if (this.eat(types$1.star)) {
    return this.parseExportAllDeclaration(node, exports$1)
  }
  if (this.eat(types$1._default)) { // export default ...
    this.checkExport(exports$1, "default", this.lastTokStart);
    node.declaration = this.parseExportDefaultDeclaration();
    return this.finishNode(node, "ExportDefaultDeclaration")
  }
  // export var|const|let|function|class ...
  if (this.shouldParseExportStatement()) {
    node.declaration = this.parseExportDeclaration(node);
    if (node.declaration.type === "VariableDeclaration")
      { this.checkVariableExport(exports$1, node.declaration.declarations); }
    else
      { this.checkExport(exports$1, node.declaration.id, node.declaration.id.start); }
    node.specifiers = [];
    node.source = null;
    if (this.options.ecmaVersion >= 16)
      { node.attributes = []; }
  } else { // export { x, y as z } [from '...']
    node.declaration = null;
    node.specifiers = this.parseExportSpecifiers(exports$1);
    if (this.eatContextual("from")) {
      if (this.type !== types$1.string) { this.unexpected(); }
      node.source = this.parseExprAtom();
      if (this.options.ecmaVersion >= 16)
        { node.attributes = this.parseWithClause(); }
    } else {
      for (var i = 0, list = node.specifiers; i < list.length; i += 1) {
        // check for keywords used as local names
        var spec = list[i];

        this.checkUnreserved(spec.local);
        // check if export is defined
        this.checkLocalExport(spec.local);

        if (spec.local.type === "Literal") {
          this.raise(spec.local.start, "A string literal cannot be used as an exported binding without `from`.");
        }
      }

      node.source = null;
      if (this.options.ecmaVersion >= 16)
        { node.attributes = []; }
    }
    this.semicolon();
  }
  return this.finishNode(node, "ExportNamedDeclaration")
};

pp$8.parseExportDeclaration = function(node) {
  return this.parseStatement(null)
};

pp$8.parseExportDefaultDeclaration = function() {
  var isAsync;
  if (this.type === types$1._function || (isAsync = this.isAsyncFunction())) {
    var fNode = this.startNode();
    this.next();
    if (isAsync) { this.next(); }
    return this.parseFunction(fNode, FUNC_STATEMENT$1 | FUNC_NULLABLE_ID$1, false, isAsync)
  } else if (this.type === types$1._class) {
    var cNode = this.startNode();
    return this.parseClass(cNode, "nullableID")
  } else {
    var declaration = this.parseMaybeAssign();
    this.semicolon();
    return declaration
  }
};

pp$8.checkExport = function(exports$1, name, pos) {
  if (!exports$1) { return }
  if (typeof name !== "string")
    { name = name.type === "Identifier" ? name.name : name.value; }
  if (hasOwn(exports$1, name))
    { this.raiseRecoverable(pos, "Duplicate export '" + name + "'"); }
  exports$1[name] = true;
};

pp$8.checkPatternExport = function(exports$1, pat) {
  var type = pat.type;
  if (type === "Identifier")
    { this.checkExport(exports$1, pat, pat.start); }
  else if (type === "ObjectPattern")
    { for (var i = 0, list = pat.properties; i < list.length; i += 1)
      {
        var prop = list[i];

        this.checkPatternExport(exports$1, prop);
      } }
  else if (type === "ArrayPattern")
    { for (var i$1 = 0, list$1 = pat.elements; i$1 < list$1.length; i$1 += 1) {
      var elt = list$1[i$1];

        if (elt) { this.checkPatternExport(exports$1, elt); }
    } }
  else if (type === "Property")
    { this.checkPatternExport(exports$1, pat.value); }
  else if (type === "AssignmentPattern")
    { this.checkPatternExport(exports$1, pat.left); }
  else if (type === "RestElement")
    { this.checkPatternExport(exports$1, pat.argument); }
};

pp$8.checkVariableExport = function(exports$1, decls) {
  if (!exports$1) { return }
  for (var i = 0, list = decls; i < list.length; i += 1)
    {
    var decl = list[i];

    this.checkPatternExport(exports$1, decl.id);
  }
};

pp$8.shouldParseExportStatement = function() {
  return this.type.keyword === "var" ||
    this.type.keyword === "const" ||
    this.type.keyword === "class" ||
    this.type.keyword === "function" ||
    this.isLet() ||
    this.isAsyncFunction()
};

// Parses a comma-separated list of module exports.

pp$8.parseExportSpecifier = function(exports$1) {
  var node = this.startNode();
  node.local = this.parseModuleExportName();

  node.exported = this.eatContextual("as") ? this.parseModuleExportName() : node.local;
  this.checkExport(
    exports$1,
    node.exported,
    node.exported.start
  );

  return this.finishNode(node, "ExportSpecifier")
};

pp$8.parseExportSpecifiers = function(exports$1) {
  var nodes = [], first = true;
  // export { x, y as z } [from '...']
  this.expect(types$1.braceL);
  while (!this.eat(types$1.braceR)) {
    if (!first) {
      this.expect(types$1.comma);
      if (this.afterTrailingComma(types$1.braceR)) { break }
    } else { first = false; }

    nodes.push(this.parseExportSpecifier(exports$1));
  }
  return nodes
};

// Parses import declaration.

pp$8.parseImport = function(node) {
  this.next();

  // import '...'
  if (this.type === types$1.string) {
    node.specifiers = empty$1;
    node.source = this.parseExprAtom();
  } else {
    node.specifiers = this.parseImportSpecifiers();
    this.expectContextual("from");
    node.source = this.type === types$1.string ? this.parseExprAtom() : this.unexpected();
  }
  if (this.options.ecmaVersion >= 16)
    { node.attributes = this.parseWithClause(); }
  this.semicolon();
  return this.finishNode(node, "ImportDeclaration")
};

// Parses a comma-separated list of module imports.

pp$8.parseImportSpecifier = function() {
  var node = this.startNode();
  node.imported = this.parseModuleExportName();

  if (this.eatContextual("as")) {
    node.local = this.parseIdent();
  } else {
    this.checkUnreserved(node.imported);
    node.local = node.imported;
  }
  this.checkLValSimple(node.local, BIND_LEXICAL);

  return this.finishNode(node, "ImportSpecifier")
};

pp$8.parseImportDefaultSpecifier = function() {
  // import defaultObj, { x, y as z } from '...'
  var node = this.startNode();
  node.local = this.parseIdent();
  this.checkLValSimple(node.local, BIND_LEXICAL);
  return this.finishNode(node, "ImportDefaultSpecifier")
};

pp$8.parseImportNamespaceSpecifier = function() {
  var node = this.startNode();
  this.next();
  this.expectContextual("as");
  node.local = this.parseIdent();
  this.checkLValSimple(node.local, BIND_LEXICAL);
  return this.finishNode(node, "ImportNamespaceSpecifier")
};

pp$8.parseImportSpecifiers = function() {
  var nodes = [], first = true;
  if (this.type === types$1.name) {
    nodes.push(this.parseImportDefaultSpecifier());
    if (!this.eat(types$1.comma)) { return nodes }
  }
  if (this.type === types$1.star) {
    nodes.push(this.parseImportNamespaceSpecifier());
    return nodes
  }
  this.expect(types$1.braceL);
  while (!this.eat(types$1.braceR)) {
    if (!first) {
      this.expect(types$1.comma);
      if (this.afterTrailingComma(types$1.braceR)) { break }
    } else { first = false; }

    nodes.push(this.parseImportSpecifier());
  }
  return nodes
};

pp$8.parseWithClause = function() {
  var nodes = [];
  if (!this.eat(types$1._with)) {
    return nodes
  }
  this.expect(types$1.braceL);
  var attributeKeys = {};
  var first = true;
  while (!this.eat(types$1.braceR)) {
    if (!first) {
      this.expect(types$1.comma);
      if (this.afterTrailingComma(types$1.braceR)) { break }
    } else { first = false; }

    var attr = this.parseImportAttribute();
    var keyName = attr.key.type === "Identifier" ? attr.key.name : attr.key.value;
    if (hasOwn(attributeKeys, keyName))
      { this.raiseRecoverable(attr.key.start, "Duplicate attribute key '" + keyName + "'"); }
    attributeKeys[keyName] = true;
    nodes.push(attr);
  }
  return nodes
};

pp$8.parseImportAttribute = function() {
  var node = this.startNode();
  node.key = this.type === types$1.string ? this.parseExprAtom() : this.parseIdent(this.options.allowReserved !== "never");
  this.expect(types$1.colon);
  if (this.type !== types$1.string) {
    this.unexpected();
  }
  node.value = this.parseExprAtom();
  return this.finishNode(node, "ImportAttribute")
};

pp$8.parseModuleExportName = function() {
  if (this.options.ecmaVersion >= 13 && this.type === types$1.string) {
    var stringLiteral = this.parseLiteral(this.value);
    if (loneSurrogate.test(stringLiteral.value)) {
      this.raise(stringLiteral.start, "An export name cannot include a lone surrogate.");
    }
    return stringLiteral
  }
  return this.parseIdent(true)
};

// Set `ExpressionStatement#directive` property for directive prologues.
pp$8.adaptDirectivePrologue = function(statements) {
  for (var i = 0; i < statements.length && this.isDirectiveCandidate(statements[i]); ++i) {
    statements[i].directive = statements[i].expression.raw.slice(1, -1);
  }
};
pp$8.isDirectiveCandidate = function(statement) {
  return (
    this.options.ecmaVersion >= 5 &&
    statement.type === "ExpressionStatement" &&
    statement.expression.type === "Literal" &&
    typeof statement.expression.value === "string" &&
    // Reject parenthesized strings.
    (this.input[statement.start] === "\"" || this.input[statement.start] === "'")
  )
};

var pp$7 = Parser$1.prototype;

// Convert existing expression atom to assignable pattern
// if possible.

pp$7.toAssignable = function(node, isBinding, refDestructuringErrors) {
  if (this.options.ecmaVersion >= 6 && node) {
    switch (node.type) {
    case "Identifier":
      if (this.inAsync && node.name === "await")
        { this.raise(node.start, "Cannot use 'await' as identifier inside an async function"); }
      break

    case "ObjectPattern":
    case "ArrayPattern":
    case "AssignmentPattern":
    case "RestElement":
      break

    case "ObjectExpression":
      node.type = "ObjectPattern";
      if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); }
      for (var i = 0, list = node.properties; i < list.length; i += 1) {
        var prop = list[i];

      this.toAssignable(prop, isBinding);
        // Early error:
        //   AssignmentRestProperty[Yield, Await] :
        //     `...` DestructuringAssignmentTarget[Yield, Await]
        //
        //   It is a Syntax Error if |DestructuringAssignmentTarget| is an |ArrayLiteral| or an |ObjectLiteral|.
        if (
          prop.type === "RestElement" &&
          (prop.argument.type === "ArrayPattern" || prop.argument.type === "ObjectPattern")
        ) {
          this.raise(prop.argument.start, "Unexpected token");
        }
      }
      break

    case "Property":
      // AssignmentProperty has type === "Property"
      if (node.kind !== "init") { this.raise(node.key.start, "Object pattern can't contain getter or setter"); }
      this.toAssignable(node.value, isBinding);
      break

    case "ArrayExpression":
      node.type = "ArrayPattern";
      if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); }
      this.toAssignableList(node.elements, isBinding);
      break

    case "SpreadElement":
      node.type = "RestElement";
      this.toAssignable(node.argument, isBinding);
      if (node.argument.type === "AssignmentPattern")
        { this.raise(node.argument.start, "Rest elements cannot have a default value"); }
      break

    case "AssignmentExpression":
      if (node.operator !== "=") { this.raise(node.left.end, "Only '=' operator can be used for specifying default value."); }
      node.type = "AssignmentPattern";
      delete node.operator;
      this.toAssignable(node.left, isBinding);
      break

    case "ParenthesizedExpression":
      this.toAssignable(node.expression, isBinding, refDestructuringErrors);
      break

    case "ChainExpression":
      this.raiseRecoverable(node.start, "Optional chaining cannot appear in left-hand side");
      break

    case "MemberExpression":
      if (!isBinding) { break }

    default:
      this.raise(node.start, "Assigning to rvalue");
    }
  } else if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); }
  return node
};

// Convert list of expression atoms to binding list.

pp$7.toAssignableList = function(exprList, isBinding) {
  var end = exprList.length;
  for (var i = 0; i < end; i++) {
    var elt = exprList[i];
    if (elt) { this.toAssignable(elt, isBinding); }
  }
  if (end) {
    var last = exprList[end - 1];
    if (this.options.ecmaVersion === 6 && isBinding && last && last.type === "RestElement" && last.argument.type !== "Identifier")
      { this.unexpected(last.argument.start); }
  }
  return exprList
};

// Parses spread element.

pp$7.parseSpread = function(refDestructuringErrors) {
  var node = this.startNode();
  this.next();
  node.argument = this.parseMaybeAssign(false, refDestructuringErrors);
  return this.finishNode(node, "SpreadElement")
};

pp$7.parseRestBinding = function() {
  var node = this.startNode();
  this.next();

  // RestElement inside of a function parameter must be an identifier
  if (this.options.ecmaVersion === 6 && this.type !== types$1.name)
    { this.unexpected(); }

  node.argument = this.parseBindingAtom();

  return this.finishNode(node, "RestElement")
};

// Parses lvalue (assignable) atom.

pp$7.parseBindingAtom = function() {
  if (this.options.ecmaVersion >= 6) {
    switch (this.type) {
    case types$1.bracketL:
      var node = this.startNode();
      this.next();
      node.elements = this.parseBindingList(types$1.bracketR, true, true);
      return this.finishNode(node, "ArrayPattern")

    case types$1.braceL:
      return this.parseObj(true)
    }
  }
  return this.parseIdent()
};

pp$7.parseBindingList = function(close, allowEmpty, allowTrailingComma, allowModifiers) {
  var elts = [], first = true;
  while (!this.eat(close)) {
    if (first) { first = false; }
    else { this.expect(types$1.comma); }
    if (allowEmpty && this.type === types$1.comma) {
      elts.push(null);
    } else if (allowTrailingComma && this.afterTrailingComma(close)) {
      break
    } else if (this.type === types$1.ellipsis) {
      var rest = this.parseRestBinding();
      this.parseBindingListItem(rest);
      elts.push(rest);
      if (this.type === types$1.comma) { this.raiseRecoverable(this.start, "Comma is not permitted after the rest element"); }
      this.expect(close);
      break
    } else {
      elts.push(this.parseAssignableListItem(allowModifiers));
    }
  }
  return elts
};

pp$7.parseAssignableListItem = function(allowModifiers) {
  var elem = this.parseMaybeDefault(this.start, this.startLoc);
  this.parseBindingListItem(elem);
  return elem
};

pp$7.parseBindingListItem = function(param) {
  return param
};

// Parses assignment pattern around given atom if possible.

pp$7.parseMaybeDefault = function(startPos, startLoc, left) {
  left = left || this.parseBindingAtom();
  if (this.options.ecmaVersion < 6 || !this.eat(types$1.eq)) { return left }
  var node = this.startNodeAt(startPos, startLoc);
  node.left = left;
  node.right = this.parseMaybeAssign();
  return this.finishNode(node, "AssignmentPattern")
};

// The following three functions all verify that a node is an lvalue —
// something that can be bound, or assigned to. In order to do so, they perform
// a variety of checks:
//
// - Check that none of the bound/assigned-to identifiers are reserved words.
// - Record name declarations for bindings in the appropriate scope.
// - Check duplicate argument names, if checkClashes is set.
//
// If a complex binding pattern is encountered (e.g., object and array
// destructuring), the entire pattern is recursively checked.
//
// There are three versions of checkLVal*() appropriate for different
// circumstances:
//
// - checkLValSimple() shall be used if the syntactic construct supports
//   nothing other than identifiers and member expressions. Parenthesized
//   expressions are also correctly handled. This is generally appropriate for
//   constructs for which the spec says
//
//   > It is a Syntax Error if AssignmentTargetType of [the production] is not
//   > simple.
//
//   It is also appropriate for checking if an identifier is valid and not
//   defined elsewhere, like import declarations or function/class identifiers.
//
//   Examples where this is used include:
//     a += …;
//     import a from '…';
//   where a is the node to be checked.
//
// - checkLValPattern() shall be used if the syntactic construct supports
//   anything checkLValSimple() supports, as well as object and array
//   destructuring patterns. This is generally appropriate for constructs for
//   which the spec says
//
//   > It is a Syntax Error if [the production] is neither an ObjectLiteral nor
//   > an ArrayLiteral and AssignmentTargetType of [the production] is not
//   > simple.
//
//   Examples where this is used include:
//     (a = …);
//     const a = …;
//     try { … } catch (a) { … }
//   where a is the node to be checked.
//
// - checkLValInnerPattern() shall be used if the syntactic construct supports
//   anything checkLValPattern() supports, as well as default assignment
//   patterns, rest elements, and other constructs that may appear within an
//   object or array destructuring pattern.
//
//   As a special case, function parameters also use checkLValInnerPattern(),
//   as they also support defaults and rest constructs.
//
// These functions deliberately support both assignment and binding constructs,
// as the logic for both is exceedingly similar. If the node is the target of
// an assignment, then bindingType should be set to BIND_NONE. Otherwise, it
// should be set to the appropriate BIND_* constant, like BIND_VAR or
// BIND_LEXICAL.
//
// If the function is called with a non-BIND_NONE bindingType, then
// additionally a checkClashes object may be specified to allow checking for
// duplicate argument names. checkClashes is ignored if the provided construct
// is an assignment (i.e., bindingType is BIND_NONE).

pp$7.checkLValSimple = function(expr, bindingType, checkClashes) {
  if ( bindingType === void 0 ) bindingType = BIND_NONE;

  var isBind = bindingType !== BIND_NONE;

  switch (expr.type) {
  case "Identifier":
    if (this.strict && this.reservedWordsStrictBind.test(expr.name))
      { this.raiseRecoverable(expr.start, (isBind ? "Binding " : "Assigning to ") + expr.name + " in strict mode"); }
    if (isBind) {
      if (bindingType === BIND_LEXICAL && expr.name === "let")
        { this.raiseRecoverable(expr.start, "let is disallowed as a lexically bound name"); }
      if (checkClashes) {
        if (hasOwn(checkClashes, expr.name))
          { this.raiseRecoverable(expr.start, "Argument name clash"); }
        checkClashes[expr.name] = true;
      }
      if (bindingType !== BIND_OUTSIDE) { this.declareName(expr.name, bindingType, expr.start); }
    }
    break

  case "ChainExpression":
    this.raiseRecoverable(expr.start, "Optional chaining cannot appear in left-hand side");
    break

  case "MemberExpression":
    if (isBind) { this.raiseRecoverable(expr.start, "Binding member expression"); }
    break

  case "ParenthesizedExpression":
    if (isBind) { this.raiseRecoverable(expr.start, "Binding parenthesized expression"); }
    return this.checkLValSimple(expr.expression, bindingType, checkClashes)

  default:
    this.raise(expr.start, (isBind ? "Binding" : "Assigning to") + " rvalue");
  }
};

pp$7.checkLValPattern = function(expr, bindingType, checkClashes) {
  if ( bindingType === void 0 ) bindingType = BIND_NONE;

  switch (expr.type) {
  case "ObjectPattern":
    for (var i = 0, list = expr.properties; i < list.length; i += 1) {
      var prop = list[i];

    this.checkLValInnerPattern(prop, bindingType, checkClashes);
    }
    break

  case "ArrayPattern":
    for (var i$1 = 0, list$1 = expr.elements; i$1 < list$1.length; i$1 += 1) {
      var elem = list$1[i$1];

    if (elem) { this.checkLValInnerPattern(elem, bindingType, checkClashes); }
    }
    break

  default:
    this.checkLValSimple(expr, bindingType, checkClashes);
  }
};

pp$7.checkLValInnerPattern = function(expr, bindingType, checkClashes) {
  if ( bindingType === void 0 ) bindingType = BIND_NONE;

  switch (expr.type) {
  case "Property":
    // AssignmentProperty has type === "Property"
    this.checkLValInnerPattern(expr.value, bindingType, checkClashes);
    break

  case "AssignmentPattern":
    this.checkLValPattern(expr.left, bindingType, checkClashes);
    break

  case "RestElement":
    this.checkLValPattern(expr.argument, bindingType, checkClashes);
    break

  default:
    this.checkLValPattern(expr, bindingType, checkClashes);
  }
};

// The algorithm used to determine whether a regexp can appear at a
// given point in the program is loosely based on sweet.js' approach.
// See https://github.com/mozilla/sweet.js/wiki/design


var TokContext = function TokContext(token, isExpr, preserveSpace, override, generator) {
  this.token = token;
  this.isExpr = !!isExpr;
  this.preserveSpace = !!preserveSpace;
  this.override = override;
  this.generator = !!generator;
};

var types = {
  b_stat: new TokContext("{", false),
  b_expr: new TokContext("{", true),
  b_tmpl: new TokContext("${", false),
  p_stat: new TokContext("(", false),
  p_expr: new TokContext("(", true),
  q_tmpl: new TokContext("`", true, true, function (p) { return p.tryReadTemplateToken(); }),
  f_stat: new TokContext("function", false),
  f_expr: new TokContext("function", true),
  f_expr_gen: new TokContext("function", true, false, null, true),
  f_gen: new TokContext("function", false, false, null, true)
};

var pp$6 = Parser$1.prototype;

pp$6.initialContext = function() {
  return [types.b_stat]
};

pp$6.curContext = function() {
  return this.context[this.context.length - 1]
};

pp$6.braceIsBlock = function(prevType) {
  var parent = this.curContext();
  if (parent === types.f_expr || parent === types.f_stat)
    { return true }
  if (prevType === types$1.colon && (parent === types.b_stat || parent === types.b_expr))
    { return !parent.isExpr }

  // The check for `tt.name && exprAllowed` detects whether we are
  // after a `yield` or `of` construct. See the `updateContext` for
  // `tt.name`.
  if (prevType === types$1._return || prevType === types$1.name && this.exprAllowed)
    { return lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) }
  if (prevType === types$1._else || prevType === types$1.semi || prevType === types$1.eof || prevType === types$1.parenR || prevType === types$1.arrow)
    { return true }
  if (prevType === types$1.braceL)
    { return parent === types.b_stat }
  if (prevType === types$1._var || prevType === types$1._const || prevType === types$1.name)
    { return false }
  return !this.exprAllowed
};

pp$6.inGeneratorContext = function() {
  for (var i = this.context.length - 1; i >= 1; i--) {
    var context = this.context[i];
    if (context.token === "function")
      { return context.generator }
  }
  return false
};

pp$6.updateContext = function(prevType) {
  var update, type = this.type;
  if (type.keyword && prevType === types$1.dot)
    { this.exprAllowed = false; }
  else if (update = type.updateContext)
    { update.call(this, prevType); }
  else
    { this.exprAllowed = type.beforeExpr; }
};

// Used to handle edge cases when token context could not be inferred correctly during tokenization phase

pp$6.overrideContext = function(tokenCtx) {
  if (this.curContext() !== tokenCtx) {
    this.context[this.context.length - 1] = tokenCtx;
  }
};

// Token-specific context update code

types$1.parenR.updateContext = types$1.braceR.updateContext = function() {
  if (this.context.length === 1) {
    this.exprAllowed = true;
    return
  }
  var out = this.context.pop();
  if (out === types.b_stat && this.curContext().token === "function") {
    out = this.context.pop();
  }
  this.exprAllowed = !out.isExpr;
};

types$1.braceL.updateContext = function(prevType) {
  this.context.push(this.braceIsBlock(prevType) ? types.b_stat : types.b_expr);
  this.exprAllowed = true;
};

types$1.dollarBraceL.updateContext = function() {
  this.context.push(types.b_tmpl);
  this.exprAllowed = true;
};

types$1.parenL.updateContext = function(prevType) {
  var statementParens = prevType === types$1._if || prevType === types$1._for || prevType === types$1._with || prevType === types$1._while;
  this.context.push(statementParens ? types.p_stat : types.p_expr);
  this.exprAllowed = true;
};

types$1.incDec.updateContext = function() {
  // tokExprAllowed stays unchanged
};

types$1._function.updateContext = types$1._class.updateContext = function(prevType) {
  if (prevType.beforeExpr && prevType !== types$1._else &&
      !(prevType === types$1.semi && this.curContext() !== types.p_stat) &&
      !(prevType === types$1._return && lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) &&
      !((prevType === types$1.colon || prevType === types$1.braceL) && this.curContext() === types.b_stat))
    { this.context.push(types.f_expr); }
  else
    { this.context.push(types.f_stat); }
  this.exprAllowed = false;
};

types$1.colon.updateContext = function() {
  if (this.curContext().token === "function") { this.context.pop(); }
  this.exprAllowed = true;
};

types$1.backQuote.updateContext = function() {
  if (this.curContext() === types.q_tmpl)
    { this.context.pop(); }
  else
    { this.context.push(types.q_tmpl); }
  this.exprAllowed = false;
};

types$1.star.updateContext = function(prevType) {
  if (prevType === types$1._function) {
    var index = this.context.length - 1;
    if (this.context[index] === types.f_expr)
      { this.context[index] = types.f_expr_gen; }
    else
      { this.context[index] = types.f_gen; }
  }
  this.exprAllowed = true;
};

types$1.name.updateContext = function(prevType) {
  var allowed = false;
  if (this.options.ecmaVersion >= 6 && prevType !== types$1.dot) {
    if (this.value === "of" && !this.exprAllowed ||
        this.value === "yield" && this.inGeneratorContext())
      { allowed = true; }
  }
  this.exprAllowed = allowed;
};

// A recursive descent parser operates by defining functions for all
// syntactic elements, and recursively calling those, each function
// advancing the input stream and returning an AST node. Precedence
// of constructs (for example, the fact that `!x[1]` means `!(x[1])`
// instead of `(!x)[1]` is handled by the fact that the parser
// function that parses unary prefix operators is called first, and
// in turn calls the function that parses `[]` subscripts — that
// way, it'll receive the node for `x[1]` already parsed, and wraps
// *that* in the unary operator node.
//
// Acorn uses an [operator precedence parser][opp] to handle binary
// operator precedence, because it is much more compact than using
// the technique outlined above, which uses different, nesting
// functions to specify precedence, for all of the ten binary
// precedence levels that JavaScript defines.
//
// [opp]: http://en.wikipedia.org/wiki/Operator-precedence_parser


var pp$5 = Parser$1.prototype;

// Check if property name clashes with already added.
// Object/class getters and setters are not allowed to clash —
// either with each other or with an init property — and in
// strict mode, init properties are also not allowed to be repeated.

pp$5.checkPropClash = function(prop, propHash, refDestructuringErrors) {
  if (this.options.ecmaVersion >= 9 && prop.type === "SpreadElement")
    { return }
  if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand))
    { return }
  var key = prop.key;
  var name;
  switch (key.type) {
  case "Identifier": name = key.name; break
  case "Literal": name = String(key.value); break
  default: return
  }
  var kind = prop.kind;
  if (this.options.ecmaVersion >= 6) {
    if (name === "__proto__" && kind === "init") {
      if (propHash.proto) {
        if (refDestructuringErrors) {
          if (refDestructuringErrors.doubleProto < 0) {
            refDestructuringErrors.doubleProto = key.start;
          }
        } else {
          this.raiseRecoverable(key.start, "Redefinition of __proto__ property");
        }
      }
      propHash.proto = true;
    }
    return
  }
  name = "$" + name;
  var other = propHash[name];
  if (other) {
    var redefinition;
    if (kind === "init") {
      redefinition = this.strict && other.init || other.get || other.set;
    } else {
      redefinition = other.init || other[kind];
    }
    if (redefinition)
      { this.raiseRecoverable(key.start, "Redefinition of property"); }
  } else {
    other = propHash[name] = {
      init: false,
      get: false,
      set: false
    };
  }
  other[kind] = true;
};

// ### Expression parsing

// These nest, from the most general expression type at the top to
// 'atomic', nondivisible expression types at the bottom. Most of
// the functions will simply let the function(s) below them parse,
// and, *if* the syntactic construct they handle is present, wrap
// the AST node that the inner parser gave them in another node.

// Parse a full expression. The optional arguments are used to
// forbid the `in` operator (in for loops initalization expressions)
// and provide reference for storing '=' operator inside shorthand
// property assignment in contexts where both object expression
// and object pattern might appear (so it's possible to raise
// delayed syntax error at correct position).

pp$5.parseExpression = function(forInit, refDestructuringErrors) {
  var startPos = this.start, startLoc = this.startLoc;
  var expr = this.parseMaybeAssign(forInit, refDestructuringErrors);
  if (this.type === types$1.comma) {
    var node = this.startNodeAt(startPos, startLoc);
    node.expressions = [expr];
    while (this.eat(types$1.comma)) { node.expressions.push(this.parseMaybeAssign(forInit, refDestructuringErrors)); }
    return this.finishNode(node, "SequenceExpression")
  }
  return expr
};

// Parse an assignment expression. This includes applications of
// operators like `+=`.

pp$5.parseMaybeAssign = function(forInit, refDestructuringErrors, afterLeftParse) {
  if (this.isContextual("yield")) {
    if (this.inGenerator) { return this.parseYield(forInit) }
    // The tokenizer will assume an expression is allowed after
    // `yield`, but this isn't that kind of yield
    else { this.exprAllowed = false; }
  }

  var ownDestructuringErrors = false, oldParenAssign = -1, oldTrailingComma = -1, oldDoubleProto = -1;
  if (refDestructuringErrors) {
    oldParenAssign = refDestructuringErrors.parenthesizedAssign;
    oldTrailingComma = refDestructuringErrors.trailingComma;
    oldDoubleProto = refDestructuringErrors.doubleProto;
    refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = -1;
  } else {
    refDestructuringErrors = new DestructuringErrors$1;
    ownDestructuringErrors = true;
  }

  var startPos = this.start, startLoc = this.startLoc;
  if (this.type === types$1.parenL || this.type === types$1.name) {
    this.potentialArrowAt = this.start;
    this.potentialArrowInForAwait = forInit === "await";
  }
  var left = this.parseMaybeConditional(forInit, refDestructuringErrors);
  if (afterLeftParse) { left = afterLeftParse.call(this, left, startPos, startLoc); }
  if (this.type.isAssign) {
    var node = this.startNodeAt(startPos, startLoc);
    node.operator = this.value;
    if (this.type === types$1.eq)
      { left = this.toAssignable(left, false, refDestructuringErrors); }
    if (!ownDestructuringErrors) {
      refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = refDestructuringErrors.doubleProto = -1;
    }
    if (refDestructuringErrors.shorthandAssign >= left.start)
      { refDestructuringErrors.shorthandAssign = -1; } // reset because shorthand default was used correctly
    if (this.type === types$1.eq)
      { this.checkLValPattern(left); }
    else
      { this.checkLValSimple(left); }
    node.left = left;
    this.next();
    node.right = this.parseMaybeAssign(forInit);
    if (oldDoubleProto > -1) { refDestructuringErrors.doubleProto = oldDoubleProto; }
    return this.finishNode(node, "AssignmentExpression")
  } else {
    if (ownDestructuringErrors) { this.checkExpressionErrors(refDestructuringErrors, true); }
  }
  if (oldParenAssign > -1) { refDestructuringErrors.parenthesizedAssign = oldParenAssign; }
  if (oldTrailingComma > -1) { refDestructuringErrors.trailingComma = oldTrailingComma; }
  return left
};

// Parse a ternary conditional (`?:`) operator.

pp$5.parseMaybeConditional = function(forInit, refDestructuringErrors) {
  var startPos = this.start, startLoc = this.startLoc;
  var expr = this.parseExprOps(forInit, refDestructuringErrors);
  if (this.checkExpressionErrors(refDestructuringErrors)) { return expr }
  if (this.eat(types$1.question)) {
    var node = this.startNodeAt(startPos, startLoc);
    node.test = expr;
    node.consequent = this.parseMaybeAssign();
    this.expect(types$1.colon);
    node.alternate = this.parseMaybeAssign(forInit);
    return this.finishNode(node, "ConditionalExpression")
  }
  return expr
};

// Start the precedence parser.

pp$5.parseExprOps = function(forInit, refDestructuringErrors) {
  var startPos = this.start, startLoc = this.startLoc;
  var expr = this.parseMaybeUnary(refDestructuringErrors, false, false, forInit);
  if (this.checkExpressionErrors(refDestructuringErrors)) { return expr }
  return expr.start === startPos && expr.type === "ArrowFunctionExpression" ? expr : this.parseExprOp(expr, startPos, startLoc, -1, forInit)
};

// Parse binary operators with the operator precedence parsing
// algorithm. `left` is the left-hand side of the operator.
// `minPrec` provides context that allows the function to stop and
// defer further parser to one of its callers when it encounters an
// operator that has a lower precedence than the set it is parsing.

pp$5.parseExprOp = function(left, leftStartPos, leftStartLoc, minPrec, forInit) {
  var prec = this.type.binop;
  if (prec != null && (!forInit || this.type !== types$1._in)) {
    if (prec > minPrec) {
      var logical = this.type === types$1.logicalOR || this.type === types$1.logicalAND;
      var coalesce = this.type === types$1.coalesce;
      if (coalesce) {
        // Handle the precedence of `tt.coalesce` as equal to the range of logical expressions.
        // In other words, `node.right` shouldn't contain logical expressions in order to check the mixed error.
        prec = types$1.logicalAND.binop;
      }
      var op = this.value;
      this.next();
      var startPos = this.start, startLoc = this.startLoc;
      var right = this.parseExprOp(this.parseMaybeUnary(null, false, false, forInit), startPos, startLoc, prec, forInit);
      var node = this.buildBinary(leftStartPos, leftStartLoc, left, right, op, logical || coalesce);
      if ((logical && this.type === types$1.coalesce) || (coalesce && (this.type === types$1.logicalOR || this.type === types$1.logicalAND))) {
        this.raiseRecoverable(this.start, "Logical expressions and coalesce expressions cannot be mixed. Wrap either by parentheses");
      }
      return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, forInit)
    }
  }
  return left
};

pp$5.buildBinary = function(startPos, startLoc, left, right, op, logical) {
  if (right.type === "PrivateIdentifier") { this.raise(right.start, "Private identifier can only be left side of binary expression"); }
  var node = this.startNodeAt(startPos, startLoc);
  node.left = left;
  node.operator = op;
  node.right = right;
  return this.finishNode(node, logical ? "LogicalExpression" : "BinaryExpression")
};

// Parse unary operators, both prefix and postfix.

pp$5.parseMaybeUnary = function(refDestructuringErrors, sawUnary, incDec, forInit) {
  var startPos = this.start, startLoc = this.startLoc, expr;
  if (this.isContextual("await") && this.canAwait) {
    expr = this.parseAwait(forInit);
    sawUnary = true;
  } else if (this.type.prefix) {
    var node = this.startNode(), update = this.type === types$1.incDec;
    node.operator = this.value;
    node.prefix = true;
    this.next();
    node.argument = this.parseMaybeUnary(null, true, update, forInit);
    this.checkExpressionErrors(refDestructuringErrors, true);
    if (update) { this.checkLValSimple(node.argument); }
    else if (this.strict && node.operator === "delete" && isLocalVariableAccess(node.argument))
      { this.raiseRecoverable(node.start, "Deleting local variable in strict mode"); }
    else if (node.operator === "delete" && isPrivateFieldAccess(node.argument))
      { this.raiseRecoverable(node.start, "Private fields can not be deleted"); }
    else { sawUnary = true; }
    expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression");
  } else if (!sawUnary && this.type === types$1.privateId) {
    if ((forInit || this.privateNameStack.length === 0) && this.options.checkPrivateFields) { this.unexpected(); }
    expr = this.parsePrivateIdent();
    // only could be private fields in 'in', such as #x in obj
    if (this.type !== types$1._in) { this.unexpected(); }
  } else {
    expr = this.parseExprSubscripts(refDestructuringErrors, forInit);
    if (this.checkExpressionErrors(refDestructuringErrors)) { return expr }
    while (this.type.postfix && !this.canInsertSemicolon()) {
      var node$1 = this.startNodeAt(startPos, startLoc);
      node$1.operator = this.value;
      node$1.prefix = false;
      node$1.argument = expr;
      this.checkLValSimple(expr);
      this.next();
      expr = this.finishNode(node$1, "UpdateExpression");
    }
  }

  if (!incDec && this.eat(types$1.starstar)) {
    if (sawUnary)
      { this.unexpected(this.lastTokStart); }
    else
      { return this.buildBinary(startPos, startLoc, expr, this.parseMaybeUnary(null, false, false, forInit), "**", false) }
  } else {
    return expr
  }
};

function isLocalVariableAccess(node) {
  return (
    node.type === "Identifier" ||
    node.type === "ParenthesizedExpression" && isLocalVariableAccess(node.expression)
  )
}

function isPrivateFieldAccess(node) {
  return (
    node.type === "MemberExpression" && node.property.type === "PrivateIdentifier" ||
    node.type === "ChainExpression" && isPrivateFieldAccess(node.expression) ||
    node.type === "ParenthesizedExpression" && isPrivateFieldAccess(node.expression)
  )
}

// Parse call, dot, and `[]`-subscript expressions.

pp$5.parseExprSubscripts = function(refDestructuringErrors, forInit) {
  var startPos = this.start, startLoc = this.startLoc;
  var expr = this.parseExprAtom(refDestructuringErrors, forInit);
  if (expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")")
    { return expr }
  var result = this.parseSubscripts(expr, startPos, startLoc, false, forInit);
  if (refDestructuringErrors && result.type === "MemberExpression") {
    if (refDestructuringErrors.parenthesizedAssign >= result.start) { refDestructuringErrors.parenthesizedAssign = -1; }
    if (refDestructuringErrors.parenthesizedBind >= result.start) { refDestructuringErrors.parenthesizedBind = -1; }
    if (refDestructuringErrors.trailingComma >= result.start) { refDestructuringErrors.trailingComma = -1; }
  }
  return result
};

pp$5.parseSubscripts = function(base, startPos, startLoc, noCalls, forInit) {
  var maybeAsyncArrow = this.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" &&
      this.lastTokEnd === base.end && !this.canInsertSemicolon() && base.end - base.start === 5 &&
      this.potentialArrowAt === base.start;
  var optionalChained = false;

  while (true) {
    var element = this.parseSubscript(base, startPos, startLoc, noCalls, maybeAsyncArrow, optionalChained, forInit);

    if (element.optional) { optionalChained = true; }
    if (element === base || element.type === "ArrowFunctionExpression") {
      if (optionalChained) {
        var chainNode = this.startNodeAt(startPos, startLoc);
        chainNode.expression = element;
        element = this.finishNode(chainNode, "ChainExpression");
      }
      return element
    }

    base = element;
  }
};

pp$5.shouldParseAsyncArrow = function() {
  return !this.canInsertSemicolon() && this.eat(types$1.arrow)
};

pp$5.parseSubscriptAsyncArrow = function(startPos, startLoc, exprList, forInit) {
  return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList, true, forInit)
};

pp$5.parseSubscript = function(base, startPos, startLoc, noCalls, maybeAsyncArrow, optionalChained, forInit) {
  var optionalSupported = this.options.ecmaVersion >= 11;
  var optional = optionalSupported && this.eat(types$1.questionDot);
  if (noCalls && optional) { this.raise(this.lastTokStart, "Optional chaining cannot appear in the callee of new expressions"); }

  var computed = this.eat(types$1.bracketL);
  if (computed || (optional && this.type !== types$1.parenL && this.type !== types$1.backQuote) || this.eat(types$1.dot)) {
    var node = this.startNodeAt(startPos, startLoc);
    node.object = base;
    if (computed) {
      node.property = this.parseExpression();
      this.expect(types$1.bracketR);
    } else if (this.type === types$1.privateId && base.type !== "Super") {
      node.property = this.parsePrivateIdent();
    } else {
      node.property = this.parseIdent(this.options.allowReserved !== "never");
    }
    node.computed = !!computed;
    if (optionalSupported) {
      node.optional = optional;
    }
    base = this.finishNode(node, "MemberExpression");
  } else if (!noCalls && this.eat(types$1.parenL)) {
    var refDestructuringErrors = new DestructuringErrors$1, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos;
    this.yieldPos = 0;
    this.awaitPos = 0;
    this.awaitIdentPos = 0;
    var exprList = this.parseExprList(types$1.parenR, this.options.ecmaVersion >= 8, false, refDestructuringErrors);
    if (maybeAsyncArrow && !optional && this.shouldParseAsyncArrow()) {
      this.checkPatternErrors(refDestructuringErrors, false);
      this.checkYieldAwaitInDefaultParams();
      if (this.awaitIdentPos > 0)
        { this.raise(this.awaitIdentPos, "Cannot use 'await' as identifier inside an async function"); }
      this.yieldPos = oldYieldPos;
      this.awaitPos = oldAwaitPos;
      this.awaitIdentPos = oldAwaitIdentPos;
      return this.parseSubscriptAsyncArrow(startPos, startLoc, exprList, forInit)
    }
    this.checkExpressionErrors(refDestructuringErrors, true);
    this.yieldPos = oldYieldPos || this.yieldPos;
    this.awaitPos = oldAwaitPos || this.awaitPos;
    this.awaitIdentPos = oldAwaitIdentPos || this.awaitIdentPos;
    var node$1 = this.startNodeAt(startPos, startLoc);
    node$1.callee = base;
    node$1.arguments = exprList;
    if (optionalSupported) {
      node$1.optional = optional;
    }
    base = this.finishNode(node$1, "CallExpression");
  } else if (this.type === types$1.backQuote) {
    if (optional || optionalChained) {
      this.raise(this.start, "Optional chaining cannot appear in the tag of tagged template expressions");
    }
    var node$2 = this.startNodeAt(startPos, startLoc);
    node$2.tag = base;
    node$2.quasi = this.parseTemplate({isTagged: true});
    base = this.finishNode(node$2, "TaggedTemplateExpression");
  }
  return base
};

// Parse an atomic expression — either a single token that is an
// expression, an expression started by a keyword like `function` or
// `new`, or an expression wrapped in punctuation like `()`, `[]`,
// or `{}`.

pp$5.parseExprAtom = function(refDestructuringErrors, forInit, forNew) {
  // If a division operator appears in an expression position, the
  // tokenizer got confused, and we force it to read a regexp instead.
  if (this.type === types$1.slash) { this.readRegexp(); }

  var node, canBeArrow = this.potentialArrowAt === this.start;
  switch (this.type) {
  case types$1._super:
    if (!this.allowSuper)
      { this.raise(this.start, "'super' keyword outside a method"); }
    node = this.startNode();
    this.next();
    if (this.type === types$1.parenL && !this.allowDirectSuper)
      { this.raise(node.start, "super() call outside constructor of a subclass"); }
    // The `super` keyword can appear at below:
    // SuperProperty:
    //     super [ Expression ]
    //     super . IdentifierName
    // SuperCall:
    //     super ( Arguments )
    if (this.type !== types$1.dot && this.type !== types$1.bracketL && this.type !== types$1.parenL)
      { this.unexpected(); }
    return this.finishNode(node, "Super")

  case types$1._this:
    node = this.startNode();
    this.next();
    return this.finishNode(node, "ThisExpression")

  case types$1.name:
    var startPos = this.start, startLoc = this.startLoc, containsEsc = this.containsEsc;
    var id = this.parseIdent(false);
    if (this.options.ecmaVersion >= 8 && !containsEsc && id.name === "async" && !this.canInsertSemicolon() && this.eat(types$1._function)) {
      this.overrideContext(types.f_expr);
      return this.parseFunction(this.startNodeAt(startPos, startLoc), 0, false, true, forInit)
    }
    if (canBeArrow && !this.canInsertSemicolon()) {
      if (this.eat(types$1.arrow))
        { return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], false, forInit) }
      if (this.options.ecmaVersion >= 8 && id.name === "async" && this.type === types$1.name && !containsEsc &&
          (!this.potentialArrowInForAwait || this.value !== "of" || this.containsEsc)) {
        id = this.parseIdent(false);
        if (this.canInsertSemicolon() || !this.eat(types$1.arrow))
          { this.unexpected(); }
        return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], true, forInit)
      }
    }
    return id

  case types$1.regexp:
    var value = this.value;
    node = this.parseLiteral(value.value);
    node.regex = {pattern: value.pattern, flags: value.flags};
    return node

  case types$1.num: case types$1.string:
    return this.parseLiteral(this.value)

  case types$1._null: case types$1._true: case types$1._false:
    node = this.startNode();
    node.value = this.type === types$1._null ? null : this.type === types$1._true;
    node.raw = this.type.keyword;
    this.next();
    return this.finishNode(node, "Literal")

  case types$1.parenL:
    var start = this.start, expr = this.parseParenAndDistinguishExpression(canBeArrow, forInit);
    if (refDestructuringErrors) {
      if (refDestructuringErrors.parenthesizedAssign < 0 && !this.isSimpleAssignTarget(expr))
        { refDestructuringErrors.parenthesizedAssign = start; }
      if (refDestructuringErrors.parenthesizedBind < 0)
        { refDestructuringErrors.parenthesizedBind = start; }
    }
    return expr

  case types$1.bracketL:
    node = this.startNode();
    this.next();
    node.elements = this.parseExprList(types$1.bracketR, true, true, refDestructuringErrors);
    return this.finishNode(node, "ArrayExpression")

  case types$1.braceL:
    this.overrideContext(types.b_expr);
    return this.parseObj(false, refDestructuringErrors)

  case types$1._function:
    node = this.startNode();
    this.next();
    return this.parseFunction(node, 0)

  case types$1._class:
    return this.parseClass(this.startNode(), false)

  case types$1._new:
    return this.parseNew()

  case types$1.backQuote:
    return this.parseTemplate()

  case types$1._import:
    if (this.options.ecmaVersion >= 11) {
      return this.parseExprImport(forNew)
    } else {
      return this.unexpected()
    }

  default:
    return this.parseExprAtomDefault()
  }
};

pp$5.parseExprAtomDefault = function() {
  this.unexpected();
};

pp$5.parseExprImport = function(forNew) {
  var node = this.startNode();

  // Consume `import` as an identifier for `import.meta`.
  // Because `this.parseIdent(true)` doesn't check escape sequences, it needs the check of `this.containsEsc`.
  if (this.containsEsc) { this.raiseRecoverable(this.start, "Escape sequence in keyword import"); }
  this.next();

  if (this.type === types$1.parenL && !forNew) {
    return this.parseDynamicImport(node)
  } else if (this.type === types$1.dot) {
    var meta = this.startNodeAt(node.start, node.loc && node.loc.start);
    meta.name = "import";
    node.meta = this.finishNode(meta, "Identifier");
    return this.parseImportMeta(node)
  } else {
    this.unexpected();
  }
};

pp$5.parseDynamicImport = function(node) {
  this.next(); // skip `(`

  // Parse node.source.
  node.source = this.parseMaybeAssign();

  if (this.options.ecmaVersion >= 16) {
    if (!this.eat(types$1.parenR)) {
      this.expect(types$1.comma);
      if (!this.afterTrailingComma(types$1.parenR)) {
        node.options = this.parseMaybeAssign();
        if (!this.eat(types$1.parenR)) {
          this.expect(types$1.comma);
          if (!this.afterTrailingComma(types$1.parenR)) {
            this.unexpected();
          }
        }
      } else {
        node.options = null;
      }
    } else {
      node.options = null;
    }
  } else {
    // Verify ending.
    if (!this.eat(types$1.parenR)) {
      var errorPos = this.start;
      if (this.eat(types$1.comma) && this.eat(types$1.parenR)) {
        this.raiseRecoverable(errorPos, "Trailing comma is not allowed in import()");
      } else {
        this.unexpected(errorPos);
      }
    }
  }

  return this.finishNode(node, "ImportExpression")
};

pp$5.parseImportMeta = function(node) {
  this.next(); // skip `.`

  var containsEsc = this.containsEsc;
  node.property = this.parseIdent(true);

  if (node.property.name !== "meta")
    { this.raiseRecoverable(node.property.start, "The only valid meta property for import is 'import.meta'"); }
  if (containsEsc)
    { this.raiseRecoverable(node.start, "'import.meta' must not contain escaped characters"); }
  if (this.options.sourceType !== "module" && !this.options.allowImportExportEverywhere)
    { this.raiseRecoverable(node.start, "Cannot use 'import.meta' outside a module"); }

  return this.finishNode(node, "MetaProperty")
};

pp$5.parseLiteral = function(value) {
  var node = this.startNode();
  node.value = value;
  node.raw = this.input.slice(this.start, this.end);
  if (node.raw.charCodeAt(node.raw.length - 1) === 110)
    { node.bigint = node.value != null ? node.value.toString() : node.raw.slice(0, -1).replace(/_/g, ""); }
  this.next();
  return this.finishNode(node, "Literal")
};

pp$5.parseParenExpression = function() {
  this.expect(types$1.parenL);
  var val = this.parseExpression();
  this.expect(types$1.parenR);
  return val
};

pp$5.shouldParseArrow = function(exprList) {
  return !this.canInsertSemicolon()
};

pp$5.parseParenAndDistinguishExpression = function(canBeArrow, forInit) {
  var startPos = this.start, startLoc = this.startLoc, val, allowTrailingComma = this.options.ecmaVersion >= 8;
  if (this.options.ecmaVersion >= 6) {
    this.next();

    var innerStartPos = this.start, innerStartLoc = this.startLoc;
    var exprList = [], first = true, lastIsComma = false;
    var refDestructuringErrors = new DestructuringErrors$1, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, spreadStart;
    this.yieldPos = 0;
    this.awaitPos = 0;
    // Do not save awaitIdentPos to allow checking awaits nested in parameters
    while (this.type !== types$1.parenR) {
      first ? first = false : this.expect(types$1.comma);
      if (allowTrailingComma && this.afterTrailingComma(types$1.parenR, true)) {
        lastIsComma = true;
        break
      } else if (this.type === types$1.ellipsis) {
        spreadStart = this.start;
        exprList.push(this.parseParenItem(this.parseRestBinding()));
        if (this.type === types$1.comma) {
          this.raiseRecoverable(
            this.start,
            "Comma is not permitted after the rest element"
          );
        }
        break
      } else {
        exprList.push(this.parseMaybeAssign(false, refDestructuringErrors, this.parseParenItem));
      }
    }
    var innerEndPos = this.lastTokEnd, innerEndLoc = this.lastTokEndLoc;
    this.expect(types$1.parenR);

    if (canBeArrow && this.shouldParseArrow(exprList) && this.eat(types$1.arrow)) {
      this.checkPatternErrors(refDestructuringErrors, false);
      this.checkYieldAwaitInDefaultParams();
      this.yieldPos = oldYieldPos;
      this.awaitPos = oldAwaitPos;
      return this.parseParenArrowList(startPos, startLoc, exprList, forInit)
    }

    if (!exprList.length || lastIsComma) { this.unexpected(this.lastTokStart); }
    if (spreadStart) { this.unexpected(spreadStart); }
    this.checkExpressionErrors(refDestructuringErrors, true);
    this.yieldPos = oldYieldPos || this.yieldPos;
    this.awaitPos = oldAwaitPos || this.awaitPos;

    if (exprList.length > 1) {
      val = this.startNodeAt(innerStartPos, innerStartLoc);
      val.expressions = exprList;
      this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc);
    } else {
      val = exprList[0];
    }
  } else {
    val = this.parseParenExpression();
  }

  if (this.options.preserveParens) {
    var par = this.startNodeAt(startPos, startLoc);
    par.expression = val;
    return this.finishNode(par, "ParenthesizedExpression")
  } else {
    return val
  }
};

pp$5.parseParenItem = function(item) {
  return item
};

pp$5.parseParenArrowList = function(startPos, startLoc, exprList, forInit) {
  return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList, false, forInit)
};

// New's precedence is slightly tricky. It must allow its argument to
// be a `[]` or dot subscript expression, but not a call — at least,
// not without wrapping it in parentheses. Thus, it uses the noCalls
// argument to parseSubscripts to prevent it from consuming the
// argument list.

var empty$2 = [];

pp$5.parseNew = function() {
  if (this.containsEsc) { this.raiseRecoverable(this.start, "Escape sequence in keyword new"); }
  var node = this.startNode();
  this.next();
  if (this.options.ecmaVersion >= 6 && this.type === types$1.dot) {
    var meta = this.startNodeAt(node.start, node.loc && node.loc.start);
    meta.name = "new";
    node.meta = this.finishNode(meta, "Identifier");
    this.next();
    var containsEsc = this.containsEsc;
    node.property = this.parseIdent(true);
    if (node.property.name !== "target")
      { this.raiseRecoverable(node.property.start, "The only valid meta property for new is 'new.target'"); }
    if (containsEsc)
      { this.raiseRecoverable(node.start, "'new.target' must not contain escaped characters"); }
    if (!this.allowNewDotTarget)
      { this.raiseRecoverable(node.start, "'new.target' can only be used in functions and class static block"); }
    return this.finishNode(node, "MetaProperty")
  }
  var startPos = this.start, startLoc = this.startLoc;
  node.callee = this.parseSubscripts(this.parseExprAtom(null, false, true), startPos, startLoc, true, false);
  if (this.eat(types$1.parenL)) { node.arguments = this.parseExprList(types$1.parenR, this.options.ecmaVersion >= 8, false); }
  else { node.arguments = empty$2; }
  return this.finishNode(node, "NewExpression")
};

// Parse template expression.

pp$5.parseTemplateElement = function(ref) {
  var isTagged = ref.isTagged;

  var elem = this.startNode();
  if (this.type === types$1.invalidTemplate) {
    if (!isTagged) {
      this.raiseRecoverable(this.start, "Bad escape sequence in untagged template literal");
    }
    elem.value = {
      raw: this.value.replace(/\r\n?/g, "\n"),
      cooked: null
    };
  } else {
    elem.value = {
      raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, "\n"),
      cooked: this.value
    };
  }
  this.next();
  elem.tail = this.type === types$1.backQuote;
  return this.finishNode(elem, "TemplateElement")
};

pp$5.parseTemplate = function(ref) {
  if ( ref === void 0 ) ref = {};
  var isTagged = ref.isTagged; if ( isTagged === void 0 ) isTagged = false;

  var node = this.startNode();
  this.next();
  node.expressions = [];
  var curElt = this.parseTemplateElement({isTagged: isTagged});
  node.quasis = [curElt];
  while (!curElt.tail) {
    if (this.type === types$1.eof) { this.raise(this.pos, "Unterminated template literal"); }
    this.expect(types$1.dollarBraceL);
    node.expressions.push(this.parseExpression());
    this.expect(types$1.braceR);
    node.quasis.push(curElt = this.parseTemplateElement({isTagged: isTagged}));
  }
  this.next();
  return this.finishNode(node, "TemplateLiteral")
};

pp$5.isAsyncProp = function(prop) {
  return !prop.computed && prop.key.type === "Identifier" && prop.key.name === "async" &&
    (this.type === types$1.name || this.type === types$1.num || this.type === types$1.string || this.type === types$1.bracketL || this.type.keyword || (this.options.ecmaVersion >= 9 && this.type === types$1.star)) &&
    !lineBreak.test(this.input.slice(this.lastTokEnd, this.start))
};

// Parse an object literal or binding pattern.

pp$5.parseObj = function(isPattern, refDestructuringErrors) {
  var node = this.startNode(), first = true, propHash = {};
  node.properties = [];
  this.next();
  while (!this.eat(types$1.braceR)) {
    if (!first) {
      this.expect(types$1.comma);
      if (this.options.ecmaVersion >= 5 && this.afterTrailingComma(types$1.braceR)) { break }
    } else { first = false; }

    var prop = this.parseProperty(isPattern, refDestructuringErrors);
    if (!isPattern) { this.checkPropClash(prop, propHash, refDestructuringErrors); }
    node.properties.push(prop);
  }
  return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression")
};

pp$5.parseProperty = function(isPattern, refDestructuringErrors) {
  var prop = this.startNode(), isGenerator, isAsync, startPos, startLoc;
  if (this.options.ecmaVersion >= 9 && this.eat(types$1.ellipsis)) {
    if (isPattern) {
      prop.argument = this.parseIdent(false);
      if (this.type === types$1.comma) {
        this.raiseRecoverable(this.start, "Comma is not permitted after the rest element");
      }
      return this.finishNode(prop, "RestElement")
    }
    // Parse argument.
    prop.argument = this.parseMaybeAssign(false, refDestructuringErrors);
    // To disallow trailing comma via `this.toAssignable()`.
    if (this.type === types$1.comma && refDestructuringErrors && refDestructuringErrors.trailingComma < 0) {
      refDestructuringErrors.trailingComma = this.start;
    }
    // Finish
    return this.finishNode(prop, "SpreadElement")
  }
  if (this.options.ecmaVersion >= 6) {
    prop.method = false;
    prop.shorthand = false;
    if (isPattern || refDestructuringErrors) {
      startPos = this.start;
      startLoc = this.startLoc;
    }
    if (!isPattern)
      { isGenerator = this.eat(types$1.star); }
  }
  var containsEsc = this.containsEsc;
  this.parsePropertyName(prop);
  if (!isPattern && !containsEsc && this.options.ecmaVersion >= 8 && !isGenerator && this.isAsyncProp(prop)) {
    isAsync = true;
    isGenerator = this.options.ecmaVersion >= 9 && this.eat(types$1.star);
    this.parsePropertyName(prop);
  } else {
    isAsync = false;
  }
  this.parsePropertyValue(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc);
  return this.finishNode(prop, "Property")
};

pp$5.parseGetterSetter = function(prop) {
  var kind = prop.key.name;
  this.parsePropertyName(prop);
  prop.value = this.parseMethod(false);
  prop.kind = kind;
  var paramCount = prop.kind === "get" ? 0 : 1;
  if (prop.value.params.length !== paramCount) {
    var start = prop.value.start;
    if (prop.kind === "get")
      { this.raiseRecoverable(start, "getter should have no params"); }
    else
      { this.raiseRecoverable(start, "setter should have exactly one param"); }
  } else {
    if (prop.kind === "set" && prop.value.params[0].type === "RestElement")
      { this.raiseRecoverable(prop.value.params[0].start, "Setter cannot use rest params"); }
  }
};

pp$5.parsePropertyValue = function(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc) {
  if ((isGenerator || isAsync) && this.type === types$1.colon)
    { this.unexpected(); }

  if (this.eat(types$1.colon)) {
    prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refDestructuringErrors);
    prop.kind = "init";
  } else if (this.options.ecmaVersion >= 6 && this.type === types$1.parenL) {
    if (isPattern) { this.unexpected(); }
    prop.method = true;
    prop.value = this.parseMethod(isGenerator, isAsync);
    prop.kind = "init";
  } else if (!isPattern && !containsEsc &&
             this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" &&
             (prop.key.name === "get" || prop.key.name === "set") &&
             (this.type !== types$1.comma && this.type !== types$1.braceR && this.type !== types$1.eq)) {
    if (isGenerator || isAsync) { this.unexpected(); }
    this.parseGetterSetter(prop);
  } else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") {
    if (isGenerator || isAsync) { this.unexpected(); }
    this.checkUnreserved(prop.key);
    if (prop.key.name === "await" && !this.awaitIdentPos)
      { this.awaitIdentPos = startPos; }
    if (isPattern) {
      prop.value = this.parseMaybeDefault(startPos, startLoc, this.copyNode(prop.key));
    } else if (this.type === types$1.eq && refDestructuringErrors) {
      if (refDestructuringErrors.shorthandAssign < 0)
        { refDestructuringErrors.shorthandAssign = this.start; }
      prop.value = this.parseMaybeDefault(startPos, startLoc, this.copyNode(prop.key));
    } else {
      prop.value = this.copyNode(prop.key);
    }
    prop.kind = "init";
    prop.shorthand = true;
  } else { this.unexpected(); }
};

pp$5.parsePropertyName = function(prop) {
  if (this.options.ecmaVersion >= 6) {
    if (this.eat(types$1.bracketL)) {
      prop.computed = true;
      prop.key = this.parseMaybeAssign();
      this.expect(types$1.bracketR);
      return prop.key
    } else {
      prop.computed = false;
    }
  }
  return prop.key = this.type === types$1.num || this.type === types$1.string ? this.parseExprAtom() : this.parseIdent(this.options.allowReserved !== "never")
};

// Initialize empty function node.

pp$5.initFunction = function(node) {
  node.id = null;
  if (this.options.ecmaVersion >= 6) { node.generator = node.expression = false; }
  if (this.options.ecmaVersion >= 8) { node.async = false; }
};

// Parse object or class method.

pp$5.parseMethod = function(isGenerator, isAsync, allowDirectSuper) {
  var node = this.startNode(), oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos;

  this.initFunction(node);
  if (this.options.ecmaVersion >= 6)
    { node.generator = isGenerator; }
  if (this.options.ecmaVersion >= 8)
    { node.async = !!isAsync; }

  this.yieldPos = 0;
  this.awaitPos = 0;
  this.awaitIdentPos = 0;
  this.enterScope(functionFlags$1(isAsync, node.generator) | SCOPE_SUPER | (allowDirectSuper ? SCOPE_DIRECT_SUPER : 0));

  this.expect(types$1.parenL);
  node.params = this.parseBindingList(types$1.parenR, false, this.options.ecmaVersion >= 8);
  this.checkYieldAwaitInDefaultParams();
  this.parseFunctionBody(node, false, true, false);

  this.yieldPos = oldYieldPos;
  this.awaitPos = oldAwaitPos;
  this.awaitIdentPos = oldAwaitIdentPos;
  return this.finishNode(node, "FunctionExpression")
};

// Parse arrow function expression with given parameters.

pp$5.parseArrowExpression = function(node, params, isAsync, forInit) {
  var oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos;

  this.enterScope(functionFlags$1(isAsync, false) | SCOPE_ARROW);
  this.initFunction(node);
  if (this.options.ecmaVersion >= 8) { node.async = !!isAsync; }

  this.yieldPos = 0;
  this.awaitPos = 0;
  this.awaitIdentPos = 0;

  node.params = this.toAssignableList(params, true);
  this.parseFunctionBody(node, true, false, forInit);

  this.yieldPos = oldYieldPos;
  this.awaitPos = oldAwaitPos;
  this.awaitIdentPos = oldAwaitIdentPos;
  return this.finishNode(node, "ArrowFunctionExpression")
};

// Parse function body and check parameters.

pp$5.parseFunctionBody = function(node, isArrowFunction, isMethod, forInit) {
  var isExpression = isArrowFunction && this.type !== types$1.braceL;
  var oldStrict = this.strict, useStrict = false;

  if (isExpression) {
    node.body = this.parseMaybeAssign(forInit);
    node.expression = true;
    this.checkParams(node, false);
  } else {
    var nonSimple = this.options.ecmaVersion >= 7 && !this.isSimpleParamList(node.params);
    if (!oldStrict || nonSimple) {
      useStrict = this.strictDirective(this.end);
      // If this is a strict mode function, verify that argument names
      // are not repeated, and it does not try to bind the words `eval`
      // or `arguments`.
      if (useStrict && nonSimple)
        { this.raiseRecoverable(node.start, "Illegal 'use strict' directive in function with non-simple parameter list"); }
    }
    // Start a new scope with regard to labels and the `inFunction`
    // flag (restore them to their old value afterwards).
    var oldLabels = this.labels;
    this.labels = [];
    if (useStrict) { this.strict = true; }

    // Add the params to varDeclaredNames to ensure that an error is thrown
    // if a let/const declaration in the function clashes with one of the params.
    this.checkParams(node, !oldStrict && !useStrict && !isArrowFunction && !isMethod && this.isSimpleParamList(node.params));
    // Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval'
    if (this.strict && node.id) { this.checkLValSimple(node.id, BIND_OUTSIDE); }
    node.body = this.parseBlock(false, undefined, useStrict && !oldStrict);
    node.expression = false;
    this.adaptDirectivePrologue(node.body.body);
    this.labels = oldLabels;
  }
  this.exitScope();
};

pp$5.isSimpleParamList = function(params) {
  for (var i = 0, list = params; i < list.length; i += 1)
    {
    var param = list[i];

    if (param.type !== "Identifier") { return false
  } }
  return true
};

// Checks function params for various disallowed patterns such as using "eval"
// or "arguments" and duplicate parameters.

pp$5.checkParams = function(node, allowDuplicates) {
  var nameHash = Object.create(null);
  for (var i = 0, list = node.params; i < list.length; i += 1)
    {
    var param = list[i];

    this.checkLValInnerPattern(param, BIND_VAR, allowDuplicates ? null : nameHash);
  }
};

// Parses a comma-separated list of expressions, and returns them as
// an array. `close` is the token type that ends the list, and
// `allowEmpty` can be turned on to allow subsequent commas with
// nothing in between them to be parsed as `null` (which is needed
// for array literals).

pp$5.parseExprList = function(close, allowTrailingComma, allowEmpty, refDestructuringErrors) {
  var elts = [], first = true;
  while (!this.eat(close)) {
    if (!first) {
      this.expect(types$1.comma);
      if (allowTrailingComma && this.afterTrailingComma(close)) { break }
    } else { first = false; }

    var elt = (void 0);
    if (allowEmpty && this.type === types$1.comma)
      { elt = null; }
    else if (this.type === types$1.ellipsis) {
      elt = this.parseSpread(refDestructuringErrors);
      if (refDestructuringErrors && this.type === types$1.comma && refDestructuringErrors.trailingComma < 0)
        { refDestructuringErrors.trailingComma = this.start; }
    } else {
      elt = this.parseMaybeAssign(false, refDestructuringErrors);
    }
    elts.push(elt);
  }
  return elts
};

pp$5.checkUnreserved = function(ref) {
  var start = ref.start;
  var end = ref.end;
  var name = ref.name;

  if (this.inGenerator && name === "yield")
    { this.raiseRecoverable(start, "Cannot use 'yield' as identifier inside a generator"); }
  if (this.inAsync && name === "await")
    { this.raiseRecoverable(start, "Cannot use 'await' as identifier inside an async function"); }
  if (!(this.currentThisScope().flags & SCOPE_VAR) && name === "arguments")
    { this.raiseRecoverable(start, "Cannot use 'arguments' in class field initializer"); }
  if (this.inClassStaticBlock && (name === "arguments" || name === "await"))
    { this.raise(start, ("Cannot use " + name + " in class static initialization block")); }
  if (this.keywords.test(name))
    { this.raise(start, ("Unexpected keyword '" + name + "'")); }
  if (this.options.ecmaVersion < 6 &&
    this.input.slice(start, end).indexOf("\\") !== -1) { return }
  var re = this.strict ? this.reservedWordsStrict : this.reservedWords;
  if (re.test(name)) {
    if (!this.inAsync && name === "await")
      { this.raiseRecoverable(start, "Cannot use keyword 'await' outside an async function"); }
    this.raiseRecoverable(start, ("The keyword '" + name + "' is reserved"));
  }
};

// Parse the next token as an identifier. If `liberal` is true (used
// when parsing properties), it will also convert keywords into
// identifiers.

pp$5.parseIdent = function(liberal) {
  var node = this.parseIdentNode();
  this.next(!!liberal);
  this.finishNode(node, "Identifier");
  if (!liberal) {
    this.checkUnreserved(node);
    if (node.name === "await" && !this.awaitIdentPos)
      { this.awaitIdentPos = node.start; }
  }
  return node
};

pp$5.parseIdentNode = function() {
  var node = this.startNode();
  if (this.type === types$1.name) {
    node.name = this.value;
  } else if (this.type.keyword) {
    node.name = this.type.keyword;

    // To fix https://github.com/acornjs/acorn/issues/575
    // `class` and `function` keywords push new context into this.context.
    // But there is no chance to pop the context if the keyword is consumed as an identifier such as a property name.
    // If the previous token is a dot, this does not apply because the context-managing code already ignored the keyword
    if ((node.name === "class" || node.name === "function") &&
      (this.lastTokEnd !== this.lastTokStart + 1 || this.input.charCodeAt(this.lastTokStart) !== 46)) {
      this.context.pop();
    }
    this.type = types$1.name;
  } else {
    this.unexpected();
  }
  return node
};

pp$5.parsePrivateIdent = function() {
  var node = this.startNode();
  if (this.type === types$1.privateId) {
    node.name = this.value;
  } else {
    this.unexpected();
  }
  this.next();
  this.finishNode(node, "PrivateIdentifier");

  // For validating existence
  if (this.options.checkPrivateFields) {
    if (this.privateNameStack.length === 0) {
      this.raise(node.start, ("Private field '#" + (node.name) + "' must be declared in an enclosing class"));
    } else {
      this.privateNameStack[this.privateNameStack.length - 1].used.push(node);
    }
  }

  return node
};

// Parses yield expression inside generator.

pp$5.parseYield = function(forInit) {
  if (!this.yieldPos) { this.yieldPos = this.start; }

  var node = this.startNode();
  this.next();
  if (this.type === types$1.semi || this.canInsertSemicolon() || (this.type !== types$1.star && !this.type.startsExpr)) {
    node.delegate = false;
    node.argument = null;
  } else {
    node.delegate = this.eat(types$1.star);
    node.argument = this.parseMaybeAssign(forInit);
  }
  return this.finishNode(node, "YieldExpression")
};

pp$5.parseAwait = function(forInit) {
  if (!this.awaitPos) { this.awaitPos = this.start; }

  var node = this.startNode();
  this.next();
  node.argument = this.parseMaybeUnary(null, true, false, forInit);
  return this.finishNode(node, "AwaitExpression")
};

var pp$4 = Parser$1.prototype;

// This function is used to raise exceptions on parse errors. It
// takes an offset integer (into the current `input`) to indicate
// the location of the error, attaches the position to the end
// of the error message, and then raises a `SyntaxError` with that
// message.

pp$4.raise = function(pos, message) {
  var loc = getLineInfo(this.input, pos);
  message += " (" + loc.line + ":" + loc.column + ")";
  if (this.sourceFile) {
    message += " in " + this.sourceFile;
  }
  var err = new SyntaxError(message);
  err.pos = pos; err.loc = loc; err.raisedAt = this.pos;
  throw err
};

pp$4.raiseRecoverable = pp$4.raise;

pp$4.curPosition = function() {
  if (this.options.locations) {
    return new Position(this.curLine, this.pos - this.lineStart)
  }
};

var pp$3 = Parser$1.prototype;

var Scope$1 = function Scope(flags) {
  this.flags = flags;
  // A list of var-declared names in the current lexical scope
  this.var = [];
  // A list of lexically-declared names in the current lexical scope
  this.lexical = [];
  // A list of lexically-declared FunctionDeclaration names in the current lexical scope
  this.functions = [];
};

// The functions in this module keep track of declared variables in the current scope in order to detect duplicate variable names.

pp$3.enterScope = function(flags) {
  this.scopeStack.push(new Scope$1(flags));
};

pp$3.exitScope = function() {
  this.scopeStack.pop();
};

// The spec says:
// > At the top level of a function, or script, function declarations are
// > treated like var declarations rather than like lexical declarations.
pp$3.treatFunctionsAsVarInScope = function(scope) {
  return (scope.flags & SCOPE_FUNCTION) || !this.inModule && (scope.flags & SCOPE_TOP)
};

pp$3.declareName = function(name, bindingType, pos) {
  var redeclared = false;
  if (bindingType === BIND_LEXICAL) {
    var scope = this.currentScope();
    redeclared = scope.lexical.indexOf(name) > -1 || scope.functions.indexOf(name) > -1 || scope.var.indexOf(name) > -1;
    scope.lexical.push(name);
    if (this.inModule && (scope.flags & SCOPE_TOP))
      { delete this.undefinedExports[name]; }
  } else if (bindingType === BIND_SIMPLE_CATCH) {
    var scope$1 = this.currentScope();
    scope$1.lexical.push(name);
  } else if (bindingType === BIND_FUNCTION) {
    var scope$2 = this.currentScope();
    if (this.treatFunctionsAsVar)
      { redeclared = scope$2.lexical.indexOf(name) > -1; }
    else
      { redeclared = scope$2.lexical.indexOf(name) > -1 || scope$2.var.indexOf(name) > -1; }
    scope$2.functions.push(name);
  } else {
    for (var i = this.scopeStack.length - 1; i >= 0; --i) {
      var scope$3 = this.scopeStack[i];
      if (scope$3.lexical.indexOf(name) > -1 && !((scope$3.flags & SCOPE_SIMPLE_CATCH) && scope$3.lexical[0] === name) ||
          !this.treatFunctionsAsVarInScope(scope$3) && scope$3.functions.indexOf(name) > -1) {
        redeclared = true;
        break
      }
      scope$3.var.push(name);
      if (this.inModule && (scope$3.flags & SCOPE_TOP))
        { delete this.undefinedExports[name]; }
      if (scope$3.flags & SCOPE_VAR) { break }
    }
  }
  if (redeclared) { this.raiseRecoverable(pos, ("Identifier '" + name + "' has already been declared")); }
};

pp$3.checkLocalExport = function(id) {
  // scope.functions must be empty as Module code is always strict.
  if (this.scopeStack[0].lexical.indexOf(id.name) === -1 &&
      this.scopeStack[0].var.indexOf(id.name) === -1) {
    this.undefinedExports[id.name] = id;
  }
};

pp$3.currentScope = function() {
  return this.scopeStack[this.scopeStack.length - 1]
};

pp$3.currentVarScope = function() {
  for (var i = this.scopeStack.length - 1;; i--) {
    var scope = this.scopeStack[i];
    if (scope.flags & (SCOPE_VAR | SCOPE_CLASS_FIELD_INIT | SCOPE_CLASS_STATIC_BLOCK)) { return scope }
  }
};

// Could be useful for `this`, `new.target`, `super()`, `super.property`, and `super[property]`.
pp$3.currentThisScope = function() {
  for (var i = this.scopeStack.length - 1;; i--) {
    var scope = this.scopeStack[i];
    if (scope.flags & (SCOPE_VAR | SCOPE_CLASS_FIELD_INIT | SCOPE_CLASS_STATIC_BLOCK) &&
        !(scope.flags & SCOPE_ARROW)) { return scope }
  }
};

var Node = function Node(parser, pos, loc) {
  this.type = "";
  this.start = pos;
  this.end = 0;
  if (parser.options.locations)
    { this.loc = new SourceLocation(parser, loc); }
  if (parser.options.directSourceFile)
    { this.sourceFile = parser.options.directSourceFile; }
  if (parser.options.ranges)
    { this.range = [pos, 0]; }
};

// Start an AST node, attaching a start offset.

var pp$2 = Parser$1.prototype;

pp$2.startNode = function() {
  return new Node(this, this.start, this.startLoc)
};

pp$2.startNodeAt = function(pos, loc) {
  return new Node(this, pos, loc)
};

// Finish an AST node, adding `type` and `end` properties.

function finishNodeAt(node, type, pos, loc) {
  node.type = type;
  node.end = pos;
  if (this.options.locations)
    { node.loc.end = loc; }
  if (this.options.ranges)
    { node.range[1] = pos; }
  return node
}

pp$2.finishNode = function(node, type) {
  return finishNodeAt.call(this, node, type, this.lastTokEnd, this.lastTokEndLoc)
};

// Finish node at given position

pp$2.finishNodeAt = function(node, type, pos, loc) {
  return finishNodeAt.call(this, node, type, pos, loc)
};

pp$2.copyNode = function(node) {
  var newNode = new Node(this, node.start, this.startLoc);
  for (var prop in node) { newNode[prop] = node[prop]; }
  return newNode
};

// This file was generated by "bin/generate-unicode-script-values.js". Do not modify manually!
var scriptValuesAddedInUnicode = "Gara Garay Gukh Gurung_Khema Hrkt Katakana_Or_Hiragana Kawi Kirat_Rai Krai Nag_Mundari Nagm Ol_Onal Onao Sunu Sunuwar Todhri Todr Tulu_Tigalari Tutg Unknown Zzzz";

// This file contains Unicode properties extracted from the ECMAScript specification.
// The lists are extracted like so:
// $$('#table-binary-unicode-properties > figure > table > tbody > tr > td:nth-child(1) code').map(el => el.innerText)

// #table-binary-unicode-properties
var ecma9BinaryProperties = "ASCII ASCII_Hex_Digit AHex Alphabetic Alpha Any Assigned Bidi_Control Bidi_C Bidi_Mirrored Bidi_M Case_Ignorable CI Cased Changes_When_Casefolded CWCF Changes_When_Casemapped CWCM Changes_When_Lowercased CWL Changes_When_NFKC_Casefolded CWKCF Changes_When_Titlecased CWT Changes_When_Uppercased CWU Dash Default_Ignorable_Code_Point DI Deprecated Dep Diacritic Dia Emoji Emoji_Component Emoji_Modifier Emoji_Modifier_Base Emoji_Presentation Extender Ext Grapheme_Base Gr_Base Grapheme_Extend Gr_Ext Hex_Digit Hex IDS_Binary_Operator IDSB IDS_Trinary_Operator IDST ID_Continue IDC ID_Start IDS Ideographic Ideo Join_Control Join_C Logical_Order_Exception LOE Lowercase Lower Math Noncharacter_Code_Point NChar Pattern_Syntax Pat_Syn Pattern_White_Space Pat_WS Quotation_Mark QMark Radical Regional_Indicator RI Sentence_Terminal STerm Soft_Dotted SD Terminal_Punctuation Term Unified_Ideograph UIdeo Uppercase Upper Variation_Selector VS White_Space space XID_Continue XIDC XID_Start XIDS";
var ecma10BinaryProperties = ecma9BinaryProperties + " Extended_Pictographic";
var ecma11BinaryProperties = ecma10BinaryProperties;
var ecma12BinaryProperties = ecma11BinaryProperties + " EBase EComp EMod EPres ExtPict";
var ecma13BinaryProperties = ecma12BinaryProperties;
var ecma14BinaryProperties = ecma13BinaryProperties;

var unicodeBinaryProperties = {
  9: ecma9BinaryProperties,
  10: ecma10BinaryProperties,
  11: ecma11BinaryProperties,
  12: ecma12BinaryProperties,
  13: ecma13BinaryProperties,
  14: ecma14BinaryProperties
};

// #table-binary-unicode-properties-of-strings
var ecma14BinaryPropertiesOfStrings = "Basic_Emoji Emoji_Keycap_Sequence RGI_Emoji_Modifier_Sequence RGI_Emoji_Flag_Sequence RGI_Emoji_Tag_Sequence RGI_Emoji_ZWJ_Sequence RGI_Emoji";

var unicodeBinaryPropertiesOfStrings = {
  9: "",
  10: "",
  11: "",
  12: "",
  13: "",
  14: ecma14BinaryPropertiesOfStrings
};

// #table-unicode-general-category-values
var unicodeGeneralCategoryValues = "Cased_Letter LC Close_Punctuation Pe Connector_Punctuation Pc Control Cc cntrl Currency_Symbol Sc Dash_Punctuation Pd Decimal_Number Nd digit Enclosing_Mark Me Final_Punctuation Pf Format Cf Initial_Punctuation Pi Letter L Letter_Number Nl Line_Separator Zl Lowercase_Letter Ll Mark M Combining_Mark Math_Symbol Sm Modifier_Letter Lm Modifier_Symbol Sk Nonspacing_Mark Mn Number N Open_Punctuation Ps Other C Other_Letter Lo Other_Number No Other_Punctuation Po Other_Symbol So Paragraph_Separator Zp Private_Use Co Punctuation P punct Separator Z Space_Separator Zs Spacing_Mark Mc Surrogate Cs Symbol S Titlecase_Letter Lt Unassigned Cn Uppercase_Letter Lu";

// #table-unicode-script-values
var ecma9ScriptValues = "Adlam Adlm Ahom Anatolian_Hieroglyphs Hluw Arabic Arab Armenian Armn Avestan Avst Balinese Bali Bamum Bamu Bassa_Vah Bass Batak Batk Bengali Beng Bhaiksuki Bhks Bopomofo Bopo Brahmi Brah Braille Brai Buginese Bugi Buhid Buhd Canadian_Aboriginal Cans Carian Cari Caucasian_Albanian Aghb Chakma Cakm Cham Cham Cherokee Cher Common Zyyy Coptic Copt Qaac Cuneiform Xsux Cypriot Cprt Cyrillic Cyrl Deseret Dsrt Devanagari Deva Duployan Dupl Egyptian_Hieroglyphs Egyp Elbasan Elba Ethiopic Ethi Georgian Geor Glagolitic Glag Gothic Goth Grantha Gran Greek Grek Gujarati Gujr Gurmukhi Guru Han Hani Hangul Hang Hanunoo Hano Hatran Hatr Hebrew Hebr Hiragana Hira Imperial_Aramaic Armi Inherited Zinh Qaai Inscriptional_Pahlavi Phli Inscriptional_Parthian Prti Javanese Java Kaithi Kthi Kannada Knda Katakana Kana Kayah_Li Kali Kharoshthi Khar Khmer Khmr Khojki Khoj Khudawadi Sind Lao Laoo Latin Latn Lepcha Lepc Limbu Limb Linear_A Lina Linear_B Linb Lisu Lisu Lycian Lyci Lydian Lydi Mahajani Mahj Malayalam Mlym Mandaic Mand Manichaean Mani Marchen Marc Masaram_Gondi Gonm Meetei_Mayek Mtei Mende_Kikakui Mend Meroitic_Cursive Merc Meroitic_Hieroglyphs Mero Miao Plrd Modi Mongolian Mong Mro Mroo Multani Mult Myanmar Mymr Nabataean Nbat New_Tai_Lue Talu Newa Newa Nko Nkoo Nushu Nshu Ogham Ogam Ol_Chiki Olck Old_Hungarian Hung Old_Italic Ital Old_North_Arabian Narb Old_Permic Perm Old_Persian Xpeo Old_South_Arabian Sarb Old_Turkic Orkh Oriya Orya Osage Osge Osmanya Osma Pahawh_Hmong Hmng Palmyrene Palm Pau_Cin_Hau Pauc Phags_Pa Phag Phoenician Phnx Psalter_Pahlavi Phlp Rejang Rjng Runic Runr Samaritan Samr Saurashtra Saur Sharada Shrd Shavian Shaw Siddham Sidd SignWriting Sgnw Sinhala Sinh Sora_Sompeng Sora Soyombo Soyo Sundanese Sund Syloti_Nagri Sylo Syriac Syrc Tagalog Tglg Tagbanwa Tagb Tai_Le Tale Tai_Tham Lana Tai_Viet Tavt Takri Takr Tamil Taml Tangut Tang Telugu Telu Thaana Thaa Thai Thai Tibetan Tibt Tifinagh Tfng Tirhuta Tirh Ugaritic Ugar Vai Vaii Warang_Citi Wara Yi Yiii Zanabazar_Square Zanb";
var ecma10ScriptValues = ecma9ScriptValues + " Dogra Dogr Gunjala_Gondi Gong Hanifi_Rohingya Rohg Makasar Maka Medefaidrin Medf Old_Sogdian Sogo Sogdian Sogd";
var ecma11ScriptValues = ecma10ScriptValues + " Elymaic Elym Nandinagari Nand Nyiakeng_Puachue_Hmong Hmnp Wancho Wcho";
var ecma12ScriptValues = ecma11ScriptValues + " Chorasmian Chrs Diak Dives_Akuru Khitan_Small_Script Kits Yezi Yezidi";
var ecma13ScriptValues = ecma12ScriptValues + " Cypro_Minoan Cpmn Old_Uyghur Ougr Tangsa Tnsa Toto Vithkuqi Vith";
var ecma14ScriptValues = ecma13ScriptValues + " " + scriptValuesAddedInUnicode;

var unicodeScriptValues = {
  9: ecma9ScriptValues,
  10: ecma10ScriptValues,
  11: ecma11ScriptValues,
  12: ecma12ScriptValues,
  13: ecma13ScriptValues,
  14: ecma14ScriptValues
};

var data = {};
function buildUnicodeData(ecmaVersion) {
  var d = data[ecmaVersion] = {
    binary: wordsRegexp(unicodeBinaryProperties[ecmaVersion] + " " + unicodeGeneralCategoryValues),
    binaryOfStrings: wordsRegexp(unicodeBinaryPropertiesOfStrings[ecmaVersion]),
    nonBinary: {
      General_Category: wordsRegexp(unicodeGeneralCategoryValues),
      Script: wordsRegexp(unicodeScriptValues[ecmaVersion])
    }
  };
  d.nonBinary.Script_Extensions = d.nonBinary.Script;

  d.nonBinary.gc = d.nonBinary.General_Category;
  d.nonBinary.sc = d.nonBinary.Script;
  d.nonBinary.scx = d.nonBinary.Script_Extensions;
}

for (var i = 0, list$2 = [9, 10, 11, 12, 13, 14]; i < list$2.length; i += 1) {
  var ecmaVersion = list$2[i];

  buildUnicodeData(ecmaVersion);
}

var pp$1 = Parser$1.prototype;

// Track disjunction structure to determine whether a duplicate
// capture group name is allowed because it is in a separate branch.
var BranchID = function BranchID(parent, base) {
  // Parent disjunction branch
  this.parent = parent;
  // Identifies this set of sibling branches
  this.base = base || this;
};

BranchID.prototype.separatedFrom = function separatedFrom (alt) {
  // A branch is separate from another branch if they or any of
  // their parents are siblings in a given disjunction
  for (var self = this; self; self = self.parent) {
    for (var other = alt; other; other = other.parent) {
      if (self.base === other.base && self !== other) { return true }
    }
  }
  return false
};

BranchID.prototype.sibling = function sibling () {
  return new BranchID(this.parent, this.base)
};

var RegExpValidationState = function RegExpValidationState(parser) {
  this.parser = parser;
  this.validFlags = "gim" + (parser.options.ecmaVersion >= 6 ? "uy" : "") + (parser.options.ecmaVersion >= 9 ? "s" : "") + (parser.options.ecmaVersion >= 13 ? "d" : "") + (parser.options.ecmaVersion >= 15 ? "v" : "");
  this.unicodeProperties = data[parser.options.ecmaVersion >= 14 ? 14 : parser.options.ecmaVersion];
  this.source = "";
  this.flags = "";
  this.start = 0;
  this.switchU = false;
  this.switchV = false;
  this.switchN = false;
  this.pos = 0;
  this.lastIntValue = 0;
  this.lastStringValue = "";
  this.lastAssertionIsQuantifiable = false;
  this.numCapturingParens = 0;
  this.maxBackReference = 0;
  this.groupNames = Object.create(null);
  this.backReferenceNames = [];
  this.branchID = null;
};

RegExpValidationState.prototype.reset = function reset (start, pattern, flags) {
  var unicodeSets = flags.indexOf("v") !== -1;
  var unicode = flags.indexOf("u") !== -1;
  this.start = start | 0;
  this.source = pattern + "";
  this.flags = flags;
  if (unicodeSets && this.parser.options.ecmaVersion >= 15) {
    this.switchU = true;
    this.switchV = true;
    this.switchN = true;
  } else {
    this.switchU = unicode && this.parser.options.ecmaVersion >= 6;
    this.switchV = false;
    this.switchN = unicode && this.parser.options.ecmaVersion >= 9;
  }
};

RegExpValidationState.prototype.raise = function raise (message) {
  this.parser.raiseRecoverable(this.start, ("Invalid regular expression: /" + (this.source) + "/: " + message));
};

// If u flag is given, this returns the code point at the index (it combines a surrogate pair).
// Otherwise, this returns the code unit of the index (can be a part of a surrogate pair).
RegExpValidationState.prototype.at = function at (i, forceU) {
    if ( forceU === void 0 ) forceU = false;

  var s = this.source;
  var l = s.length;
  if (i >= l) {
    return -1
  }
  var c = s.charCodeAt(i);
  if (!(forceU || this.switchU) || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) {
    return c
  }
  var next = s.charCodeAt(i + 1);
  return next >= 0xDC00 && next <= 0xDFFF ? (c << 10) + next - 0x35FDC00 : c
};

RegExpValidationState.prototype.nextIndex = function nextIndex (i, forceU) {
    if ( forceU === void 0 ) forceU = false;

  var s = this.source;
  var l = s.length;
  if (i >= l) {
    return l
  }
  var c = s.charCodeAt(i), next;
  if (!(forceU || this.switchU) || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l ||
      (next = s.charCodeAt(i + 1)) < 0xDC00 || next > 0xDFFF) {
    return i + 1
  }
  return i + 2
};

RegExpValidationState.prototype.current = function current (forceU) {
    if ( forceU === void 0 ) forceU = false;

  return this.at(this.pos, forceU)
};

RegExpValidationState.prototype.lookahead = function lookahead (forceU) {
    if ( forceU === void 0 ) forceU = false;

  return this.at(this.nextIndex(this.pos, forceU), forceU)
};

RegExpValidationState.prototype.advance = function advance (forceU) {
    if ( forceU === void 0 ) forceU = false;

  this.pos = this.nextIndex(this.pos, forceU);
};

RegExpValidationState.prototype.eat = function eat (ch, forceU) {
    if ( forceU === void 0 ) forceU = false;

  if (this.current(forceU) === ch) {
    this.advance(forceU);
    return true
  }
  return false
};

RegExpValidationState.prototype.eatChars = function eatChars (chs, forceU) {
    if ( forceU === void 0 ) forceU = false;

  var pos = this.pos;
  for (var i = 0, list = chs; i < list.length; i += 1) {
    var ch = list[i];

      var current = this.at(pos, forceU);
    if (current === -1 || current !== ch) {
      return false
    }
    pos = this.nextIndex(pos, forceU);
  }
  this.pos = pos;
  return true
};

/**
 * Validate the flags part of a given RegExpLiteral.
 *
 * @param {RegExpValidationState} state The state to validate RegExp.
 * @returns {void}
 */
pp$1.validateRegExpFlags = function(state) {
  var validFlags = state.validFlags;
  var flags = state.flags;

  var u = false;
  var v = false;

  for (var i = 0; i < flags.length; i++) {
    var flag = flags.charAt(i);
    if (validFlags.indexOf(flag) === -1) {
      this.raise(state.start, "Invalid regular expression flag");
    }
    if (flags.indexOf(flag, i + 1) > -1) {
      this.raise(state.start, "Duplicate regular expression flag");
    }
    if (flag === "u") { u = true; }
    if (flag === "v") { v = true; }
  }
  if (this.options.ecmaVersion >= 15 && u && v) {
    this.raise(state.start, "Invalid regular expression flag");
  }
};

function hasProp(obj) {
  for (var _ in obj) { return true }
  return false
}

/**
 * Validate the pattern part of a given RegExpLiteral.
 *
 * @param {RegExpValidationState} state The state to validate RegExp.
 * @returns {void}
 */
pp$1.validateRegExpPattern = function(state) {
  this.regexp_pattern(state);

  // The goal symbol for the parse is |Pattern[~U, ~N]|. If the result of
  // parsing contains a |GroupName|, reparse with the goal symbol
  // |Pattern[~U, +N]| and use this result instead. Throw a *SyntaxError*
  // exception if _P_ did not conform to the grammar, if any elements of _P_
  // were not matched by the parse, or if any Early Error conditions exist.
  if (!state.switchN && this.options.ecmaVersion >= 9 && hasProp(state.groupNames)) {
    state.switchN = true;
    this.regexp_pattern(state);
  }
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-Pattern
pp$1.regexp_pattern = function(state) {
  state.pos = 0;
  state.lastIntValue = 0;
  state.lastStringValue = "";
  state.lastAssertionIsQuantifiable = false;
  state.numCapturingParens = 0;
  state.maxBackReference = 0;
  state.groupNames = Object.create(null);
  state.backReferenceNames.length = 0;
  state.branchID = null;

  this.regexp_disjunction(state);

  if (state.pos !== state.source.length) {
    // Make the same messages as V8.
    if (state.eat(0x29 /* ) */)) {
      state.raise("Unmatched ')'");
    }
    if (state.eat(0x5D /* ] */) || state.eat(0x7D /* } */)) {
      state.raise("Lone quantifier brackets");
    }
  }
  if (state.maxBackReference > state.numCapturingParens) {
    state.raise("Invalid escape");
  }
  for (var i = 0, list = state.backReferenceNames; i < list.length; i += 1) {
    var name = list[i];

    if (!state.groupNames[name]) {
      state.raise("Invalid named capture referenced");
    }
  }
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-Disjunction
pp$1.regexp_disjunction = function(state) {
  var trackDisjunction = this.options.ecmaVersion >= 16;
  if (trackDisjunction) { state.branchID = new BranchID(state.branchID, null); }
  this.regexp_alternative(state);
  while (state.eat(0x7C /* | */)) {
    if (trackDisjunction) { state.branchID = state.branchID.sibling(); }
    this.regexp_alternative(state);
  }
  if (trackDisjunction) { state.branchID = state.branchID.parent; }

  // Make the same message as V8.
  if (this.regexp_eatQuantifier(state, true)) {
    state.raise("Nothing to repeat");
  }
  if (state.eat(0x7B /* { */)) {
    state.raise("Lone quantifier brackets");
  }
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-Alternative
pp$1.regexp_alternative = function(state) {
  while (state.pos < state.source.length && this.regexp_eatTerm(state)) {}
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Term
pp$1.regexp_eatTerm = function(state) {
  if (this.regexp_eatAssertion(state)) {
    // Handle `QuantifiableAssertion Quantifier` alternative.
    // `state.lastAssertionIsQuantifiable` is true if the last eaten Assertion
    // is a QuantifiableAssertion.
    if (state.lastAssertionIsQuantifiable && this.regexp_eatQuantifier(state)) {
      // Make the same message as V8.
      if (state.switchU) {
        state.raise("Invalid quantifier");
      }
    }
    return true
  }

  if (state.switchU ? this.regexp_eatAtom(state) : this.regexp_eatExtendedAtom(state)) {
    this.regexp_eatQuantifier(state);
    return true
  }

  return false
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Assertion
pp$1.regexp_eatAssertion = function(state) {
  var start = state.pos;
  state.lastAssertionIsQuantifiable = false;

  // ^, $
  if (state.eat(0x5E /* ^ */) || state.eat(0x24 /* $ */)) {
    return true
  }

  // \b \B
  if (state.eat(0x5C /* \ */)) {
    if (state.eat(0x42 /* B */) || state.eat(0x62 /* b */)) {
      return true
    }
    state.pos = start;
  }

  // Lookahead / Lookbehind
  if (state.eat(0x28 /* ( */) && state.eat(0x3F /* ? */)) {
    var lookbehind = false;
    if (this.options.ecmaVersion >= 9) {
      lookbehind = state.eat(0x3C /* < */);
    }
    if (state.eat(0x3D /* = */) || state.eat(0x21 /* ! */)) {
      this.regexp_disjunction(state);
      if (!state.eat(0x29 /* ) */)) {
        state.raise("Unterminated group");
      }
      state.lastAssertionIsQuantifiable = !lookbehind;
      return true
    }
  }

  state.pos = start;
  return false
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-Quantifier
pp$1.regexp_eatQuantifier = function(state, noError) {
  if ( noError === void 0 ) noError = false;

  if (this.regexp_eatQuantifierPrefix(state, noError)) {
    state.eat(0x3F /* ? */);
    return true
  }
  return false
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-QuantifierPrefix
pp$1.regexp_eatQuantifierPrefix = function(state, noError) {
  return (
    state.eat(0x2A /* * */) ||
    state.eat(0x2B /* + */) ||
    state.eat(0x3F /* ? */) ||
    this.regexp_eatBracedQuantifier(state, noError)
  )
};
pp$1.regexp_eatBracedQuantifier = function(state, noError) {
  var start = state.pos;
  if (state.eat(0x7B /* { */)) {
    var min = 0, max = -1;
    if (this.regexp_eatDecimalDigits(state)) {
      min = state.lastIntValue;
      if (state.eat(0x2C /* , */) && this.regexp_eatDecimalDigits(state)) {
        max = state.lastIntValue;
      }
      if (state.eat(0x7D /* } */)) {
        // SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-term
        if (max !== -1 && max < min && !noError) {
          state.raise("numbers out of order in {} quantifier");
        }
        return true
      }
    }
    if (state.switchU && !noError) {
      state.raise("Incomplete quantifier");
    }
    state.pos = start;
  }
  return false
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-Atom
pp$1.regexp_eatAtom = function(state) {
  return (
    this.regexp_eatPatternCharacters(state) ||
    state.eat(0x2E /* . */) ||
    this.regexp_eatReverseSolidusAtomEscape(state) ||
    this.regexp_eatCharacterClass(state) ||
    this.regexp_eatUncapturingGroup(state) ||
    this.regexp_eatCapturingGroup(state)
  )
};
pp$1.regexp_eatReverseSolidusAtomEscape = function(state) {
  var start = state.pos;
  if (state.eat(0x5C /* \ */)) {
    if (this.regexp_eatAtomEscape(state)) {
      return true
    }
    state.pos = start;
  }
  return false
};
pp$1.regexp_eatUncapturingGroup = function(state) {
  var start = state.pos;
  if (state.eat(0x28 /* ( */)) {
    if (state.eat(0x3F /* ? */)) {
      if (this.options.ecmaVersion >= 16) {
        var addModifiers = this.regexp_eatModifiers(state);
        var hasHyphen = state.eat(0x2D /* - */);
        if (addModifiers || hasHyphen) {
          for (var i = 0; i < addModifiers.length; i++) {
            var modifier = addModifiers.charAt(i);
            if (addModifiers.indexOf(modifier, i + 1) > -1) {
              state.raise("Duplicate regular expression modifiers");
            }
          }
          if (hasHyphen) {
            var removeModifiers = this.regexp_eatModifiers(state);
            if (!addModifiers && !removeModifiers && state.current() === 0x3A /* : */) {
              state.raise("Invalid regular expression modifiers");
            }
            for (var i$1 = 0; i$1 < removeModifiers.length; i$1++) {
              var modifier$1 = removeModifiers.charAt(i$1);
              if (
                removeModifiers.indexOf(modifier$1, i$1 + 1) > -1 ||
                addModifiers.indexOf(modifier$1) > -1
              ) {
                state.raise("Duplicate regular expression modifiers");
              }
            }
          }
        }
      }
      if (state.eat(0x3A /* : */)) {
        this.regexp_disjunction(state);
        if (state.eat(0x29 /* ) */)) {
          return true
        }
        state.raise("Unterminated group");
      }
    }
    state.pos = start;
  }
  return false
};
pp$1.regexp_eatCapturingGroup = function(state) {
  if (state.eat(0x28 /* ( */)) {
    if (this.options.ecmaVersion >= 9) {
      this.regexp_groupSpecifier(state);
    } else if (state.current() === 0x3F /* ? */) {
      state.raise("Invalid group");
    }
    this.regexp_disjunction(state);
    if (state.eat(0x29 /* ) */)) {
      state.numCapturingParens += 1;
      return true
    }
    state.raise("Unterminated group");
  }
  return false
};
// RegularExpressionModifiers ::
//   [empty]
//   RegularExpressionModifiers RegularExpressionModifier
pp$1.regexp_eatModifiers = function(state) {
  var modifiers = "";
  var ch = 0;
  while ((ch = state.current()) !== -1 && isRegularExpressionModifier(ch)) {
    modifiers += codePointToString(ch);
    state.advance();
  }
  return modifiers
};
// RegularExpressionModifier :: one of
//   `i` `m` `s`
function isRegularExpressionModifier(ch) {
  return ch === 0x69 /* i */ || ch === 0x6d /* m */ || ch === 0x73 /* s */
}

// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedAtom
pp$1.regexp_eatExtendedAtom = function(state) {
  return (
    state.eat(0x2E /* . */) ||
    this.regexp_eatReverseSolidusAtomEscape(state) ||
    this.regexp_eatCharacterClass(state) ||
    this.regexp_eatUncapturingGroup(state) ||
    this.regexp_eatCapturingGroup(state) ||
    this.regexp_eatInvalidBracedQuantifier(state) ||
    this.regexp_eatExtendedPatternCharacter(state)
  )
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-InvalidBracedQuantifier
pp$1.regexp_eatInvalidBracedQuantifier = function(state) {
  if (this.regexp_eatBracedQuantifier(state, true)) {
    state.raise("Nothing to repeat");
  }
  return false
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-SyntaxCharacter
pp$1.regexp_eatSyntaxCharacter = function(state) {
  var ch = state.current();
  if (isSyntaxCharacter(ch)) {
    state.lastIntValue = ch;
    state.advance();
    return true
  }
  return false
};
function isSyntaxCharacter(ch) {
  return (
    ch === 0x24 /* $ */ ||
    ch >= 0x28 /* ( */ && ch <= 0x2B /* + */ ||
    ch === 0x2E /* . */ ||
    ch === 0x3F /* ? */ ||
    ch >= 0x5B /* [ */ && ch <= 0x5E /* ^ */ ||
    ch >= 0x7B /* { */ && ch <= 0x7D /* } */
  )
}

// https://www.ecma-international.org/ecma-262/8.0/#prod-PatternCharacter
// But eat eager.
pp$1.regexp_eatPatternCharacters = function(state) {
  var start = state.pos;
  var ch = 0;
  while ((ch = state.current()) !== -1 && !isSyntaxCharacter(ch)) {
    state.advance();
  }
  return state.pos !== start
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedPatternCharacter
pp$1.regexp_eatExtendedPatternCharacter = function(state) {
  var ch = state.current();
  if (
    ch !== -1 &&
    ch !== 0x24 /* $ */ &&
    !(ch >= 0x28 /* ( */ && ch <= 0x2B /* + */) &&
    ch !== 0x2E /* . */ &&
    ch !== 0x3F /* ? */ &&
    ch !== 0x5B /* [ */ &&
    ch !== 0x5E /* ^ */ &&
    ch !== 0x7C /* | */
  ) {
    state.advance();
    return true
  }
  return false
};

// GroupSpecifier ::
//   [empty]
//   `?` GroupName
pp$1.regexp_groupSpecifier = function(state) {
  if (state.eat(0x3F /* ? */)) {
    if (!this.regexp_eatGroupName(state)) { state.raise("Invalid group"); }
    var trackDisjunction = this.options.ecmaVersion >= 16;
    var known = state.groupNames[state.lastStringValue];
    if (known) {
      if (trackDisjunction) {
        for (var i = 0, list = known; i < list.length; i += 1) {
          var altID = list[i];

          if (!altID.separatedFrom(state.branchID))
            { state.raise("Duplicate capture group name"); }
        }
      } else {
        state.raise("Duplicate capture group name");
      }
    }
    if (trackDisjunction) {
      (known || (state.groupNames[state.lastStringValue] = [])).push(state.branchID);
    } else {
      state.groupNames[state.lastStringValue] = true;
    }
  }
};

// GroupName ::
//   `<` RegExpIdentifierName `>`
// Note: this updates `state.lastStringValue` property with the eaten name.
pp$1.regexp_eatGroupName = function(state) {
  state.lastStringValue = "";
  if (state.eat(0x3C /* < */)) {
    if (this.regexp_eatRegExpIdentifierName(state) && state.eat(0x3E /* > */)) {
      return true
    }
    state.raise("Invalid capture group name");
  }
  return false
};

// RegExpIdentifierName ::
//   RegExpIdentifierStart
//   RegExpIdentifierName RegExpIdentifierPart
// Note: this updates `state.lastStringValue` property with the eaten name.
pp$1.regexp_eatRegExpIdentifierName = function(state) {
  state.lastStringValue = "";
  if (this.regexp_eatRegExpIdentifierStart(state)) {
    state.lastStringValue += codePointToString(state.lastIntValue);
    while (this.regexp_eatRegExpIdentifierPart(state)) {
      state.lastStringValue += codePointToString(state.lastIntValue);
    }
    return true
  }
  return false
};

// RegExpIdentifierStart ::
//   UnicodeIDStart
//   `$`
//   `_`
//   `\` RegExpUnicodeEscapeSequence[+U]
pp$1.regexp_eatRegExpIdentifierStart = function(state) {
  var start = state.pos;
  var forceU = this.options.ecmaVersion >= 11;
  var ch = state.current(forceU);
  state.advance(forceU);

  if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state, forceU)) {
    ch = state.lastIntValue;
  }
  if (isRegExpIdentifierStart(ch)) {
    state.lastIntValue = ch;
    return true
  }

  state.pos = start;
  return false
};
function isRegExpIdentifierStart(ch) {
  return isIdentifierStart(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */
}

// RegExpIdentifierPart ::
//   UnicodeIDContinue
//   `$`
//   `_`
//   `\` RegExpUnicodeEscapeSequence[+U]
//   <ZWNJ>
//   <ZWJ>
pp$1.regexp_eatRegExpIdentifierPart = function(state) {
  var start = state.pos;
  var forceU = this.options.ecmaVersion >= 11;
  var ch = state.current(forceU);
  state.advance(forceU);

  if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state, forceU)) {
    ch = state.lastIntValue;
  }
  if (isRegExpIdentifierPart(ch)) {
    state.lastIntValue = ch;
    return true
  }

  state.pos = start;
  return false
};
function isRegExpIdentifierPart(ch) {
  return isIdentifierChar(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */ || ch === 0x200C /* <ZWNJ> */ || ch === 0x200D /* <ZWJ> */
}

// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-AtomEscape
pp$1.regexp_eatAtomEscape = function(state) {
  if (
    this.regexp_eatBackReference(state) ||
    this.regexp_eatCharacterClassEscape(state) ||
    this.regexp_eatCharacterEscape(state) ||
    (state.switchN && this.regexp_eatKGroupName(state))
  ) {
    return true
  }
  if (state.switchU) {
    // Make the same message as V8.
    if (state.current() === 0x63 /* c */) {
      state.raise("Invalid unicode escape");
    }
    state.raise("Invalid escape");
  }
  return false
};
pp$1.regexp_eatBackReference = function(state) {
  var start = state.pos;
  if (this.regexp_eatDecimalEscape(state)) {
    var n = state.lastIntValue;
    if (state.switchU) {
      // For SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-atomescape
      if (n > state.maxBackReference) {
        state.maxBackReference = n;
      }
      return true
    }
    if (n <= state.numCapturingParens) {
      return true
    }
    state.pos = start;
  }
  return false
};
pp$1.regexp_eatKGroupName = function(state) {
  if (state.eat(0x6B /* k */)) {
    if (this.regexp_eatGroupName(state)) {
      state.backReferenceNames.push(state.lastStringValue);
      return true
    }
    state.raise("Invalid named reference");
  }
  return false
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-CharacterEscape
pp$1.regexp_eatCharacterEscape = function(state) {
  return (
    this.regexp_eatControlEscape(state) ||
    this.regexp_eatCControlLetter(state) ||
    this.regexp_eatZero(state) ||
    this.regexp_eatHexEscapeSequence(state) ||
    this.regexp_eatRegExpUnicodeEscapeSequence(state, false) ||
    (!state.switchU && this.regexp_eatLegacyOctalEscapeSequence(state)) ||
    this.regexp_eatIdentityEscape(state)
  )
};
pp$1.regexp_eatCControlLetter = function(state) {
  var start = state.pos;
  if (state.eat(0x63 /* c */)) {
    if (this.regexp_eatControlLetter(state)) {
      return true
    }
    state.pos = start;
  }
  return false
};
pp$1.regexp_eatZero = function(state) {
  if (state.current() === 0x30 /* 0 */ && !isDecimalDigit(state.lookahead())) {
    state.lastIntValue = 0;
    state.advance();
    return true
  }
  return false
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-ControlEscape
pp$1.regexp_eatControlEscape = function(state) {
  var ch = state.current();
  if (ch === 0x74 /* t */) {
    state.lastIntValue = 0x09; /* \t */
    state.advance();
    return true
  }
  if (ch === 0x6E /* n */) {
    state.lastIntValue = 0x0A; /* \n */
    state.advance();
    return true
  }
  if (ch === 0x76 /* v */) {
    state.lastIntValue = 0x0B; /* \v */
    state.advance();
    return true
  }
  if (ch === 0x66 /* f */) {
    state.lastIntValue = 0x0C; /* \f */
    state.advance();
    return true
  }
  if (ch === 0x72 /* r */) {
    state.lastIntValue = 0x0D; /* \r */
    state.advance();
    return true
  }
  return false
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-ControlLetter
pp$1.regexp_eatControlLetter = function(state) {
  var ch = state.current();
  if (isControlLetter(ch)) {
    state.lastIntValue = ch % 0x20;
    state.advance();
    return true
  }
  return false
};
function isControlLetter(ch) {
  return (
    (ch >= 0x41 /* A */ && ch <= 0x5A /* Z */) ||
    (ch >= 0x61 /* a */ && ch <= 0x7A /* z */)
  )
}

// https://www.ecma-international.org/ecma-262/8.0/#prod-RegExpUnicodeEscapeSequence
pp$1.regexp_eatRegExpUnicodeEscapeSequence = function(state, forceU) {
  if ( forceU === void 0 ) forceU = false;

  var start = state.pos;
  var switchU = forceU || state.switchU;

  if (state.eat(0x75 /* u */)) {
    if (this.regexp_eatFixedHexDigits(state, 4)) {
      var lead = state.lastIntValue;
      if (switchU && lead >= 0xD800 && lead <= 0xDBFF) {
        var leadSurrogateEnd = state.pos;
        if (state.eat(0x5C /* \ */) && state.eat(0x75 /* u */) && this.regexp_eatFixedHexDigits(state, 4)) {
          var trail = state.lastIntValue;
          if (trail >= 0xDC00 && trail <= 0xDFFF) {
            state.lastIntValue = (lead - 0xD800) * 0x400 + (trail - 0xDC00) + 0x10000;
            return true
          }
        }
        state.pos = leadSurrogateEnd;
        state.lastIntValue = lead;
      }
      return true
    }
    if (
      switchU &&
      state.eat(0x7B /* { */) &&
      this.regexp_eatHexDigits(state) &&
      state.eat(0x7D /* } */) &&
      isValidUnicode(state.lastIntValue)
    ) {
      return true
    }
    if (switchU) {
      state.raise("Invalid unicode escape");
    }
    state.pos = start;
  }

  return false
};
function isValidUnicode(ch) {
  return ch >= 0 && ch <= 0x10FFFF
}

// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-IdentityEscape
pp$1.regexp_eatIdentityEscape = function(state) {
  if (state.switchU) {
    if (this.regexp_eatSyntaxCharacter(state)) {
      return true
    }
    if (state.eat(0x2F /* / */)) {
      state.lastIntValue = 0x2F; /* / */
      return true
    }
    return false
  }

  var ch = state.current();
  if (ch !== 0x63 /* c */ && (!state.switchN || ch !== 0x6B /* k */)) {
    state.lastIntValue = ch;
    state.advance();
    return true
  }

  return false
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalEscape
pp$1.regexp_eatDecimalEscape = function(state) {
  state.lastIntValue = 0;
  var ch = state.current();
  if (ch >= 0x31 /* 1 */ && ch <= 0x39 /* 9 */) {
    do {
      state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */);
      state.advance();
    } while ((ch = state.current()) >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */)
    return true
  }
  return false
};

// Return values used by character set parsing methods, needed to
// forbid negation of sets that can match strings.
var CharSetNone = 0; // Nothing parsed
var CharSetOk = 1; // Construct parsed, cannot contain strings
var CharSetString = 2; // Construct parsed, can contain strings

// https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClassEscape
pp$1.regexp_eatCharacterClassEscape = function(state) {
  var ch = state.current();

  if (isCharacterClassEscape(ch)) {
    state.lastIntValue = -1;
    state.advance();
    return CharSetOk
  }

  var negate = false;
  if (
    state.switchU &&
    this.options.ecmaVersion >= 9 &&
    ((negate = ch === 0x50 /* P */) || ch === 0x70 /* p */)
  ) {
    state.lastIntValue = -1;
    state.advance();
    var result;
    if (
      state.eat(0x7B /* { */) &&
      (result = this.regexp_eatUnicodePropertyValueExpression(state)) &&
      state.eat(0x7D /* } */)
    ) {
      if (negate && result === CharSetString) { state.raise("Invalid property name"); }
      return result
    }
    state.raise("Invalid property name");
  }

  return CharSetNone
};

function isCharacterClassEscape(ch) {
  return (
    ch === 0x64 /* d */ ||
    ch === 0x44 /* D */ ||
    ch === 0x73 /* s */ ||
    ch === 0x53 /* S */ ||
    ch === 0x77 /* w */ ||
    ch === 0x57 /* W */
  )
}

// UnicodePropertyValueExpression ::
//   UnicodePropertyName `=` UnicodePropertyValue
//   LoneUnicodePropertyNameOrValue
pp$1.regexp_eatUnicodePropertyValueExpression = function(state) {
  var start = state.pos;

  // UnicodePropertyName `=` UnicodePropertyValue
  if (this.regexp_eatUnicodePropertyName(state) && state.eat(0x3D /* = */)) {
    var name = state.lastStringValue;
    if (this.regexp_eatUnicodePropertyValue(state)) {
      var value = state.lastStringValue;
      this.regexp_validateUnicodePropertyNameAndValue(state, name, value);
      return CharSetOk
    }
  }
  state.pos = start;

  // LoneUnicodePropertyNameOrValue
  if (this.regexp_eatLoneUnicodePropertyNameOrValue(state)) {
    var nameOrValue = state.lastStringValue;
    return this.regexp_validateUnicodePropertyNameOrValue(state, nameOrValue)
  }
  return CharSetNone
};

pp$1.regexp_validateUnicodePropertyNameAndValue = function(state, name, value) {
  if (!hasOwn(state.unicodeProperties.nonBinary, name))
    { state.raise("Invalid property name"); }
  if (!state.unicodeProperties.nonBinary[name].test(value))
    { state.raise("Invalid property value"); }
};

pp$1.regexp_validateUnicodePropertyNameOrValue = function(state, nameOrValue) {
  if (state.unicodeProperties.binary.test(nameOrValue)) { return CharSetOk }
  if (state.switchV && state.unicodeProperties.binaryOfStrings.test(nameOrValue)) { return CharSetString }
  state.raise("Invalid property name");
};

// UnicodePropertyName ::
//   UnicodePropertyNameCharacters
pp$1.regexp_eatUnicodePropertyName = function(state) {
  var ch = 0;
  state.lastStringValue = "";
  while (isUnicodePropertyNameCharacter(ch = state.current())) {
    state.lastStringValue += codePointToString(ch);
    state.advance();
  }
  return state.lastStringValue !== ""
};

function isUnicodePropertyNameCharacter(ch) {
  return isControlLetter(ch) || ch === 0x5F /* _ */
}

// UnicodePropertyValue ::
//   UnicodePropertyValueCharacters
pp$1.regexp_eatUnicodePropertyValue = function(state) {
  var ch = 0;
  state.lastStringValue = "";
  while (isUnicodePropertyValueCharacter(ch = state.current())) {
    state.lastStringValue += codePointToString(ch);
    state.advance();
  }
  return state.lastStringValue !== ""
};
function isUnicodePropertyValueCharacter(ch) {
  return isUnicodePropertyNameCharacter(ch) || isDecimalDigit(ch)
}

// LoneUnicodePropertyNameOrValue ::
//   UnicodePropertyValueCharacters
pp$1.regexp_eatLoneUnicodePropertyNameOrValue = function(state) {
  return this.regexp_eatUnicodePropertyValue(state)
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClass
pp$1.regexp_eatCharacterClass = function(state) {
  if (state.eat(0x5B /* [ */)) {
    var negate = state.eat(0x5E /* ^ */);
    var result = this.regexp_classContents(state);
    if (!state.eat(0x5D /* ] */))
      { state.raise("Unterminated character class"); }
    if (negate && result === CharSetString)
      { state.raise("Negated character class may contain strings"); }
    return true
  }
  return false
};

// https://tc39.es/ecma262/#prod-ClassContents
// https://www.ecma-international.org/ecma-262/8.0/#prod-ClassRanges
pp$1.regexp_classContents = function(state) {
  if (state.current() === 0x5D /* ] */) { return CharSetOk }
  if (state.switchV) { return this.regexp_classSetExpression(state) }
  this.regexp_nonEmptyClassRanges(state);
  return CharSetOk
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRanges
// https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRangesNoDash
pp$1.regexp_nonEmptyClassRanges = function(state) {
  while (this.regexp_eatClassAtom(state)) {
    var left = state.lastIntValue;
    if (state.eat(0x2D /* - */) && this.regexp_eatClassAtom(state)) {
      var right = state.lastIntValue;
      if (state.switchU && (left === -1 || right === -1)) {
        state.raise("Invalid character class");
      }
      if (left !== -1 && right !== -1 && left > right) {
        state.raise("Range out of order in character class");
      }
    }
  }
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtom
// https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtomNoDash
pp$1.regexp_eatClassAtom = function(state) {
  var start = state.pos;

  if (state.eat(0x5C /* \ */)) {
    if (this.regexp_eatClassEscape(state)) {
      return true
    }
    if (state.switchU) {
      // Make the same message as V8.
      var ch$1 = state.current();
      if (ch$1 === 0x63 /* c */ || isOctalDigit(ch$1)) {
        state.raise("Invalid class escape");
      }
      state.raise("Invalid escape");
    }
    state.pos = start;
  }

  var ch = state.current();
  if (ch !== 0x5D /* ] */) {
    state.lastIntValue = ch;
    state.advance();
    return true
  }

  return false
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassEscape
pp$1.regexp_eatClassEscape = function(state) {
  var start = state.pos;

  if (state.eat(0x62 /* b */)) {
    state.lastIntValue = 0x08; /* <BS> */
    return true
  }

  if (state.switchU && state.eat(0x2D /* - */)) {
    state.lastIntValue = 0x2D; /* - */
    return true
  }

  if (!state.switchU && state.eat(0x63 /* c */)) {
    if (this.regexp_eatClassControlLetter(state)) {
      return true
    }
    state.pos = start;
  }

  return (
    this.regexp_eatCharacterClassEscape(state) ||
    this.regexp_eatCharacterEscape(state)
  )
};

// https://tc39.es/ecma262/#prod-ClassSetExpression
// https://tc39.es/ecma262/#prod-ClassUnion
// https://tc39.es/ecma262/#prod-ClassIntersection
// https://tc39.es/ecma262/#prod-ClassSubtraction
pp$1.regexp_classSetExpression = function(state) {
  var result = CharSetOk, subResult;
  if (this.regexp_eatClassSetRange(state)) ; else if (subResult = this.regexp_eatClassSetOperand(state)) {
    if (subResult === CharSetString) { result = CharSetString; }
    // https://tc39.es/ecma262/#prod-ClassIntersection
    var start = state.pos;
    while (state.eatChars([0x26, 0x26] /* && */)) {
      if (
        state.current() !== 0x26 /* & */ &&
        (subResult = this.regexp_eatClassSetOperand(state))
      ) {
        if (subResult !== CharSetString) { result = CharSetOk; }
        continue
      }
      state.raise("Invalid character in character class");
    }
    if (start !== state.pos) { return result }
    // https://tc39.es/ecma262/#prod-ClassSubtraction
    while (state.eatChars([0x2D, 0x2D] /* -- */)) {
      if (this.regexp_eatClassSetOperand(state)) { continue }
      state.raise("Invalid character in character class");
    }
    if (start !== state.pos) { return result }
  } else {
    state.raise("Invalid character in character class");
  }
  // https://tc39.es/ecma262/#prod-ClassUnion
  for (;;) {
    if (this.regexp_eatClassSetRange(state)) { continue }
    subResult = this.regexp_eatClassSetOperand(state);
    if (!subResult) { return result }
    if (subResult === CharSetString) { result = CharSetString; }
  }
};

// https://tc39.es/ecma262/#prod-ClassSetRange
pp$1.regexp_eatClassSetRange = function(state) {
  var start = state.pos;
  if (this.regexp_eatClassSetCharacter(state)) {
    var left = state.lastIntValue;
    if (state.eat(0x2D /* - */) && this.regexp_eatClassSetCharacter(state)) {
      var right = state.lastIntValue;
      if (left !== -1 && right !== -1 && left > right) {
        state.raise("Range out of order in character class");
      }
      return true
    }
    state.pos = start;
  }
  return false
};

// https://tc39.es/ecma262/#prod-ClassSetOperand
pp$1.regexp_eatClassSetOperand = function(state) {
  if (this.regexp_eatClassSetCharacter(state)) { return CharSetOk }
  return this.regexp_eatClassStringDisjunction(state) || this.regexp_eatNestedClass(state)
};

// https://tc39.es/ecma262/#prod-NestedClass
pp$1.regexp_eatNestedClass = function(state) {
  var start = state.pos;
  if (state.eat(0x5B /* [ */)) {
    var negate = state.eat(0x5E /* ^ */);
    var result = this.regexp_classContents(state);
    if (state.eat(0x5D /* ] */)) {
      if (negate && result === CharSetString) {
        state.raise("Negated character class may contain strings");
      }
      return result
    }
    state.pos = start;
  }
  if (state.eat(0x5C /* \ */)) {
    var result$1 = this.regexp_eatCharacterClassEscape(state);
    if (result$1) {
      return result$1
    }
    state.pos = start;
  }
  return null
};

// https://tc39.es/ecma262/#prod-ClassStringDisjunction
pp$1.regexp_eatClassStringDisjunction = function(state) {
  var start = state.pos;
  if (state.eatChars([0x5C, 0x71] /* \q */)) {
    if (state.eat(0x7B /* { */)) {
      var result = this.regexp_classStringDisjunctionContents(state);
      if (state.eat(0x7D /* } */)) {
        return result
      }
    } else {
      // Make the same message as V8.
      state.raise("Invalid escape");
    }
    state.pos = start;
  }
  return null
};

// https://tc39.es/ecma262/#prod-ClassStringDisjunctionContents
pp$1.regexp_classStringDisjunctionContents = function(state) {
  var result = this.regexp_classString(state);
  while (state.eat(0x7C /* | */)) {
    if (this.regexp_classString(state) === CharSetString) { result = CharSetString; }
  }
  return result
};

// https://tc39.es/ecma262/#prod-ClassString
// https://tc39.es/ecma262/#prod-NonEmptyClassString
pp$1.regexp_classString = function(state) {
  var count = 0;
  while (this.regexp_eatClassSetCharacter(state)) { count++; }
  return count === 1 ? CharSetOk : CharSetString
};

// https://tc39.es/ecma262/#prod-ClassSetCharacter
pp$1.regexp_eatClassSetCharacter = function(state) {
  var start = state.pos;
  if (state.eat(0x5C /* \ */)) {
    if (
      this.regexp_eatCharacterEscape(state) ||
      this.regexp_eatClassSetReservedPunctuator(state)
    ) {
      return true
    }
    if (state.eat(0x62 /* b */)) {
      state.lastIntValue = 0x08; /* <BS> */
      return true
    }
    state.pos = start;
    return false
  }
  var ch = state.current();
  if (ch < 0 || ch === state.lookahead() && isClassSetReservedDoublePunctuatorCharacter(ch)) { return false }
  if (isClassSetSyntaxCharacter(ch)) { return false }
  state.advance();
  state.lastIntValue = ch;
  return true
};

// https://tc39.es/ecma262/#prod-ClassSetReservedDoublePunctuator
function isClassSetReservedDoublePunctuatorCharacter(ch) {
  return (
    ch === 0x21 /* ! */ ||
    ch >= 0x23 /* # */ && ch <= 0x26 /* & */ ||
    ch >= 0x2A /* * */ && ch <= 0x2C /* , */ ||
    ch === 0x2E /* . */ ||
    ch >= 0x3A /* : */ && ch <= 0x40 /* @ */ ||
    ch === 0x5E /* ^ */ ||
    ch === 0x60 /* ` */ ||
    ch === 0x7E /* ~ */
  )
}

// https://tc39.es/ecma262/#prod-ClassSetSyntaxCharacter
function isClassSetSyntaxCharacter(ch) {
  return (
    ch === 0x28 /* ( */ ||
    ch === 0x29 /* ) */ ||
    ch === 0x2D /* - */ ||
    ch === 0x2F /* / */ ||
    ch >= 0x5B /* [ */ && ch <= 0x5D /* ] */ ||
    ch >= 0x7B /* { */ && ch <= 0x7D /* } */
  )
}

// https://tc39.es/ecma262/#prod-ClassSetReservedPunctuator
pp$1.regexp_eatClassSetReservedPunctuator = function(state) {
  var ch = state.current();
  if (isClassSetReservedPunctuator(ch)) {
    state.lastIntValue = ch;
    state.advance();
    return true
  }
  return false
};

// https://tc39.es/ecma262/#prod-ClassSetReservedPunctuator
function isClassSetReservedPunctuator(ch) {
  return (
    ch === 0x21 /* ! */ ||
    ch === 0x23 /* # */ ||
    ch === 0x25 /* % */ ||
    ch === 0x26 /* & */ ||
    ch === 0x2C /* , */ ||
    ch === 0x2D /* - */ ||
    ch >= 0x3A /* : */ && ch <= 0x3E /* > */ ||
    ch === 0x40 /* @ */ ||
    ch === 0x60 /* ` */ ||
    ch === 0x7E /* ~ */
  )
}

// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassControlLetter
pp$1.regexp_eatClassControlLetter = function(state) {
  var ch = state.current();
  if (isDecimalDigit(ch) || ch === 0x5F /* _ */) {
    state.lastIntValue = ch % 0x20;
    state.advance();
    return true
  }
  return false
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence
pp$1.regexp_eatHexEscapeSequence = function(state) {
  var start = state.pos;
  if (state.eat(0x78 /* x */)) {
    if (this.regexp_eatFixedHexDigits(state, 2)) {
      return true
    }
    if (state.switchU) {
      state.raise("Invalid escape");
    }
    state.pos = start;
  }
  return false
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalDigits
pp$1.regexp_eatDecimalDigits = function(state) {
  var start = state.pos;
  var ch = 0;
  state.lastIntValue = 0;
  while (isDecimalDigit(ch = state.current())) {
    state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */);
    state.advance();
  }
  return state.pos !== start
};
function isDecimalDigit(ch) {
  return ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */
}

// https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigits
pp$1.regexp_eatHexDigits = function(state) {
  var start = state.pos;
  var ch = 0;
  state.lastIntValue = 0;
  while (isHexDigit(ch = state.current())) {
    state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch);
    state.advance();
  }
  return state.pos !== start
};
function isHexDigit(ch) {
  return (
    (ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */) ||
    (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) ||
    (ch >= 0x61 /* a */ && ch <= 0x66 /* f */)
  )
}
function hexToInt(ch) {
  if (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) {
    return 10 + (ch - 0x41 /* A */)
  }
  if (ch >= 0x61 /* a */ && ch <= 0x66 /* f */) {
    return 10 + (ch - 0x61 /* a */)
  }
  return ch - 0x30 /* 0 */
}

// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-LegacyOctalEscapeSequence
// Allows only 0-377(octal) i.e. 0-255(decimal).
pp$1.regexp_eatLegacyOctalEscapeSequence = function(state) {
  if (this.regexp_eatOctalDigit(state)) {
    var n1 = state.lastIntValue;
    if (this.regexp_eatOctalDigit(state)) {
      var n2 = state.lastIntValue;
      if (n1 <= 3 && this.regexp_eatOctalDigit(state)) {
        state.lastIntValue = n1 * 64 + n2 * 8 + state.lastIntValue;
      } else {
        state.lastIntValue = n1 * 8 + n2;
      }
    } else {
      state.lastIntValue = n1;
    }
    return true
  }
  return false
};

// https://www.ecma-international.org/ecma-262/8.0/#prod-OctalDigit
pp$1.regexp_eatOctalDigit = function(state) {
  var ch = state.current();
  if (isOctalDigit(ch)) {
    state.lastIntValue = ch - 0x30; /* 0 */
    state.advance();
    return true
  }
  state.lastIntValue = 0;
  return false
};
function isOctalDigit(ch) {
  return ch >= 0x30 /* 0 */ && ch <= 0x37 /* 7 */
}

// https://www.ecma-international.org/ecma-262/8.0/#prod-Hex4Digits
// https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigit
// And HexDigit HexDigit in https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence
pp$1.regexp_eatFixedHexDigits = function(state, length) {
  var start = state.pos;
  state.lastIntValue = 0;
  for (var i = 0; i < length; ++i) {
    var ch = state.current();
    if (!isHexDigit(ch)) {
      state.pos = start;
      return false
    }
    state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch);
    state.advance();
  }
  return true
};

// Object type used to represent tokens. Note that normally, tokens
// simply exist as properties on the parser object. This is only
// used for the onToken callback and the external tokenizer.

var Token = function Token(p) {
  this.type = p.type;
  this.value = p.value;
  this.start = p.start;
  this.end = p.end;
  if (p.options.locations)
    { this.loc = new SourceLocation(p, p.startLoc, p.endLoc); }
  if (p.options.ranges)
    { this.range = [p.start, p.end]; }
};

// ## Tokenizer

var pp = Parser$1.prototype;

// Move to the next token

pp.next = function(ignoreEscapeSequenceInKeyword) {
  if (!ignoreEscapeSequenceInKeyword && this.type.keyword && this.containsEsc)
    { this.raiseRecoverable(this.start, "Escape sequence in keyword " + this.type.keyword); }
  if (this.options.onToken)
    { this.options.onToken(new Token(this)); }

  this.lastTokEnd = this.end;
  this.lastTokStart = this.start;
  this.lastTokEndLoc = this.endLoc;
  this.lastTokStartLoc = this.startLoc;
  this.nextToken();
};

pp.getToken = function() {
  this.next();
  return new Token(this)
};

// If we're in an ES6 environment, make parsers iterable
if (typeof Symbol !== "undefined")
  { pp[Symbol.iterator] = function() {
    var this$1$1 = this;

    return {
      next: function () {
        var token = this$1$1.getToken();
        return {
          done: token.type === types$1.eof,
          value: token
        }
      }
    }
  }; }

// Toggle strict mode. Re-reads the next number or string to please
// pedantic tests (`"use strict"; 010;` should fail).

// Read a single token, updating the parser object's token-related
// properties.

pp.nextToken = function() {
  var curContext = this.curContext();
  if (!curContext || !curContext.preserveSpace) { this.skipSpace(); }

  this.start = this.pos;
  if (this.options.locations) { this.startLoc = this.curPosition(); }
  if (this.pos >= this.input.length) { return this.finishToken(types$1.eof) }

  if (curContext.override) { return curContext.override(this) }
  else { this.readToken(this.fullCharCodeAtPos()); }
};

pp.readToken = function(code) {
  // Identifier or keyword. '\uXXXX' sequences are allowed in
  // identifiers, so '\' also dispatches to that.
  if (isIdentifierStart(code, this.options.ecmaVersion >= 6) || code === 92 /* '\' */)
    { return this.readWord() }

  return this.getTokenFromCode(code)
};

pp.fullCharCodeAtPos = function() {
  var code = this.input.charCodeAt(this.pos);
  if (code <= 0xd7ff || code >= 0xdc00) { return code }
  var next = this.input.charCodeAt(this.pos + 1);
  return next <= 0xdbff || next >= 0xe000 ? code : (code << 10) + next - 0x35fdc00
};

pp.skipBlockComment = function() {
  var startLoc = this.options.onComment && this.curPosition();
  var start = this.pos, end = this.input.indexOf("*/", this.pos += 2);
  if (end === -1) { this.raise(this.pos - 2, "Unterminated comment"); }
  this.pos = end + 2;
  if (this.options.locations) {
    for (var nextBreak = (void 0), pos = start; (nextBreak = nextLineBreak(this.input, pos, this.pos)) > -1;) {
      ++this.curLine;
      pos = this.lineStart = nextBreak;
    }
  }
  if (this.options.onComment)
    { this.options.onComment(true, this.input.slice(start + 2, end), start, this.pos,
                           startLoc, this.curPosition()); }
};

pp.skipLineComment = function(startSkip) {
  var start = this.pos;
  var startLoc = this.options.onComment && this.curPosition();
  var ch = this.input.charCodeAt(this.pos += startSkip);
  while (this.pos < this.input.length && !isNewLine(ch)) {
    ch = this.input.charCodeAt(++this.pos);
  }
  if (this.options.onComment)
    { this.options.onComment(false, this.input.slice(start + startSkip, this.pos), start, this.pos,
                           startLoc, this.curPosition()); }
};

// Called at the start of the parse and after every token. Skips
// whitespace and comments, and.

pp.skipSpace = function() {
  loop: while (this.pos < this.input.length) {
    var ch = this.input.charCodeAt(this.pos);
    switch (ch) {
    case 32: case 160: // ' '
      ++this.pos;
      break
    case 13:
      if (this.input.charCodeAt(this.pos + 1) === 10) {
        ++this.pos;
      }
    case 10: case 8232: case 8233:
      ++this.pos;
      if (this.options.locations) {
        ++this.curLine;
        this.lineStart = this.pos;
      }
      break
    case 47: // '/'
      switch (this.input.charCodeAt(this.pos + 1)) {
      case 42: // '*'
        this.skipBlockComment();
        break
      case 47:
        this.skipLineComment(2);
        break
      default:
        break loop
      }
      break
    default:
      if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) {
        ++this.pos;
      } else {
        break loop
      }
    }
  }
};

// Called at the end of every token. Sets `end`, `val`, and
// maintains `context` and `exprAllowed`, and skips the space after
// the token, so that the next one's `start` will point at the
// right position.

pp.finishToken = function(type, val) {
  this.end = this.pos;
  if (this.options.locations) { this.endLoc = this.curPosition(); }
  var prevType = this.type;
  this.type = type;
  this.value = val;

  this.updateContext(prevType);
};

// ### Token reading

// This is the function that is called to fetch the next token. It
// is somewhat obscure, because it works in character codes rather
// than characters, and because operator parsing has been inlined
// into it.
//
// All in the name of speed.
//
pp.readToken_dot = function() {
  var next = this.input.charCodeAt(this.pos + 1);
  if (next >= 48 && next <= 57) { return this.readNumber(true) }
  var next2 = this.input.charCodeAt(this.pos + 2);
  if (this.options.ecmaVersion >= 6 && next === 46 && next2 === 46) { // 46 = dot '.'
    this.pos += 3;
    return this.finishToken(types$1.ellipsis)
  } else {
    ++this.pos;
    return this.finishToken(types$1.dot)
  }
};

pp.readToken_slash = function() { // '/'
  var next = this.input.charCodeAt(this.pos + 1);
  if (this.exprAllowed) { ++this.pos; return this.readRegexp() }
  if (next === 61) { return this.finishOp(types$1.assign, 2) }
  return this.finishOp(types$1.slash, 1)
};

pp.readToken_mult_modulo_exp = function(code) { // '%*'
  var next = this.input.charCodeAt(this.pos + 1);
  var size = 1;
  var tokentype = code === 42 ? types$1.star : types$1.modulo;

  // exponentiation operator ** and **=
  if (this.options.ecmaVersion >= 7 && code === 42 && next === 42) {
    ++size;
    tokentype = types$1.starstar;
    next = this.input.charCodeAt(this.pos + 2);
  }

  if (next === 61) { return this.finishOp(types$1.assign, size + 1) }
  return this.finishOp(tokentype, size)
};

pp.readToken_pipe_amp = function(code) { // '|&'
  var next = this.input.charCodeAt(this.pos + 1);
  if (next === code) {
    if (this.options.ecmaVersion >= 12) {
      var next2 = this.input.charCodeAt(this.pos + 2);
      if (next2 === 61) { return this.finishOp(types$1.assign, 3) }
    }
    return this.finishOp(code === 124 ? types$1.logicalOR : types$1.logicalAND, 2)
  }
  if (next === 61) { return this.finishOp(types$1.assign, 2) }
  return this.finishOp(code === 124 ? types$1.bitwiseOR : types$1.bitwiseAND, 1)
};

pp.readToken_caret = function() { // '^'
  var next = this.input.charCodeAt(this.pos + 1);
  if (next === 61) { return this.finishOp(types$1.assign, 2) }
  return this.finishOp(types$1.bitwiseXOR, 1)
};

pp.readToken_plus_min = function(code) { // '+-'
  var next = this.input.charCodeAt(this.pos + 1);
  if (next === code) {
    if (next === 45 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 62 &&
        (this.lastTokEnd === 0 || lineBreak.test(this.input.slice(this.lastTokEnd, this.pos)))) {
      // A `-->` line comment
      this.skipLineComment(3);
      this.skipSpace();
      return this.nextToken()
    }
    return this.finishOp(types$1.incDec, 2)
  }
  if (next === 61) { return this.finishOp(types$1.assign, 2) }
  return this.finishOp(types$1.plusMin, 1)
};

pp.readToken_lt_gt = function(code) { // '<>'
  var next = this.input.charCodeAt(this.pos + 1);
  var size = 1;
  if (next === code) {
    size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2;
    if (this.input.charCodeAt(this.pos + size) === 61) { return this.finishOp(types$1.assign, size + 1) }
    return this.finishOp(types$1.bitShift, size)
  }
  if (next === 33 && code === 60 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 45 &&
      this.input.charCodeAt(this.pos + 3) === 45) {
    // `<!--`, an XML-style comment that should be interpreted as a line comment
    this.skipLineComment(4);
    this.skipSpace();
    return this.nextToken()
  }
  if (next === 61) { size = 2; }
  return this.finishOp(types$1.relational, size)
};

pp.readToken_eq_excl = function(code) { // '=!'
  var next = this.input.charCodeAt(this.pos + 1);
  if (next === 61) { return this.finishOp(types$1.equality, this.input.charCodeAt(this.pos + 2) === 61 ? 3 : 2) }
  if (code === 61 && next === 62 && this.options.ecmaVersion >= 6) { // '=>'
    this.pos += 2;
    return this.finishToken(types$1.arrow)
  }
  return this.finishOp(code === 61 ? types$1.eq : types$1.prefix, 1)
};

pp.readToken_question = function() { // '?'
  var ecmaVersion = this.options.ecmaVersion;
  if (ecmaVersion >= 11) {
    var next = this.input.charCodeAt(this.pos + 1);
    if (next === 46) {
      var next2 = this.input.charCodeAt(this.pos + 2);
      if (next2 < 48 || next2 > 57) { return this.finishOp(types$1.questionDot, 2) }
    }
    if (next === 63) {
      if (ecmaVersion >= 12) {
        var next2$1 = this.input.charCodeAt(this.pos + 2);
        if (next2$1 === 61) { return this.finishOp(types$1.assign, 3) }
      }
      return this.finishOp(types$1.coalesce, 2)
    }
  }
  return this.finishOp(types$1.question, 1)
};

pp.readToken_numberSign = function() { // '#'
  var ecmaVersion = this.options.ecmaVersion;
  var code = 35; // '#'
  if (ecmaVersion >= 13) {
    ++this.pos;
    code = this.fullCharCodeAtPos();
    if (isIdentifierStart(code, true) || code === 92 /* '\' */) {
      return this.finishToken(types$1.privateId, this.readWord1())
    }
  }

  this.raise(this.pos, "Unexpected character '" + codePointToString(code) + "'");
};

pp.getTokenFromCode = function(code) {
  switch (code) {
  // The interpretation of a dot depends on whether it is followed
  // by a digit or another two dots.
  case 46: // '.'
    return this.readToken_dot()

  // Punctuation tokens.
  case 40: ++this.pos; return this.finishToken(types$1.parenL)
  case 41: ++this.pos; return this.finishToken(types$1.parenR)
  case 59: ++this.pos; return this.finishToken(types$1.semi)
  case 44: ++this.pos; return this.finishToken(types$1.comma)
  case 91: ++this.pos; return this.finishToken(types$1.bracketL)
  case 93: ++this.pos; return this.finishToken(types$1.bracketR)
  case 123: ++this.pos; return this.finishToken(types$1.braceL)
  case 125: ++this.pos; return this.finishToken(types$1.braceR)
  case 58: ++this.pos; return this.finishToken(types$1.colon)

  case 96: // '`'
    if (this.options.ecmaVersion < 6) { break }
    ++this.pos;
    return this.finishToken(types$1.backQuote)

  case 48: // '0'
    var next = this.input.charCodeAt(this.pos + 1);
    if (next === 120 || next === 88) { return this.readRadixNumber(16) } // '0x', '0X' - hex number
    if (this.options.ecmaVersion >= 6) {
      if (next === 111 || next === 79) { return this.readRadixNumber(8) } // '0o', '0O' - octal number
      if (next === 98 || next === 66) { return this.readRadixNumber(2) } // '0b', '0B' - binary number
    }

  // Anything else beginning with a digit is an integer, octal
  // number, or float.
  case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: // 1-9
    return this.readNumber(false)

  // Quotes produce strings.
  case 34: case 39: // '"', "'"
    return this.readString(code)

  // Operators are parsed inline in tiny state machines. '=' (61) is
  // often referred to. `finishOp` simply skips the amount of
  // characters it is given as second argument, and returns a token
  // of the type given by its first argument.
  case 47: // '/'
    return this.readToken_slash()

  case 37: case 42: // '%*'
    return this.readToken_mult_modulo_exp(code)

  case 124: case 38: // '|&'
    return this.readToken_pipe_amp(code)

  case 94: // '^'
    return this.readToken_caret()

  case 43: case 45: // '+-'
    return this.readToken_plus_min(code)

  case 60: case 62: // '<>'
    return this.readToken_lt_gt(code)

  case 61: case 33: // '=!'
    return this.readToken_eq_excl(code)

  case 63: // '?'
    return this.readToken_question()

  case 126: // '~'
    return this.finishOp(types$1.prefix, 1)

  case 35: // '#'
    return this.readToken_numberSign()
  }

  this.raise(this.pos, "Unexpected character '" + codePointToString(code) + "'");
};

pp.finishOp = function(type, size) {
  var str = this.input.slice(this.pos, this.pos + size);
  this.pos += size;
  return this.finishToken(type, str)
};

pp.readRegexp = function() {
  var escaped, inClass, start = this.pos;
  for (;;) {
    if (this.pos >= this.input.length) { this.raise(start, "Unterminated regular expression"); }
    var ch = this.input.charAt(this.pos);
    if (lineBreak.test(ch)) { this.raise(start, "Unterminated regular expression"); }
    if (!escaped) {
      if (ch === "[") { inClass = true; }
      else if (ch === "]" && inClass) { inClass = false; }
      else if (ch === "/" && !inClass) { break }
      escaped = ch === "\\";
    } else { escaped = false; }
    ++this.pos;
  }
  var pattern = this.input.slice(start, this.pos);
  ++this.pos;
  var flagsStart = this.pos;
  var flags = this.readWord1();
  if (this.containsEsc) { this.unexpected(flagsStart); }

  // Validate pattern
  var state = this.regexpState || (this.regexpState = new RegExpValidationState(this));
  state.reset(start, pattern, flags);
  this.validateRegExpFlags(state);
  this.validateRegExpPattern(state);

  // Create Literal#value property value.
  var value = null;
  try {
    value = new RegExp(pattern, flags);
  } catch (e) {
    // ESTree requires null if it failed to instantiate RegExp object.
    // https://github.com/estree/estree/blob/a27003adf4fd7bfad44de9cef372a2eacd527b1c/es5.md#regexpliteral
  }

  return this.finishToken(types$1.regexp, {pattern: pattern, flags: flags, value: value})
};

// Read an integer in the given radix. Return null if zero digits
// were read, the integer value otherwise. When `len` is given, this
// will return `null` unless the integer has exactly `len` digits.

pp.readInt = function(radix, len, maybeLegacyOctalNumericLiteral) {
  // `len` is used for character escape sequences. In that case, disallow separators.
  var allowSeparators = this.options.ecmaVersion >= 12 && len === undefined;

  // `maybeLegacyOctalNumericLiteral` is true if it doesn't have prefix (0x,0o,0b)
  // and isn't fraction part nor exponent part. In that case, if the first digit
  // is zero then disallow separators.
  var isLegacyOctalNumericLiteral = maybeLegacyOctalNumericLiteral && this.input.charCodeAt(this.pos) === 48;

  var start = this.pos, total = 0, lastCode = 0;
  for (var i = 0, e = len == null ? Infinity : len; i < e; ++i, ++this.pos) {
    var code = this.input.charCodeAt(this.pos), val = (void 0);

    if (allowSeparators && code === 95) {
      if (isLegacyOctalNumericLiteral) { this.raiseRecoverable(this.pos, "Numeric separator is not allowed in legacy octal numeric literals"); }
      if (lastCode === 95) { this.raiseRecoverable(this.pos, "Numeric separator must be exactly one underscore"); }
      if (i === 0) { this.raiseRecoverable(this.pos, "Numeric separator is not allowed at the first of digits"); }
      lastCode = code;
      continue
    }

    if (code >= 97) { val = code - 97 + 10; } // a
    else if (code >= 65) { val = code - 65 + 10; } // A
    else if (code >= 48 && code <= 57) { val = code - 48; } // 0-9
    else { val = Infinity; }
    if (val >= radix) { break }
    lastCode = code;
    total = total * radix + val;
  }

  if (allowSeparators && lastCode === 95) { this.raiseRecoverable(this.pos - 1, "Numeric separator is not allowed at the last of digits"); }
  if (this.pos === start || len != null && this.pos - start !== len) { return null }

  return total
};

function stringToNumber(str, isLegacyOctalNumericLiteral) {
  if (isLegacyOctalNumericLiteral) {
    return parseInt(str, 8)
  }

  // `parseFloat(value)` stops parsing at the first numeric separator then returns a wrong value.
  return parseFloat(str.replace(/_/g, ""))
}

function stringToBigInt(str) {
  if (typeof BigInt !== "function") {
    return null
  }

  // `BigInt(value)` throws syntax error if the string contains numeric separators.
  return BigInt(str.replace(/_/g, ""))
}

pp.readRadixNumber = function(radix) {
  var start = this.pos;
  this.pos += 2; // 0x
  var val = this.readInt(radix);
  if (val == null) { this.raise(this.start + 2, "Expected number in radix " + radix); }
  if (this.options.ecmaVersion >= 11 && this.input.charCodeAt(this.pos) === 110) {
    val = stringToBigInt(this.input.slice(start, this.pos));
    ++this.pos;
  } else if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); }
  return this.finishToken(types$1.num, val)
};

// Read an integer, octal integer, or floating-point number.

pp.readNumber = function(startsWithDot) {
  var start = this.pos;
  if (!startsWithDot && this.readInt(10, undefined, true) === null) { this.raise(start, "Invalid number"); }
  var octal = this.pos - start >= 2 && this.input.charCodeAt(start) === 48;
  if (octal && this.strict) { this.raise(start, "Invalid number"); }
  var next = this.input.charCodeAt(this.pos);
  if (!octal && !startsWithDot && this.options.ecmaVersion >= 11 && next === 110) {
    var val$1 = stringToBigInt(this.input.slice(start, this.pos));
    ++this.pos;
    if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); }
    return this.finishToken(types$1.num, val$1)
  }
  if (octal && /[89]/.test(this.input.slice(start, this.pos))) { octal = false; }
  if (next === 46 && !octal) { // '.'
    ++this.pos;
    this.readInt(10);
    next = this.input.charCodeAt(this.pos);
  }
  if ((next === 69 || next === 101) && !octal) { // 'eE'
    next = this.input.charCodeAt(++this.pos);
    if (next === 43 || next === 45) { ++this.pos; } // '+-'
    if (this.readInt(10) === null) { this.raise(start, "Invalid number"); }
  }
  if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); }

  var val = stringToNumber(this.input.slice(start, this.pos), octal);
  return this.finishToken(types$1.num, val)
};

// Read a string value, interpreting backslash-escapes.

pp.readCodePoint = function() {
  var ch = this.input.charCodeAt(this.pos), code;

  if (ch === 123) { // '{'
    if (this.options.ecmaVersion < 6) { this.unexpected(); }
    var codePos = ++this.pos;
    code = this.readHexChar(this.input.indexOf("}", this.pos) - this.pos);
    ++this.pos;
    if (code > 0x10FFFF) { this.invalidStringToken(codePos, "Code point out of bounds"); }
  } else {
    code = this.readHexChar(4);
  }
  return code
};

pp.readString = function(quote) {
  var out = "", chunkStart = ++this.pos;
  for (;;) {
    if (this.pos >= this.input.length) { this.raise(this.start, "Unterminated string constant"); }
    var ch = this.input.charCodeAt(this.pos);
    if (ch === quote) { break }
    if (ch === 92) { // '\'
      out += this.input.slice(chunkStart, this.pos);
      out += this.readEscapedChar(false);
      chunkStart = this.pos;
    } else if (ch === 0x2028 || ch === 0x2029) {
      if (this.options.ecmaVersion < 10) { this.raise(this.start, "Unterminated string constant"); }
      ++this.pos;
      if (this.options.locations) {
        this.curLine++;
        this.lineStart = this.pos;
      }
    } else {
      if (isNewLine(ch)) { this.raise(this.start, "Unterminated string constant"); }
      ++this.pos;
    }
  }
  out += this.input.slice(chunkStart, this.pos++);
  return this.finishToken(types$1.string, out)
};

// Reads template string tokens.

var INVALID_TEMPLATE_ESCAPE_ERROR = {};

pp.tryReadTemplateToken = function() {
  this.inTemplateElement = true;
  try {
    this.readTmplToken();
  } catch (err) {
    if (err === INVALID_TEMPLATE_ESCAPE_ERROR) {
      this.readInvalidTemplateToken();
    } else {
      throw err
    }
  }

  this.inTemplateElement = false;
};

pp.invalidStringToken = function(position, message) {
  if (this.inTemplateElement && this.options.ecmaVersion >= 9) {
    throw INVALID_TEMPLATE_ESCAPE_ERROR
  } else {
    this.raise(position, message);
  }
};

pp.readTmplToken = function() {
  var out = "", chunkStart = this.pos;
  for (;;) {
    if (this.pos >= this.input.length) { this.raise(this.start, "Unterminated template"); }
    var ch = this.input.charCodeAt(this.pos);
    if (ch === 96 || ch === 36 && this.input.charCodeAt(this.pos + 1) === 123) { // '`', '${'
      if (this.pos === this.start && (this.type === types$1.template || this.type === types$1.invalidTemplate)) {
        if (ch === 36) {
          this.pos += 2;
          return this.finishToken(types$1.dollarBraceL)
        } else {
          ++this.pos;
          return this.finishToken(types$1.backQuote)
        }
      }
      out += this.input.slice(chunkStart, this.pos);
      return this.finishToken(types$1.template, out)
    }
    if (ch === 92) { // '\'
      out += this.input.slice(chunkStart, this.pos);
      out += this.readEscapedChar(true);
      chunkStart = this.pos;
    } else if (isNewLine(ch)) {
      out += this.input.slice(chunkStart, this.pos);
      ++this.pos;
      switch (ch) {
      case 13:
        if (this.input.charCodeAt(this.pos) === 10) { ++this.pos; }
      case 10:
        out += "\n";
        break
      default:
        out += String.fromCharCode(ch);
        break
      }
      if (this.options.locations) {
        ++this.curLine;
        this.lineStart = this.pos;
      }
      chunkStart = this.pos;
    } else {
      ++this.pos;
    }
  }
};

// Reads a template token to search for the end, without validating any escape sequences
pp.readInvalidTemplateToken = function() {
  for (; this.pos < this.input.length; this.pos++) {
    switch (this.input[this.pos]) {
    case "\\":
      ++this.pos;
      break

    case "$":
      if (this.input[this.pos + 1] !== "{") { break }
      // fall through
    case "`":
      return this.finishToken(types$1.invalidTemplate, this.input.slice(this.start, this.pos))

    case "\r":
      if (this.input[this.pos + 1] === "\n") { ++this.pos; }
      // fall through
    case "\n": case "\u2028": case "\u2029":
      ++this.curLine;
      this.lineStart = this.pos + 1;
      break
    }
  }
  this.raise(this.start, "Unterminated template");
};

// Used to read escaped characters

pp.readEscapedChar = function(inTemplate) {
  var ch = this.input.charCodeAt(++this.pos);
  ++this.pos;
  switch (ch) {
  case 110: return "\n" // 'n' -> '\n'
  case 114: return "\r" // 'r' -> '\r'
  case 120: return String.fromCharCode(this.readHexChar(2)) // 'x'
  case 117: return codePointToString(this.readCodePoint()) // 'u'
  case 116: return "\t" // 't' -> '\t'
  case 98: return "\b" // 'b' -> '\b'
  case 118: return "\u000b" // 'v' -> '\u000b'
  case 102: return "\f" // 'f' -> '\f'
  case 13: if (this.input.charCodeAt(this.pos) === 10) { ++this.pos; } // '\r\n'
  case 10: // ' \n'
    if (this.options.locations) { this.lineStart = this.pos; ++this.curLine; }
    return ""
  case 56:
  case 57:
    if (this.strict) {
      this.invalidStringToken(
        this.pos - 1,
        "Invalid escape sequence"
      );
    }
    if (inTemplate) {
      var codePos = this.pos - 1;

      this.invalidStringToken(
        codePos,
        "Invalid escape sequence in template string"
      );
    }
  default:
    if (ch >= 48 && ch <= 55) {
      var octalStr = this.input.substr(this.pos - 1, 3).match(/^[0-7]+/)[0];
      var octal = parseInt(octalStr, 8);
      if (octal > 255) {
        octalStr = octalStr.slice(0, -1);
        octal = parseInt(octalStr, 8);
      }
      this.pos += octalStr.length - 1;
      ch = this.input.charCodeAt(this.pos);
      if ((octalStr !== "0" || ch === 56 || ch === 57) && (this.strict || inTemplate)) {
        this.invalidStringToken(
          this.pos - 1 - octalStr.length,
          inTemplate
            ? "Octal literal in template string"
            : "Octal literal in strict mode"
        );
      }
      return String.fromCharCode(octal)
    }
    if (isNewLine(ch)) {
      // Unicode new line characters after \ get removed from output in both
      // template literals and strings
      if (this.options.locations) { this.lineStart = this.pos; ++this.curLine; }
      return ""
    }
    return String.fromCharCode(ch)
  }
};

// Used to read character escape sequences ('\x', '\u', '\U').

pp.readHexChar = function(len) {
  var codePos = this.pos;
  var n = this.readInt(16, len);
  if (n === null) { this.invalidStringToken(codePos, "Bad character escape sequence"); }
  return n
};

// Read an identifier, and return it as a string. Sets `this.containsEsc`
// to whether the word contained a '\u' escape.
//
// Incrementally adds only escaped chars, adding other chunks as-is
// as a micro-optimization.

pp.readWord1 = function() {
  this.containsEsc = false;
  var word = "", first = true, chunkStart = this.pos;
  var astral = this.options.ecmaVersion >= 6;
  while (this.pos < this.input.length) {
    var ch = this.fullCharCodeAtPos();
    if (isIdentifierChar(ch, astral)) {
      this.pos += ch <= 0xffff ? 1 : 2;
    } else if (ch === 92) { // "\"
      this.containsEsc = true;
      word += this.input.slice(chunkStart, this.pos);
      var escStart = this.pos;
      if (this.input.charCodeAt(++this.pos) !== 117) // "u"
        { this.invalidStringToken(this.pos, "Expecting Unicode escape sequence \\uXXXX"); }
      ++this.pos;
      var esc = this.readCodePoint();
      if (!(first ? isIdentifierStart : isIdentifierChar)(esc, astral))
        { this.invalidStringToken(escStart, "Invalid Unicode escape"); }
      word += codePointToString(esc);
      chunkStart = this.pos;
    } else {
      break
    }
    first = false;
  }
  return word + this.input.slice(chunkStart, this.pos)
};

// Read an identifier or keyword token. Will check for reserved
// words when necessary.

pp.readWord = function() {
  var word = this.readWord1();
  var type = types$1.name;
  if (this.keywords.test(word)) {
    type = keywords[word];
  }
  return this.finishToken(type, word)
};

// Acorn is a tiny, fast JavaScript parser written in JavaScript.
//
// Acorn was written by Marijn Haverbeke, Ingvar Stepanyan, and
// various contributors and released under an MIT license.
//
// Git repositories for Acorn are available at
//
//     http://marijnhaverbeke.nl/git/acorn
//     https://github.com/acornjs/acorn.git
//
// Please use the [github bug tracker][ghbt] to report issues.
//
// [ghbt]: https://github.com/acornjs/acorn/issues


var version = "8.15.0";

Parser$1.acorn = {
  Parser: Parser$1,
  version: version,
  defaultOptions: defaultOptions,
  Position: Position,
  SourceLocation: SourceLocation,
  getLineInfo: getLineInfo,
  Node: Node,
  TokenType: TokenType,
  tokTypes: types$1,
  keywordTypes: keywords,
  TokContext: TokContext,
  tokContexts: types,
  isIdentifierChar: isIdentifierChar,
  isIdentifierStart: isIdentifierStart,
  Token: Token,
  isNewLine: isNewLine,
  lineBreak: lineBreak,
  lineBreakG: lineBreakG,
  nonASCIIwhitespace: nonASCIIwhitespace
};

// The main exported interface (under `self.acorn` when in the
// browser) is a `parse` function that takes a code string and returns
// an abstract syntax tree as specified by the [ESTree spec][estree].
//
// [estree]: https://github.com/estree/estree

function parse$4(input, options) {
  return Parser$1.parse(input, options)
}

// This function tries to parse a single expression at a given
// offset in a string. Useful for parsing mixed-language formats
// that embed JavaScript expressions.

function parseExpressionAt(input, pos, options) {
  return Parser$1.parseExpressionAt(input, pos, options)
}

// Acorn is organized as a tokenizer and a recursive-descent parser.
// The `tokenizer` export provides an interface to the tokenizer.

function tokenizer(input, options) {
  return Parser$1.tokenizer(input, options)
}

var acornNamespace = /*#__PURE__*/Object.freeze({
	__proto__: null,
	Node: Node,
	Parser: Parser$1,
	Position: Position,
	SourceLocation: SourceLocation,
	TokContext: TokContext,
	Token: Token,
	TokenType: TokenType,
	defaultOptions: defaultOptions,
	getLineInfo: getLineInfo,
	isIdentifierChar: isIdentifierChar,
	isIdentifierStart: isIdentifierStart,
	isNewLine: isNewLine,
	keywordTypes: keywords,
	lineBreak: lineBreak,
	lineBreakG: lineBreakG,
	nonASCIIwhitespace: nonASCIIwhitespace,
	parse: parse$4,
	parseExpressionAt: parseExpressionAt,
	tokContexts: types,
	tokTypes: types$1,
	tokenizer: tokenizer,
	version: version
});

// src/index.ts
var startsExpr = true;
function kwLike(_name, options = {}) {
  return new TokenType("name", options);
}
var acornTypeScriptMap = /* @__PURE__ */ new WeakMap();
var keywordTypeValues = Object.values(keywords);
function generateAcornTypeScript(_acorn) {
  const acorn = _acorn.Parser.acorn || _acorn;
  let acornTypeScript = acornTypeScriptMap.get(acorn);
  if (!acornTypeScript) {
    let tokenIsLiteralPropertyName = function(token) {
      return token === types$1.name || token === types$1.string || token === types$1.num || keywordTypeValues.includes(token) || tsKwTokenTypeValues.includes(token);
    }, tokenIsKeywordOrIdentifier = function(token) {
      return token === types$1.name || keywordTypeValues.includes(token) || tsKwTokenTypeValues.includes(token);
    }, tokenIsIdentifier = function(token) {
      return token === types$1.name || tsKwTokenTypeValues.includes(token);
    }, tokenIsTSDeclarationStart = function(token) {
      return token === tsKwTokenType.abstract || token === tsKwTokenType.declare || token === tsKwTokenType.enum || token === tsKwTokenType.module || token === tsKwTokenType.namespace || token === tsKwTokenType.interface || token === tsKwTokenType.type;
    }, tokenIsTSTypeOperator = function(token) {
      return token === tsKwTokenType.keyof || token === tsKwTokenType.readonly || token === tsKwTokenType.unique;
    }, tokenIsTemplate = function(token) {
      return token === types$1.invalidTemplate;
    };
    const tsKwTokenType = generateTsKwTokenType();
    const tsKwTokenTypeValues = Object.values(tsKwTokenType);
    const tsTokenType = generateTsTokenType();
    const tsTokenContext = generateTsTokenContext();
    const tsKeywordsRegExp = new RegExp(`^(?:${Object.keys(tsKwTokenType).join("|")})$`);
    tsTokenType.jsxTagStart.updateContext = function() {
      this.context.push(tsTokenContext.tc_expr);
      this.context.push(tsTokenContext.tc_oTag);
      this.exprAllowed = false;
    };
    tsTokenType.jsxTagEnd.updateContext = function(prevType) {
      let out = this.context.pop();
      if (out === tsTokenContext.tc_oTag && prevType === types$1.slash || out === tsTokenContext.tc_cTag) {
        this.context.pop();
        this.exprAllowed = this.curContext() === tsTokenContext.tc_expr;
      } else {
        this.exprAllowed = true;
      }
    };
    acornTypeScript = {
      tokTypes: {
        ...tsKwTokenType,
        ...tsTokenType
      },
      tokContexts: {
        ...tsTokenContext
      },
      keywordsRegExp: tsKeywordsRegExp,
      tokenIsLiteralPropertyName,
      tokenIsKeywordOrIdentifier,
      tokenIsIdentifier,
      tokenIsTSDeclarationStart,
      tokenIsTSTypeOperator,
      tokenIsTemplate
    };
  }
  return acornTypeScript;
}
function generateTsTokenContext() {
  return {
    tc_oTag: new TokContext("<tag", false, false),
    tc_cTag: new TokContext("</tag", false, false),
    tc_expr: new TokContext("<tag>...</tag>", true, true)
  };
}
function generateTsTokenType() {
  return {
    // @ts-expect-error
    at: new TokenType("@"),
    // @ts-expect-error
    jsxName: new TokenType("jsxName"),
    // @ts-expect-error
    jsxText: new TokenType("jsxText", { beforeExpr: true }),
    // @ts-expect-error
    jsxTagStart: new TokenType("jsxTagStart", { startsExpr: true }),
    // @ts-expect-error
    jsxTagEnd: new TokenType("jsxTagEnd")
  };
}
function generateTsKwTokenType() {
  return {
    assert: kwLike("assert", { startsExpr }),
    asserts: kwLike("asserts", { startsExpr }),
    global: kwLike("global", { startsExpr }),
    keyof: kwLike("keyof", { startsExpr }),
    readonly: kwLike("readonly", { startsExpr }),
    unique: kwLike("unique", { startsExpr }),
    abstract: kwLike("abstract", { startsExpr }),
    declare: kwLike("declare", { startsExpr }),
    enum: kwLike("enum", { startsExpr }),
    module: kwLike("module", { startsExpr }),
    namespace: kwLike("namespace", { startsExpr }),
    interface: kwLike("interface", { startsExpr }),
    type: kwLike("type", { startsExpr })
  };
}

// src/scopeflags.ts
var TS_SCOPE_OTHER = 512;
var TS_SCOPE_TS_MODULE = 1024;

// src/whitespace.ts
var skipWhiteSpaceInLine = /(?:[^\S\n\r\u2028\u2029]|\/\/.*|\/\*.*?\*\/)*/y;
var skipWhiteSpaceToLineBreak = new RegExp(
  // Unfortunately JS doesn't support Perl's atomic /(?>pattern)/ or
  // possessive quantifiers, so we use a trick to prevent backtracking
  // when the look-ahead for line terminator fails.
  "(?=(" + // Capture the whitespace and comments that should be skipped inside
  // a look-ahead assertion, and then re-match the group as a unit.
  skipWhiteSpaceInLine.source + "))\\1" + // Look-ahead for either line terminator, start of multi-line comment,
  // or end of string.
  /(?=[\n\r\u2028\u2029]|\/\*(?!.*?\*\/)|$)/.source,
  "y"
  // sticky
);

// src/parseutil.ts
var DestructuringErrors = class {
  constructor() {
    this.shorthandAssign = this.trailingComma = this.parenthesizedAssign = this.parenthesizedBind = this.doubleProto = -1;
  }
};
function isPrivateNameConflicted(privateNameMap, element) {
  const name = element.key.name;
  const curr = privateNameMap[name];
  let next = "true";
  if (element.type === "MethodDefinition" && (element.kind === "get" || element.kind === "set")) {
    next = (element.static ? "s" : "i") + element.kind;
  }
  if (curr === "iget" && next === "iset" || curr === "iset" && next === "iget" || curr === "sget" && next === "sset" || curr === "sset" && next === "sget") {
    privateNameMap[name] = "true";
    return false;
  } else if (!curr) {
    privateNameMap[name] = next;
    return false;
  } else {
    return true;
  }
}
function checkKeyName(node, name) {
  const { computed, key } = node;
  return !computed && (key.type === "Identifier" && key.name === name || key.type === "Literal" && key.value === name);
}

// src/error.ts
var TypeScriptError = {
  AbstractMethodHasImplementation: ({ methodName }) => `Method '${methodName}' cannot have an implementation because it is marked abstract.`,
  AbstractPropertyHasInitializer: ({ propertyName }) => `Property '${propertyName}' cannot have an initializer because it is marked abstract.`,
  AccesorCannotDeclareThisParameter: "'get' and 'set' accessors cannot declare 'this' parameters.",
  AccesorCannotHaveTypeParameters: "An accessor cannot have type parameters.",
  CannotFindName: ({ name }) => `Cannot find name '${name}'.`,
  ClassMethodHasDeclare: "Class methods cannot have the 'declare' modifier.",
  ClassMethodHasReadonly: "Class methods cannot have the 'readonly' modifier.",
  ConstInitiailizerMustBeStringOrNumericLiteralOrLiteralEnumReference: "A 'const' initializer in an ambient context must be a string or numeric literal or literal enum reference.",
  ConstructorHasTypeParameters: "Type parameters cannot appear on a constructor declaration.",
  DeclareAccessor: ({ kind }) => `'declare' is not allowed in ${kind}ters.`,
  DeclareClassFieldHasInitializer: "Initializers are not allowed in ambient contexts.",
  DeclareFunctionHasImplementation: "An implementation cannot be declared in ambient contexts.",
  DuplicateAccessibilityModifier: (
    // `Accessibility modifier already seen: ${modifier}` would be more helpful.
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    () => `Accessibility modifier already seen.`
  ),
  DuplicateModifier: ({ modifier }) => `Duplicate modifier: '${modifier}'.`,
  // `token` matches the terminology used by typescript:
  // https://github.com/microsoft/TypeScript/blob/main/src/compiler/types.ts#L2915
  EmptyHeritageClauseType: ({ token }) => `'${token}' list cannot be empty.`,
  EmptyTypeArguments: "Type argument list cannot be empty.",
  EmptyTypeParameters: "Type parameter list cannot be empty.",
  ExpectedAmbientAfterExportDeclare: "'export declare' must be followed by an ambient declaration.",
  ImportAliasHasImportType: "An import alias can not use 'import type'.",
  IncompatibleModifiers: ({ modifiers }) => `'${modifiers[0]}' modifier cannot be used with '${modifiers[1]}' modifier.`,
  IndexSignatureHasAbstract: "Index signatures cannot have the 'abstract' modifier.",
  IndexSignatureHasAccessibility: ({ modifier }) => `Index signatures cannot have an accessibility modifier ('${modifier}').`,
  IndexSignatureHasDeclare: "Index signatures cannot have the 'declare' modifier.",
  IndexSignatureHasOverride: "'override' modifier cannot appear on an index signature.",
  IndexSignatureHasStatic: "Index signatures cannot have the 'static' modifier.",
  InitializerNotAllowedInAmbientContext: "Initializers are not allowed in ambient contexts.",
  InvalidModifierOnTypeMember: ({ modifier }) => `'${modifier}' modifier cannot appear on a type member.`,
  InvalidModifierOnTypeParameter: ({ modifier }) => `'${modifier}' modifier cannot appear on a type parameter.`,
  InvalidModifierOnTypeParameterPositions: ({ modifier }) => `'${modifier}' modifier can only appear on a type parameter of a class, interface or type alias.`,
  InvalidModifiersOrder: ({ orderedModifiers }) => `'${orderedModifiers[0]}' modifier must precede '${orderedModifiers[1]}' modifier.`,
  InvalidPropertyAccessAfterInstantiationExpression: "Invalid property access after an instantiation expression. You can either wrap the instantiation expression in parentheses, or delete the type arguments.",
  InvalidTupleMemberLabel: "Tuple members must be labeled with a simple identifier.",
  MissingInterfaceName: "'interface' declarations must be followed by an identifier.",
  MixedLabeledAndUnlabeledElements: "Tuple members must all have names or all not have names.",
  NonAbstractClassHasAbstractMethod: "Abstract methods can only appear within an abstract class.",
  NonClassMethodPropertyHasAbstractModifer: "'abstract' modifier can only appear on a class, method, or property declaration.",
  OptionalTypeBeforeRequired: "A required element cannot follow an optional element.",
  OverrideNotInSubClass: "This member cannot have an 'override' modifier because its containing class does not extend another class.",
  PatternIsOptional: "A binding pattern parameter cannot be optional in an implementation signature.",
  PrivateElementHasAbstract: "Private elements cannot have the 'abstract' modifier.",
  PrivateElementHasAccessibility: ({ modifier }) => `Private elements cannot have an accessibility modifier ('${modifier}').`,
  PrivateMethodsHasAccessibility: ({ modifier }) => `Private methods cannot have an accessibility modifier ('${modifier}').`,
  ReadonlyForMethodSignature: "'readonly' modifier can only appear on a property declaration or index signature.",
  ReservedArrowTypeParam: "This syntax is reserved in files with the .mts or .cts extension. Add a trailing comma, as in `<T,>() => ...`.",
  ReservedTypeAssertion: "This syntax is reserved in files with the .mts or .cts extension. Use an `as` expression instead.",
  SetAccesorCannotHaveOptionalParameter: "A 'set' accessor cannot have an optional parameter.",
  SetAccesorCannotHaveRestParameter: "A 'set' accessor cannot have rest parameter.",
  SetAccesorCannotHaveReturnType: "A 'set' accessor cannot have a return type annotation.",
  SingleTypeParameterWithoutTrailingComma: ({ typeParameterName }) => `Single type parameter ${typeParameterName} should have a trailing comma. Example usage: <${typeParameterName},>.`,
  StaticBlockCannotHaveModifier: "Static class blocks cannot have any modifier.",
  TypeAnnotationAfterAssign: "Type annotations must come before default assignments, e.g. instead of `age = 25: number` use `age: number = 25`.",
  TypeImportCannotSpecifyDefaultAndNamed: "A type-only import can specify a default import or named bindings, but not both.",
  TypeModifierIsUsedInTypeExports: "The 'type' modifier cannot be used on a named export when 'export type' is used on its export statement.",
  TypeModifierIsUsedInTypeImports: "The 'type' modifier cannot be used on a named import when 'import type' is used on its import statement.",
  UnexpectedParameterModifier: "A parameter property is only allowed in a constructor implementation.",
  UnexpectedReadonly: "'readonly' type modifier is only permitted on array and tuple literal types.",
  GenericsEndWithComma: `Trailing comma is not allowed at the end of generics.`,
  UnexpectedTypeAnnotation: "Did not expect a type annotation here.",
  UnexpectedTypeCastInParameter: "Unexpected type cast in parameter position.",
  UnsupportedImportTypeArgument: "Argument in a type import must be a string literal.",
  UnsupportedParameterPropertyKind: "A parameter property may not be declared using a binding pattern.",
  UnsupportedSignatureParameterKind: ({ type }) => `Name in a signature must be an Identifier, ObjectPattern or ArrayPattern, instead got ${type}.`,
  LetInLexicalBinding: "'let' is not allowed to be used as a name in 'let' or 'const' declarations."
};
var DecoratorsError = {
  UnexpectedLeadingDecorator: "Leading decorators must be attached to a class declaration.",
  DecoratorConstructor: "Decorators can't be used with a constructor. Did you mean '@dec class { ... }'?",
  TrailingDecorator: "Decorators must be attached to a class element.",
  SpreadElementDecorator: `Decorators can't be used with SpreadElement`
};

// src/extentions/decorators.ts
function generateParseDecorators(Parse, acornTypeScript, acorn) {
  const { tokTypes: tt } = acorn;
  const { tokTypes: tokTypes2 } = acornTypeScript;
  return class ParseDecorators extends Parse {
    takeDecorators(node) {
      const decorators = this.decoratorStack[this.decoratorStack.length - 1];
      if (decorators.length) {
        node.decorators = decorators;
        this.resetStartLocationFromNode(node, decorators[0]);
        this.decoratorStack[this.decoratorStack.length - 1] = [];
      }
    }
    parseDecorators(allowExport) {
      const currentContextDecorators = this.decoratorStack[this.decoratorStack.length - 1];
      while (this.match(tokTypes2.at)) {
        const decorator = this.parseDecorator();
        currentContextDecorators.push(decorator);
      }
      if (this.match(tt._export)) {
        if (!allowExport) {
          this.unexpected();
        }
      } else if (!this.canHaveLeadingDecorator()) {
        this.raise(this.start, DecoratorsError.UnexpectedLeadingDecorator);
      }
    }
    parseDecorator() {
      const node = this.startNode();
      this.next();
      this.decoratorStack.push([]);
      const startPos = this.start;
      const startLoc = this.startLoc;
      let expr;
      if (this.match(tt.parenL)) {
        const startPos2 = this.start;
        const startLoc2 = this.startLoc;
        this.next();
        expr = this.parseExpression();
        this.expect(tt.parenR);
        if (this.options.preserveParens) {
          let par = this.startNodeAt(startPos2, startLoc2);
          par.expression = expr;
          expr = this.finishNode(par, "ParenthesizedExpression");
        }
      } else {
        expr = this.parseIdent(false);
        while (this.eat(tt.dot)) {
          const node2 = this.startNodeAt(startPos, startLoc);
          node2.object = expr;
          node2.property = this.parseIdent(true);
          node2.computed = false;
          expr = this.finishNode(node2, "MemberExpression");
        }
      }
      node.expression = this.parseMaybeDecoratorArguments(expr);
      this.decoratorStack.pop();
      return this.finishNode(node, "Decorator");
    }
    parseMaybeDecoratorArguments(expr) {
      if (this.eat(tt.parenL)) {
        const node = this.startNodeAtNode(expr);
        node.callee = expr;
        node.arguments = this.parseExprList(tt.parenR, false);
        return this.finishNode(node, "CallExpression");
      }
      return expr;
    }
  };
}

// src/extentions/import-assertions.ts
function generateParseImportAssertions(Parse, acornTypeScript, acorn) {
  const { tokTypes: tokTypes2 } = acornTypeScript;
  const { tokTypes: tt } = acorn;
  return class ImportAttributes extends Parse {
    parseMaybeImportAttributes(node) {
      if (this.type === tt._with || this.type === tokTypes2.assert) {
        this.next();
        const attributes = this.parseImportAttributes();
        if (attributes) {
          node.attributes = attributes;
        }
      }
    }
    parseImportAttributes() {
      this.expect(tt.braceL);
      const attrs = this.parseWithEntries();
      this.expect(tt.braceR);
      return attrs;
    }
    parseWithEntries() {
      const attrs = [];
      const attrNames = /* @__PURE__ */ new Set();
      do {
        if (this.type === tt.braceR) {
          break;
        }
        const node = this.startNode();
        let withionKeyNode;
        if (this.type === tt.string) {
          withionKeyNode = this.parseLiteral(this.value);
        } else {
          withionKeyNode = this.parseIdent(true);
        }
        this.next();
        node.key = withionKeyNode;
        if (attrNames.has(node.key.name)) {
          this.raise(this.pos, "Duplicated key in attributes");
        }
        attrNames.add(node.key.name);
        if (this.type !== tt.string) {
          this.raise(this.pos, "Only string is supported as an attribute value");
        }
        node.value = this.parseLiteral(this.value);
        attrs.push(this.finishNode(node, "ImportAttribute"));
      } while (this.eat(tt.comma));
      return attrs;
    }
  };
}

// src/index.ts
var skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g;
function assert(x) {
  if (!x) {
    throw new Error("Assert fail");
  }
}
function tsIsClassAccessor(modifier) {
  return modifier === "accessor";
}
function tsIsVarianceAnnotations(modifier) {
  return modifier === "in" || modifier === "out";
}
var FUNC_STATEMENT = 1;
var FUNC_HANGING_STATEMENT = 2;
var FUNC_NULLABLE_ID = 4;
var acornScope = {
  SCOPE_TOP: 1,
  SCOPE_FUNCTION: 2,
  SCOPE_ASYNC: 4,
  SCOPE_GENERATOR: 8,
  SCOPE_ARROW: 16,
  SCOPE_SIMPLE_CATCH: 32,
  SCOPE_SUPER: 64,
  SCOPE_DIRECT_SUPER: 128,
  BIND_NONE: 0,
  // Not a binding
  BIND_VAR: 1,
  // Var-style binding
  BIND_LEXICAL: 2,
  // Let- or const-style binding
  BIND_FUNCTION: 3,
  // Function declaration
  BIND_SIMPLE_CATCH: 4,
  // Special case for function names as bound inside the
  BIND_TS_TYPE: 6,
  BIND_TS_INTERFACE: 7,
  BIND_TS_NAMESPACE: 8,
  BIND_FLAGS_TS_EXPORT_ONLY: 1024,
  BIND_FLAGS_TS_IMPORT: 4096,
  BIND_FLAGS_TS_ENUM: 256,
  BIND_FLAGS_TS_CONST_ENUM: 512,
  BIND_FLAGS_CLASS: 128
  // function
};
function functionFlags(async, generator) {
  return acornScope.SCOPE_FUNCTION | (async ? acornScope.SCOPE_ASYNC : 0) | (generator ? acornScope.SCOPE_GENERATOR : 0);
}
function isPossiblyLiteralEnum(expression) {
  if (expression.type !== "MemberExpression") return false;
  const { computed, property } = expression;
  if (computed && (property.type !== "TemplateLiteral" || property.expressions.length > 0)) {
    return false;
  }
  return isUncomputedMemberExpressionChain(expression.object);
}
function isUncomputedMemberExpressionChain(expression) {
  if (expression.type === "Identifier") return true;
  if (expression.type !== "MemberExpression") return false;
  if (expression.computed) return false;
  return isUncomputedMemberExpressionChain(expression.object);
}
function tsIsAccessModifier(modifier) {
  return modifier === "private" || modifier === "public" || modifier === "protected";
}
function tokenCanStartExpression(token) {
  return Boolean(token.startsExpr);
}
function nonNull(x) {
  if (x == null) {
    throw new Error(`Unexpected ${x} value.`);
  }
  return x;
}
function keywordTypeFromName(value) {
  switch (value) {
    case "any":
      return "TSAnyKeyword";
    case "boolean":
      return "TSBooleanKeyword";
    case "bigint":
      return "TSBigIntKeyword";
    case "never":
      return "TSNeverKeyword";
    case "number":
      return "TSNumberKeyword";
    case "object":
      return "TSObjectKeyword";
    case "string":
      return "TSStringKeyword";
    case "symbol":
      return "TSSymbolKeyword";
    case "undefined":
      return "TSUndefinedKeyword";
    case "unknown":
      return "TSUnknownKeyword";
    default:
      return void 0;
  }
}
function tsPlugin(options) {
  const { dts = false } = {};
  const disallowAmbiguousJSXLike = false;
  return function(Parser) {
    const _acorn = Parser.acorn || acornNamespace;
    const acornTypeScript = generateAcornTypeScript(_acorn);
    const tt = _acorn.tokTypes;
    const keywordTypes2 = _acorn.keywordTypes;
    const isIdentifierStart = _acorn.isIdentifierStart;
    const lineBreak = _acorn.lineBreak;
    const isNewLine = _acorn.isNewLine;
    const tokContexts = _acorn.tokContexts;
    const isIdentifierChar = _acorn.isIdentifierChar;
    const {
      tokTypes: tokTypes2,
      tokContexts: tsTokContexts,
      keywordsRegExp,
      tokenIsLiteralPropertyName,
      tokenIsTemplate,
      tokenIsTSDeclarationStart,
      tokenIsIdentifier,
      tokenIsKeywordOrIdentifier,
      tokenIsTSTypeOperator
    } = acornTypeScript;
    function nextLineBreak(code, from, end = code.length) {
      for (let i = from; i < end; i++) {
        let next = code.charCodeAt(i);
        if (isNewLine(next))
          return i < end - 1 && next === 13 && code.charCodeAt(i + 1) === 10 ? i + 2 : i + 1;
      }
      return -1;
    }
    Parser = generateParseDecorators(Parser, acornTypeScript, _acorn);
    Parser = generateParseImportAssertions(Parser, acornTypeScript, _acorn);
    class TypeScriptParser extends Parser {
      constructor(options2, input, startPos) {
        super(options2, input, startPos);
        this.preValue = null;
        this.preToken = null;
        this.isLookahead = false;
        this.isAmbientContext = false;
        this.inAbstractClass = false;
        this.inType = false;
        this.inDisallowConditionalTypesContext = false;
        this.maybeInArrowParameters = false;
        this.shouldParseArrowReturnType = void 0;
        this.shouldParseAsyncArrowReturnType = void 0;
        this.decoratorStack = [[]];
        this.importsStack = [[]];
        /**
         * we will only parse one import node or export node at same time.
         * default kind is undefined
         * */
        this.importOrExportOuterKind = void 0;
        this.tsParseConstModifier = (node) => {
          this.tsParseModifiers({
            modified: node,
            allowedModifiers: ["const"],
            // for better error recovery
            disallowedModifiers: ["in", "out"],
            errorTemplate: TypeScriptError.InvalidModifierOnTypeParameterPositions
          });
        };
        this.ecmaVersion = this.options.ecmaVersion;
      }
      // support in Class static
      static get acornTypeScript() {
        return acornTypeScript;
      }
      // support in runtime, get acornTypeScript be this
      get acornTypeScript() {
        return acornTypeScript;
      }
      getTokenFromCodeInType(code) {
        if (code === 62) {
          return this.finishOp(tt.relational, 1);
        }
        if (code === 60) {
          return this.finishOp(tt.relational, 1);
        }
        return super.getTokenFromCode(code);
      }
      readToken(code) {
        if (!this.inType) {
          let context = this.curContext();
          if (context === tsTokContexts.tc_expr) return this.jsx_readToken();
          if (context === tsTokContexts.tc_oTag || context === tsTokContexts.tc_cTag) {
            if (isIdentifierStart(code)) return this.jsx_readWord();
            if (code == 62) {
              ++this.pos;
              return this.finishToken(tokTypes2.jsxTagEnd);
            }
            if ((code === 34 || code === 39) && context == tsTokContexts.tc_oTag)
              return this.jsx_readString(code);
          }
          if (code === 60 && this.exprAllowed && this.input.charCodeAt(this.pos + 1) !== 33) {
            ++this.pos;
            {
              return this.finishToken(tt.relational, "<");
            }
          }
        }
        return super.readToken(code);
      }
      getTokenFromCode(code) {
        if (this.inType) {
          return this.getTokenFromCodeInType(code);
        }
        if (code === 64) {
          ++this.pos;
          return this.finishToken(tokTypes2.at);
        }
        return super.getTokenFromCode(code);
      }
      isAbstractClass() {
        return this.ts_isContextual(tokTypes2.abstract) && this.lookahead().type === tt._class;
      }
      finishNode(node, type) {
        if (node.type !== "" && node.end !== 0) {
          return node;
        }
        return super.finishNode(node, type);
      }
      // tryParse will clone parser state.
      // It is expensive and should be used with cautions
      tryParse(fn, oldState = this.cloneCurLookaheadState()) {
        const abortSignal = { node: null };
        try {
          const node = fn((node2 = null) => {
            abortSignal.node = node2;
            throw abortSignal;
          });
          return {
            node,
            error: null,
            thrown: false,
            aborted: false,
            failState: null
          };
        } catch (error) {
          const failState = this.getCurLookaheadState();
          this.setLookaheadState(oldState);
          if (error instanceof SyntaxError) {
            return {
              node: null,
              error,
              thrown: true,
              aborted: false,
              failState
            };
          }
          if (error === abortSignal) {
            return {
              node: abortSignal.node,
              error: null,
              thrown: false,
              aborted: true,
              failState
            };
          }
          throw error;
        }
      }
      setOptionalParametersError(refExpressionErrors, resultError) {
        refExpressionErrors.optionalParametersLoc = resultError?.loc ?? this.startLoc;
      }
      // used after we have finished parsing types
      reScan_lt_gt() {
        if (this.type === tt.relational) {
          this.pos -= 1;
          this.readToken_lt_gt(this.fullCharCodeAtPos());
        }
      }
      reScan_lt() {
        const { type } = this;
        if (type === tt.bitShift) {
          this.pos -= 2;
          this.finishOp(tt.relational, 1);
          return tt.relational;
        }
        return type;
      }
      resetEndLocation(node, endPos = this.lastTokEnd, endLoc = this.lastTokEndLoc) {
        node.end = endPos;
        node.loc.end = endLoc;
        if (this.options.ranges) node.range[1] = endPos;
      }
      startNodeAtNode(type) {
        return super.startNodeAt(type.start, type.loc.start);
      }
      nextTokenStart() {
        return this.nextTokenStartSince(this.pos);
      }
      tsHasSomeModifiers(member, modifiers) {
        return modifiers.some((modifier) => {
          if (tsIsAccessModifier(modifier)) {
            return member.accessibility === modifier;
          }
          return !!member[modifier];
        });
      }
      tsIsStartOfStaticBlocks() {
        return this.isContextual("static") && this.lookaheadCharCode() === 123;
      }
      tsCheckForInvalidTypeCasts(items) {
        items.forEach((node) => {
          if (node?.type === "TSTypeCastExpression") {
            this.raise(node.typeAnnotation.start, TypeScriptError.UnexpectedTypeAnnotation);
          }
        });
      }
      atPossibleAsyncArrow(base) {
        return base.type === "Identifier" && base.name === "async" && this.lastTokEnd === base.end && !this.canInsertSemicolon() && base.end - base.start === 5 && base.start === this.potentialArrowAt;
      }
      tsIsIdentifier() {
        return tokenIsIdentifier(this.type);
      }
      tsTryParseTypeOrTypePredicateAnnotation() {
        return this.match(tt.colon) ? this.tsParseTypeOrTypePredicateAnnotation(tt.colon) : void 0;
      }
      tsTryParseGenericAsyncArrowFunction(startPos, startLoc, forInit) {
        if (!this.tsMatchLeftRelational()) {
          return void 0;
        }
        const oldMaybeInArrowParameters = this.maybeInArrowParameters;
        this.maybeInArrowParameters = true;
        const res = this.tsTryParseAndCatch(() => {
          const node = this.startNodeAt(startPos, startLoc);
          node.typeParameters = this.tsParseTypeParameters(this.tsParseConstModifier);
          super.parseFunctionParams(node);
          node.returnType = this.tsTryParseTypeOrTypePredicateAnnotation();
          this.expect(tt.arrow);
          return node;
        });
        this.maybeInArrowParameters = oldMaybeInArrowParameters;
        if (!res) {
          return void 0;
        }
        return super.parseArrowExpression(
          res,
          /* params are already set */
          null,
          /* async */
          true,
          /* forInit */
          forInit
        );
      }
      // Used when parsing type arguments from ES productions, where the first token
      // has been created without state.inType. Thus we need to rescan the lt token.
      tsParseTypeArgumentsInExpression() {
        if (this.reScan_lt() !== tt.relational) {
          return void 0;
        }
        return this.tsParseTypeArguments();
      }
      tsInNoContext(cb) {
        const oldContext = this.context;
        this.context = [oldContext[0]];
        try {
          return cb();
        } finally {
          this.context = oldContext;
        }
      }
      tsTryParseTypeAnnotation() {
        return this.match(tt.colon) ? this.tsParseTypeAnnotation() : void 0;
      }
      isUnparsedContextual(nameStart, name) {
        const nameEnd = nameStart + name.length;
        if (this.input.slice(nameStart, nameEnd) === name) {
          const nextCh = this.input.charCodeAt(nameEnd);
          return !(isIdentifierChar(nextCh) || // check if `nextCh is between 0xd800 - 0xdbff,
          // if `nextCh` is NaN, `NaN & 0xfc00` is 0, the function
          // returns true
          (nextCh & 64512) === 55296);
        }
        return false;
      }
      isAbstractConstructorSignature() {
        return this.ts_isContextual(tokTypes2.abstract) && this.lookahead().type === tt._new;
      }
      nextTokenStartSince(pos) {
        skipWhiteSpace.lastIndex = pos;
        return skipWhiteSpace.test(this.input) ? skipWhiteSpace.lastIndex : pos;
      }
      lookaheadCharCode() {
        return this.input.charCodeAt(this.nextTokenStart());
      }
      compareLookaheadState(state, state2) {
        for (const key of Object.keys(state)) {
          if (state[key] !== state2[key]) return false;
        }
        return true;
      }
      createLookaheadState() {
        this.value = null;
        this.context = [this.curContext()];
      }
      getCurLookaheadState() {
        return {
          endLoc: this.endLoc,
          lastTokEnd: this.lastTokEnd,
          lastTokStart: this.lastTokStart,
          lastTokStartLoc: this.lastTokStartLoc,
          pos: this.pos,
          value: this.value,
          type: this.type,
          start: this.start,
          end: this.end,
          context: this.context,
          startLoc: this.startLoc,
          lastTokEndLoc: this.lastTokEndLoc,
          curLine: this.curLine,
          lineStart: this.lineStart,
          curPosition: this.curPosition,
          containsEsc: this.containsEsc
        };
      }
      cloneCurLookaheadState() {
        return {
          pos: this.pos,
          value: this.value,
          type: this.type,
          start: this.start,
          end: this.end,
          context: this.context && this.context.slice(),
          startLoc: this.startLoc,
          lastTokEndLoc: this.lastTokEndLoc,
          endLoc: this.endLoc,
          lastTokEnd: this.lastTokEnd,
          lastTokStart: this.lastTokStart,
          lastTokStartLoc: this.lastTokStartLoc,
          curLine: this.curLine,
          lineStart: this.lineStart,
          curPosition: this.curPosition,
          containsEsc: this.containsEsc
        };
      }
      setLookaheadState(state) {
        this.pos = state.pos;
        this.value = state.value;
        this.endLoc = state.endLoc;
        this.lastTokEnd = state.lastTokEnd;
        this.lastTokStart = state.lastTokStart;
        this.lastTokStartLoc = state.lastTokStartLoc;
        this.type = state.type;
        this.start = state.start;
        this.end = state.end;
        this.context = state.context;
        this.startLoc = state.startLoc;
        this.lastTokEndLoc = state.lastTokEndLoc;
        this.curLine = state.curLine;
        this.lineStart = state.lineStart;
        this.curPosition = state.curPosition;
        this.containsEsc = state.containsEsc;
      }
      // Utilities
      tsLookAhead(f) {
        const state = this.getCurLookaheadState();
        const res = f();
        this.setLookaheadState(state);
        return res;
      }
      lookahead(number) {
        const oldState = this.getCurLookaheadState();
        this.createLookaheadState();
        this.isLookahead = true;
        if (number !== void 0) {
          for (let i = 0; i < number; i++) {
            this.nextToken();
          }
        } else {
          this.nextToken();
        }
        this.isLookahead = false;
        const curState = this.getCurLookaheadState();
        this.setLookaheadState(oldState);
        return curState;
      }
      readWord() {
        let word = this.readWord1();
        let type = tt.name;
        if (this.keywords.test(word)) {
          type = keywordTypes2[word];
        } else if (new RegExp(keywordsRegExp).test(word)) {
          type = tokTypes2[word];
        }
        return this.finishToken(type, word);
      }
      skipBlockComment() {
        let startLoc;
        if (!this.isLookahead) startLoc = this.options.onComment && this.curPosition();
        let start = this.pos, end = this.input.indexOf("*/", this.pos += 2);
        if (end === -1) this.raise(this.pos - 2, "Unterminated comment");
        this.pos = end + 2;
        if (this.options.locations) {
          for (let nextBreak, pos = start; (nextBreak = nextLineBreak(this.input, pos, this.pos)) > -1; ) {
            ++this.curLine;
            pos = this.lineStart = nextBreak;
          }
        }
        if (this.isLookahead) return;
        if (this.options.onComment) {
          this.options.onComment(
            true,
            this.input.slice(start + 2, end),
            start,
            this.pos,
            startLoc,
            this.curPosition()
          );
        }
      }
      skipLineComment(startSkip) {
        let start = this.pos;
        let startLoc;
        if (!this.isLookahead) startLoc = this.options.onComment && this.curPosition();
        let ch = this.input.charCodeAt(this.pos += startSkip);
        while (this.pos < this.input.length && !isNewLine(ch)) {
          ch = this.input.charCodeAt(++this.pos);
        }
        if (this.isLookahead) return;
        if (this.options.onComment)
          this.options.onComment(
            false,
            this.input.slice(start + startSkip, this.pos),
            start,
            this.pos,
            startLoc,
            this.curPosition()
          );
      }
      finishToken(type, val) {
        this.preValue = this.value;
        this.preToken = this.type;
        this.end = this.pos;
        if (this.options.locations) this.endLoc = this.curPosition();
        let prevType = this.type;
        this.type = type;
        this.value = val;
        if (!this.isLookahead) {
          this.updateContext(prevType);
        }
      }
      resetStartLocation(node, start, startLoc) {
        node.start = start;
        node.loc.start = startLoc;
        if (this.options.ranges) node.range[0] = start;
      }
      isLineTerminator() {
        return this.eat(tt.semi) || super.canInsertSemicolon();
      }
      hasFollowingLineBreak() {
        skipWhiteSpaceToLineBreak.lastIndex = this.end;
        return skipWhiteSpaceToLineBreak.test(this.input);
      }
      addExtra(node, key, value, enumerable = true) {
        if (!node) return;
        const extra = node.extra = node.extra || {};
        if (enumerable) {
          extra[key] = value;
        } else {
          Object.defineProperty(extra, key, { enumerable, value });
        }
      }
      /**
       * Test if current token is a literal property name
       * https://tc39.es/ecma262/#prod-LiteralPropertyName
       * LiteralPropertyName:
       *   IdentifierName
       *   StringLiteral
       *   NumericLiteral
       *   BigIntLiteral
       */
      isLiteralPropertyName() {
        return tokenIsLiteralPropertyName(this.type);
      }
      hasPrecedingLineBreak() {
        return lineBreak.test(this.input.slice(this.lastTokEnd, this.start));
      }
      createIdentifier(node, name) {
        node.name = name;
        return this.finishNode(node, "Identifier");
      }
      /**
       * Reset the start location of node to the start location of locationNode
       */
      resetStartLocationFromNode(node, locationNode) {
        this.resetStartLocation(node, locationNode.start, locationNode.loc.start);
      }
      // This is used in flow and typescript plugin
      // Determine whether a parameter is a this param
      isThisParam(param) {
        return param.type === "Identifier" && param.name === "this";
      }
      isLookaheadContextual(name) {
        const next = this.nextTokenStart();
        return this.isUnparsedContextual(next, name);
      }
      /**
       * ts type isContextual
       * @param {TokenType} type
       * @param {TokenType} token
       * @returns {boolean}
       * */
      ts_type_isContextual(type, token) {
        return type === token && !this.containsEsc;
      }
      /**
       * ts isContextual
       * @param {TokenType} token
       * @returns {boolean}
       * */
      ts_isContextual(token) {
        return this.type === token && !this.containsEsc;
      }
      ts_isContextualWithState(state, token) {
        return state.type === token && !state.containsEsc;
      }
      isContextualWithState(keyword, state) {
        return state.type === tt.name && state.value === keyword && !state.containsEsc;
      }
      tsIsStartOfMappedType() {
        this.next();
        if (this.eat(tt.plusMin)) {
          return this.ts_isContextual(tokTypes2.readonly);
        }
        if (this.ts_isContextual(tokTypes2.readonly)) {
          this.next();
        }
        if (!this.match(tt.bracketL)) {
          return false;
        }
        this.next();
        if (!this.tsIsIdentifier()) {
          return false;
        }
        this.next();
        return this.match(tt._in);
      }
      tsInDisallowConditionalTypesContext(cb) {
        const oldInDisallowConditionalTypesContext = this.inDisallowConditionalTypesContext;
        this.inDisallowConditionalTypesContext = true;
        try {
          return cb();
        } finally {
          this.inDisallowConditionalTypesContext = oldInDisallowConditionalTypesContext;
        }
      }
      tsTryParseType() {
        return this.tsEatThenParseType(tt.colon);
      }
      /**
       * Whether current token matches given type
       *
       * @param {TokenType} type
       * @returns {boolean}
       * @memberof Tokenizer
       */
      match(type) {
        return this.type === type;
      }
      matchJsx(type) {
        return this.type === acornTypeScript.tokTypes[type];
      }
      ts_eatWithState(type, nextCount, state) {
        const targetType = state.type;
        if (type === targetType) {
          for (let i = 0; i < nextCount; i++) {
            this.next();
          }
          return true;
        } else {
          return false;
        }
      }
      ts_eatContextualWithState(name, nextCount, state) {
        if (keywordsRegExp.test(name)) {
          if (this.ts_isContextualWithState(state, tokTypes2[name])) {
            for (let i = 0; i < nextCount; i++) {
              this.next();
            }
            return true;
          }
          return false;
        } else {
          if (!this.isContextualWithState(name, state)) return false;
          for (let i = 0; i < nextCount; i++) {
            this.next();
          }
          return true;
        }
      }
      canHaveLeadingDecorator() {
        return this.match(tt._class);
      }
      eatContextual(name) {
        if (keywordsRegExp.test(name)) {
          if (this.ts_isContextual(tokTypes2[name])) {
            this.next();
            return true;
          }
          return false;
        } else {
          return super.eatContextual(name);
        }
      }
      tsIsExternalModuleReference() {
        return this.isContextual("require") && this.lookaheadCharCode() === 40;
      }
      tsParseExternalModuleReference() {
        const node = this.startNode();
        this.expectContextual("require");
        this.expect(tt.parenL);
        if (!this.match(tt.string)) {
          this.unexpected();
        }
        node.expression = this.parseExprAtom();
        this.expect(tt.parenR);
        return this.finishNode(node, "TSExternalModuleReference");
      }
      tsParseEntityName(allowReservedWords = true) {
        let entity = this.parseIdent(allowReservedWords);
        while (this.eat(tt.dot)) {
          const node = this.startNodeAtNode(entity);
          node.left = entity;
          node.right = this.parseIdent(allowReservedWords);
          entity = this.finishNode(node, "TSQualifiedName");
        }
        return entity;
      }
      tsParseEnumMember() {
        const node = this.startNode();
        node.id = this.match(tt.string) ? this.parseLiteral(this.value) : this.parseIdent(
          /* liberal */
          true
        );
        if (this.eat(tt.eq)) {
          node.initializer = this.parseMaybeAssign();
        }
        return this.finishNode(node, "TSEnumMember");
      }
      tsParseEnumDeclaration(node, properties = {}) {
        if (properties.const) node.const = true;
        if (properties.declare) node.declare = true;
        this.expectContextual("enum");
        node.id = this.parseIdent();
        this.checkLValSimple(node.id);
        this.expect(tt.braceL);
        node.members = this.tsParseDelimitedList("EnumMembers", this.tsParseEnumMember.bind(this));
        this.expect(tt.braceR);
        return this.finishNode(node, "TSEnumDeclaration");
      }
      tsParseModuleBlock() {
        const node = this.startNode();
        this.enterScope(TS_SCOPE_OTHER);
        this.expect(tt.braceL);
        node.body = [];
        while (this.type !== tt.braceR) {
          let stmt = this.parseStatement(null, true);
          node.body.push(stmt);
        }
        this.next();
        super.exitScope();
        return this.finishNode(node, "TSModuleBlock");
      }
      tsParseAmbientExternalModuleDeclaration(node) {
        if (this.ts_isContextual(tokTypes2.global)) {
          node.global = true;
          node.id = this.parseIdent();
        } else if (this.match(tt.string)) {
          node.id = this.parseLiteral(this.value);
        } else {
          this.unexpected();
        }
        if (this.match(tt.braceL)) {
          this.enterScope(TS_SCOPE_TS_MODULE);
          node.body = this.tsParseModuleBlock();
          super.exitScope();
        } else {
          super.semicolon();
        }
        return this.finishNode(node, "TSModuleDeclaration");
      }
      tsTryParseDeclare(nany) {
        if (this.isLineTerminator()) {
          return;
        }
        let starttype = this.type;
        let kind;
        if (this.isContextual("let")) {
          starttype = tt._var;
          kind = "let";
        }
        return this.tsInAmbientContext(() => {
          if (starttype === tt._function) {
            nany.declare = true;
            return this.parseFunctionStatement(
              nany,
              /* async */
              false,
              /* declarationPosition */
              true
            );
          }
          if (starttype === tt._class) {
            nany.declare = true;
            return this.parseClass(nany, true);
          }
          if (starttype === tokTypes2.enum) {
            return this.tsParseEnumDeclaration(nany, { declare: true });
          }
          if (starttype === tokTypes2.global) {
            return this.tsParseAmbientExternalModuleDeclaration(nany);
          }
          if (starttype === tt._const || starttype === tt._var) {
            if (!this.match(tt._const) || !this.isLookaheadContextual("enum")) {
              nany.declare = true;
              return this.parseVarStatement(nany, kind || this.value, true);
            }
            this.expect(tt._const);
            return this.tsParseEnumDeclaration(nany, {
              const: true,
              declare: true
            });
          }
          if (starttype === tokTypes2.interface) {
            const result = this.tsParseInterfaceDeclaration(nany, {
              declare: true
            });
            if (result) return result;
          }
          if (tokenIsIdentifier(starttype)) {
            return this.tsParseDeclaration(
              nany,
              this.value,
              /* next */
              true
            );
          }
        });
      }
      tsIsListTerminator(kind) {
        switch (kind) {
          case "EnumMembers":
          case "TypeMembers":
            return this.match(tt.braceR);
          case "HeritageClauseElement":
            return this.match(tt.braceL);
          case "TupleElementTypes":
            return this.match(tt.bracketR);
          case "TypeParametersOrArguments":
            return this.tsMatchRightRelational();
        }
      }
      /**
       * If !expectSuccess, returns undefined instead of failing to parse.
       * If expectSuccess, parseElement should always return a defined value.
       */
      tsParseDelimitedListWorker(kind, parseElement, expectSuccess, refTrailingCommaPos) {
        const result = [];
        let trailingCommaPos = -1;
        for (; ; ) {
          if (this.tsIsListTerminator(kind)) {
            break;
          }
          trailingCommaPos = -1;
          const element = parseElement();
          if (element == null) {
            return void 0;
          }
          result.push(element);
          if (this.eat(tt.comma)) {
            trailingCommaPos = this.lastTokStart;
            continue;
          }
          if (this.tsIsListTerminator(kind)) {
            break;
          }
          if (expectSuccess) {
            this.expect(tt.comma);
          }
          return void 0;
        }
        if (refTrailingCommaPos) {
          refTrailingCommaPos.value = trailingCommaPos;
        }
        return result;
      }
      tsParseDelimitedList(kind, parseElement, refTrailingCommaPos) {
        return nonNull(
          this.tsParseDelimitedListWorker(
            kind,
            parseElement,
            /* expectSuccess */
            true,
            refTrailingCommaPos
          )
        );
      }
      tsParseBracketedList(kind, parseElement, bracket, skipFirstToken, refTrailingCommaPos) {
        if (!skipFirstToken) {
          if (bracket) {
            this.expect(tt.bracketL);
          } else {
            this.expect(tt.relational);
          }
        }
        const result = this.tsParseDelimitedList(kind, parseElement, refTrailingCommaPos);
        if (bracket) {
          this.expect(tt.bracketR);
        } else {
          this.expect(tt.relational);
        }
        return result;
      }
      tsParseTypeParameterName() {
        const typeName = this.parseIdent();
        return typeName.name;
      }
      tsEatThenParseType(token) {
        return !this.match(token) ? void 0 : this.tsNextThenParseType();
      }
      tsExpectThenParseType(token) {
        return this.tsDoThenParseType(() => this.expect(token));
      }
      tsNextThenParseType() {
        return this.tsDoThenParseType(() => this.next());
      }
      tsDoThenParseType(cb) {
        return this.tsInType(() => {
          cb();
          return this.tsParseType();
        });
      }
      tsSkipParameterStart() {
        if (tokenIsIdentifier(this.type) || this.match(tt._this)) {
          this.next();
          return true;
        }
        if (this.match(tt.braceL)) {
          try {
            this.parseObj(true);
            return true;
          } catch {
            return false;
          }
        }
        if (this.match(tt.bracketL)) {
          this.next();
          try {
            this.parseBindingList(tt.bracketR, true, true);
            return true;
          } catch {
            return false;
          }
        }
        return false;
      }
      tsIsUnambiguouslyStartOfFunctionType() {
        this.next();
        if (this.match(tt.parenR) || this.match(tt.ellipsis)) {
          return true;
        }
        if (this.tsSkipParameterStart()) {
          if (this.match(tt.colon) || this.match(tt.comma) || this.match(tt.question) || this.match(tt.eq)) {
            return true;
          }
          if (this.match(tt.parenR)) {
            this.next();
            if (this.match(tt.arrow)) {
              return true;
            }
          }
        }
        return false;
      }
      tsIsStartOfFunctionType() {
        if (this.tsMatchLeftRelational()) {
          return true;
        }
        return this.match(tt.parenL) && this.tsLookAhead(this.tsIsUnambiguouslyStartOfFunctionType.bind(this));
      }
      tsInAllowConditionalTypesContext(cb) {
        const oldInDisallowConditionalTypesContext = this.inDisallowConditionalTypesContext;
        this.inDisallowConditionalTypesContext = false;
        try {
          return cb();
        } finally {
          this.inDisallowConditionalTypesContext = oldInDisallowConditionalTypesContext;
        }
      }
      tsParseBindingListForSignature() {
        return super.parseBindingList(tt.parenR, true, true).map((pattern) => {
          if (pattern.type !== "Identifier" && pattern.type !== "RestElement" && pattern.type !== "ObjectPattern" && pattern.type !== "ArrayPattern") {
            this.raise(
              pattern.start,
              TypeScriptError.UnsupportedSignatureParameterKind({ type: pattern.type })
            );
          }
          return pattern;
        });
      }
      tsParseTypePredicateAsserts() {
        if (this.type !== tokTypes2.asserts) {
          return false;
        }
        const containsEsc = this.containsEsc;
        this.next();
        if (!tokenIsIdentifier(this.type) && !this.match(tt._this)) {
          return false;
        }
        if (containsEsc) {
          this.raise(this.lastTokStart, "Escape sequence in keyword asserts");
        }
        return true;
      }
      tsParseThisTypeNode() {
        const node = this.startNode();
        this.next();
        return this.finishNode(node, "TSThisType");
      }
      tsParseTypeAnnotation(eatColon = true, t = this.startNode()) {
        this.tsInType(() => {
          if (eatColon) this.expect(tt.colon);
          t.typeAnnotation = this.tsParseType();
        });
        return this.finishNode(t, "TSTypeAnnotation");
      }
      tsParseThisTypePredicate(lhs) {
        this.next();
        const node = this.startNodeAtNode(lhs);
        node.parameterName = lhs;
        node.typeAnnotation = this.tsParseTypeAnnotation(
          /* eatColon */
          false
        );
        node.asserts = false;
        return this.finishNode(node, "TSTypePredicate");
      }
      tsParseThisTypeOrThisTypePredicate() {
        const thisKeyword = this.tsParseThisTypeNode();
        if (this.isContextual("is") && !this.hasPrecedingLineBreak()) {
          return this.tsParseThisTypePredicate(thisKeyword);
        } else {
          return thisKeyword;
        }
      }
      tsParseTypePredicatePrefix() {
        const id = this.parseIdent();
        if (this.isContextual("is") && !this.hasPrecedingLineBreak()) {
          this.next();
          return id;
        }
      }
      tsParseTypeOrTypePredicateAnnotation(returnToken) {
        return this.tsInType(() => {
          const t = this.startNode();
          this.expect(returnToken);
          const node = this.startNode();
          const asserts = !!this.tsTryParse(this.tsParseTypePredicateAsserts.bind(this));
          if (asserts && this.match(tt._this)) {
            let thisTypePredicate = this.tsParseThisTypeOrThisTypePredicate();
            if (thisTypePredicate.type === "TSThisType") {
              node.parameterName = thisTypePredicate;
              node.asserts = true;
              node.typeAnnotation = null;
              thisTypePredicate = this.finishNode(node, "TSTypePredicate");
            } else {
              this.resetStartLocationFromNode(thisTypePredicate, node);
              thisTypePredicate.asserts = true;
            }
            t.typeAnnotation = thisTypePredicate;
            return this.finishNode(t, "TSTypeAnnotation");
          }
          const typePredicateVariable = this.tsIsIdentifier() && this.tsTryParse(this.tsParseTypePredicatePrefix.bind(this));
          if (!typePredicateVariable) {
            if (!asserts) {
              return this.tsParseTypeAnnotation(
                /* eatColon */
                false,
                t
              );
            }
            node.parameterName = this.parseIdent();
            node.asserts = asserts;
            node.typeAnnotation = null;
            t.typeAnnotation = this.finishNode(node, "TSTypePredicate");
            return this.finishNode(t, "TSTypeAnnotation");
          }
          const type = this.tsParseTypeAnnotation(
            /* eatColon */
            false
          );
          node.parameterName = typePredicateVariable;
          node.typeAnnotation = type;
          node.asserts = asserts;
          t.typeAnnotation = this.finishNode(node, "TSTypePredicate");
          return this.finishNode(t, "TSTypeAnnotation");
        });
      }
      // Note: In TypeScript implementation we must provide `yieldContext` and `awaitContext`,
      // but here it's always false, because this is only used for types.
      tsFillSignature(returnToken, signature) {
        const returnTokenRequired = returnToken === tt.arrow;
        const paramsKey = "parameters";
        const returnTypeKey = "typeAnnotation";
        signature.typeParameters = this.tsTryParseTypeParameters();
        this.expect(tt.parenL);
        signature[paramsKey] = this.tsParseBindingListForSignature();
        if (returnTokenRequired) {
          signature[returnTypeKey] = this.tsParseTypeOrTypePredicateAnnotation(returnToken);
        } else if (this.match(returnToken)) {
          signature[returnTypeKey] = this.tsParseTypeOrTypePredicateAnnotation(returnToken);
        }
      }
      tsTryNextParseConstantContext() {
        if (this.lookahead().type !== tt._const) return null;
        this.next();
        const typeReference = this.tsParseTypeReference();
        if (typeReference.typeParameters || typeReference.typeArguments) {
          this.raise(
            typeReference.typeName.start,
            TypeScriptError.CannotFindName({
              name: "const"
            })
          );
        }
        return typeReference;
      }
      tsParseFunctionOrConstructorType(type, abstract) {
        const node = this.startNode();
        if (type === "TSConstructorType") {
          node.abstract = !!abstract;
          if (abstract) this.next();
          this.next();
        }
        this.tsInAllowConditionalTypesContext(() => this.tsFillSignature(tt.arrow, node));
        return this.finishNode(node, type);
      }
      tsParseUnionOrIntersectionType(kind, parseConstituentType, operator) {
        const node = this.startNode();
        const hasLeadingOperator = this.eat(operator);
        const types = [];
        do {
          types.push(parseConstituentType());
        } while (this.eat(operator));
        if (types.length === 1 && !hasLeadingOperator) {
          return types[0];
        }
        node.types = types;
        return this.finishNode(node, kind);
      }
      tsCheckTypeAnnotationForReadOnly(node) {
        switch (node.typeAnnotation.type) {
          case "TSTupleType":
          case "TSArrayType":
            return;
          default:
            this.raise(node.start, TypeScriptError.UnexpectedReadonly);
        }
      }
      tsParseTypeOperator() {
        const node = this.startNode();
        const operator = this.value;
        this.next();
        node.operator = operator;
        node.typeAnnotation = this.tsParseTypeOperatorOrHigher();
        if (operator === "readonly") {
          this.tsCheckTypeAnnotationForReadOnly(node);
        }
        return this.finishNode(node, "TSTypeOperator");
      }
      tsParseConstraintForInferType() {
        if (this.eat(tt._extends)) {
          const constraint = this.tsInDisallowConditionalTypesContext(() => this.tsParseType());
          if (this.inDisallowConditionalTypesContext || !this.match(tt.question)) {
            return constraint;
          }
        }
      }
      tsParseInferType() {
        const node = this.startNode();
        this.expectContextual("infer");
        const typeParameter = this.startNode();
        typeParameter.name = this.tsParseTypeParameterName();
        typeParameter.constraint = this.tsTryParse(() => this.tsParseConstraintForInferType());
        node.typeParameter = this.finishNode(typeParameter, "TSTypeParameter");
        return this.finishNode(node, "TSInferType");
      }
      tsParseLiteralTypeNode() {
        const node = this.startNode();
        node.literal = (() => {
          switch (this.type) {
            case tt.num:
            // we don't need bigint type here
            // case tt.bigint:
            case tt.string:
            case tt._true:
            case tt._false:
              return this.parseExprAtom();
            default:
              this.unexpected();
          }
        })();
        return this.finishNode(node, "TSLiteralType");
      }
      tsParseImportType() {
        const node = this.startNode();
        this.expect(tt._import);
        this.expect(tt.parenL);
        if (!this.match(tt.string)) {
          this.raise(this.start, TypeScriptError.UnsupportedImportTypeArgument);
        }
        node.argument = this.parseExprAtom();
        this.expect(tt.parenR);
        if (this.eat(tt.dot)) {
          node.qualifier = this.tsParseEntityName();
        }
        if (this.tsMatchLeftRelational()) {
          node.typeArguments = this.tsParseTypeArguments();
        }
        return this.finishNode(node, "TSImportType");
      }
      tsParseTypeQuery() {
        const node = this.startNode();
        this.expect(tt._typeof);
        if (this.match(tt._import)) {
          node.exprName = this.tsParseImportType();
        } else {
          node.exprName = this.tsParseEntityName();
        }
        if (!this.hasPrecedingLineBreak() && this.tsMatchLeftRelational()) {
          node.typeArguments = this.tsParseTypeArguments();
        }
        return this.finishNode(node, "TSTypeQuery");
      }
      tsParseMappedTypeParameter() {
        const node = this.startNode();
        node.name = this.tsParseTypeParameterName();
        node.constraint = this.tsExpectThenParseType(tt._in);
        return this.finishNode(node, "TSTypeParameter");
      }
      tsParseMappedType() {
        const node = this.startNode();
        this.expect(tt.braceL);
        if (this.match(tt.plusMin)) {
          node.readonly = this.value;
          this.next();
          this.expectContextual("readonly");
        } else if (this.eatContextual("readonly")) {
          node.readonly = true;
        }
        this.expect(tt.bracketL);
        node.typeParameter = this.tsParseMappedTypeParameter();
        node.nameType = this.eatContextual("as") ? this.tsParseType() : null;
        this.expect(tt.bracketR);
        if (this.match(tt.plusMin)) {
          node.optional = this.value;
          this.next();
          this.expect(tt.question);
        } else if (this.eat(tt.question)) {
          node.optional = true;
        }
        node.typeAnnotation = this.tsTryParseType();
        this.semicolon();
        this.expect(tt.braceR);
        return this.finishNode(node, "TSMappedType");
      }
      tsParseTypeLiteral() {
        const node = this.startNode();
        node.members = this.tsParseObjectTypeMembers();
        return this.finishNode(node, "TSTypeLiteral");
      }
      tsParseTupleElementType() {
        const startLoc = this.startLoc;
        const startPos = this["start"];
        const rest = this.eat(tt.ellipsis);
        let type = this.tsParseType();
        const optional = this.eat(tt.question);
        const labeled = this.eat(tt.colon);
        if (labeled) {
          const labeledNode = this.startNodeAtNode(type);
          labeledNode.optional = optional;
          if (type.type === "TSTypeReference" && !type.typeArguments && type.typeName.type === "Identifier") {
            labeledNode.label = type.typeName;
          } else {
            this.raise(type.start, TypeScriptError.InvalidTupleMemberLabel);
            labeledNode.label = type;
          }
          labeledNode.elementType = this.tsParseType();
          type = this.finishNode(labeledNode, "TSNamedTupleMember");
        } else if (optional) {
          const optionalTypeNode = this.startNodeAtNode(type);
          optionalTypeNode.typeAnnotation = type;
          type = this.finishNode(optionalTypeNode, "TSOptionalType");
        }
        if (rest) {
          const restNode = this.startNodeAt(startPos, startLoc);
          restNode.typeAnnotation = type;
          type = this.finishNode(restNode, "TSRestType");
        }
        return type;
      }
      tsParseTupleType() {
        const node = this.startNode();
        node.elementTypes = this.tsParseBracketedList(
          "TupleElementTypes",
          this.tsParseTupleElementType.bind(this),
          /* bracket */
          true,
          /* skipFirstToken */
          false
        );
        let seenOptionalElement = false;
        let labeledElements = null;
        node.elementTypes.forEach((elementNode) => {
          const { type } = elementNode;
          if (seenOptionalElement && type !== "TSRestType" && type !== "TSOptionalType" && !(type === "TSNamedTupleMember" && elementNode.optional)) {
            this.raise(elementNode.start, TypeScriptError.OptionalTypeBeforeRequired);
          }
          seenOptionalElement ||= type === "TSNamedTupleMember" && elementNode.optional || type === "TSOptionalType";
          let checkType = type;
          if (type === "TSRestType") {
            elementNode = elementNode.typeAnnotation;
            checkType = elementNode.type;
          }
          const isLabeled = checkType === "TSNamedTupleMember";
          labeledElements ??= isLabeled;
          if (labeledElements !== isLabeled) {
            this.raise(elementNode.start, TypeScriptError.MixedLabeledAndUnlabeledElements);
          }
        });
        return this.finishNode(node, "TSTupleType");
      }
      tsParseTemplateLiteralType() {
        const node = this.startNode();
        node.literal = this.parseTemplate({ isTagged: false });
        return this.finishNode(node, "TSLiteralType");
      }
      tsParseTypeReference() {
        const node = this.startNode();
        node.typeName = this.tsParseEntityName();
        if (!this.hasPrecedingLineBreak() && this.tsMatchLeftRelational()) {
          node.typeArguments = this.tsParseTypeArguments();
        }
        return this.finishNode(node, "TSTypeReference");
      }
      tsMatchLeftRelational() {
        return this.match(tt.relational) && this.value === "<";
      }
      tsMatchRightRelational() {
        return this.match(tt.relational) && this.value === ">";
      }
      tsParseParenthesizedType() {
        const node = this.startNode();
        this.expect(tt.parenL);
        node.typeAnnotation = this.tsParseType();
        this.expect(tt.parenR);
        return this.finishNode(node, "TSParenthesizedType");
      }
      tsParseNonArrayType() {
        switch (this.type) {
          case tt.string:
          case tt.num:
          // we don't need bigint type here
          // case tt.bigint:
          case tt._true:
          case tt._false:
            return this.tsParseLiteralTypeNode();
          case tt.plusMin:
            if (this.value === "-") {
              const node = this.startNode();
              const nextToken = this.lookahead();
              if (nextToken.type !== tt.num) {
                this.unexpected();
              }
              node.literal = this.parseMaybeUnary();
              return this.finishNode(node, "TSLiteralType");
            }
            break;
          case tt._this:
            return this.tsParseThisTypeOrThisTypePredicate();
          case tt._typeof:
            return this.tsParseTypeQuery();
          case tt._import:
            return this.tsParseImportType();
          case tt.braceL:
            return this.tsLookAhead(this.tsIsStartOfMappedType.bind(this)) ? this.tsParseMappedType() : this.tsParseTypeLiteral();
          case tt.bracketL:
            return this.tsParseTupleType();
          case tt.parenL:
            return this.tsParseParenthesizedType();
          // parse template string here
          case tt.backQuote:
          case tt.dollarBraceL:
            return this.tsParseTemplateLiteralType();
          default: {
            const { type } = this;
            if (tokenIsIdentifier(type) || type === tt._void || type === tt._null) {
              const nodeType = type === tt._void ? "TSVoidKeyword" : type === tt._null ? "TSNullKeyword" : keywordTypeFromName(this.value);
              if (nodeType !== void 0 && this.lookaheadCharCode() !== 46) {
                const node = this.startNode();
                this.next();
                return this.finishNode(node, nodeType);
              }
              return this.tsParseTypeReference();
            }
          }
        }
        this.unexpected();
      }
      tsParseArrayTypeOrHigher() {
        let type = this.tsParseNonArrayType();
        while (!this.hasPrecedingLineBreak() && this.eat(tt.bracketL)) {
          if (this.match(tt.bracketR)) {
            const node = this.startNodeAtNode(type);
            node.elementType = type;
            this.expect(tt.bracketR);
            type = this.finishNode(node, "TSArrayType");
          } else {
            const node = this.startNodeAtNode(type);
            node.objectType = type;
            node.indexType = this.tsParseType();
            this.expect(tt.bracketR);
            type = this.finishNode(node, "TSIndexedAccessType");
          }
        }
        return type;
      }
      tsParseTypeOperatorOrHigher() {
        const isTypeOperator = tokenIsTSTypeOperator(this.type) && !this.containsEsc;
        return isTypeOperator ? this.tsParseTypeOperator() : this.isContextual("infer") ? this.tsParseInferType() : this.tsInAllowConditionalTypesContext(() => this.tsParseArrayTypeOrHigher());
      }
      tsParseIntersectionTypeOrHigher() {
        return this.tsParseUnionOrIntersectionType(
          "TSIntersectionType",
          this.tsParseTypeOperatorOrHigher.bind(this),
          tt.bitwiseAND
        );
      }
      tsParseUnionTypeOrHigher() {
        return this.tsParseUnionOrIntersectionType(
          "TSUnionType",
          this.tsParseIntersectionTypeOrHigher.bind(this),
          tt.bitwiseOR
        );
      }
      tsParseNonConditionalType() {
        if (this.tsIsStartOfFunctionType()) {
          return this.tsParseFunctionOrConstructorType("TSFunctionType");
        }
        if (this.match(tt._new)) {
          return this.tsParseFunctionOrConstructorType("TSConstructorType");
        } else if (this.isAbstractConstructorSignature()) {
          return this.tsParseFunctionOrConstructorType(
            "TSConstructorType",
            /* abstract */
            true
          );
        }
        return this.tsParseUnionTypeOrHigher();
      }
      /** Be sure to be in a type context before calling this, using `tsInType`. */
      tsParseType() {
        assert(this.inType);
        const type = this.tsParseNonConditionalType();
        if (this.inDisallowConditionalTypesContext || this.hasPrecedingLineBreak() || !this.eat(tt._extends)) {
          return type;
        }
        const node = this.startNodeAtNode(type);
        node.checkType = type;
        node.extendsType = this.tsInDisallowConditionalTypesContext(
          () => this.tsParseNonConditionalType()
        );
        this.expect(tt.question);
        node.trueType = this.tsInAllowConditionalTypesContext(() => this.tsParseType());
        this.expect(tt.colon);
        node.falseType = this.tsInAllowConditionalTypesContext(() => this.tsParseType());
        return this.finishNode(node, "TSConditionalType");
      }
      tsIsUnambiguouslyIndexSignature() {
        this.next();
        if (tokenIsIdentifier(this.type)) {
          this.next();
          return this.match(tt.colon);
        }
        return false;
      }
      /**
       * Runs `cb` in a type context.
       * This should be called one token *before* the first type token,
       * so that the call to `next()` is run in type context.
       */
      tsInType(cb) {
        const oldInType = this.inType;
        this.inType = true;
        try {
          return cb();
        } finally {
          this.inType = oldInType;
        }
      }
      tsTryParseIndexSignature(node) {
        if (!(this.match(tt.bracketL) && this.tsLookAhead(this.tsIsUnambiguouslyIndexSignature.bind(this)))) {
          return void 0;
        }
        this.expect(tt.bracketL);
        const id = this.parseIdent();
        id.typeAnnotation = this.tsParseTypeAnnotation();
        this.resetEndLocation(id);
        this.expect(tt.bracketR);
        node.parameters = [id];
        const type = this.tsTryParseTypeAnnotation();
        if (type) node.typeAnnotation = type;
        this.tsParseTypeMemberSemicolon();
        return this.finishNode(node, "TSIndexSignature");
      }
      // for better error recover
      tsParseNoneModifiers(node) {
        this.tsParseModifiers({
          modified: node,
          allowedModifiers: [],
          disallowedModifiers: ["in", "out"],
          errorTemplate: TypeScriptError.InvalidModifierOnTypeParameterPositions
        });
      }
      tsParseTypeParameter(parseModifiers = this.tsParseNoneModifiers.bind(this)) {
        const node = this.startNode();
        parseModifiers(node);
        node.name = this.tsParseTypeParameterName();
        node.constraint = this.tsEatThenParseType(tt._extends);
        node.default = this.tsEatThenParseType(tt.eq);
        return this.finishNode(node, "TSTypeParameter");
      }
      tsParseTypeParameters(parseModifiers) {
        const node = this.startNode();
        if (this.tsMatchLeftRelational() || this.matchJsx("jsxTagStart")) {
          this.next();
        } else {
          this.unexpected();
        }
        const refTrailingCommaPos = { value: -1 };
        node.params = this.tsParseBracketedList(
          "TypeParametersOrArguments",
          this.tsParseTypeParameter.bind(this, parseModifiers),
          /* bracket */
          false,
          /* skipFirstToken */
          true,
          refTrailingCommaPos
        );
        if (node.params.length === 0) {
          this.raise(this.start, TypeScriptError.EmptyTypeParameters);
        }
        if (refTrailingCommaPos.value !== -1) {
          this.addExtra(node, "trailingComma", refTrailingCommaPos.value);
        }
        return this.finishNode(node, "TSTypeParameterDeclaration");
      }
      tsTryParseTypeParameters(parseModifiers) {
        if (this.tsMatchLeftRelational()) {
          return this.tsParseTypeParameters(parseModifiers);
        }
      }
      tsTryParse(f) {
        const state = this.getCurLookaheadState();
        const result = f();
        if (result !== void 0 && result !== false) {
          return result;
        } else {
          this.setLookaheadState(state);
          return void 0;
        }
      }
      tsTokenCanFollowModifier() {
        return (this.match(tt.bracketL) || this.match(tt.braceL) || this.match(tt.star) || this.match(tt.ellipsis) || this.match(tt.privateId) || this.isLiteralPropertyName()) && !this.hasPrecedingLineBreak();
      }
      tsNextTokenCanFollowModifier() {
        this.next(true);
        return this.tsTokenCanFollowModifier();
      }
      /** Parses a modifier matching one the given modifier names. */
      tsParseModifier(allowedModifiers, stopOnStartOfClassStaticBlock) {
        const modifier = this.value;
        if (allowedModifiers.indexOf(modifier) !== -1 && !this.containsEsc) {
          if (stopOnStartOfClassStaticBlock && this.tsIsStartOfStaticBlocks()) {
            return void 0;
          }
          if (this.tsTryParse(this.tsNextTokenCanFollowModifier.bind(this))) {
            return modifier;
          }
        }
        return void 0;
      }
      tsParseModifiersByMap({
        modified,
        map
      }) {
        for (const key of Object.keys(map)) {
          modified[key] = map[key];
        }
      }
      /** Parses a list of modifiers, in any order.
       *  If you need a specific order, you must call this function multiple times:
       *    this.tsParseModifiers({ modified: node, allowedModifiers: ['public'] });
       *    this.tsParseModifiers({ modified: node, allowedModifiers: ["abstract", "readonly"] });
       */
      tsParseModifiers({
        modified,
        allowedModifiers,
        disallowedModifiers,
        stopOnStartOfClassStaticBlock,
        errorTemplate = TypeScriptError.InvalidModifierOnTypeMember
      }) {
        const modifiedMap = {};
        const enforceOrder = (loc, modifier, before, after) => {
          if (modifier === before && modified[after]) {
            this.raise(
              loc.column,
              TypeScriptError.InvalidModifiersOrder({ orderedModifiers: [before, after] })
            );
          }
        };
        const incompatible = (loc, modifier, mod1, mod2) => {
          if (modified[mod1] && modifier === mod2 || modified[mod2] && modifier === mod1) {
            this.raise(
              loc.column,
              TypeScriptError.IncompatibleModifiers({ modifiers: [mod1, mod2] })
            );
          }
        };
        for (; ; ) {
          const startLoc = this.startLoc;
          const modifier = this.tsParseModifier(
            allowedModifiers.concat(disallowedModifiers ?? []),
            stopOnStartOfClassStaticBlock
          );
          if (!modifier) break;
          if (tsIsAccessModifier(modifier)) {
            if (modified.accessibility) {
              this.raise(this.start, TypeScriptError.DuplicateAccessibilityModifier());
            } else {
              enforceOrder(startLoc, modifier, modifier, "override");
              enforceOrder(startLoc, modifier, modifier, "static");
              enforceOrder(startLoc, modifier, modifier, "readonly");
              enforceOrder(startLoc, modifier, modifier, "accessor");
              modifiedMap.accessibility = modifier;
              modified["accessibility"] = modifier;
            }
          } else if (tsIsVarianceAnnotations(modifier)) {
            if (modified[modifier]) {
              this.raise(this.start, TypeScriptError.DuplicateModifier({ modifier }));
            } else {
              enforceOrder(startLoc, modifier, "in", "out");
              modifiedMap[modifier] = modifier;
              modified[modifier] = true;
            }
          } else if (tsIsClassAccessor(modifier)) {
            if (modified[modifier]) {
              this.raise(this.start, TypeScriptError.DuplicateModifier({ modifier }));
            } else {
              incompatible(startLoc, modifier, "accessor", "readonly");
              incompatible(startLoc, modifier, "accessor", "static");
              incompatible(startLoc, modifier, "accessor", "override");
              modifiedMap[modifier] = modifier;
              modified[modifier] = true;
            }
          } else if (modifier === "const") {
            if (modified[modifier]) {
              this.raise(this.start, TypeScriptError.DuplicateModifier({ modifier }));
            } else {
              modifiedMap[modifier] = modifier;
              modified[modifier] = true;
            }
          } else {
            if (Object.hasOwnProperty.call(modified, modifier)) {
              this.raise(this.start, TypeScriptError.DuplicateModifier({ modifier }));
            } else {
              enforceOrder(startLoc, modifier, "static", "readonly");
              enforceOrder(startLoc, modifier, "static", "override");
              enforceOrder(startLoc, modifier, "override", "readonly");
              enforceOrder(startLoc, modifier, "abstract", "override");
              incompatible(startLoc, modifier, "declare", "override");
              incompatible(startLoc, modifier, "static", "abstract");
              modifiedMap[modifier] = modifier;
              modified[modifier] = true;
            }
          }
          if (disallowedModifiers?.includes(modifier)) {
            this.raise(this.start, errorTemplate);
          }
        }
        return modifiedMap;
      }
      tsParseInOutModifiers(node) {
        this.tsParseModifiers({
          modified: node,
          allowedModifiers: ["in", "out"],
          disallowedModifiers: [
            "public",
            "private",
            "protected",
            "readonly",
            "declare",
            "abstract",
            "override"
          ],
          errorTemplate: TypeScriptError.InvalidModifierOnTypeParameter
        });
      }
      // Handle type assertions
      parseMaybeUnary(refExpressionErrors, sawUnary, incDec, forInit) {
        if (this.tsMatchLeftRelational()) {
          return this.tsParseTypeAssertion();
        } else {
          return super.parseMaybeUnary(refExpressionErrors, sawUnary, incDec, forInit);
        }
      }
      tsParseTypeAssertion() {
        const result = this.tryParse(() => {
          const node = this.startNode();
          const _const = this.tsTryNextParseConstantContext();
          node.typeAnnotation = _const || this.tsNextThenParseType();
          this.expect(tt.relational);
          node.expression = this.parseMaybeUnary();
          return this.finishNode(node, "TSTypeAssertion");
        });
        if (result.error) {
          return this.tsParseTypeParameters(this.tsParseConstModifier);
        } else {
          return result.node;
        }
      }
      tsParseTypeArguments() {
        const node = this.startNode();
        node.params = this.tsInType(
          () => (
            // Temporarily remove a JSX parsing context, which makes us scan different tokens.
            this.tsInNoContext(() => {
              this.expect(tt.relational);
              return this.tsParseDelimitedList(
                "TypeParametersOrArguments",
                this.tsParseType.bind(this)
              );
            })
          )
        );
        if (node.params.length === 0) {
          this.raise(this.start, TypeScriptError.EmptyTypeArguments);
        }
        this.exprAllowed = false;
        this.expect(tt.relational);
        return this.finishNode(node, "TSTypeParameterInstantiation");
      }
      tsParseHeritageClause(token) {
        const originalStart = this.start;
        const delimitedList = this.tsParseDelimitedList("HeritageClauseElement", () => {
          const node = this.startNode();
          node.expression = this.tsParseEntityName();
          if (this.tsMatchLeftRelational()) {
            node.typeParameters = this.tsParseTypeArguments();
          }
          return this.finishNode(node, "TSExpressionWithTypeArguments");
        });
        if (!delimitedList.length) {
          this.raise(originalStart, TypeScriptError.EmptyHeritageClauseType({ token }));
        }
        return delimitedList;
      }
      tsParseTypeMemberSemicolon() {
        if (!this.eat(tt.comma) && !this.isLineTerminator()) {
          this.expect(tt.semi);
        }
      }
      tsTryParseAndCatch(f) {
        const result = this.tryParse(
          (abort) => (
            // @ts-expect-error todo(flow->ts)
            f() || abort()
          )
        );
        if (result.aborted || !result.node) return void 0;
        if (result.error) this.setLookaheadState(result.failState);
        return result.node;
      }
      tsParseSignatureMember(kind, node) {
        this.tsFillSignature(tt.colon, node);
        this.tsParseTypeMemberSemicolon();
        return this.finishNode(node, kind);
      }
      tsParsePropertyOrMethodSignature(node, readonly) {
        if (this.eat(tt.question)) node.optional = true;
        const nodeAny = node;
        if (this.match(tt.parenL) || this.tsMatchLeftRelational()) {
          if (readonly) {
            this.raise(node.start, TypeScriptError.ReadonlyForMethodSignature);
          }
          const method = nodeAny;
          if (method.kind && this.tsMatchLeftRelational()) {
            this.raise(this.start, TypeScriptError.AccesorCannotHaveTypeParameters);
          }
          this.tsFillSignature(tt.colon, method);
          this.tsParseTypeMemberSemicolon();
          const paramsKey = "parameters";
          const returnTypeKey = "typeAnnotation";
          if (method.kind === "get") {
            if (method[paramsKey].length > 0) {
              this.raise(this.start, "A 'get' accesor must not have any formal parameters.");
              if (this.isThisParam(method[paramsKey][0])) {
                this.raise(this.start, TypeScriptError.AccesorCannotDeclareThisParameter);
              }
            }
          } else if (method.kind === "set") {
            if (method[paramsKey].length !== 1) {
              this.raise(this.start, "A 'get' accesor must not have any formal parameters.");
            } else {
              const firstParameter = method[paramsKey][0];
              if (this.isThisParam(firstParameter)) {
                this.raise(this.start, TypeScriptError.AccesorCannotDeclareThisParameter);
              }
              if (firstParameter.type === "Identifier" && firstParameter.optional) {
                this.raise(this.start, TypeScriptError.SetAccesorCannotHaveOptionalParameter);
              }
              if (firstParameter.type === "RestElement") {
                this.raise(this.start, TypeScriptError.SetAccesorCannotHaveRestParameter);
              }
            }
            if (method[returnTypeKey]) {
              this.raise(
                method[returnTypeKey].start,
                TypeScriptError.SetAccesorCannotHaveReturnType
              );
            }
          } else {
            method.kind = "method";
          }
          return this.finishNode(method, "TSMethodSignature");
        } else {
          const property = nodeAny;
          if (readonly) property.readonly = true;
          const type = this.tsTryParseTypeAnnotation();
          if (type) property.typeAnnotation = type;
          this.tsParseTypeMemberSemicolon();
          return this.finishNode(property, "TSPropertySignature");
        }
      }
      tsParseTypeMember() {
        const node = this.startNode();
        if (this.match(tt.parenL) || this.tsMatchLeftRelational()) {
          return this.tsParseSignatureMember("TSCallSignatureDeclaration", node);
        }
        if (this.match(tt._new)) {
          const id = this.startNode();
          this.next();
          if (this.match(tt.parenL) || this.tsMatchLeftRelational()) {
            return this.tsParseSignatureMember("TSConstructSignatureDeclaration", node);
          } else {
            node.key = this.createIdentifier(id, "new");
            return this.tsParsePropertyOrMethodSignature(node, false);
          }
        }
        this.tsParseModifiers({
          modified: node,
          allowedModifiers: ["readonly"],
          disallowedModifiers: [
            "declare",
            "abstract",
            "private",
            "protected",
            "public",
            "static",
            "override"
          ]
        });
        const idx = this.tsTryParseIndexSignature(node);
        if (idx) {
          return idx;
        }
        this.parsePropertyName(node);
        if (!node.computed && node.key.type === "Identifier" && (node.key.name === "get" || node.key.name === "set") && this.tsTokenCanFollowModifier()) {
          node.kind = node.key.name;
          this.parsePropertyName(node);
        }
        return this.tsParsePropertyOrMethodSignature(node, !!node.readonly);
      }
      tsParseList(kind, parseElement) {
        const result = [];
        while (!this.tsIsListTerminator(kind)) {
          result.push(parseElement());
        }
        return result;
      }
      tsParseObjectTypeMembers() {
        this.expect(tt.braceL);
        const members = this.tsParseList("TypeMembers", this.tsParseTypeMember.bind(this));
        this.expect(tt.braceR);
        return members;
      }
      tsParseInterfaceDeclaration(node, properties = {}) {
        if (this.hasFollowingLineBreak()) return null;
        this.expectContextual("interface");
        if (properties.declare) node.declare = true;
        if (tokenIsIdentifier(this.type)) {
          node.id = this.parseIdent();
          this.checkLValSimple(node.id, acornScope.BIND_TS_INTERFACE);
        } else {
          node.id = null;
          this.raise(this.start, TypeScriptError.MissingInterfaceName);
        }
        node.typeParameters = this.tsTryParseTypeParameters(this.tsParseInOutModifiers.bind(this));
        if (this.eat(tt._extends)) {
          node.extends = this.tsParseHeritageClause("extends");
        }
        const body = this.startNode();
        body.body = this.tsInType(this.tsParseObjectTypeMembers.bind(this));
        node.body = this.finishNode(body, "TSInterfaceBody");
        return this.finishNode(node, "TSInterfaceDeclaration");
      }
      tsParseAbstractDeclaration(node) {
        if (this.match(tt._class)) {
          node.abstract = true;
          return this.parseClass(node, true);
        } else if (this.ts_isContextual(tokTypes2.interface)) {
          if (!this.hasFollowingLineBreak()) {
            node.abstract = true;
            return this.tsParseInterfaceDeclaration(node);
          }
        } else {
          this.unexpected(node.start);
        }
      }
      tsIsDeclarationStart() {
        return tokenIsTSDeclarationStart(this.type);
      }
      tsParseExpressionStatement(node, expr) {
        switch (expr.name) {
          case "declare": {
            const declaration = this.tsTryParseDeclare(node);
            if (declaration) {
              declaration.declare = true;
              return declaration;
            }
            break;
          }
          case "global":
            if (this.match(tt.braceL)) {
              this.enterScope(TS_SCOPE_TS_MODULE);
              const mod = node;
              mod.global = true;
              mod.id = expr;
              mod.body = this.tsParseModuleBlock();
              super.exitScope();
              return this.finishNode(mod, "TSModuleDeclaration");
            }
            break;
          default:
            return this.tsParseDeclaration(
              node,
              expr.name,
              /* next */
              false
            );
        }
      }
      tsParseModuleReference() {
        return this.tsIsExternalModuleReference() ? this.tsParseExternalModuleReference() : this.tsParseEntityName(
          /* allowReservedWords */
          false
        );
      }
      tsIsExportDefaultSpecifier() {
        const { type } = this;
        const isAsync = this.isAsyncFunction();
        const isLet = this.isLet();
        if (tokenIsIdentifier(type)) {
          if (isAsync && !this.containsEsc || isLet) {
            return false;
          }
          if ((type === tokTypes2.type || type === tokTypes2.interface) && !this.containsEsc) {
            const ahead = this.lookahead();
            if (tokenIsIdentifier(ahead.type) && !this.isContextualWithState("from", ahead) || ahead.type === tt.braceL) {
              return false;
            }
          }
        } else if (!this.match(tt._default)) {
          return false;
        }
        const next = this.nextTokenStart();
        const hasFrom = this.isUnparsedContextual(next, "from");
        if (this.input.charCodeAt(next) === 44 || tokenIsIdentifier(this.type) && hasFrom) {
          return true;
        }
        if (this.match(tt._default) && hasFrom) {
          const nextAfterFrom = this.input.charCodeAt(this.nextTokenStartSince(next + 4));
          return nextAfterFrom === 34 || nextAfterFrom === 39;
        }
        return false;
      }
      tsInAmbientContext(cb) {
        const oldIsAmbientContext = this.isAmbientContext;
        this.isAmbientContext = true;
        try {
          return cb();
        } finally {
          this.isAmbientContext = oldIsAmbientContext;
        }
      }
      tsCheckLineTerminator(next) {
        if (next) {
          if (this.hasFollowingLineBreak()) return false;
          this.next();
          return true;
        }
        return !this.isLineTerminator();
      }
      tsParseModuleOrNamespaceDeclaration(node, nested = false) {
        node.id = this.parseIdent();
        if (!nested) {
          this.checkLValSimple(node.id, acornScope.BIND_TS_NAMESPACE);
        }
        if (this.eat(tt.dot)) {
          const inner = this.startNode();
          this.tsParseModuleOrNamespaceDeclaration(inner, true);
          node.body = inner;
        } else {
          this.enterScope(TS_SCOPE_TS_MODULE);
          node.body = this.tsParseModuleBlock();
          super.exitScope();
        }
        return this.finishNode(node, "TSModuleDeclaration");
      }
      checkLValSimple(expr, bindingType = acornScope.BIND_NONE, checkClashes) {
        if (expr.type === "TSNonNullExpression" || expr.type === "TSAsExpression") {
          expr = expr.expression;
        }
        return super.checkLValSimple(expr, bindingType, checkClashes);
      }
      tsParseTypeAliasDeclaration(node) {
        node.id = this.parseIdent();
        this.checkLValSimple(node.id, acornScope.BIND_TS_TYPE);
        node.typeAnnotation = this.tsInType(() => {
          node.typeParameters = this.tsTryParseTypeParameters(
            this.tsParseInOutModifiers.bind(this)
          );
          this.expect(tt.eq);
          if (this.ts_isContextual(tokTypes2.interface) && this.lookahead().type !== tt.dot) {
            const node2 = this.startNode();
            this.next();
            return this.finishNode(node2, "TSIntrinsicKeyword");
          }
          return this.tsParseType();
        });
        this.semicolon();
        return this.finishNode(node, "TSTypeAliasDeclaration");
      }
      // Common to tsTryParseDeclare, tsTryParseExportDeclaration, and tsParseExpressionStatement.
      tsParseDeclaration(node, value, next) {
        switch (value) {
          case "abstract":
            if (this.tsCheckLineTerminator(next) && (this.match(tt._class) || tokenIsIdentifier(this.type))) {
              return this.tsParseAbstractDeclaration(node);
            }
            break;
          case "module":
            if (this.tsCheckLineTerminator(next)) {
              if (this.match(tt.string)) {
                return this.tsParseAmbientExternalModuleDeclaration(node);
              } else if (tokenIsIdentifier(this.type)) {
                return this.tsParseModuleOrNamespaceDeclaration(node);
              }
            }
            break;
          case "namespace":
            if (this.tsCheckLineTerminator(next) && tokenIsIdentifier(this.type)) {
              return this.tsParseModuleOrNamespaceDeclaration(node);
            }
            break;
          case "type":
            if (this.tsCheckLineTerminator(next) && tokenIsIdentifier(this.type)) {
              return this.tsParseTypeAliasDeclaration(node);
            }
            break;
        }
      }
      // Note: this won't b·e called unless the keyword is allowed in
      // `shouldParseExportDeclaration`.
      tsTryParseExportDeclaration() {
        return this.tsParseDeclaration(
          this.startNode(),
          this.value,
          /* next */
          true
        );
      }
      tsParseImportEqualsDeclaration(node, isExport) {
        node.isExport = isExport || false;
        node.id = this.parseIdent();
        this.checkLValSimple(node.id, acornScope.BIND_LEXICAL);
        super.expect(tt.eq);
        const moduleReference = this.tsParseModuleReference();
        if (node.importKind === "type" && moduleReference.type !== "TSExternalModuleReference") {
          this.raise(moduleReference.start, TypeScriptError.ImportAliasHasImportType);
        }
        node.moduleReference = moduleReference;
        super.semicolon();
        return this.finishNode(node, "TSImportEqualsDeclaration");
      }
      isExportDefaultSpecifier() {
        if (this.tsIsDeclarationStart()) return false;
        const { type } = this;
        if (tokenIsIdentifier(type)) {
          if (this.isContextual("async") || this.isContextual("let")) {
            return false;
          }
          if ((type === tokTypes2.type || type === tokTypes2.interface) && !this.containsEsc) {
            const ahead = this.lookahead();
            if (tokenIsIdentifier(ahead.type) && !this.isContextualWithState("from", ahead) || ahead.type === tt.braceL) {
              return false;
            }
          }
        } else if (!this.match(tt._default)) {
          return false;
        }
        const next = this.nextTokenStart();
        const hasFrom = this.isUnparsedContextual(next, "from");
        if (this.input.charCodeAt(next) === 44 || tokenIsIdentifier(this.type) && hasFrom) {
          return true;
        }
        if (this.match(tt._default) && hasFrom) {
          const nextAfterFrom = this.input.charCodeAt(this.nextTokenStartSince(next + 4));
          return nextAfterFrom === 34 || nextAfterFrom === 39;
        }
        return false;
      }
      parseTemplate({ isTagged = false } = {}) {
        let node = this.startNode();
        this.next();
        node.expressions = [];
        let curElt = this.parseTemplateElement({ isTagged });
        node.quasis = [curElt];
        while (!curElt.tail) {
          if (this.type === tt.eof) this.raise(this.pos, "Unterminated template literal");
          this.expect(tt.dollarBraceL);
          node.expressions.push(this.inType ? this.tsParseType() : this.parseExpression());
          this.expect(tt.braceR);
          node.quasis.push(curElt = this.parseTemplateElement({ isTagged }));
        }
        this.next();
        return this.finishNode(node, "TemplateLiteral");
      }
      parseFunction(node, statement, allowExpressionBody, isAsync, forInit) {
        this.initFunction(node);
        if (this.ecmaVersion >= 9 || this.ecmaVersion >= 6 && !isAsync) {
          if (this.type === tt.star && statement & FUNC_HANGING_STATEMENT) {
            this.unexpected();
          }
          node.generator = this.eat(tt.star);
        }
        if (this.ecmaVersion >= 8) {
          node.async = !!isAsync;
        }
        if (statement & FUNC_STATEMENT) {
          node.id = statement & FUNC_NULLABLE_ID && this.type !== tt.name ? null : this.parseIdent();
        }
        let oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos;
        const oldMaybeInArrowParameters = this.maybeInArrowParameters;
        this.maybeInArrowParameters = false;
        this.yieldPos = 0;
        this.awaitPos = 0;
        this.awaitIdentPos = 0;
        this.enterScope(functionFlags(node.async, node.generator));
        if (!(statement & FUNC_STATEMENT)) {
          node.id = this.type === tt.name ? this.parseIdent() : null;
        }
        this.parseFunctionParams(node);
        const isDeclaration = statement & FUNC_STATEMENT;
        this.parseFunctionBody(node, allowExpressionBody, false, forInit, {
          isFunctionDeclaration: isDeclaration
        });
        this.yieldPos = oldYieldPos;
        this.awaitPos = oldAwaitPos;
        this.awaitIdentPos = oldAwaitIdentPos;
        if (statement & FUNC_STATEMENT && node.id && !(statement & FUNC_HANGING_STATEMENT)) {
          if (node.body) {
            this.checkLValSimple(
              node.id,
              this.strict || node.generator || node.async ? this.treatFunctionsAsVar ? acornScope.BIND_VAR : acornScope.BIND_LEXICAL : acornScope.BIND_FUNCTION
            );
          } else {
            this.checkLValSimple(node.id, acornScope.BIND_NONE);
          }
        }
        this.maybeInArrowParameters = oldMaybeInArrowParameters;
        return this.finishNode(node, isDeclaration ? "FunctionDeclaration" : "FunctionExpression");
      }
      parseFunctionBody(node, isArrowFunction = false, isMethod = false, forInit = false, tsConfig) {
        if (this.match(tt.colon)) {
          node.returnType = this.tsParseTypeOrTypePredicateAnnotation(tt.colon);
        }
        const bodilessType = tsConfig?.isFunctionDeclaration ? "TSDeclareFunction" : tsConfig?.isClassMethod ? "TSDeclareMethod" : void 0;
        if (bodilessType && !this.match(tt.braceL) && this.isLineTerminator()) {
          return this.finishNode(node, bodilessType);
        }
        if (bodilessType === "TSDeclareFunction" && this.isAmbientContext) {
          this.raise(node.start, TypeScriptError.DeclareFunctionHasImplementation);
          if (node.declare) {
            super.parseFunctionBody(node, isArrowFunction, isMethod, false);
            return this.finishNode(node, bodilessType);
          }
        }
        super.parseFunctionBody(node, isArrowFunction, isMethod, forInit);
        return node;
      }
      parseNew() {
        if (this.containsEsc) this.raiseRecoverable(this.start, "Escape sequence in keyword new");
        let node = this.startNode();
        let meta = this.parseIdent(true);
        if (this.ecmaVersion >= 6 && this.eat(tt.dot)) {
          node.meta = meta;
          let containsEsc = this.containsEsc;
          node.property = this.parseIdent(true);
          if (node.property.name !== "target")
            this.raiseRecoverable(
              node.property.start,
              "The only valid meta property for new is 'new.target'"
            );
          if (containsEsc)
            this.raiseRecoverable(node.start, "'new.target' must not contain escaped characters");
          if (!this["allowNewDotTarget"])
            this.raiseRecoverable(
              node.start,
              "'new.target' can only be used in functions and class static block"
            );
          return this.finishNode(node, "MetaProperty");
        }
        let startPos = this.start, startLoc = this.startLoc, isImport = this.type === tt._import;
        node.callee = this.parseSubscripts(this.parseExprAtom(), startPos, startLoc, true, false);
        if (isImport && node.callee.type === "ImportExpression") {
          this.raise(startPos, "Cannot use new with import()");
        }
        const { callee } = node;
        if (callee.type === "TSInstantiationExpression" && !callee.extra?.parenthesized) {
          node.typeArguments = callee.typeArguments;
          node.callee = callee.expression;
        }
        if (this.eat(tt.parenL))
          node.arguments = this.parseExprList(tt.parenR, this.ecmaVersion >= 8, false);
        else node.arguments = [];
        return this.finishNode(node, "NewExpression");
      }
      parseExprOp(left, leftStartPos, leftStartLoc, minPrec, forInit) {
        if (tt._in.binop > minPrec && !this.hasPrecedingLineBreak()) {
          let nodeType;
          if (this.isContextual("as")) {
            nodeType = "TSAsExpression";
          }
          if (this.isContextual("satisfies")) {
            nodeType = "TSSatisfiesExpression";
          }
          if (nodeType) {
            const node = this.startNodeAt(leftStartPos, leftStartLoc);
            node.expression = left;
            const _const = this.tsTryNextParseConstantContext();
            if (_const) {
              node.typeAnnotation = _const;
            } else {
              node.typeAnnotation = this.tsNextThenParseType();
            }
            this.finishNode(node, nodeType);
            this.reScan_lt_gt();
            return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, forInit);
          }
        }
        return super.parseExprOp(left, leftStartPos, leftStartLoc, minPrec, forInit);
      }
      parseImportSpecifiers() {
        let nodes = [], first = true;
        if (acornTypeScript.tokenIsIdentifier(this.type)) {
          nodes.push(this.parseImportDefaultSpecifier());
          if (!this.eat(tt.comma)) return nodes;
        }
        if (this.type === tt.star) {
          nodes.push(this.parseImportNamespaceSpecifier());
          return nodes;
        }
        this.expect(tt.braceL);
        while (!this.eat(tt.braceR)) {
          if (!first) {
            this.expect(tt.comma);
            if (this.afterTrailingComma(tt.braceR)) break;
          } else first = false;
          nodes.push(this.parseImportSpecifier());
        }
        return nodes;
      }
      /**
       * @param {Node} node this may be ImportDeclaration |
       * TsImportEqualsDeclaration
       * @returns AnyImport
       * */
      parseImport(node) {
        let enterHead = this.lookahead();
        node.importKind = "value";
        this.importOrExportOuterKind = "value";
        if (tokenIsIdentifier(enterHead.type) || this.match(tt.star) || this.match(tt.braceL)) {
          let ahead = this.lookahead(2);
          if (
            // import type, { a } from "b";
            ahead.type !== tt.comma && // import type from "a";
            !this.isContextualWithState("from", ahead) && // import type = require("a");
            ahead.type !== tt.eq && this.ts_eatContextualWithState("type", 1, enterHead)
          ) {
            this.importOrExportOuterKind = "type";
            node.importKind = "type";
            enterHead = this.lookahead();
            ahead = this.lookahead(2);
          }
          if (tokenIsIdentifier(enterHead.type) && ahead.type === tt.eq) {
            this.next();
            const importNode = this.tsParseImportEqualsDeclaration(node);
            this.importOrExportOuterKind = "value";
            return importNode;
          }
        }
        this.next();
        if (this.type === tt.string) {
          node.specifiers = [];
          node.source = this.parseExprAtom();
        } else {
          node.specifiers = this.parseImportSpecifiers();
          this.expectContextual("from");
          node.source = this.type === tt.string ? this.parseExprAtom() : this.unexpected();
        }
        this.parseMaybeImportAttributes(node);
        this.semicolon();
        this.finishNode(node, "ImportDeclaration");
        this.importOrExportOuterKind = "value";
        if (node.importKind === "type" && node.specifiers.length > 1 && node.specifiers[0].type === "ImportDefaultSpecifier") {
          this.raise(node.start, TypeScriptError.TypeImportCannotSpecifyDefaultAndNamed);
        }
        return node;
      }
      parseExportDefaultDeclaration() {
        if (this.isAbstractClass()) {
          const cls = this.startNode();
          this.next();
          cls.abstract = true;
          return this.parseClass(cls, true);
        }
        if (this.match(tokTypes2.interface)) {
          const result = this.tsParseInterfaceDeclaration(this.startNode());
          if (result) return result;
        }
        return super.parseExportDefaultDeclaration();
      }
      parseExportAllDeclaration(node, exports$1) {
        if (this.ecmaVersion >= 11) {
          if (this.eatContextual("as")) {
            node.exported = this.parseModuleExportName();
            this.checkExport(exports$1, node.exported, this.lastTokStart);
          } else {
            node.exported = null;
          }
        }
        this.expectContextual("from");
        if (this.type !== tt.string) this.unexpected();
        node.source = this.parseExprAtom();
        this.parseMaybeImportAttributes(node);
        this.semicolon();
        return this.finishNode(node, "ExportAllDeclaration");
      }
      parseDynamicImport(node) {
        this.next();
        node.source = this.parseMaybeAssign();
        if (this.eat(tt.comma)) {
          const expr = this.parseExpression();
          node.arguments = [expr];
        }
        if (!this.eat(tt.parenR)) {
          const errorPos = this.start;
          if (this.eat(tt.comma) && this.eat(tt.parenR)) {
            this.raiseRecoverable(errorPos, "Trailing comma is not allowed in import()");
          } else {
            this.unexpected(errorPos);
          }
        }
        return this.finishNode(node, "ImportExpression");
      }
      parseExport(node, exports$1) {
        let enterHead = this.lookahead();
        if (this.ts_eatWithState(tt._import, 2, enterHead)) {
          if (this.ts_isContextual(tokTypes2.type) && this.lookaheadCharCode() !== 61) {
            node.importKind = "type";
            this.importOrExportOuterKind = "type";
            this.next();
          } else {
            node.importKind = "value";
            this.importOrExportOuterKind = "value";
          }
          const exportEqualsNode = this.tsParseImportEqualsDeclaration(
            node,
            /* isExport */
            true
          );
          this.importOrExportOuterKind = void 0;
          return exportEqualsNode;
        } else if (this.ts_eatWithState(tt.eq, 2, enterHead)) {
          const assign = node;
          assign.expression = this.parseExpression();
          this.semicolon();
          this.importOrExportOuterKind = void 0;
          return this.finishNode(assign, "TSExportAssignment");
        } else if (this.ts_eatContextualWithState("as", 2, enterHead)) {
          const decl = node;
          this.expectContextual("namespace");
          decl.id = this.parseIdent();
          this.semicolon();
          this.importOrExportOuterKind = void 0;
          return this.finishNode(decl, "TSNamespaceExportDeclaration");
        } else {
          const lookahead2 = this.lookahead(2).type;
          if (this.ts_isContextualWithState(enterHead, tokTypes2.type) && (lookahead2 === tt.braceL || // export type { ... }
          lookahead2 === tt.star)) {
            this.next();
            this.importOrExportOuterKind = "type";
            node.exportKind = "type";
          } else {
            this.importOrExportOuterKind = "value";
            node.exportKind = "value";
          }
          this.next();
          if (this.eat(tt.star)) {
            return this.parseExportAllDeclaration(node, exports$1);
          }
          if (this.eat(tt._default)) {
            this.checkExport(exports$1, "default", this.lastTokStart);
            node.declaration = this.parseExportDefaultDeclaration();
            return this.finishNode(node, "ExportDefaultDeclaration");
          }
          if (this.shouldParseExportStatement()) {
            node.declaration = this.parseExportDeclaration(node);
            if (node.declaration.type === "VariableDeclaration")
              this.checkVariableExport(exports$1, node.declaration.declarations);
            else this.checkExport(exports$1, node.declaration.id, node.declaration.id.start);
            node.specifiers = [];
            node.source = null;
          } else {
            node.declaration = null;
            node.specifiers = this.parseExportSpecifiers(exports$1);
            if (this.eatContextual("from")) {
              if (this.type !== tt.string) this.unexpected();
              node.source = this.parseExprAtom();
              this.parseMaybeImportAttributes(node);
            } else {
              for (let spec of node.specifiers) {
                this.checkUnreserved(spec.local);
                this.checkLocalExport(spec.local);
                if (spec.local.type === "Literal") {
                  this.raise(
                    spec.local.start,
                    "A string literal cannot be used as an exported binding without `from`."
                  );
                }
              }
              node.source = null;
            }
            this.semicolon();
          }
          return this.finishNode(node, "ExportNamedDeclaration");
        }
      }
      checkExport(exports$1, name, _) {
        if (!exports$1) {
          return;
        }
        if (typeof name !== "string") {
          name = name.type === "Identifier" ? name.name : name.value;
        }
        exports$1[name] = true;
      }
      parseMaybeDefault(startPos, startLoc, left) {
        const node = super.parseMaybeDefault(startPos, startLoc, left);
        if (node.type === "AssignmentPattern" && node.typeAnnotation && node.right.start < node.typeAnnotation.start) {
          this.raise(node.typeAnnotation.start, TypeScriptError.TypeAnnotationAfterAssign);
        }
        return node;
      }
      typeCastToParameter(node) {
        node.expression.typeAnnotation = node.typeAnnotation;
        this.resetEndLocation(
          node.expression,
          node.typeAnnotation.end,
          node.typeAnnotation.loc?.end
        );
        return node.expression;
      }
      toAssignableList(exprList, isBinding) {
        if (!exprList) exprList = [];
        for (let i = 0; i < exprList.length; i++) {
          const expr = exprList[i];
          if (expr?.type === "TSTypeCastExpression") {
            exprList[i] = this.typeCastToParameter(expr);
          }
        }
        return super.toAssignableList(exprList, isBinding);
      }
      reportReservedArrowTypeParam(node) {
        if (node.params.length === 1 && !node.extra?.trailingComma && disallowAmbiguousJSXLike) ;
      }
      parseExprAtom(refDestructuringErrors, forInit, forNew) {
        if (this.type === tokTypes2.jsxText) {
          return this.jsx_parseText();
        } else if (this.type === tokTypes2.jsxTagStart) {
          return this.jsx_parseElement();
        } else if (this.type === tokTypes2.at) {
          this.parseDecorators();
          return this.parseExprAtom();
        } else if (tokenIsIdentifier(this.type)) {
          let canBeArrow = this.potentialArrowAt === this.start;
          let startPos = this.start, startLoc = this.startLoc, containsEsc = this.containsEsc;
          let id = this.parseIdent(false);
          if (this.ecmaVersion >= 8 && !containsEsc && id.name === "async" && !this.canInsertSemicolon() && this.eat(tt._function)) {
            this.overrideContext(tokContexts.f_expr);
            return this.parseFunction(
              this.startNodeAt(startPos, startLoc),
              0,
              false,
              true,
              forInit
            );
          }
          if (canBeArrow && !this.canInsertSemicolon()) {
            if (this.eat(tt.arrow))
              return this.parseArrowExpression(
                this.startNodeAt(startPos, startLoc),
                [id],
                false,
                forInit
              );
            if (this.ecmaVersion >= 8 && id.name === "async" && this.type === tt.name && !containsEsc && (!this.potentialArrowInForAwait || this.value !== "of" || this.containsEsc)) {
              id = this.parseIdent(false);
              if (this.canInsertSemicolon() || !this.eat(tt.arrow)) this.unexpected();
              return this.parseArrowExpression(
                this.startNodeAt(startPos, startLoc),
                [id],
                true,
                forInit
              );
            }
          }
          return id;
        } else {
          return super.parseExprAtom(refDestructuringErrors, forInit, forNew);
        }
      }
      parseExprAtomDefault() {
        if (tokenIsIdentifier(this.type)) {
          const canBeArrow = this["potentialArrowAt"] === this.start;
          const containsEsc = this.containsEsc;
          const id = this.parseIdent();
          if (!containsEsc && id.name === "async" && !this.canInsertSemicolon()) {
            const { type } = this;
            if (type === tt._function) {
              this.next();
              return this.parseFunction(this.startNodeAtNode(id), void 0, true, true);
            } else if (tokenIsIdentifier(type)) {
              if (this.lookaheadCharCode() === 61) {
                const paramId = this.parseIdent(false);
                if (this.canInsertSemicolon() || !this.eat(tt.arrow)) this.unexpected();
                return this.parseArrowExpression(this.startNodeAtNode(id), [paramId], true);
              } else {
                return id;
              }
            }
          }
          if (canBeArrow && this.match(tt.arrow) && !this.canInsertSemicolon()) {
            this.next();
            return this.parseArrowExpression(this.startNodeAtNode(id), [id], false);
          }
          return id;
        } else {
          this.unexpected();
        }
      }
      parseIdentNode() {
        let node = this.startNode();
        if (tokenIsKeywordOrIdentifier(this.type) && // Taken from super-class method
        !((this.type.keyword === "class" || this.type.keyword === "function") && (this.lastTokEnd !== this.lastTokStart + 1 || this.input.charCodeAt(this.lastTokStart) !== 46))) {
          node.name = this.value;
        } else {
          return super.parseIdentNode();
        }
        return node;
      }
      parseVarStatement(node, kind, allowMissingInitializer = false) {
        const { isAmbientContext } = this;
        this.next();
        super.parseVar(node, false, kind, allowMissingInitializer || isAmbientContext);
        this.semicolon();
        const declaration = this.finishNode(node, "VariableDeclaration");
        if (!isAmbientContext) return declaration;
        for (const { id, init } of declaration.declarations) {
          if (!init) continue;
          if (kind !== "const" || !!id.typeAnnotation) {
            this.raise(init.start, TypeScriptError.InitializerNotAllowedInAmbientContext);
          } else if (init.type !== "StringLiteral" && init.type !== "BooleanLiteral" && init.type !== "NumericLiteral" && init.type !== "BigIntLiteral" && (init.type !== "TemplateLiteral" || init.expressions.length > 0) && !isPossiblyLiteralEnum(init)) {
            this.raise(
              init.start,
              TypeScriptError.ConstInitiailizerMustBeStringOrNumericLiteralOrLiteralEnumReference
            );
          }
        }
        return declaration;
      }
      parseStatement(context, topLevel, exports$1) {
        if (this.match(tokTypes2.at)) {
          this.parseDecorators(true);
        }
        if (this.match(tt._const) && this.isLookaheadContextual("enum")) {
          const node = this.startNode();
          this.expect(tt._const);
          return this.tsParseEnumDeclaration(node, { const: true });
        }
        if (this.ts_isContextual(tokTypes2.enum)) {
          return this.tsParseEnumDeclaration(this.startNode());
        }
        if (this.ts_isContextual(tokTypes2.interface)) {
          const result = this.tsParseInterfaceDeclaration(this.startNode());
          if (result) return result;
        }
        return super.parseStatement(context, topLevel, exports$1);
      }
      // NOTE: unused function
      parseAccessModifier() {
        return this.tsParseModifier(["public", "protected", "private"]);
      }
      parsePostMemberNameModifiers(methodOrProp) {
        const optional = this.eat(tt.question);
        if (optional) methodOrProp.optional = true;
        if (methodOrProp.readonly && this.match(tt.parenL)) {
          this.raise(methodOrProp.start, TypeScriptError.ClassMethodHasReadonly);
        }
        if (methodOrProp.declare && this.match(tt.parenL)) {
          this.raise(methodOrProp.start, TypeScriptError.ClassMethodHasDeclare);
        }
      }
      // Note: The reason we do this in `parseExpressionStatement` and not `parseStatement`
      // is that e.g. `type()` is valid JS, so we must try parsing that first.
      // If it's really a type, we will parse `type` as the statement, and can correct it here
      // by parsing the rest.
      parseExpressionStatement(node, expr) {
        const decl = expr.type === "Identifier" ? this.tsParseExpressionStatement(node, expr) : void 0;
        return decl || super.parseExpressionStatement(node, expr);
      }
      shouldParseExportStatement() {
        if (this.tsIsDeclarationStart()) return true;
        if (this.match(tokTypes2.at)) {
          return true;
        }
        return super.shouldParseExportStatement();
      }
      parseConditional(expr, startPos, startLoc, forInit, refDestructuringErrors) {
        if (this.eat(tt.question)) {
          let node = this.startNodeAt(startPos, startLoc);
          node.test = expr;
          node.consequent = this.parseMaybeAssign();
          this.expect(tt.colon);
          node.alternate = this.parseMaybeAssign(forInit);
          return this.finishNode(node, "ConditionalExpression");
        }
        return expr;
      }
      parseMaybeConditional(forInit, refDestructuringErrors) {
        let startPos = this.start, startLoc = this.startLoc;
        let expr = this.parseExprOps(forInit, refDestructuringErrors);
        if (this.checkExpressionErrors(refDestructuringErrors)) return expr;
        if (!this.maybeInArrowParameters || !this.match(tt.question)) {
          return this.parseConditional(expr, startPos, startLoc, forInit, refDestructuringErrors);
        }
        const result = this.tryParse(
          () => this.parseConditional(expr, startPos, startLoc, forInit, refDestructuringErrors)
        );
        if (!result.node) {
          if (result.error) {
            this.setOptionalParametersError(refDestructuringErrors, result.error);
          }
          return expr;
        }
        if (result.error) this.setLookaheadState(result.failState);
        return result.node;
      }
      parseParenItem(node) {
        const startPos = this.start;
        const startLoc = this.startLoc;
        node = super.parseParenItem(node);
        if (this.eat(tt.question)) {
          node.optional = true;
          this.resetEndLocation(node);
        }
        if (this.match(tt.colon)) {
          const typeCastNode = this.startNodeAt(startPos, startLoc);
          typeCastNode.expression = node;
          typeCastNode.typeAnnotation = this.tsParseTypeAnnotation();
          return this.finishNode(typeCastNode, "TSTypeCastExpression");
        }
        return node;
      }
      parseExportDeclaration(node) {
        if (!this.isAmbientContext && this.ts_isContextual(tokTypes2.declare)) {
          return this.tsInAmbientContext(() => this.parseExportDeclaration(node));
        }
        const startPos = this.start;
        const startLoc = this.startLoc;
        const isDeclare = this.eatContextual("declare");
        if (isDeclare && (this.ts_isContextual(tokTypes2.declare) || !this.shouldParseExportStatement())) {
          this.raise(this.start, TypeScriptError.ExpectedAmbientAfterExportDeclare);
        }
        const isIdentifier = tokenIsIdentifier(this.type);
        const declaration = isIdentifier && this.tsTryParseExportDeclaration() || this.parseStatement(null);
        if (!declaration) return null;
        if (declaration.type === "TSInterfaceDeclaration" || declaration.type === "TSTypeAliasDeclaration" || isDeclare) {
          node.exportKind = "type";
        }
        if (isDeclare) {
          this.resetStartLocation(declaration, startPos, startLoc);
          declaration.declare = true;
        }
        return declaration;
      }
      parseClassId(node, isStatement) {
        if (!isStatement && this.isContextual("implements")) {
          return;
        }
        super.parseClassId(node, isStatement);
        const typeParameters = this.tsTryParseTypeParameters(this.tsParseInOutModifiers.bind(this));
        if (typeParameters) node.typeParameters = typeParameters;
      }
      parseClassPropertyAnnotation(node) {
        if (!node.optional) {
          if (this.value === "!" && this.eat(tt.prefix)) {
            node.definite = true;
          } else if (this.eat(tt.question)) {
            node.optional = true;
          }
        }
        const type = this.tsTryParseTypeAnnotation();
        if (type) node.typeAnnotation = type;
      }
      parseClassField(field) {
        const isPrivate = field.key.type === "PrivateIdentifier";
        if (isPrivate) {
          if (field.abstract) {
            this.raise(field.start, TypeScriptError.PrivateElementHasAbstract);
          }
          if (field.accessibility) {
            this.raise(
              field.start,
              TypeScriptError.PrivateElementHasAccessibility({
                modifier: field.accessibility
              })
            );
          }
          this.parseClassPropertyAnnotation(field);
        } else {
          this.parseClassPropertyAnnotation(field);
          if (this.isAmbientContext && !(field.readonly && !field.typeAnnotation) && this.match(tt.eq)) {
            this.raise(this.start, TypeScriptError.DeclareClassFieldHasInitializer);
          }
          if (field.abstract && this.match(tt.eq)) {
            const { key } = field;
            this.raise(
              this.start,
              TypeScriptError.AbstractPropertyHasInitializer({
                propertyName: key.type === "Identifier" && !field.computed ? key.name : `[${this.input.slice(key.start, key.end)}]`
              })
            );
          }
        }
        return super.parseClassField(field);
      }
      parseClassMethod(method, isGenerator, isAsync, allowsDirectSuper) {
        const isConstructor = method.kind === "constructor";
        const isPrivate = method.key.type === "PrivateIdentifier";
        const typeParameters = this.tsTryParseTypeParameters(this.tsParseConstModifier);
        if (isPrivate) {
          if (typeParameters) method.typeParameters = typeParameters;
          if (method.accessibility) {
            this.raise(
              method.start,
              TypeScriptError.PrivateMethodsHasAccessibility({
                modifier: method.accessibility
              })
            );
          }
        } else {
          if (typeParameters && isConstructor) {
            this.raise(typeParameters.start, TypeScriptError.ConstructorHasTypeParameters);
          }
        }
        const { declare = false, kind } = method;
        if (declare && (kind === "get" || kind === "set")) {
          this.raise(method.start, TypeScriptError.DeclareAccessor({ kind }));
        }
        if (typeParameters) method.typeParameters = typeParameters;
        const key = method.key;
        if (method.kind === "constructor") {
          if (isGenerator) this.raise(key.start, "Constructor can't be a generator");
          if (isAsync) this.raise(key.start, "Constructor can't be an async method");
        } else if (method.static && checkKeyName(method, "prototype")) {
          this.raise(key.start, "Classes may not have a static property named prototype");
        }
        const value = method.value = this.parseMethod(
          isGenerator,
          isAsync,
          allowsDirectSuper,
          true,
          method
        );
        if (method.kind === "get" && value["params"].length !== 0)
          this.raiseRecoverable(value.start, "getter should have no params");
        if (method.kind === "set" && value["params"].length !== 1)
          this.raiseRecoverable(value.start, "setter should have exactly one param");
        if (method.kind === "set" && value["params"][0].type === "RestElement")
          this.raiseRecoverable(value["params"][0].start, "Setter cannot use rest params");
        return this.finishNode(method, "MethodDefinition");
      }
      isClassMethod() {
        return this.match(tt.relational);
      }
      parseClassElement(constructorAllowsSuper) {
        if (this.eat(tt.semi)) return null;
        let node = this.startNode();
        let keyName = "";
        let isGenerator = false;
        let isAsync = false;
        let kind = "method";
        let isStatic = false;
        const modifiers = [
          "declare",
          "private",
          "public",
          "protected",
          "accessor",
          "override",
          "abstract",
          "readonly",
          "static"
        ];
        const modifierMap = this.tsParseModifiers({
          modified: node,
          allowedModifiers: modifiers,
          disallowedModifiers: ["in", "out"],
          stopOnStartOfClassStaticBlock: true,
          errorTemplate: TypeScriptError.InvalidModifierOnTypeParameterPositions
        });
        isStatic = Boolean(modifierMap.static);
        const callParseClassMemberWithIsStatic = () => {
          if (this.tsIsStartOfStaticBlocks()) {
            this.next();
            this.next();
            if (this.tsHasSomeModifiers(node, modifiers)) {
              this.raise(this.start, TypeScriptError.StaticBlockCannotHaveModifier);
            }
            if (this.ecmaVersion >= 13) {
              super.parseClassStaticBlock(node);
              return node;
            }
          } else {
            const idx = this.tsTryParseIndexSignature(node);
            if (idx) {
              if (node.abstract) {
                this.raise(node.start, TypeScriptError.IndexSignatureHasAbstract);
              }
              if (node.accessibility) {
                this.raise(
                  node.start,
                  TypeScriptError.IndexSignatureHasAccessibility({
                    modifier: node.accessibility
                  })
                );
              }
              if (node.declare) {
                this.raise(node.start, TypeScriptError.IndexSignatureHasDeclare);
              }
              if (node.override) {
                this.raise(node.start, TypeScriptError.IndexSignatureHasOverride);
              }
              return idx;
            }
            if (!this.inAbstractClass && node.abstract) {
              this.raise(node.start, TypeScriptError.NonAbstractClassHasAbstractMethod);
            }
            if (node.override) {
              if (!constructorAllowsSuper) {
                this.raise(node.start, TypeScriptError.OverrideNotInSubClass);
              }
            }
            node.static = isStatic;
            if (isStatic) {
              if (!(this.isClassElementNameStart() || this.type === tt.star)) {
                keyName = "static";
              }
            }
            if (!keyName && this.ecmaVersion >= 8 && this.eatContextual("async")) {
              if ((this.isClassElementNameStart() || this.type === tt.star) && !this.canInsertSemicolon()) {
                isAsync = true;
              } else {
                keyName = "async";
              }
            }
            if (!keyName && (this.ecmaVersion >= 9 || !isAsync) && this.eat(tt.star)) {
              isGenerator = true;
            }
            if (!keyName && !isAsync && !isGenerator) {
              const lastValue = this.value;
              if (this.eatContextual("get") || this.eatContextual("set")) {
                if (this.isClassElementNameStart()) {
                  kind = lastValue;
                } else {
                  keyName = lastValue;
                }
              }
            }
            if (keyName) {
              node.computed = false;
              node.key = this.startNodeAt(this.lastTokStart, this.lastTokStartLoc);
              node.key.name = keyName;
              this.finishNode(node.key, "Identifier");
            } else {
              this.parseClassElementName(node);
            }
            this.parsePostMemberNameModifiers(node);
            if (this.isClassMethod() || this.ecmaVersion < 13 || this.type === tt.parenL || kind !== "method" || isGenerator || isAsync) {
              const isConstructor = !node.static && checkKeyName(node, "constructor");
              const allowsDirectSuper = isConstructor && constructorAllowsSuper;
              if (isConstructor && kind !== "method")
                this.raise(node.key.start, "Constructor can't have get/set modifier");
              node.kind = isConstructor ? "constructor" : kind;
              this.parseClassMethod(node, isGenerator, isAsync, allowsDirectSuper);
            } else {
              this.parseClassField(node);
            }
            return node;
          }
        };
        if (node.declare) {
          this.tsInAmbientContext(callParseClassMemberWithIsStatic);
        } else {
          callParseClassMemberWithIsStatic();
        }
        return node;
      }
      isClassElementNameStart() {
        if (this.tsIsIdentifier()) {
          return true;
        }
        return super.isClassElementNameStart();
      }
      parseClassSuper(node) {
        super.parseClassSuper(node);
        if (node.superClass && (this.tsMatchLeftRelational() || this.match(tt.bitShift))) {
          node.superTypeParameters = this.tsParseTypeArgumentsInExpression();
        }
        if (this.eatContextual("implements")) {
          node.implements = this.tsParseHeritageClause("implements");
        }
      }
      parseFunctionParams(node) {
        const typeParameters = this.tsTryParseTypeParameters(this.tsParseConstModifier);
        if (typeParameters) node.typeParameters = typeParameters;
        super.parseFunctionParams(node);
      }
      // `let x: number;`
      parseVarId(decl, kind) {
        super.parseVarId(decl, kind);
        if (decl.id.type === "Identifier" && !this.hasPrecedingLineBreak() && this.value === "!" && this.eat(tt.prefix)) {
          decl.definite = true;
        }
        const type = this.tsTryParseTypeAnnotation();
        if (type) {
          decl.id.typeAnnotation = type;
          this.resetEndLocation(decl.id);
        }
      }
      // parse the return type of an async arrow function - let foo = (async (): number => {});
      parseArrowExpression(node, params, isAsync, forInit) {
        if (this.match(tt.colon)) {
          node.returnType = this.tsParseTypeAnnotation();
        }
        let oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos;
        this.enterScope(functionFlags(isAsync, false) | acornScope.SCOPE_ARROW);
        this.initFunction(node);
        const oldMaybeInArrowParameters = this.maybeInArrowParameters;
        if (this.ecmaVersion >= 8) node.async = !!isAsync;
        this.yieldPos = 0;
        this.awaitPos = 0;
        this.awaitIdentPos = 0;
        this.maybeInArrowParameters = true;
        node.params = this.toAssignableList(params, true);
        this.maybeInArrowParameters = false;
        this.parseFunctionBody(node, true, false, forInit);
        this.yieldPos = oldYieldPos;
        this.awaitPos = oldAwaitPos;
        this.awaitIdentPos = oldAwaitIdentPos;
        this.maybeInArrowParameters = oldMaybeInArrowParameters;
        return this.finishNode(node, "ArrowFunctionExpression");
      }
      parseMaybeAssignOrigin(forInit, refDestructuringErrors, afterLeftParse) {
        if (this.isContextual("yield")) {
          if (this.inGenerator) return this.parseYield(forInit);
          else this.exprAllowed = false;
        }
        let ownDestructuringErrors = false, oldParenAssign = -1, oldTrailingComma = -1, oldDoubleProto = -1;
        if (refDestructuringErrors) {
          oldParenAssign = refDestructuringErrors.parenthesizedAssign;
          oldTrailingComma = refDestructuringErrors.trailingComma;
          oldDoubleProto = refDestructuringErrors.doubleProto;
          refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = -1;
        } else {
          refDestructuringErrors = new DestructuringErrors();
          ownDestructuringErrors = true;
        }
        let startPos = this.start, startLoc = this.startLoc;
        if (this.type === tt.parenL || tokenIsIdentifier(this.type)) {
          this.potentialArrowAt = this.start;
          this.potentialArrowInForAwait = forInit === "await";
        }
        let left = this.parseMaybeConditional(forInit, refDestructuringErrors);
        if (afterLeftParse) left = afterLeftParse.call(this, left, startPos, startLoc);
        if (this.type.isAssign) {
          let node = this.startNodeAt(startPos, startLoc);
          node.operator = this.value;
          if (this.type === tt.eq) left = this.toAssignable(left, true, refDestructuringErrors);
          if (!ownDestructuringErrors) {
            refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = refDestructuringErrors.doubleProto = -1;
          }
          if (refDestructuringErrors.shorthandAssign >= left.start)
            refDestructuringErrors.shorthandAssign = -1;
          if (!this.maybeInArrowParameters) {
            if (this.type === tt.eq) this.checkLValPattern(left);
            else this.checkLValSimple(left);
          }
          node.left = left;
          this.next();
          node.right = this.parseMaybeAssign(forInit);
          if (oldDoubleProto > -1) refDestructuringErrors.doubleProto = oldDoubleProto;
          return this.finishNode(node, "AssignmentExpression");
        } else {
          if (ownDestructuringErrors) this.checkExpressionErrors(refDestructuringErrors, true);
        }
        if (oldParenAssign > -1) refDestructuringErrors.parenthesizedAssign = oldParenAssign;
        if (oldTrailingComma > -1) refDestructuringErrors.trailingComma = oldTrailingComma;
        return left;
      }
      parseMaybeAssign(forInit, refExpressionErrors, afterLeftParse) {
        let state;
        let typeCast;
        if (!this.tsMatchLeftRelational()) {
          return this.parseMaybeAssignOrigin(forInit, refExpressionErrors, afterLeftParse);
        }
        if (!state || this.compareLookaheadState(state, this.getCurLookaheadState())) {
          state = this.cloneCurLookaheadState();
        }
        let typeParameters;
        const arrow = this.tryParse((abort) => {
          typeParameters = this.tsParseTypeParameters(this.tsParseConstModifier);
          const expr = this.parseMaybeAssignOrigin(forInit, refExpressionErrors, afterLeftParse);
          if (expr.type !== "ArrowFunctionExpression" || expr.extra?.parenthesized) {
            abort();
          }
          if (typeParameters?.params.length !== 0) {
            this.resetStartLocationFromNode(expr, typeParameters);
          }
          expr.typeParameters = typeParameters;
          return expr;
        }, state);
        if (!arrow.error && !arrow.aborted) {
          if (typeParameters) this.reportReservedArrowTypeParam(typeParameters);
          return arrow.node;
        }
        {
          assert(true);
          typeCast = this.tryParse(
            () => this.parseMaybeAssignOrigin(forInit, refExpressionErrors, afterLeftParse),
            state
          );
          if (!typeCast.error) return typeCast.node;
        }
        if (arrow.node) {
          this.setLookaheadState(arrow.failState);
          if (typeParameters) this.reportReservedArrowTypeParam(typeParameters);
          return arrow.node;
        }
        if (typeCast?.node) {
          this.setLookaheadState(typeCast.failState);
          return typeCast.node;
        }
        if (arrow.thrown) throw arrow.error;
        if (typeCast?.thrown) throw typeCast.error;
        throw arrow.error || typeCast?.error;
      }
      parseAssignableListItem(allowModifiers) {
        const decorators = [];
        while (this.match(tokTypes2.at)) {
          decorators.push(this.parseDecorator());
        }
        const startPos = this.start;
        const startLoc = this.startLoc;
        let accessibility;
        let readonly = false;
        let override = false;
        if (allowModifiers !== void 0) {
          const modified = {};
          this.tsParseModifiers({
            modified,
            allowedModifiers: ["public", "private", "protected", "override", "readonly"]
          });
          accessibility = modified.accessibility;
          override = modified.override;
          readonly = modified.readonly;
          if (allowModifiers === false && (accessibility || readonly || override)) {
            this.raise(startLoc.column, TypeScriptError.UnexpectedParameterModifier);
          }
        }
        const left = this.parseMaybeDefault(startPos, startLoc);
        this.parseBindingListItem(left);
        const elt = this.parseMaybeDefault(left["start"], left["loc"], left);
        if (decorators.length) {
          elt.decorators = decorators;
        }
        if (accessibility || readonly || override) {
          const pp = this.startNodeAt(startPos, startLoc);
          if (accessibility) pp.accessibility = accessibility;
          if (readonly) pp.readonly = readonly;
          if (override) pp.override = override;
          if (elt.type !== "Identifier" && elt.type !== "AssignmentPattern") {
            this.raise(pp.start, TypeScriptError.UnsupportedParameterPropertyKind);
          }
          pp.parameter = elt;
          return this.finishNode(pp, "TSParameterProperty");
        }
        return elt;
      }
      // AssignmentPattern
      checkLValInnerPattern(expr, bindingType = acornScope.BIND_NONE, checkClashes) {
        switch (expr.type) {
          case "TSParameterProperty":
            this.checkLValInnerPattern(expr.parameter, bindingType, checkClashes);
            break;
          default: {
            super.checkLValInnerPattern(expr, bindingType, checkClashes);
            break;
          }
        }
      }
      // Allow type annotations inside of a parameter list.
      parseBindingListItem(param) {
        if (this.eat(tt.question)) {
          if (param.type !== "Identifier" && !this.isAmbientContext && !this.inType) {
            this.raise(param.start, TypeScriptError.PatternIsOptional);
          }
          param.optional = true;
        }
        const type = this.tsTryParseTypeAnnotation();
        if (type) param.typeAnnotation = type;
        this.resetEndLocation(param);
        return param;
      }
      isAssignable(node, isBinding) {
        switch (node.type) {
          case "TSTypeCastExpression":
            return this.isAssignable(node.expression, isBinding);
          case "TSParameterProperty":
            return true;
          case "Identifier":
          case "ObjectPattern":
          case "ArrayPattern":
          case "AssignmentPattern":
          case "RestElement":
            return true;
          case "ObjectExpression": {
            const last = node.properties.length - 1;
            return node.properties.every((prop, i) => {
              return prop.type !== "ObjectMethod" && (i === last || prop.type !== "SpreadElement") && this.isAssignable(prop);
            });
          }
          case "Property":
          case "ObjectProperty":
            return this.isAssignable(node.value);
          case "SpreadElement":
            return this.isAssignable(node.argument);
          case "ArrayExpression":
            return node.elements.every(
              (element) => element === null || this.isAssignable(element)
            );
          case "AssignmentExpression":
            return node.operator === "=";
          case "ParenthesizedExpression":
            return this.isAssignable(node.expression);
          case "MemberExpression":
          case "OptionalMemberExpression":
            return !isBinding;
          default:
            return false;
        }
      }
      toAssignable(node, isBinding = false, refDestructuringErrors = new DestructuringErrors()) {
        switch (node.type) {
          case "ParenthesizedExpression":
            return this.toAssignableParenthesizedExpression(
              node,
              isBinding,
              refDestructuringErrors
            );
          case "TSAsExpression":
          case "TSSatisfiesExpression":
          case "TSNonNullExpression":
          case "TSTypeAssertion":
            if (isBinding) ; else {
              this.raise(node.start, TypeScriptError.UnexpectedTypeCastInParameter);
            }
            return this.toAssignable(node.expression, isBinding, refDestructuringErrors);
          case "MemberExpression":
            break;
          case "AssignmentExpression":
            if (!isBinding && node.left.type === "TSTypeCastExpression") {
              node.left = this.typeCastToParameter(node.left);
            }
            return super.toAssignable(node, isBinding, refDestructuringErrors);
          case "TSTypeCastExpression": {
            return this.typeCastToParameter(node);
          }
          default:
            return super.toAssignable(node, isBinding, refDestructuringErrors);
        }
        return node;
      }
      toAssignableParenthesizedExpression(node, isBinding, refDestructuringErrors) {
        switch (node.expression.type) {
          case "TSAsExpression":
          case "TSSatisfiesExpression":
          case "TSNonNullExpression":
          case "TSTypeAssertion":
          case "ParenthesizedExpression":
            return this.toAssignable(node.expression, isBinding, refDestructuringErrors);
          default:
            return super.toAssignable(node, isBinding, refDestructuringErrors);
        }
      }
      parseBindingAtom() {
        switch (this.type) {
          case tt._this:
            return this.parseIdent(
              /* liberal */
              true
            );
          default:
            return super.parseBindingAtom();
        }
      }
      shouldParseArrow(exprList) {
        let shouldParseArrowRes;
        if (this.match(tt.colon)) {
          shouldParseArrowRes = exprList.every((expr) => this.isAssignable(expr, true));
        } else {
          shouldParseArrowRes = !this.canInsertSemicolon();
        }
        if (shouldParseArrowRes) {
          if (this.match(tt.colon)) {
            const result = this.tryParse((abort) => {
              const returnType = this.tsParseTypeOrTypePredicateAnnotation(tt.colon);
              if (this.canInsertSemicolon() || !this.match(tt.arrow)) abort();
              return returnType;
            });
            if (result.aborted) {
              this.shouldParseArrowReturnType = void 0;
              return false;
            }
            if (!result.thrown) {
              if (result.error) this.setLookaheadState(result.failState);
              this.shouldParseArrowReturnType = result.node;
            }
          }
          if (!this.match(tt.arrow)) {
            this.shouldParseArrowReturnType = void 0;
            return false;
          }
          return true;
        }
        this.shouldParseArrowReturnType = void 0;
        return shouldParseArrowRes;
      }
      parseParenArrowList(startPos, startLoc, exprList, forInit) {
        const node = this.startNodeAt(startPos, startLoc);
        node.returnType = this.shouldParseArrowReturnType;
        this.shouldParseArrowReturnType = void 0;
        return this.parseArrowExpression(node, exprList, false, forInit);
      }
      parseParenAndDistinguishExpression(canBeArrow, forInit) {
        let startPos = this.start, startLoc = this.startLoc, val, allowTrailingComma = this.ecmaVersion >= 8;
        if (this.ecmaVersion >= 6) {
          const oldMaybeInArrowParameters = this.maybeInArrowParameters;
          this.maybeInArrowParameters = true;
          this.next();
          let innerStartPos = this.start, innerStartLoc = this.startLoc;
          let exprList = [], first = true, lastIsComma = false;
          let refDestructuringErrors = new DestructuringErrors(), oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, spreadStart;
          this.yieldPos = 0;
          this.awaitPos = 0;
          while (this.type !== tt.parenR) {
            first ? first = false : this.expect(tt.comma);
            if (allowTrailingComma && this.afterTrailingComma(tt.parenR, true)) {
              lastIsComma = true;
              break;
            } else if (this.type === tt.ellipsis) {
              spreadStart = this.start;
              exprList.push(this.parseParenItem(this.parseRestBinding()));
              if (this.type === tt.comma) {
                this.raise(this.start, "Comma is not permitted after the rest element");
              }
              break;
            } else {
              exprList.push(
                this.parseMaybeAssign(forInit, refDestructuringErrors, this.parseParenItem)
              );
            }
          }
          let innerEndPos = this.lastTokEnd, innerEndLoc = this.lastTokEndLoc;
          this.expect(tt.parenR);
          this.maybeInArrowParameters = oldMaybeInArrowParameters;
          if (canBeArrow && this.shouldParseArrow(exprList) && this.eat(tt.arrow)) {
            this.checkPatternErrors(refDestructuringErrors, false);
            this.checkYieldAwaitInDefaultParams();
            this.yieldPos = oldYieldPos;
            this.awaitPos = oldAwaitPos;
            return this.parseParenArrowList(startPos, startLoc, exprList, forInit);
          }
          if (!exprList.length || lastIsComma) this.unexpected(this.lastTokStart);
          if (spreadStart) this.unexpected(spreadStart);
          this.checkExpressionErrors(refDestructuringErrors, true);
          this.yieldPos = oldYieldPos || this.yieldPos;
          this.awaitPos = oldAwaitPos || this.awaitPos;
          if (exprList.length > 1) {
            val = this.startNodeAt(innerStartPos, innerStartLoc);
            val.expressions = exprList;
            this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc);
          } else {
            val = exprList[0];
          }
        } else {
          val = this.parseParenExpression();
        }
        if (this.options.preserveParens) {
          let par = this.startNodeAt(startPos, startLoc);
          par.expression = val;
          return this.finishNode(par, "ParenthesizedExpression");
        } else {
          return val;
        }
      }
      parseTaggedTemplateExpression(base, startPos, startLoc, optionalChainMember) {
        const node = this.startNodeAt(startPos, startLoc);
        node.tag = base;
        node.quasi = this.parseTemplate({ isTagged: true });
        if (optionalChainMember) {
          this.raise(
            startPos,
            "Tagged Template Literals are not allowed in optionalChain."
          );
        }
        return this.finishNode(node, "TaggedTemplateExpression");
      }
      shouldParseAsyncArrow() {
        if (this.match(tt.colon)) {
          const result = this.tryParse((abort) => {
            const returnType = this.tsParseTypeOrTypePredicateAnnotation(tt.colon);
            if (this.canInsertSemicolon() || !this.match(tt.arrow)) abort();
            return returnType;
          });
          if (result.aborted) {
            this.shouldParseAsyncArrowReturnType = void 0;
            return false;
          }
          if (!result.thrown) {
            if (result.error) this.setLookaheadState(result.failState);
            this.shouldParseAsyncArrowReturnType = result.node;
            return !this.canInsertSemicolon() && this.eat(tt.arrow);
          }
        } else {
          return !this.canInsertSemicolon() && this.eat(tt.arrow);
        }
      }
      parseSubscriptAsyncArrow(startPos, startLoc, exprList, forInit) {
        const arrN = this.startNodeAt(startPos, startLoc);
        arrN.returnType = this.shouldParseAsyncArrowReturnType;
        this.shouldParseAsyncArrowReturnType = void 0;
        return this.parseArrowExpression(arrN, exprList, true, forInit);
      }
      parseExprList(close, allowTrailingComma, allowEmpty, refDestructuringErrors) {
        let elts = [], first = true;
        while (!this.eat(close)) {
          if (!first) {
            this.expect(tt.comma);
            if (allowTrailingComma && this.afterTrailingComma(close)) break;
          } else first = false;
          let elt;
          if (allowEmpty && this.type === tt.comma) elt = null;
          else if (this.type === tt.ellipsis) {
            elt = this.parseSpread(refDestructuringErrors);
            if (this.maybeInArrowParameters && this.match(tt.colon)) {
              elt.typeAnnotation = this.tsParseTypeAnnotation();
            }
            if (refDestructuringErrors && this.type === tt.comma && refDestructuringErrors.trailingComma < 0)
              refDestructuringErrors.trailingComma = this.start;
          } else {
            elt = this.parseMaybeAssign(false, refDestructuringErrors, this.parseParenItem);
          }
          elts.push(elt);
        }
        return elts;
      }
      parseSubscript(base, startPos, startLoc, noCalls, maybeAsyncArrow, optionalChained, forInit) {
        let _optionalChained = optionalChained;
        if (!this.hasPrecedingLineBreak() && // NODE: replace bang
        this.value === "!" && this.match(tt.prefix)) {
          this.exprAllowed = false;
          this.next();
          const nonNullExpression = this.startNodeAt(startPos, startLoc);
          nonNullExpression.expression = base;
          base = this.finishNode(nonNullExpression, "TSNonNullExpression");
          return base;
        }
        let isOptionalCall = false;
        if (this.match(tt.questionDot) && this.lookaheadCharCode() === 60) {
          if (noCalls) {
            return base;
          }
          base.optional = true;
          _optionalChained = isOptionalCall = true;
          this.next();
        }
        if (this.tsMatchLeftRelational() || this.match(tt.bitShift)) {
          let missingParenErrorLoc;
          const result = this.tsTryParseAndCatch(() => {
            if (!noCalls && this.atPossibleAsyncArrow(base)) {
              const asyncArrowFn = this.tsTryParseGenericAsyncArrowFunction(
                startPos,
                startLoc,
                forInit
              );
              if (asyncArrowFn) {
                base = asyncArrowFn;
                return base;
              }
            }
            const typeArguments = this.tsParseTypeArgumentsInExpression();
            if (!typeArguments) return base;
            if (isOptionalCall && !this.match(tt.parenL)) {
              missingParenErrorLoc = this.curPosition();
              return base;
            }
            if (tokenIsTemplate(this.type) || this.type === tt.backQuote) {
              const result2 = this.parseTaggedTemplateExpression(
                base,
                startPos,
                startLoc,
                _optionalChained
              );
              result2.typeArguments = typeArguments;
              return result2;
            }
            if (!noCalls && this.eat(tt.parenL)) {
              let refDestructuringErrors = new DestructuringErrors();
              const node2 = this.startNodeAt(startPos, startLoc);
              node2.callee = base;
              node2.arguments = this.parseExprList(
                tt.parenR,
                this.ecmaVersion >= 8,
                false,
                refDestructuringErrors
              );
              this.tsCheckForInvalidTypeCasts(node2.arguments);
              node2.typeArguments = typeArguments;
              if (_optionalChained) {
                node2.optional = isOptionalCall;
              }
              this.checkExpressionErrors(refDestructuringErrors, true);
              base = this.finishNode(node2, "CallExpression");
              return base;
            }
            const tokenType = this.type;
            if (
              // a<b>>c is not (a<b>)>c, but a<(b>>c)
              this.tsMatchRightRelational() || // a<b>>>c is not (a<b>)>>c, but a<(b>>>c)
              tokenType === tt.bitShift || // a<b>c is (a<b)>c
              tokenType !== tt.parenL && tokenCanStartExpression(tokenType) && !this.hasPrecedingLineBreak()
            ) {
              return;
            }
            const node = this.startNodeAt(startPos, startLoc);
            node.expression = base;
            node.typeArguments = typeArguments;
            return this.finishNode(node, "TSInstantiationExpression");
          });
          if (missingParenErrorLoc) {
            this.unexpected(missingParenErrorLoc);
          }
          if (result) {
            if (result.type === "TSInstantiationExpression" && (this.match(tt.dot) || this.match(tt.questionDot) && this.lookaheadCharCode() !== 40)) {
              this.raise(
                this.start,
                TypeScriptError.InvalidPropertyAccessAfterInstantiationExpression
              );
            }
            base = result;
            return base;
          }
        }
        let optionalSupported = this.ecmaVersion >= 11;
        let optional = optionalSupported && this.eat(tt.questionDot);
        if (noCalls && optional)
          this.raise(
            this.lastTokStart,
            "Optional chaining cannot appear in the callee of new expressions"
          );
        let computed = this.eat(tt.bracketL);
        if (computed || optional && this.type !== tt.parenL && this.type !== tt.backQuote || this.eat(tt.dot)) {
          let node = this.startNodeAt(startPos, startLoc);
          node.object = base;
          if (computed) {
            node.property = this.parseExpression();
            this.expect(tt.bracketR);
          } else if (this.type === tt.privateId && base.type !== "Super") {
            node.property = this.parsePrivateIdent();
          } else {
            node.property = this.parseIdent(this.options.allowReserved !== "never");
          }
          node.computed = !!computed;
          if (optionalSupported) {
            node.optional = optional;
          }
          base = this.finishNode(node, "MemberExpression");
        } else if (!noCalls && this.eat(tt.parenL)) {
          const oldMaybeInArrowParameters = this.maybeInArrowParameters;
          this.maybeInArrowParameters = true;
          let refDestructuringErrors = new DestructuringErrors(), oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos;
          this.yieldPos = 0;
          this.awaitPos = 0;
          this.awaitIdentPos = 0;
          let exprList = this.parseExprList(
            tt.parenR,
            this.ecmaVersion >= 8,
            false,
            refDestructuringErrors
          );
          if (maybeAsyncArrow && !optional && this.shouldParseAsyncArrow()) {
            this.checkPatternErrors(refDestructuringErrors, false);
            this.checkYieldAwaitInDefaultParams();
            if (this.awaitIdentPos > 0)
              this.raise(
                this.awaitIdentPos,
                "Cannot use 'await' as identifier inside an async function"
              );
            this.yieldPos = oldYieldPos;
            this.awaitPos = oldAwaitPos;
            this.awaitIdentPos = oldAwaitIdentPos;
            base = this.parseSubscriptAsyncArrow(startPos, startLoc, exprList, forInit);
          } else {
            this.checkExpressionErrors(refDestructuringErrors, true);
            this.yieldPos = oldYieldPos || this.yieldPos;
            this.awaitPos = oldAwaitPos || this.awaitPos;
            this.awaitIdentPos = oldAwaitIdentPos || this.awaitIdentPos;
            let node = this.startNodeAt(startPos, startLoc);
            node.callee = base;
            node.arguments = exprList;
            if (optionalSupported) {
              node.optional = optional;
            }
            base = this.finishNode(node, "CallExpression");
          }
          this.maybeInArrowParameters = oldMaybeInArrowParameters;
        } else if (this.type === tt.backQuote) {
          if (optional || _optionalChained) {
            this.raise(
              this.start,
              "Optional chaining cannot appear in the tag of tagged template expressions"
            );
          }
          let node = this.startNodeAt(startPos, startLoc);
          node.tag = base;
          node.quasi = this.parseTemplate({ isTagged: true });
          base = this.finishNode(node, "TaggedTemplateExpression");
        }
        return base;
      }
      parseGetterSetter(prop) {
        prop.kind = prop.key.name;
        this.parsePropertyName(prop);
        prop.value = this.parseMethod(false);
        let paramCount = prop.kind === "get" ? 0 : 1;
        const firstParam = prop.value.params[0];
        const hasContextParam = firstParam && this.isThisParam(firstParam);
        paramCount = hasContextParam ? paramCount + 1 : paramCount;
        if (prop.value.params.length !== paramCount) {
          let start = prop.value.start;
          if (prop.kind === "get") this.raiseRecoverable(start, "getter should have no params");
          else this.raiseRecoverable(start, "setter should have exactly one param");
        } else {
          if (prop.kind === "set" && prop.value.params[0].type === "RestElement")
            this.raiseRecoverable(prop.value.params[0].start, "Setter cannot use rest params");
        }
      }
      parseProperty(isPattern, refDestructuringErrors) {
        if (!isPattern) {
          let decorators = [];
          if (this.match(tokTypes2.at)) {
            while (this.match(tokTypes2.at)) {
              decorators.push(this.parseDecorator());
            }
          }
          const property = super.parseProperty(isPattern, refDestructuringErrors);
          if (property.type === "SpreadElement") {
            if (decorators.length)
              this.raise(property.start, DecoratorsError.SpreadElementDecorator);
          }
          if (decorators.length) {
            property.decorators = decorators;
            decorators = [];
          }
          return property;
        }
        return super.parseProperty(isPattern, refDestructuringErrors);
      }
      parseCatchClauseParam() {
        const param = this.parseBindingAtom();
        let simple = param.type === "Identifier";
        this.enterScope(simple ? acornScope.SCOPE_SIMPLE_CATCH : 0);
        this.checkLValPattern(
          param,
          simple ? acornScope.BIND_SIMPLE_CATCH : acornScope.BIND_LEXICAL
        );
        const type = this.tsTryParseTypeAnnotation();
        if (type) {
          param.typeAnnotation = type;
          this.resetEndLocation(param);
        }
        this.expect(tt.parenR);
        return param;
      }
      parseClass(node, isStatement) {
        const oldInAbstractClass = this.inAbstractClass;
        this.inAbstractClass = !!node.abstract;
        try {
          this.next();
          this.takeDecorators(node);
          const oldStrict = this.strict;
          this.strict = true;
          this.parseClassId(node, isStatement);
          this.parseClassSuper(node);
          const privateNameMap = this.enterClassBody();
          const classBody = this.startNode();
          let hadConstructor = false;
          classBody.body = [];
          let decorators = [];
          this.expect(tt.braceL);
          while (this.type !== tt.braceR) {
            if (this.match(tokTypes2.at)) {
              decorators.push(this.parseDecorator());
              continue;
            }
            const element = this.parseClassElement(node.superClass !== null);
            if (decorators.length) {
              element.decorators = decorators;
              this.resetStartLocationFromNode(element, decorators[0]);
              decorators = [];
            }
            if (element) {
              classBody.body.push(element);
              if (element.type === "MethodDefinition" && element.kind === "constructor" && element.value.type === "FunctionExpression") {
                if (hadConstructor) {
                  this.raiseRecoverable(element.start, "Duplicate constructor in the same class");
                }
                hadConstructor = true;
                if (element.decorators && element.decorators.length > 0) {
                  this.raise(element.start, DecoratorsError.DecoratorConstructor);
                }
              } else if (element.key && element.key.type === "PrivateIdentifier" && isPrivateNameConflicted(privateNameMap, element)) {
                this.raiseRecoverable(
                  element.key.start,
                  `Identifier '#${element.key.name}' has already been declared`
                );
              }
            }
          }
          this.strict = oldStrict;
          this.next();
          if (decorators.length) {
            this.raise(this.start, DecoratorsError.TrailingDecorator);
          }
          node.body = this.finishNode(classBody, "ClassBody");
          this.exitClassBody();
          return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression");
        } finally {
          this.inAbstractClass = oldInAbstractClass;
        }
      }
      parseClassFunctionParams() {
        const typeParameters = this.tsTryParseTypeParameters();
        let params = this.parseBindingList(tt.parenR, false, this.ecmaVersion >= 8, true);
        if (typeParameters) params.typeParameters = typeParameters;
        return params;
      }
      parseMethod(isGenerator, isAsync, allowDirectSuper, inClassScope, method) {
        let node = this.startNode(), oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos;
        this.initFunction(node);
        if (this.ecmaVersion >= 6) node.generator = isGenerator;
        if (this.ecmaVersion >= 8) node.async = !!isAsync;
        this.yieldPos = 0;
        this.awaitPos = 0;
        this.awaitIdentPos = 0;
        this.enterScope(
          functionFlags(isAsync, node.generator) | acornScope.SCOPE_SUPER | (allowDirectSuper ? acornScope.SCOPE_DIRECT_SUPER : 0)
        );
        this.expect(tt.parenL);
        node.params = this.parseClassFunctionParams();
        this.checkYieldAwaitInDefaultParams();
        this.parseFunctionBody(node, false, true, false, {
          isClassMethod: inClassScope
        });
        this.yieldPos = oldYieldPos;
        this.awaitPos = oldAwaitPos;
        this.awaitIdentPos = oldAwaitIdentPos;
        if (method && method.abstract) {
          const hasBody = !!node.body;
          if (hasBody) {
            const { key } = method;
            this.raise(
              method.start,
              TypeScriptError.AbstractMethodHasImplementation({
                methodName: key.type === "Identifier" && !method.computed ? key.name : `[${this.input.slice(key.start, key.end)}]`
              })
            );
          }
        }
        return this.finishNode(node, "FunctionExpression");
      }
      static parse(input, options2) {
        if (options2.locations === false) {
          throw new Error(`You have to enable options.locations while using acorn-typescript`);
        } else {
          options2.locations = true;
        }
        const parser = new this(options2, input);
        if (dts) {
          parser.isAmbientContext = true;
        }
        return parser.parse();
      }
      static parseExpressionAt(input, pos, options2) {
        if (options2.locations === false) {
          throw new Error(`You have to enable options.locations while using acorn-typescript`);
        } else {
          options2.locations = true;
        }
        const parser = new this(options2, input, pos);
        if (dts) {
          parser.isAmbientContext = true;
        }
        parser.nextToken();
        return parser.parseExpression();
      }
      parseImportSpecifier() {
        const isMaybeTypeOnly = this.ts_isContextual(tokTypes2.type);
        if (isMaybeTypeOnly) {
          let node = this.startNode();
          node.imported = this.parseModuleExportName();
          this.parseTypeOnlyImportExportSpecifier(
            node,
            /* isImport */
            true,
            this.importOrExportOuterKind === "type"
          );
          return this.finishNode(node, "ImportSpecifier");
        } else {
          const node = super.parseImportSpecifier();
          node.importKind = "value";
          return node;
        }
      }
      parseExportSpecifier(exports$1) {
        const isMaybeTypeOnly = this.ts_isContextual(tokTypes2.type);
        const isString = this.match(tt.string);
        if (!isString && isMaybeTypeOnly) {
          let node = this.startNode();
          node.local = this.parseModuleExportName();
          this.parseTypeOnlyImportExportSpecifier(
            node,
            /* isImport */
            false,
            this.importOrExportOuterKind === "type"
          );
          this.finishNode(node, "ExportSpecifier");
          this.checkExport(exports$1, node.exported, node.exported.start);
          return node;
        } else {
          const node = super.parseExportSpecifier(exports$1);
          node.exportKind = "value";
          return node;
        }
      }
      parseTypeOnlyImportExportSpecifier(node, isImport, isInTypeOnlyImportExport) {
        const leftOfAsKey = isImport ? "imported" : "local";
        const rightOfAsKey = isImport ? "local" : "exported";
        let leftOfAs = node[leftOfAsKey];
        let rightOfAs;
        let hasTypeSpecifier = false;
        let canParseAsKeyword = true;
        const loc = leftOfAs.start;
        if (this.isContextual("as")) {
          const firstAs = this.parseIdent();
          if (this.isContextual("as")) {
            const secondAs = this.parseIdent();
            if (tokenIsKeywordOrIdentifier(this.type)) {
              hasTypeSpecifier = true;
              leftOfAs = firstAs;
              rightOfAs = isImport ? this.parseIdent() : this.parseModuleExportName();
              canParseAsKeyword = false;
            } else {
              rightOfAs = secondAs;
              canParseAsKeyword = false;
            }
          } else if (tokenIsKeywordOrIdentifier(this.type)) {
            canParseAsKeyword = false;
            rightOfAs = isImport ? this.parseIdent() : this.parseModuleExportName();
          } else {
            hasTypeSpecifier = true;
            leftOfAs = firstAs;
          }
        } else if (tokenIsKeywordOrIdentifier(this.type)) {
          hasTypeSpecifier = true;
          if (isImport) {
            leftOfAs = super.parseIdent(true);
            if (!this.isContextual("as")) {
              this.checkUnreserved(leftOfAs);
            }
          } else {
            leftOfAs = this.parseModuleExportName();
          }
        }
        if (hasTypeSpecifier && isInTypeOnlyImportExport) {
          this.raise(
            loc,
            isImport ? TypeScriptError.TypeModifierIsUsedInTypeImports : TypeScriptError.TypeModifierIsUsedInTypeExports
          );
        }
        node[leftOfAsKey] = leftOfAs;
        node[rightOfAsKey] = rightOfAs;
        const kindKey = isImport ? "importKind" : "exportKind";
        node[kindKey] = hasTypeSpecifier ? "type" : "value";
        if (canParseAsKeyword && this.eatContextual("as")) {
          node[rightOfAsKey] = isImport ? this.parseIdent() : this.parseModuleExportName();
        }
        if (!node[rightOfAsKey]) {
          node[rightOfAsKey] = this.copyNode(node[leftOfAsKey]);
        }
        if (isImport) {
          this.checkLValSimple(node[rightOfAsKey], acornScope.BIND_LEXICAL);
        }
      }
      raiseCommonCheck(pos, message, recoverable) {
        switch (message) {
          case "Comma is not permitted after the rest element": {
            if (this.isAmbientContext && this.match(tt.comma) && this.lookaheadCharCode() === 41) {
              this.next();
              return;
            } else {
              return super.raise(pos, message);
            }
          }
        }
        return recoverable ? super.raiseRecoverable(pos, message) : super.raise(pos, message);
      }
      raiseRecoverable(pos, message) {
        return this.raiseCommonCheck(pos, message, true);
      }
      raise(pos, message) {
        return this.raiseCommonCheck(pos, message, true);
      }
      updateContext(prevType) {
        const { type } = this;
        if (type == tt.braceL) {
          var curContext = this.curContext();
          if (curContext == tsTokContexts.tc_oTag) this.context.push(tokContexts.b_expr);
          else if (curContext == tsTokContexts.tc_expr) this.context.push(tokContexts.b_tmpl);
          else super.updateContext(prevType);
          this.exprAllowed = true;
        } else if (type === tt.slash && prevType === tokTypes2.jsxTagStart) {
          this.context.length -= 2;
          this.context.push(tsTokContexts.tc_cTag);
          this.exprAllowed = false;
        } else {
          return super.updateContext(prevType);
        }
      }
      // Parses JSX opening tag starting after '<'.
      jsx_parseOpeningElementAt(startPos, startLoc) {
        let node = this.startNodeAt(startPos, startLoc);
        let nodeName = this.jsx_parseElementName();
        if (nodeName) node.name = nodeName;
        if (this.match(tt.relational) || this.match(tt.bitShift)) {
          const typeArguments = this.tsTryParseAndCatch(
            () => this.tsParseTypeArgumentsInExpression()
          );
          if (typeArguments) node.typeArguments = typeArguments;
        }
        node.attributes = [];
        while (this.type !== tt.slash && this.type !== tokTypes2.jsxTagEnd)
          node.attributes.push(this.jsx_parseAttribute());
        node.selfClosing = this.eat(tt.slash);
        this.expect(tokTypes2.jsxTagEnd);
        return this.finishNode(node, nodeName ? "JSXOpeningElement" : "JSXOpeningFragment");
      }
      enterScope(flags) {
        if (flags === TS_SCOPE_TS_MODULE) {
          this.importsStack.push([]);
        }
        super.enterScope(flags);
        const scope = super.currentScope();
        scope.types = [];
        scope.enums = [];
        scope.constEnums = [];
        scope.classes = [];
        scope.exportOnlyBindings = [];
      }
      exitScope() {
        const scope = super.currentScope();
        if (scope.flags === TS_SCOPE_TS_MODULE) {
          this.importsStack.pop();
        }
        super.exitScope();
      }
      hasImport(name, allowShadow) {
        const len = this.importsStack.length;
        if (this.importsStack[len - 1].indexOf(name) > -1) {
          return true;
        }
        if (!allowShadow && len > 1) {
          for (let i = 0; i < len - 1; i++) {
            if (this.importsStack[i].indexOf(name) > -1) return true;
          }
        }
        return false;
      }
      maybeExportDefined(scope, name) {
        if (this.inModule && scope.flags & acornScope.SCOPE_TOP) {
          this.undefinedExports.delete(name);
        }
      }
      declareName(name, bindingType, pos) {
        if (bindingType & acornScope.BIND_FLAGS_TS_IMPORT) {
          if (this.hasImport(name, true)) {
            this.raise(pos, `Identifier '${name}' has already been declared.`);
          }
          this.importsStack[this.importsStack.length - 1].push(name);
          return;
        }
        const scope = this.currentScope();
        if (bindingType & acornScope.BIND_FLAGS_TS_EXPORT_ONLY) {
          this.maybeExportDefined(scope, name);
          scope.exportOnlyBindings.push(name);
          return;
        }
        if (bindingType === acornScope.BIND_TS_TYPE || bindingType === acornScope.BIND_TS_INTERFACE) {
          if (bindingType === acornScope.BIND_TS_TYPE && scope.types.includes(name)) {
            this.raise(pos, `type '${name}' has already been declared.`);
          }
          scope.types.push(name);
        } else {
          super.declareName(name, bindingType, pos);
        }
        if (bindingType & acornScope.BIND_FLAGS_TS_ENUM) scope.enums.push(name);
        if (bindingType & acornScope.BIND_FLAGS_TS_CONST_ENUM) scope.constEnums.push(name);
        if (bindingType & acornScope.BIND_FLAGS_CLASS) scope.classes.push(name);
      }
      checkLocalExport(id) {
        const { name } = id;
        if (this.hasImport(name)) return;
        const len = this.scopeStack.length;
        for (let i = len - 1; i >= 0; i--) {
          const scope = this.scopeStack[i];
          if (scope.types.indexOf(name) > -1 || scope.exportOnlyBindings.indexOf(name) > -1) return;
        }
        super.checkLocalExport(id);
      }
    }
    return TypeScriptParser;
  };
}

/** @import { Comment, Program } from 'estree' */
/** @import { AST } from '#compiler' */

const ParserWithTS = Parser$1.extend(tsPlugin());

/**
 * @typedef {Comment & {
 *   start: number;
 *   end: number;
 * }} CommentWithLocation
 */

/**
 * @param {string} source
 * @param {AST.JSComment[]} comments
 * @param {boolean} typescript
 * @param {boolean} [is_script]
 */
function parse$3(source, comments, typescript, is_script) {
	const parser = typescript ? ParserWithTS : Parser$1;

	const { onComment, add_comments } = get_comment_handlers(
		source,
		/** @type {CommentWithLocation[]} */ (comments)
	);

	// @ts-ignore
	const parse_statement = parser.prototype.parseStatement;

	// If we're dealing with a <script> then it might contain an export
	// for something that doesn't exist directly inside but is inside the
	// component instead, so we need to ensure that Acorn doesn't throw
	// an error in these cases
	if (is_script) {
		// @ts-ignore
		parser.prototype.parseStatement = function (...args) {
			const v = parse_statement.call(this, ...args);
			// @ts-ignore
			this.undefinedExports = {};
			return v;
		};
	}

	let ast;

	try {
		ast = parser.parse(source, {
			onComment,
			sourceType: 'module',
			ecmaVersion: 16,
			locations: true
		});
	} finally {
		if (is_script) {
			// @ts-ignore
			parser.prototype.parseStatement = parse_statement;
		}
	}

	add_comments(ast);

	return /** @type {Program} */ (ast);
}

/**
 * @param {string} source
 * @param {Comment[]} comments
 * @param {boolean} typescript
 * @param {number} index
 * @returns {acorn.Expression & { leadingComments?: CommentWithLocation[]; trailingComments?: CommentWithLocation[]; }}
 */
function parse_expression_at(source, comments, typescript, index) {
	const parser = typescript ? ParserWithTS : Parser$1;

	const { onComment, add_comments } = get_comment_handlers(
		source,
		/** @type {CommentWithLocation[]} */ (comments),
		index
	);

	const ast = parser.parseExpressionAt(source, index, {
		onComment,
		sourceType: 'module',
		ecmaVersion: 16,
		locations: true
	});

	add_comments(ast);

	return ast;
}

/**
 * Acorn doesn't add comments to the AST by itself. This factory returns the capabilities
 * to add them after the fact. They are needed in order to support `svelte-ignore` comments
 * in JS code and so that `prettier-plugin-svelte` doesn't remove all comments when formatting.
 * @param {string} source
 * @param {CommentWithLocation[]} comments
 * @param {number} index
 */
function get_comment_handlers(source, comments, index = 0) {
	return {
		/**
		 * @param {boolean} block
		 * @param {string} value
		 * @param {number} start
		 * @param {number} end
		 * @param {import('acorn').Position} [start_loc]
		 * @param {import('acorn').Position} [end_loc]
		 */
		onComment: (block, value, start, end, start_loc, end_loc) => {
			if (block && /\n/.test(value)) {
				let a = start;
				while (a > 0 && source[a - 1] !== '\n') a -= 1;

				let b = a;
				while (/[ \t]/.test(source[b])) b += 1;

				const indentation = source.slice(a, b);
				value = value.replace(new RegExp(`^${indentation}`, 'gm'), '');
			}

			comments.push({
				type: block ? 'Block' : 'Line',
				value,
				start,
				end,
				loc: {
					start: /** @type {import('acorn').Position} */ (start_loc),
					end: /** @type {import('acorn').Position} */ (end_loc)
				}
			});
		},

		/** @param {acorn.Node & { leadingComments?: CommentWithLocation[]; trailingComments?: CommentWithLocation[]; }} ast */
		add_comments(ast) {
			if (comments.length === 0) return;

			comments = comments
				.filter((comment) => comment.start >= index)
				.map(({ type, value, start, end }) => ({ type, value, start, end }));

			walk$1(ast, null, {
				_(node, { next, path }) {
					let comment;

					while (comments[0] && comments[0].start < node.start) {
						comment = /** @type {CommentWithLocation} */ (comments.shift());
						(node.leadingComments ||= []).push(comment);
					}

					next();

					if (comments[0]) {
						const parent = /** @type {any} */ (path.at(-1));

						if (parent === undefined || node.end !== parent.end) {
							const slice = source.slice(node.end, comments[0].start);
							const is_last_in_body =
								((parent?.type === 'BlockStatement' || parent?.type === 'Program') &&
									parent.body.indexOf(node) === parent.body.length - 1) ||
								(parent?.type === 'ArrayExpression' &&
									parent.elements.indexOf(node) === parent.elements.length - 1) ||
								(parent?.type === 'ObjectExpression' &&
									parent.properties.indexOf(node) === parent.properties.length - 1);

							if (is_last_in_body) {
								// Special case: There can be multiple trailing comments after the last node in a block,
								// and they can be separated by newlines
								node.end;

								while (comments.length) {
									const comment = comments[0];
									if (parent && comment.start >= parent.end) break;

									(node.trailingComments ||= []).push(comment);
									comments.shift();
									comment.end;
								}
							} else if (node.end <= comments[0].start && /^[,) \t]*$/.test(slice)) {
								node.trailingComments = [/** @type {CommentWithLocation} */ (comments.shift())];
							}
						}
					}
				}
			});

			// Special case: Trailing comments after the root node (which can only happen for expression tags or for Program nodes).
			// Adding them ensures that we can later detect the end of the expression tag correctly.
			if (comments.length > 0 && (comments[0].start >= ast.end || ast.type === 'Program')) {
				(ast.trailingComments ||= []).push(...comments.splice(0));
			}
		}
	};
}

/* This file is generated by scripts/process-messages/index.js. Do not edit! */


/** @typedef {{ start?: number, end?: number }} NodeLike */
class InternalCompileError extends Error {
	message = ''; // ensure this property is enumerable
	#diagnostic;

	/**
	 * @param {string} code
	 * @param {string} message
	 * @param {[number, number] | undefined} position
	 */
	constructor(code, message, position) {
		super(message);
		this.stack = ''; // avoid unnecessary noise; don't set it as a class property or it becomes enumerable

		// We want to extend from Error so that various bundler plugins properly handle it.
		// But we also want to share the same object shape with that of warnings, therefore
		// we create an instance of the shared class an copy over its properties.
		this.#diagnostic = new CompileDiagnostic(code, message, position);

		Object.assign(this, this.#diagnostic);
		this.name = 'CompileError';
	}

	toString() {
		return this.#diagnostic.toString();
	}

	toJSON() {
		return this.#diagnostic.toJSON();
	}
}

/**
 * @param {null | number | NodeLike} node
 * @param {string} code
 * @param {string} message
 * @returns {never}
 */
function e(node, code, message) {
	const start = typeof node === 'number' ? node : node?.start;
	const end = typeof node === 'number' ? node : node?.end;

	throw new InternalCompileError(code, message, start !== undefined ? [start, end ?? start] : undefined);
}

/**
 * Invalid compiler option: %details%
 * @param {null | number | NodeLike} node
 * @param {string} details
 * @returns {never}
 */
function options_invalid_value(node, details) {
	e(node, 'options_invalid_value', `Invalid compiler option: ${details}\nhttps://svelte.dev/e/options_invalid_value`);
}

/**
 * Invalid compiler option: %details%
 * @param {null | number | NodeLike} node
 * @param {string} details
 * @returns {never}
 */
function options_removed(node, details) {
	e(node, 'options_removed', `Invalid compiler option: ${details}\nhttps://svelte.dev/e/options_removed`);
}

/**
 * Unrecognised compiler option %keypath%
 * @param {null | number | NodeLike} node
 * @param {string} keypath
 * @returns {never}
 */
function options_unrecognised(node, keypath) {
	e(node, 'options_unrecognised', `Unrecognised compiler option ${keypath}\nhttps://svelte.dev/e/options_unrecognised`);
}

/**
 * `$bindable()` can only be used inside a `$props()` declaration
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function bindable_invalid_location(node) {
	e(node, 'bindable_invalid_location', `\`$bindable()\` can only be used inside a \`$props()\` declaration\nhttps://svelte.dev/e/bindable_invalid_location`);
}

/**
 * Cannot assign to %thing%
 * @param {null | number | NodeLike} node
 * @param {string} thing
 * @returns {never}
 */
function constant_assignment(node, thing) {
	e(node, 'constant_assignment', `Cannot assign to ${thing}\nhttps://svelte.dev/e/constant_assignment`);
}

/**
 * Cannot bind to %thing%
 * @param {null | number | NodeLike} node
 * @param {string} thing
 * @returns {never}
 */
function constant_binding(node, thing) {
	e(node, 'constant_binding', `Cannot bind to ${thing}\nhttps://svelte.dev/e/constant_binding`);
}

/**
 * `%name%` has already been declared
 * @param {null | number | NodeLike} node
 * @param {string} name
 * @returns {never}
 */
function declaration_duplicate(node, name) {
	e(node, 'declaration_duplicate', `\`${name}\` has already been declared\nhttps://svelte.dev/e/declaration_duplicate`);
}

/**
 * Cannot declare a variable with the same name as an import inside `<script module>`
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function declaration_duplicate_module_import(node) {
	e(node, 'declaration_duplicate_module_import', `Cannot declare a variable with the same name as an import inside \`<script module>\`\nhttps://svelte.dev/e/declaration_duplicate_module_import`);
}

/**
 * Cannot export derived state from a module. To expose the current derived value, export a function returning its value
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function derived_invalid_export(node) {
	e(node, 'derived_invalid_export', `Cannot export derived state from a module. To expose the current derived value, export a function returning its value\nhttps://svelte.dev/e/derived_invalid_export`);
}

/**
 * The $ name is reserved, and cannot be used for variables and imports
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function dollar_binding_invalid(node) {
	e(node, 'dollar_binding_invalid', `The $ name is reserved, and cannot be used for variables and imports\nhttps://svelte.dev/e/dollar_binding_invalid`);
}

/**
 * The $ prefix is reserved, and cannot be used for variables and imports
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function dollar_prefix_invalid(node) {
	e(node, 'dollar_prefix_invalid', `The $ prefix is reserved, and cannot be used for variables and imports\nhttps://svelte.dev/e/dollar_prefix_invalid`);
}

/**
 * `%name%` has already been declared
 * @param {null | number | NodeLike} node
 * @param {string} name
 * @returns {never}
 */
function duplicate_class_field(node, name) {
	e(node, 'duplicate_class_field', `\`${name}\` has already been declared\nhttps://svelte.dev/e/duplicate_class_field`);
}

/**
 * Cannot reassign or bind to each block argument in runes mode. Use the array and index variables instead (e.g. `array[i] = value` instead of `entry = value`, or `bind:value={array[i]}` instead of `bind:value={entry}`)
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function each_item_invalid_assignment(node) {
	e(node, 'each_item_invalid_assignment', `Cannot reassign or bind to each block argument in runes mode. Use the array and index variables instead (e.g. \`array[i] = value\` instead of \`entry = value\`, or \`bind:value={array[i]}\` instead of \`bind:value={entry}\`)\nhttps://svelte.dev/e/each_item_invalid_assignment`);
}

/**
 * `$effect()` can only be used as an expression statement
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function effect_invalid_placement(node) {
	e(node, 'effect_invalid_placement', `\`$effect()\` can only be used as an expression statement\nhttps://svelte.dev/e/effect_invalid_placement`);
}

/**
 * Cannot use `await` in deriveds and template expressions, or at the top level of a component, unless the `experimental.async` compiler option is `true`
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function experimental_async(node) {
	e(node, 'experimental_async', `Cannot use \`await\` in deriveds and template expressions, or at the top level of a component, unless the \`experimental.async\` compiler option is \`true\`\nhttps://svelte.dev/e/experimental_async`);
}

/**
 * `%name%` is not defined
 * @param {null | number | NodeLike} node
 * @param {string} name
 * @returns {never}
 */
function export_undefined(node, name) {
	e(node, 'export_undefined', `\`${name}\` is not defined\nhttps://svelte.dev/e/export_undefined`);
}

/**
 * `%name%` is an illegal variable name. To reference a global variable called `%name%`, use `globalThis.%name%`
 * @param {null | number | NodeLike} node
 * @param {string} name
 * @returns {never}
 */
function global_reference_invalid(node, name) {
	e(node, 'global_reference_invalid', `\`${name}\` is an illegal variable name. To reference a global variable called \`${name}\`, use \`globalThis.${name}\`\nhttps://svelte.dev/e/global_reference_invalid`);
}

/**
 * `$host()` can only be used inside custom element component instances
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function host_invalid_placement(node) {
	e(node, 'host_invalid_placement', `\`$host()\` can only be used inside custom element component instances\nhttps://svelte.dev/e/host_invalid_placement`);
}

/**
 * Imports of `svelte/internal/*` are forbidden. It contains private runtime code which is subject to change without notice. If you're importing from `svelte/internal/*` to work around a limitation of Svelte, please open an issue at https://github.com/sveltejs/svelte and explain your use case
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function import_svelte_internal_forbidden(node) {
	e(node, 'import_svelte_internal_forbidden', `Imports of \`svelte/internal/*\` are forbidden. It contains private runtime code which is subject to change without notice. If you're importing from \`svelte/internal/*\` to work around a limitation of Svelte, please open an issue at https://github.com/sveltejs/svelte and explain your use case\nhttps://svelte.dev/e/import_svelte_internal_forbidden`);
}

/**
 * `$inspect.trace(...)` cannot be used inside a generator function
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function inspect_trace_generator(node) {
	e(node, 'inspect_trace_generator', `\`$inspect.trace(...)\` cannot be used inside a generator function\nhttps://svelte.dev/e/inspect_trace_generator`);
}

/**
 * `$inspect.trace(...)` must be the first statement of a function body
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function inspect_trace_invalid_placement(node) {
	e(node, 'inspect_trace_invalid_placement', `\`$inspect.trace(...)\` must be the first statement of a function body\nhttps://svelte.dev/e/inspect_trace_invalid_placement`);
}

/**
 * The arguments keyword cannot be used within the template or at the top level of a component
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function invalid_arguments_usage(node) {
	e(node, 'invalid_arguments_usage', `The arguments keyword cannot be used within the template or at the top level of a component\nhttps://svelte.dev/e/invalid_arguments_usage`);
}

/**
 * Cannot use `await` in deriveds and template expressions, or at the top level of a component, unless in runes mode
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function legacy_await_invalid(node) {
	e(node, 'legacy_await_invalid', `Cannot use \`await\` in deriveds and template expressions, or at the top level of a component, unless in runes mode\nhttps://svelte.dev/e/legacy_await_invalid`);
}

/**
 * Cannot use `export let` in runes mode — use `$props()` instead
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function legacy_export_invalid(node) {
	e(node, 'legacy_export_invalid', `Cannot use \`export let\` in runes mode — use \`$props()\` instead\nhttps://svelte.dev/e/legacy_export_invalid`);
}

/**
 * Cannot use `$$props` in runes mode
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function legacy_props_invalid(node) {
	e(node, 'legacy_props_invalid', `Cannot use \`$$props\` in runes mode\nhttps://svelte.dev/e/legacy_props_invalid`);
}

/**
 * `$:` is not allowed in runes mode, use `$derived` or `$effect` instead
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function legacy_reactive_statement_invalid(node) {
	e(node, 'legacy_reactive_statement_invalid', `\`$:\` is not allowed in runes mode, use \`$derived\` or \`$effect\` instead\nhttps://svelte.dev/e/legacy_reactive_statement_invalid`);
}

/**
 * Cannot use `$$restProps` in runes mode
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function legacy_rest_props_invalid(node) {
	e(node, 'legacy_rest_props_invalid', `Cannot use \`$$restProps\` in runes mode\nhttps://svelte.dev/e/legacy_rest_props_invalid`);
}

/**
 * A component cannot have a default export
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function module_illegal_default_export(node) {
	e(node, 'module_illegal_default_export', `A component cannot have a default export\nhttps://svelte.dev/e/module_illegal_default_export`);
}

/**
 * Cannot use `%rune%()` more than once
 * @param {null | number | NodeLike} node
 * @param {string} rune
 * @returns {never}
 */
function props_duplicate(node, rune) {
	e(node, 'props_duplicate', `Cannot use \`${rune}()\` more than once\nhttps://svelte.dev/e/props_duplicate`);
}

/**
 * `$props.id()` can only be used at the top level of components as a variable declaration initializer
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function props_id_invalid_placement(node) {
	e(node, 'props_id_invalid_placement', `\`$props.id()\` can only be used at the top level of components as a variable declaration initializer\nhttps://svelte.dev/e/props_id_invalid_placement`);
}

/**
 * Declaring or accessing a prop starting with `$$` is illegal (they are reserved for Svelte internals)
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function props_illegal_name(node) {
	e(node, 'props_illegal_name', `Declaring or accessing a prop starting with \`$$\` is illegal (they are reserved for Svelte internals)\nhttps://svelte.dev/e/props_illegal_name`);
}

/**
 * `$props()` can only be used with an object destructuring pattern
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function props_invalid_identifier(node) {
	e(node, 'props_invalid_identifier', `\`$props()\` can only be used with an object destructuring pattern\nhttps://svelte.dev/e/props_invalid_identifier`);
}

/**
 * `$props()` assignment must not contain nested properties or computed keys
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function props_invalid_pattern(node) {
	e(node, 'props_invalid_pattern', `\`$props()\` assignment must not contain nested properties or computed keys\nhttps://svelte.dev/e/props_invalid_pattern`);
}

/**
 * `$props()` can only be used at the top level of components as a variable declaration initializer
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function props_invalid_placement(node) {
	e(node, 'props_invalid_placement', `\`$props()\` can only be used at the top level of components as a variable declaration initializer\nhttps://svelte.dev/e/props_invalid_placement`);
}

/**
 * Cyclical dependency detected: %cycle%
 * @param {null | number | NodeLike} node
 * @param {string} cycle
 * @returns {never}
 */
function reactive_declaration_cycle(node, cycle) {
	e(node, 'reactive_declaration_cycle', `Cyclical dependency detected: ${cycle}\nhttps://svelte.dev/e/reactive_declaration_cycle`);
}

/**
 * `%rune%` cannot be called with arguments
 * @param {null | number | NodeLike} node
 * @param {string} rune
 * @returns {never}
 */
function rune_invalid_arguments(node, rune) {
	e(node, 'rune_invalid_arguments', `\`${rune}\` cannot be called with arguments\nhttps://svelte.dev/e/rune_invalid_arguments`);
}

/**
 * `%rune%` must be called with %args%
 * @param {null | number | NodeLike} node
 * @param {string} rune
 * @param {string} args
 * @returns {never}
 */
function rune_invalid_arguments_length(node, rune, args) {
	e(node, 'rune_invalid_arguments_length', `\`${rune}\` must be called with ${args}\nhttps://svelte.dev/e/rune_invalid_arguments_length`);
}

/**
 * Cannot access a computed property of a rune
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function rune_invalid_computed_property(node) {
	e(node, 'rune_invalid_computed_property', `Cannot access a computed property of a rune\nhttps://svelte.dev/e/rune_invalid_computed_property`);
}

/**
 * `%name%` is not a valid rune
 * @param {null | number | NodeLike} node
 * @param {string} name
 * @returns {never}
 */
function rune_invalid_name(node, name) {
	e(node, 'rune_invalid_name', `\`${name}\` is not a valid rune\nhttps://svelte.dev/e/rune_invalid_name`);
}

/**
 * `%rune%` cannot be called with a spread argument
 * @param {null | number | NodeLike} node
 * @param {string} rune
 * @returns {never}
 */
function rune_invalid_spread(node, rune) {
	e(node, 'rune_invalid_spread', `\`${rune}\` cannot be called with a spread argument\nhttps://svelte.dev/e/rune_invalid_spread`);
}

/**
 * Cannot use `%rune%` rune in non-runes mode
 * @param {null | number | NodeLike} node
 * @param {string} rune
 * @returns {never}
 */
function rune_invalid_usage(node, rune) {
	e(node, 'rune_invalid_usage', `Cannot use \`${rune}\` rune in non-runes mode\nhttps://svelte.dev/e/rune_invalid_usage`);
}

/**
 * Cannot use rune without parentheses
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function rune_missing_parentheses(node) {
	e(node, 'rune_missing_parentheses', `Cannot use rune without parentheses\nhttps://svelte.dev/e/rune_missing_parentheses`);
}

/**
 * The `%name%` rune has been removed
 * @param {null | number | NodeLike} node
 * @param {string} name
 * @returns {never}
 */
function rune_removed(node, name) {
	e(node, 'rune_removed', `The \`${name}\` rune has been removed\nhttps://svelte.dev/e/rune_removed`);
}

/**
 * `%name%` is now `%replacement%`
 * @param {null | number | NodeLike} node
 * @param {string} name
 * @param {string} replacement
 * @returns {never}
 */
function rune_renamed(node, name, replacement) {
	e(node, 'rune_renamed', `\`${name}\` is now \`${replacement}\`\nhttps://svelte.dev/e/rune_renamed`);
}

/**
 * %name% cannot be used in runes mode
 * @param {null | number | NodeLike} node
 * @param {string} name
 * @returns {never}
 */
function runes_mode_invalid_import(node, name) {
	e(node, 'runes_mode_invalid_import', `${name} cannot be used in runes mode\nhttps://svelte.dev/e/runes_mode_invalid_import`);
}

/**
 * An exported snippet can only reference things declared in a `<script module>`, or other exportable snippets
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function snippet_invalid_export(node) {
	e(node, 'snippet_invalid_export', `An exported snippet can only reference things declared in a \`<script module>\`, or other exportable snippets\nhttps://svelte.dev/e/snippet_invalid_export`);
}

/**
 * Cannot reassign or bind to snippet parameter
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function snippet_parameter_assignment(node) {
	e(node, 'snippet_parameter_assignment', `Cannot reassign or bind to snippet parameter\nhttps://svelte.dev/e/snippet_parameter_assignment`);
}

/**
 * `%name%` has already been declared on this class
 * @param {null | number | NodeLike} node
 * @param {string} name
 * @returns {never}
 */
function state_field_duplicate(node, name) {
	e(node, 'state_field_duplicate', `\`${name}\` has already been declared on this class\nhttps://svelte.dev/e/state_field_duplicate`);
}

/**
 * Cannot assign to a state field before its declaration
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function state_field_invalid_assignment(node) {
	e(node, 'state_field_invalid_assignment', `Cannot assign to a state field before its declaration\nhttps://svelte.dev/e/state_field_invalid_assignment`);
}

/**
 * Cannot export state from a module if it is reassigned. Either export a function returning the state value or only mutate the state value's properties
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function state_invalid_export(node) {
	e(node, 'state_invalid_export', `Cannot export state from a module if it is reassigned. Either export a function returning the state value or only mutate the state value's properties\nhttps://svelte.dev/e/state_invalid_export`);
}

/**
 * `%rune%(...)` can only be used as a variable declaration initializer, a class field declaration, or the first assignment to a class field at the top level of the constructor.
 * @param {null | number | NodeLike} node
 * @param {string} rune
 * @returns {never}
 */
function state_invalid_placement(node, rune) {
	e(node, 'state_invalid_placement', `\`${rune}(...)\` can only be used as a variable declaration initializer, a class field declaration, or the first assignment to a class field at the top level of the constructor.\nhttps://svelte.dev/e/state_invalid_placement`);
}

/**
 * Cannot subscribe to stores that are not declared at the top level of the component
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function store_invalid_scoped_subscription(node) {
	e(node, 'store_invalid_scoped_subscription', `Cannot subscribe to stores that are not declared at the top level of the component\nhttps://svelte.dev/e/store_invalid_scoped_subscription`);
}

/**
 * Cannot reference store value inside `<script module>`
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function store_invalid_subscription(node) {
	e(node, 'store_invalid_subscription', `Cannot reference store value inside \`<script module>\`\nhttps://svelte.dev/e/store_invalid_subscription`);
}

/**
 * Cannot reference store value outside a `.svelte` file
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function store_invalid_subscription_module(node) {
	e(node, 'store_invalid_subscription_module', `Cannot reference store value outside a \`.svelte\` file\nhttps://svelte.dev/e/store_invalid_subscription_module`);
}

/**
 * TypeScript language features like %feature% are not natively supported, and their use is generally discouraged. Outside of `<script>` tags, these features are not supported. For use within `<script>` tags, you will need to use a preprocessor to convert it to JavaScript before it gets passed to the Svelte compiler. If you are using `vitePreprocess`, make sure to specifically enable preprocessing script tags (`vitePreprocess({ script: true })`)
 * @param {null | number | NodeLike} node
 * @param {string} feature
 * @returns {never}
 */
function typescript_invalid_feature(node, feature) {
	e(node, 'typescript_invalid_feature', `TypeScript language features like ${feature} are not natively supported, and their use is generally discouraged. Outside of \`<script>\` tags, these features are not supported. For use within \`<script>\` tags, you will need to use a preprocessor to convert it to JavaScript before it gets passed to the Svelte compiler. If you are using \`vitePreprocess\`, make sure to specifically enable preprocessing script tags (\`vitePreprocess({ script: true })\`)\nhttps://svelte.dev/e/typescript_invalid_feature`);
}

/**
 * Declaration cannot be empty
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function css_empty_declaration(node) {
	e(node, 'css_empty_declaration', `Declaration cannot be empty\nhttps://svelte.dev/e/css_empty_declaration`);
}

/**
 * Expected a valid CSS identifier
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function css_expected_identifier(node) {
	e(node, 'css_expected_identifier', `Expected a valid CSS identifier\nhttps://svelte.dev/e/css_expected_identifier`);
}

/**
 * A `:global` selector cannot follow a `%name%` combinator
 * @param {null | number | NodeLike} node
 * @param {string} name
 * @returns {never}
 */
function css_global_block_invalid_combinator(node, name) {
	e(node, 'css_global_block_invalid_combinator', `A \`:global\` selector cannot follow a \`${name}\` combinator\nhttps://svelte.dev/e/css_global_block_invalid_combinator`);
}

/**
 * A top-level `:global {...}` block can only contain rules, not declarations
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function css_global_block_invalid_declaration(node) {
	e(node, 'css_global_block_invalid_declaration', `A top-level \`:global {...}\` block can only contain rules, not declarations\nhttps://svelte.dev/e/css_global_block_invalid_declaration`);
}

/**
 * A `:global` selector cannot be part of a selector list with entries that don't contain `:global`
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function css_global_block_invalid_list(node) {
	e(node, 'css_global_block_invalid_list', `A \`:global\` selector cannot be part of a selector list with entries that don't contain \`:global\`\nhttps://svelte.dev/e/css_global_block_invalid_list`);
}

/**
 * A `:global` selector cannot modify an existing selector
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function css_global_block_invalid_modifier(node) {
	e(node, 'css_global_block_invalid_modifier', `A \`:global\` selector cannot modify an existing selector\nhttps://svelte.dev/e/css_global_block_invalid_modifier`);
}

/**
 * A `:global` selector can only be modified if it is a descendant of other selectors
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function css_global_block_invalid_modifier_start(node) {
	e(node, 'css_global_block_invalid_modifier_start', `A \`:global\` selector can only be modified if it is a descendant of other selectors\nhttps://svelte.dev/e/css_global_block_invalid_modifier_start`);
}

/**
 * A `:global` selector cannot be inside a pseudoclass
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function css_global_block_invalid_placement(node) {
	e(node, 'css_global_block_invalid_placement', `A \`:global\` selector cannot be inside a pseudoclass\nhttps://svelte.dev/e/css_global_block_invalid_placement`);
}

/**
 * `:global(...)` can be at the start or end of a selector sequence, but not in the middle
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function css_global_invalid_placement(node) {
	e(node, 'css_global_invalid_placement', `\`:global(...)\` can be at the start or end of a selector sequence, but not in the middle\nhttps://svelte.dev/e/css_global_invalid_placement`);
}

/**
 * `:global(...)` must contain exactly one selector
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function css_global_invalid_selector(node) {
	e(node, 'css_global_invalid_selector', `\`:global(...)\` must contain exactly one selector\nhttps://svelte.dev/e/css_global_invalid_selector`);
}

/**
 * `:global(...)` must not contain type or universal selectors when used in a compound selector
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function css_global_invalid_selector_list(node) {
	e(node, 'css_global_invalid_selector_list', `\`:global(...)\` must not contain type or universal selectors when used in a compound selector\nhttps://svelte.dev/e/css_global_invalid_selector_list`);
}

/**
 * Nesting selectors can only be used inside a rule or as the first selector inside a lone `:global(...)`
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function css_nesting_selector_invalid_placement(node) {
	e(node, 'css_nesting_selector_invalid_placement', `Nesting selectors can only be used inside a rule or as the first selector inside a lone \`:global(...)\`\nhttps://svelte.dev/e/css_nesting_selector_invalid_placement`);
}

/**
 * Invalid selector
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function css_selector_invalid(node) {
	e(node, 'css_selector_invalid', `Invalid selector\nhttps://svelte.dev/e/css_selector_invalid`);
}

/**
 * `:global(...)` must not be followed by a type selector
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function css_type_selector_invalid_placement(node) {
	e(node, 'css_type_selector_invalid_placement', `\`:global(...)\` must not be followed by a type selector\nhttps://svelte.dev/e/css_type_selector_invalid_placement`);
}

/**
 * An element can only have one 'animate' directive
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function animation_duplicate(node) {
	e(node, 'animation_duplicate', `An element can only have one 'animate' directive\nhttps://svelte.dev/e/animation_duplicate`);
}

/**
 * An element that uses the `animate:` directive must be the only child of a keyed `{#each ...}` block
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function animation_invalid_placement(node) {
	e(node, 'animation_invalid_placement', `An element that uses the \`animate:\` directive must be the only child of a keyed \`{#each ...}\` block\nhttps://svelte.dev/e/animation_invalid_placement`);
}

/**
 * An element that uses the `animate:` directive must be the only child of a keyed `{#each ...}` block. Did you forget to add a key to your each block?
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function animation_missing_key(node) {
	e(node, 'animation_missing_key', `An element that uses the \`animate:\` directive must be the only child of a keyed \`{#each ...}\` block. Did you forget to add a key to your each block?\nhttps://svelte.dev/e/animation_missing_key`);
}

/**
 * 'contenteditable' attribute cannot be dynamic if element uses two-way binding
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function attribute_contenteditable_dynamic(node) {
	e(node, 'attribute_contenteditable_dynamic', `'contenteditable' attribute cannot be dynamic if element uses two-way binding\nhttps://svelte.dev/e/attribute_contenteditable_dynamic`);
}

/**
 * 'contenteditable' attribute is required for textContent, innerHTML and innerText two-way bindings
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function attribute_contenteditable_missing(node) {
	e(node, 'attribute_contenteditable_missing', `'contenteditable' attribute is required for textContent, innerHTML and innerText two-way bindings\nhttps://svelte.dev/e/attribute_contenteditable_missing`);
}

/**
 * Attributes need to be unique
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function attribute_duplicate(node) {
	e(node, 'attribute_duplicate', `Attributes need to be unique\nhttps://svelte.dev/e/attribute_duplicate`);
}

/**
 * Attribute shorthand cannot be empty
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function attribute_empty_shorthand(node) {
	e(node, 'attribute_empty_shorthand', `Attribute shorthand cannot be empty\nhttps://svelte.dev/e/attribute_empty_shorthand`);
}

/**
 * Event attribute must be a JavaScript expression, not a string
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function attribute_invalid_event_handler(node) {
	e(node, 'attribute_invalid_event_handler', `Event attribute must be a JavaScript expression, not a string\nhttps://svelte.dev/e/attribute_invalid_event_handler`);
}

/**
 * 'multiple' attribute must be static if select uses two-way binding
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function attribute_invalid_multiple(node) {
	e(node, 'attribute_invalid_multiple', `'multiple' attribute must be static if select uses two-way binding\nhttps://svelte.dev/e/attribute_invalid_multiple`);
}

/**
 * '%name%' is not a valid attribute name
 * @param {null | number | NodeLike} node
 * @param {string} name
 * @returns {never}
 */
function attribute_invalid_name(node, name) {
	e(node, 'attribute_invalid_name', `'${name}' is not a valid attribute name\nhttps://svelte.dev/e/attribute_invalid_name`);
}

/**
 * Sequence expressions are not allowed as attribute/directive values in runes mode, unless wrapped in parentheses
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function attribute_invalid_sequence_expression(node) {
	e(node, 'attribute_invalid_sequence_expression', `Sequence expressions are not allowed as attribute/directive values in runes mode, unless wrapped in parentheses\nhttps://svelte.dev/e/attribute_invalid_sequence_expression`);
}

/**
 * 'type' attribute must be a static text value if input uses two-way binding
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function attribute_invalid_type(node) {
	e(node, 'attribute_invalid_type', `'type' attribute must be a static text value if input uses two-way binding\nhttps://svelte.dev/e/attribute_invalid_type`);
}

/**
 * Attribute values containing `{...}` must be enclosed in quote marks, unless the value only contains the expression
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function attribute_unquoted_sequence(node) {
	e(node, 'attribute_unquoted_sequence', `Attribute values containing \`{...}\` must be enclosed in quote marks, unless the value only contains the expression\nhttps://svelte.dev/e/attribute_unquoted_sequence`);
}

/**
 * `bind:group` can only bind to an Identifier or MemberExpression
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function bind_group_invalid_expression(node) {
	e(node, 'bind_group_invalid_expression', `\`bind:group\` can only bind to an Identifier or MemberExpression\nhttps://svelte.dev/e/bind_group_invalid_expression`);
}

/**
 * Cannot `bind:group` to a snippet parameter
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function bind_group_invalid_snippet_parameter(node) {
	e(node, 'bind_group_invalid_snippet_parameter', `Cannot \`bind:group\` to a snippet parameter\nhttps://svelte.dev/e/bind_group_invalid_snippet_parameter`);
}

/**
 * Can only bind to an Identifier or MemberExpression or a `{get, set}` pair
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function bind_invalid_expression(node) {
	e(node, 'bind_invalid_expression', `Can only bind to an Identifier or MemberExpression or a \`{get, set}\` pair\nhttps://svelte.dev/e/bind_invalid_expression`);
}

/**
 * `bind:%name%` is not a valid binding. %explanation%
 * @param {null | number | NodeLike} node
 * @param {string} name
 * @param {string | undefined | null} [explanation]
 * @returns {never}
 */
function bind_invalid_name(node, name, explanation) {
	e(node, 'bind_invalid_name', `${explanation
		? `\`bind:${name}\` is not a valid binding. ${explanation}`
		: `\`bind:${name}\` is not a valid binding`}\nhttps://svelte.dev/e/bind_invalid_name`);
}

/**
 * `bind:%name%={get, set}` must not have surrounding parentheses
 * @param {null | number | NodeLike} node
 * @param {string} name
 * @returns {never}
 */
function bind_invalid_parens(node, name) {
	e(node, 'bind_invalid_parens', `\`bind:${name}={get, set}\` must not have surrounding parentheses\nhttps://svelte.dev/e/bind_invalid_parens`);
}

/**
 * `bind:%name%` can only be used with %elements%
 * @param {null | number | NodeLike} node
 * @param {string} name
 * @param {string} elements
 * @returns {never}
 */
function bind_invalid_target(node, name, elements) {
	e(node, 'bind_invalid_target', `\`bind:${name}\` can only be used with ${elements}\nhttps://svelte.dev/e/bind_invalid_target`);
}

/**
 * Can only bind to state or props
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function bind_invalid_value(node) {
	e(node, 'bind_invalid_value', `Can only bind to state or props\nhttps://svelte.dev/e/bind_invalid_value`);
}

/**
 * %name% cannot appear more than once within a block
 * @param {null | number | NodeLike} node
 * @param {string} name
 * @returns {never}
 */
function block_duplicate_clause(node, name) {
	e(node, 'block_duplicate_clause', `${name} cannot appear more than once within a block\nhttps://svelte.dev/e/block_duplicate_clause`);
}

/**
 * {:...} block is invalid at this position (did you forget to close the preceding element or block?)
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function block_invalid_continuation_placement(node) {
	e(node, 'block_invalid_continuation_placement', `{:...} block is invalid at this position (did you forget to close the preceding element or block?)\nhttps://svelte.dev/e/block_invalid_continuation_placement`);
}

/**
 * 'elseif' should be 'else if'
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function block_invalid_elseif(node) {
	e(node, 'block_invalid_elseif', `'elseif' should be 'else if'\nhttps://svelte.dev/e/block_invalid_elseif`);
}

/**
 * {#%name% ...} block cannot be %location%
 * @param {null | number | NodeLike} node
 * @param {string} name
 * @param {string} location
 * @returns {never}
 */
function block_invalid_placement(node, name, location) {
	e(node, 'block_invalid_placement', `{#${name} ...} block cannot be ${location}\nhttps://svelte.dev/e/block_invalid_placement`);
}

/**
 * Block was left open
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function block_unclosed(node) {
	e(node, 'block_unclosed', `Block was left open\nhttps://svelte.dev/e/block_unclosed`);
}

/**
 * Expected a `%character%` character immediately following the opening bracket
 * @param {null | number | NodeLike} node
 * @param {string} character
 * @returns {never}
 */
function block_unexpected_character(node, character) {
	e(node, 'block_unexpected_character', `Expected a \`${character}\` character immediately following the opening bracket\nhttps://svelte.dev/e/block_unexpected_character`);
}

/**
 * Unexpected block closing tag
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function block_unexpected_close(node) {
	e(node, 'block_unexpected_close', `Unexpected block closing tag\nhttps://svelte.dev/e/block_unexpected_close`);
}

/**
 * This type of directive is not valid on components
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function component_invalid_directive(node) {
	e(node, 'component_invalid_directive', `This type of directive is not valid on components\nhttps://svelte.dev/e/component_invalid_directive`);
}

/**
 * Cyclical dependency detected: %cycle%
 * @param {null | number | NodeLike} node
 * @param {string} cycle
 * @returns {never}
 */
function const_tag_cycle(node, cycle) {
	e(node, 'const_tag_cycle', `Cyclical dependency detected: ${cycle}\nhttps://svelte.dev/e/const_tag_cycle`);
}

/**
 * {@const ...} must consist of a single variable declaration
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function const_tag_invalid_expression(node) {
	e(node, 'const_tag_invalid_expression', `{@const ...} must consist of a single variable declaration\nhttps://svelte.dev/e/const_tag_invalid_expression`);
}

/**
 * `{@const}` must be the immediate child of `{#snippet}`, `{#if}`, `{:else if}`, `{:else}`, `{#each}`, `{:then}`, `{:catch}`, `<svelte:fragment>`, `<svelte:boundary` or `<Component>`
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function const_tag_invalid_placement(node) {
	e(node, 'const_tag_invalid_placement', `\`{@const}\` must be the immediate child of \`{#snippet}\`, \`{#if}\`, \`{:else if}\`, \`{:else}\`, \`{#each}\`, \`{:then}\`, \`{:catch}\`, \`<svelte:fragment>\`, \`<svelte:boundary\` or \`<Component>\`\nhttps://svelte.dev/e/const_tag_invalid_placement`);
}

/**
 * The `{@const %name% = ...}` declaration is not available in this snippet
 * @param {null | number | NodeLike} node
 * @param {string} name
 * @returns {never}
 */
function const_tag_invalid_reference(node, name) {
	e(node, 'const_tag_invalid_reference', `The \`{@const ${name} = ...}\` declaration is not available in this snippet\nhttps://svelte.dev/e/const_tag_invalid_reference`);
}

/**
 * {@debug ...} arguments must be identifiers, not arbitrary expressions
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function debug_tag_invalid_arguments(node) {
	e(node, 'debug_tag_invalid_arguments', `{@debug ...} arguments must be identifiers, not arbitrary expressions\nhttps://svelte.dev/e/debug_tag_invalid_arguments`);
}

/**
 * Directive value must be a JavaScript expression enclosed in curly braces
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function directive_invalid_value(node) {
	e(node, 'directive_invalid_value', `Directive value must be a JavaScript expression enclosed in curly braces\nhttps://svelte.dev/e/directive_invalid_value`);
}

/**
 * `%type%` name cannot be empty
 * @param {null | number | NodeLike} node
 * @param {string} type
 * @returns {never}
 */
function directive_missing_name(node, type) {
	e(node, 'directive_missing_name', `\`${type}\` name cannot be empty\nhttps://svelte.dev/e/directive_missing_name`);
}

/**
 * An `{#each ...}` block without an `as` clause cannot have a key
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function each_key_without_as(node) {
	e(node, 'each_key_without_as', `An \`{#each ...}\` block without an \`as\` clause cannot have a key\nhttps://svelte.dev/e/each_key_without_as`);
}

/**
 * `</%name%>` attempted to close an element that was not open
 * @param {null | number | NodeLike} node
 * @param {string} name
 * @returns {never}
 */
function element_invalid_closing_tag(node, name) {
	e(node, 'element_invalid_closing_tag', `\`</${name}>\` attempted to close an element that was not open\nhttps://svelte.dev/e/element_invalid_closing_tag`);
}

/**
 * `</%name%>` attempted to close element that was already automatically closed by `<%reason%>` (cannot nest `<%reason%>` inside `<%name%>`)
 * @param {null | number | NodeLike} node
 * @param {string} name
 * @param {string} reason
 * @returns {never}
 */
function element_invalid_closing_tag_autoclosed(node, name, reason) {
	e(node, 'element_invalid_closing_tag_autoclosed', `\`</${name}>\` attempted to close element that was already automatically closed by \`<${reason}>\` (cannot nest \`<${reason}>\` inside \`<${name}>\`)\nhttps://svelte.dev/e/element_invalid_closing_tag_autoclosed`);
}

/**
 * `<%name%>` was left open
 * @param {null | number | NodeLike} node
 * @param {string} name
 * @returns {never}
 */
function element_unclosed(node, name) {
	e(node, 'element_unclosed', `\`<${name}>\` was left open\nhttps://svelte.dev/e/element_unclosed`);
}

/**
 * Event modifiers other than 'once' can only be used on DOM elements
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function event_handler_invalid_component_modifier(node) {
	e(node, 'event_handler_invalid_component_modifier', `Event modifiers other than 'once' can only be used on DOM elements\nhttps://svelte.dev/e/event_handler_invalid_component_modifier`);
}

/**
 * Valid event modifiers are %list%
 * @param {null | number | NodeLike} node
 * @param {string} list
 * @returns {never}
 */
function event_handler_invalid_modifier(node, list) {
	e(node, 'event_handler_invalid_modifier', `Valid event modifiers are ${list}\nhttps://svelte.dev/e/event_handler_invalid_modifier`);
}

/**
 * The '%modifier1%' and '%modifier2%' modifiers cannot be used together
 * @param {null | number | NodeLike} node
 * @param {string} modifier1
 * @param {string} modifier2
 * @returns {never}
 */
function event_handler_invalid_modifier_combination(node, modifier1, modifier2) {
	e(node, 'event_handler_invalid_modifier_combination', `The '${modifier1}' and '${modifier2}' modifiers cannot be used together\nhttps://svelte.dev/e/event_handler_invalid_modifier_combination`);
}

/**
 * Expected attribute value
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function expected_attribute_value(node) {
	e(node, 'expected_attribute_value', `Expected attribute value\nhttps://svelte.dev/e/expected_attribute_value`);
}

/**
 * Expected 'if', 'each', 'await', 'key' or 'snippet'
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function expected_block_type(node) {
	e(node, 'expected_block_type', `Expected 'if', 'each', 'await', 'key' or 'snippet'\nhttps://svelte.dev/e/expected_block_type`);
}

/**
 * Expected an identifier
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function expected_identifier(node) {
	e(node, 'expected_identifier', `Expected an identifier\nhttps://svelte.dev/e/expected_identifier`);
}

/**
 * Expected identifier or destructure pattern
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function expected_pattern(node) {
	e(node, 'expected_pattern', `Expected identifier or destructure pattern\nhttps://svelte.dev/e/expected_pattern`);
}

/**
 * Expected token %token%
 * @param {null | number | NodeLike} node
 * @param {string} token
 * @returns {never}
 */
function expected_token(node, token) {
	e(node, 'expected_token', `Expected token ${token}\nhttps://svelte.dev/e/expected_token`);
}

/**
 * Expected whitespace
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function expected_whitespace(node) {
	e(node, 'expected_whitespace', `Expected whitespace\nhttps://svelte.dev/e/expected_whitespace`);
}

/**
 * `use:`, `transition:` and `animate:` directives, attachments and bindings do not support await expressions
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function illegal_await_expression(node) {
	e(node, 'illegal_await_expression', `\`use:\`, \`transition:\` and \`animate:\` directives, attachments and bindings do not support await expressions\nhttps://svelte.dev/e/illegal_await_expression`);
}

/**
 * `<%name%>` does not support non-event attributes or spread attributes
 * @param {null | number | NodeLike} node
 * @param {string} name
 * @returns {never}
 */
function illegal_element_attribute(node, name) {
	e(node, 'illegal_element_attribute', `\`<${name}>\` does not support non-event attributes or spread attributes\nhttps://svelte.dev/e/illegal_element_attribute`);
}

/**
 * %message%
 * @param {null | number | NodeLike} node
 * @param {string} message
 * @returns {never}
 */
function js_parse_error(node, message) {
	e(node, 'js_parse_error', `${message}\nhttps://svelte.dev/e/js_parse_error`);
}

/**
 * `let:` directive at invalid position
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function let_directive_invalid_placement(node) {
	e(node, 'let_directive_invalid_placement', `\`let:\` directive at invalid position\nhttps://svelte.dev/e/let_directive_invalid_placement`);
}

/**
 * Mixing old (on:%name%) and new syntaxes for event handling is not allowed. Use only the on%name% syntax
 * @param {null | number | NodeLike} node
 * @param {string} name
 * @returns {never}
 */
function mixed_event_handler_syntaxes(node, name) {
	e(node, 'mixed_event_handler_syntaxes', `Mixing old (on:${name}) and new syntaxes for event handling is not allowed. Use only the on${name} syntax\nhttps://svelte.dev/e/mixed_event_handler_syntaxes`);
}

/**
 * %message%. The browser will 'repair' the HTML (by moving, removing, or inserting elements) which breaks Svelte's assumptions about the structure of your components.
 * @param {null | number | NodeLike} node
 * @param {string} message
 * @returns {never}
 */
function node_invalid_placement(node, message) {
	e(node, 'node_invalid_placement', `${message}. The browser will 'repair' the HTML (by moving, removing, or inserting elements) which breaks Svelte's assumptions about the structure of your components.\nhttps://svelte.dev/e/node_invalid_placement`);
}

/**
 * Calling a snippet function using apply, bind or call is not allowed
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function render_tag_invalid_call_expression(node) {
	e(node, 'render_tag_invalid_call_expression', `Calling a snippet function using apply, bind or call is not allowed\nhttps://svelte.dev/e/render_tag_invalid_call_expression`);
}

/**
 * `{@render ...}` tags can only contain call expressions
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function render_tag_invalid_expression(node) {
	e(node, 'render_tag_invalid_expression', `\`{@render ...}\` tags can only contain call expressions\nhttps://svelte.dev/e/render_tag_invalid_expression`);
}

/**
 * cannot use spread arguments in `{@render ...}` tags
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function render_tag_invalid_spread_argument(node) {
	e(node, 'render_tag_invalid_spread_argument', `cannot use spread arguments in \`{@render ...}\` tags\nhttps://svelte.dev/e/render_tag_invalid_spread_argument`);
}

/**
 * A component can have a single top-level `<script>` element and/or a single top-level `<script module>` element
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function script_duplicate(node) {
	e(node, 'script_duplicate', `A component can have a single top-level \`<script>\` element and/or a single top-level \`<script module>\` element\nhttps://svelte.dev/e/script_duplicate`);
}

/**
 * If the `%name%` attribute is supplied, it must be a boolean attribute
 * @param {null | number | NodeLike} node
 * @param {string} name
 * @returns {never}
 */
function script_invalid_attribute_value(node, name) {
	e(node, 'script_invalid_attribute_value', `If the \`${name}\` attribute is supplied, it must be a boolean attribute\nhttps://svelte.dev/e/script_invalid_attribute_value`);
}

/**
 * If the context attribute is supplied, its value must be "module"
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function script_invalid_context(node) {
	e(node, 'script_invalid_context', `If the context attribute is supplied, its value must be "module"\nhttps://svelte.dev/e/script_invalid_context`);
}

/**
 * The `%name%` attribute is reserved and cannot be used
 * @param {null | number | NodeLike} node
 * @param {string} name
 * @returns {never}
 */
function script_reserved_attribute(node, name) {
	e(node, 'script_reserved_attribute', `The \`${name}\` attribute is reserved and cannot be used\nhttps://svelte.dev/e/script_reserved_attribute`);
}

/**
 * Duplicate slot name '%name%' in <%component%>
 * @param {null | number | NodeLike} node
 * @param {string} name
 * @param {string} component
 * @returns {never}
 */
function slot_attribute_duplicate(node, name, component) {
	e(node, 'slot_attribute_duplicate', `Duplicate slot name '${name}' in <${component}>\nhttps://svelte.dev/e/slot_attribute_duplicate`);
}

/**
 * slot attribute must be a static value
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function slot_attribute_invalid(node) {
	e(node, 'slot_attribute_invalid', `slot attribute must be a static value\nhttps://svelte.dev/e/slot_attribute_invalid`);
}

/**
 * Element with a slot='...' attribute must be a child of a component or a descendant of a custom element
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function slot_attribute_invalid_placement(node) {
	e(node, 'slot_attribute_invalid_placement', `Element with a slot='...' attribute must be a child of a component or a descendant of a custom element\nhttps://svelte.dev/e/slot_attribute_invalid_placement`);
}

/**
 * Found default slot content alongside an explicit slot="default"
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function slot_default_duplicate(node) {
	e(node, 'slot_default_duplicate', `Found default slot content alongside an explicit slot="default"\nhttps://svelte.dev/e/slot_default_duplicate`);
}

/**
 * `<slot>` can only receive attributes and (optionally) let directives
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function slot_element_invalid_attribute(node) {
	e(node, 'slot_element_invalid_attribute', `\`<slot>\` can only receive attributes and (optionally) let directives\nhttps://svelte.dev/e/slot_element_invalid_attribute`);
}

/**
 * slot attribute must be a static value
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function slot_element_invalid_name(node) {
	e(node, 'slot_element_invalid_name', `slot attribute must be a static value\nhttps://svelte.dev/e/slot_element_invalid_name`);
}

/**
 * `default` is a reserved word — it cannot be used as a slot name
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function slot_element_invalid_name_default(node) {
	e(node, 'slot_element_invalid_name_default', `\`default\` is a reserved word — it cannot be used as a slot name\nhttps://svelte.dev/e/slot_element_invalid_name_default`);
}

/**
 * Cannot use `<slot>` syntax and `{@render ...}` tags in the same component. Migrate towards `{@render ...}` tags completely
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function slot_snippet_conflict(node) {
	e(node, 'slot_snippet_conflict', `Cannot use \`<slot>\` syntax and \`{@render ...}\` tags in the same component. Migrate towards \`{@render ...}\` tags completely\nhttps://svelte.dev/e/slot_snippet_conflict`);
}

/**
 * Cannot use explicit children snippet at the same time as implicit children content. Remove either the non-whitespace content or the children snippet block
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function snippet_conflict(node) {
	e(node, 'snippet_conflict', `Cannot use explicit children snippet at the same time as implicit children content. Remove either the non-whitespace content or the children snippet block\nhttps://svelte.dev/e/snippet_conflict`);
}

/**
 * Snippets do not support rest parameters; use an array instead
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function snippet_invalid_rest_parameter(node) {
	e(node, 'snippet_invalid_rest_parameter', `Snippets do not support rest parameters; use an array instead\nhttps://svelte.dev/e/snippet_invalid_rest_parameter`);
}

/**
 * This snippet is shadowing the prop `%prop%` with the same name
 * @param {null | number | NodeLike} node
 * @param {string} prop
 * @returns {never}
 */
function snippet_shadowing_prop(node, prop) {
	e(node, 'snippet_shadowing_prop', `This snippet is shadowing the prop \`${prop}\` with the same name\nhttps://svelte.dev/e/snippet_shadowing_prop`);
}

/**
 * `style:` directive can only use the `important` modifier
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function style_directive_invalid_modifier(node) {
	e(node, 'style_directive_invalid_modifier', `\`style:\` directive can only use the \`important\` modifier\nhttps://svelte.dev/e/style_directive_invalid_modifier`);
}

/**
 * A component can have a single top-level `<style>` element
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function style_duplicate(node) {
	e(node, 'style_duplicate', `A component can have a single top-level \`<style>\` element\nhttps://svelte.dev/e/style_duplicate`);
}

/**
 * `<svelte:body>` does not support non-event attributes or spread attributes
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function svelte_body_illegal_attribute(node) {
	e(node, 'svelte_body_illegal_attribute', `\`<svelte:body>\` does not support non-event attributes or spread attributes\nhttps://svelte.dev/e/svelte_body_illegal_attribute`);
}

/**
 * Valid attributes on `<svelte:boundary>` are `onerror` and `failed`
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function svelte_boundary_invalid_attribute(node) {
	e(node, 'svelte_boundary_invalid_attribute', `Valid attributes on \`<svelte:boundary>\` are \`onerror\` and \`failed\`\nhttps://svelte.dev/e/svelte_boundary_invalid_attribute`);
}

/**
 * Attribute value must be a non-string expression
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function svelte_boundary_invalid_attribute_value(node) {
	e(node, 'svelte_boundary_invalid_attribute_value', `Attribute value must be a non-string expression\nhttps://svelte.dev/e/svelte_boundary_invalid_attribute_value`);
}

/**
 * Invalid component definition — must be an `{expression}`
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function svelte_component_invalid_this(node) {
	e(node, 'svelte_component_invalid_this', `Invalid component definition — must be an \`{expression}\`\nhttps://svelte.dev/e/svelte_component_invalid_this`);
}

/**
 * `<svelte:component>` must have a 'this' attribute
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function svelte_component_missing_this(node) {
	e(node, 'svelte_component_missing_this', `\`<svelte:component>\` must have a 'this' attribute\nhttps://svelte.dev/e/svelte_component_missing_this`);
}

/**
 * `<svelte:element>` must have a 'this' attribute with a value
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function svelte_element_missing_this(node) {
	e(node, 'svelte_element_missing_this', `\`<svelte:element>\` must have a 'this' attribute with a value\nhttps://svelte.dev/e/svelte_element_missing_this`);
}

/**
 * `<svelte:fragment>` can only have a slot attribute and (optionally) a let: directive
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function svelte_fragment_invalid_attribute(node) {
	e(node, 'svelte_fragment_invalid_attribute', `\`<svelte:fragment>\` can only have a slot attribute and (optionally) a let: directive\nhttps://svelte.dev/e/svelte_fragment_invalid_attribute`);
}

/**
 * `<svelte:fragment>` must be the direct child of a component
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function svelte_fragment_invalid_placement(node) {
	e(node, 'svelte_fragment_invalid_placement', `\`<svelte:fragment>\` must be the direct child of a component\nhttps://svelte.dev/e/svelte_fragment_invalid_placement`);
}

/**
 * `<svelte:head>` cannot have attributes nor directives
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function svelte_head_illegal_attribute(node) {
	e(node, 'svelte_head_illegal_attribute', `\`<svelte:head>\` cannot have attributes nor directives\nhttps://svelte.dev/e/svelte_head_illegal_attribute`);
}

/**
 * A component can only have one `<%name%>` element
 * @param {null | number | NodeLike} node
 * @param {string} name
 * @returns {never}
 */
function svelte_meta_duplicate(node, name) {
	e(node, 'svelte_meta_duplicate', `A component can only have one \`<${name}>\` element\nhttps://svelte.dev/e/svelte_meta_duplicate`);
}

/**
 * <%name%> cannot have children
 * @param {null | number | NodeLike} node
 * @param {string} name
 * @returns {never}
 */
function svelte_meta_invalid_content(node, name) {
	e(node, 'svelte_meta_invalid_content', `<${name}> cannot have children\nhttps://svelte.dev/e/svelte_meta_invalid_content`);
}

/**
 * `<%name%>` tags cannot be inside elements or blocks
 * @param {null | number | NodeLike} node
 * @param {string} name
 * @returns {never}
 */
function svelte_meta_invalid_placement(node, name) {
	e(node, 'svelte_meta_invalid_placement', `\`<${name}>\` tags cannot be inside elements or blocks\nhttps://svelte.dev/e/svelte_meta_invalid_placement`);
}

/**
 * Valid `<svelte:...>` tag names are %list%
 * @param {null | number | NodeLike} node
 * @param {string} list
 * @returns {never}
 */
function svelte_meta_invalid_tag(node, list) {
	e(node, 'svelte_meta_invalid_tag', `Valid \`<svelte:...>\` tag names are ${list}\nhttps://svelte.dev/e/svelte_meta_invalid_tag`);
}

/**
 * "tag" option is deprecated — use "customElement" instead
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function svelte_options_deprecated_tag(node) {
	e(node, 'svelte_options_deprecated_tag', `"tag" option is deprecated — use "customElement" instead\nhttps://svelte.dev/e/svelte_options_deprecated_tag`);
}

/**
 * `<svelte:options>` can only receive static attributes
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function svelte_options_invalid_attribute(node) {
	e(node, 'svelte_options_invalid_attribute', `\`<svelte:options>\` can only receive static attributes\nhttps://svelte.dev/e/svelte_options_invalid_attribute`);
}

/**
 * Value must be %list%, if specified
 * @param {null | number | NodeLike} node
 * @param {string} list
 * @returns {never}
 */
function svelte_options_invalid_attribute_value(node, list) {
	e(node, 'svelte_options_invalid_attribute_value', `Value must be ${list}, if specified\nhttps://svelte.dev/e/svelte_options_invalid_attribute_value`);
}

/**
 * "customElement" must be a string literal defining a valid custom element name or an object of the form { tag?: string; shadow?: "open" | "none"; props?: { [key: string]: { attribute?: string; reflect?: boolean; type: .. } } }
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function svelte_options_invalid_customelement(node) {
	e(node, 'svelte_options_invalid_customelement', `"customElement" must be a string literal defining a valid custom element name or an object of the form { tag?: string; shadow?: "open" | "none"; props?: { [key: string]: { attribute?: string; reflect?: boolean; type: .. } } }\nhttps://svelte.dev/e/svelte_options_invalid_customelement`);
}

/**
 * "props" must be a statically analyzable object literal of the form "{ [key: string]: { attribute?: string; reflect?: boolean; type?: "String" | "Boolean" | "Number" | "Array" | "Object" }"
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function svelte_options_invalid_customelement_props(node) {
	e(node, 'svelte_options_invalid_customelement_props', `"props" must be a statically analyzable object literal of the form "{ [key: string]: { attribute?: string; reflect?: boolean; type?: "String" | "Boolean" | "Number" | "Array" | "Object" }"\nhttps://svelte.dev/e/svelte_options_invalid_customelement_props`);
}

/**
 * "shadow" must be either "open" or "none"
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function svelte_options_invalid_customelement_shadow(node) {
	e(node, 'svelte_options_invalid_customelement_shadow', `"shadow" must be either "open" or "none"\nhttps://svelte.dev/e/svelte_options_invalid_customelement_shadow`);
}

/**
 * Tag name must be lowercase and hyphenated
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function svelte_options_invalid_tagname(node) {
	e(node, 'svelte_options_invalid_tagname', `Tag name must be lowercase and hyphenated\nhttps://svelte.dev/e/svelte_options_invalid_tagname`);
}

/**
 * Tag name is reserved
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function svelte_options_reserved_tagname(node) {
	e(node, 'svelte_options_reserved_tagname', `Tag name is reserved\nhttps://svelte.dev/e/svelte_options_reserved_tagname`);
}

/**
 * `<svelte:options>` unknown attribute '%name%'
 * @param {null | number | NodeLike} node
 * @param {string} name
 * @returns {never}
 */
function svelte_options_unknown_attribute(node, name) {
	e(node, 'svelte_options_unknown_attribute', `\`<svelte:options>\` unknown attribute '${name}'\nhttps://svelte.dev/e/svelte_options_unknown_attribute`);
}

/**
 * `<svelte:self>` components can only exist inside `{#if}` blocks, `{#each}` blocks, `{#snippet}` blocks or slots passed to components
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function svelte_self_invalid_placement(node) {
	e(node, 'svelte_self_invalid_placement', `\`<svelte:self>\` components can only exist inside \`{#if}\` blocks, \`{#each}\` blocks, \`{#snippet}\` blocks or slots passed to components\nhttps://svelte.dev/e/svelte_self_invalid_placement`);
}

/**
 * Expected a valid element or component name. Components must have a valid variable name or dot notation expression
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function tag_invalid_name(node) {
	e(node, 'tag_invalid_name', `Expected a valid element or component name. Components must have a valid variable name or dot notation expression\nhttps://svelte.dev/e/tag_invalid_name`);
}

/**
 * {@%name% ...} tag cannot be %location%
 * @param {null | number | NodeLike} node
 * @param {string} name
 * @param {string} location
 * @returns {never}
 */
function tag_invalid_placement(node, name, location) {
	e(node, 'tag_invalid_placement', `{@${name} ...} tag cannot be ${location}\nhttps://svelte.dev/e/tag_invalid_placement`);
}

/**
 * A `<textarea>` can have either a value attribute or (equivalently) child content, but not both
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function textarea_invalid_content(node) {
	e(node, 'textarea_invalid_content', `A \`<textarea>\` can have either a value attribute or (equivalently) child content, but not both\nhttps://svelte.dev/e/textarea_invalid_content`);
}

/**
 * `<title>` cannot have attributes nor directives
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function title_illegal_attribute(node) {
	e(node, 'title_illegal_attribute', `\`<title>\` cannot have attributes nor directives\nhttps://svelte.dev/e/title_illegal_attribute`);
}

/**
 * `<title>` can only contain text and {tags}
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function title_invalid_content(node) {
	e(node, 'title_invalid_content', `\`<title>\` can only contain text and {tags}\nhttps://svelte.dev/e/title_invalid_content`);
}

/**
 * Cannot use `%type%:` alongside existing `%existing%:` directive
 * @param {null | number | NodeLike} node
 * @param {string} type
 * @param {string} existing
 * @returns {never}
 */
function transition_conflict(node, type, existing) {
	e(node, 'transition_conflict', `Cannot use \`${type}:\` alongside existing \`${existing}:\` directive\nhttps://svelte.dev/e/transition_conflict`);
}

/**
 * Cannot use multiple `%type%:` directives on a single element
 * @param {null | number | NodeLike} node
 * @param {string} type
 * @returns {never}
 */
function transition_duplicate(node, type) {
	e(node, 'transition_duplicate', `Cannot use multiple \`${type}:\` directives on a single element\nhttps://svelte.dev/e/transition_duplicate`);
}

/**
 * Unexpected end of input
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function unexpected_eof(node) {
	e(node, 'unexpected_eof', `Unexpected end of input\nhttps://svelte.dev/e/unexpected_eof`);
}

/**
 * '%word%' is a reserved word in JavaScript and cannot be used here
 * @param {null | number | NodeLike} node
 * @param {string} word
 * @returns {never}
 */
function unexpected_reserved_word(node, word) {
	e(node, 'unexpected_reserved_word', `'${word}' is a reserved word in JavaScript and cannot be used here\nhttps://svelte.dev/e/unexpected_reserved_word`);
}

/**
 * Unterminated string constant
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function unterminated_string_constant(node) {
	e(node, 'unterminated_string_constant', `Unterminated string constant\nhttps://svelte.dev/e/unterminated_string_constant`);
}

/**
 * Void elements cannot have children or closing tags
 * @param {null | number | NodeLike} node
 * @returns {never}
 */
function void_element_invalid_content(node) {
	e(node, 'void_element_invalid_content', `Void elements cannot have children or closing tags\nhttps://svelte.dev/e/void_element_invalid_content`);
}

/** @import { Parser } from '../index.js' */

/**
 * @param {number} num
 * @returns {number} Infinity if {@link num} is negative, else {@link num}.
 */
function infinity_if_negative(num) {
	if (num < 0) {
		return Infinity;
	}
	return num;
}

/**
 * @param {string} string The string to search.
 * @param {number} search_start_index The index to start searching at.
 * @param {"'" | '"' | '`'} string_start_char The character that started this string.
 * @returns {number} The index of the end of this string expression, or `Infinity` if not found.
 */
function find_string_end(string, search_start_index, string_start_char) {
	let string_to_search;
	if (string_start_char === '`') {
		string_to_search = string;
	} else {
		// we could slice at the search start index, but this way the index remains valid
		string_to_search = string.slice(
			0,
			infinity_if_negative(string.indexOf('\n', search_start_index))
		);
	}

	return find_unescaped_char(string_to_search, search_start_index, string_start_char);
}

/**
 * @param {string} string The string to search.
 * @param {number} search_start_index The index to start searching at.
 * @returns {number} The index of the end of this regex expression, or `Infinity` if not found.
 */
function find_regex_end(string, search_start_index) {
	return find_unescaped_char(string, search_start_index, '/');
}

/**
 *
 * @param {string} string The string to search.
 * @param {number} search_start_index The index to begin the search at.
 * @param {string} char The character to search for.
 * @returns {number} The index of the first unescaped instance of {@link char}, or `Infinity` if not found.
 */
function find_unescaped_char(string, search_start_index, char) {
	let i = search_start_index;
	while (true) {
		const found_index = string.indexOf(char, i);
		if (found_index === -1) {
			return Infinity;
		}
		if (count_leading_backslashes(string, found_index - 1) % 2 === 0) {
			return found_index;
		}
		i = found_index + 1;
	}
}

/**
 * Count consecutive leading backslashes before {@link search_start_index}.
 *
 * @example
 * ```js
 * count_leading_backslashes('\\\\\\foo', 2); // 3 (the backslashes have to be escaped in the string literal, there are three in reality)
 * ```
 *
 * @param {string} string The string to search.
 * @param {number} search_start_index The index to begin the search at.
 */
function count_leading_backslashes(string, search_start_index) {
	let i = search_start_index;
	let count = 0;
	while (string[i] === '\\') {
		count++;
		i--;
	}
	return count;
}

/**
 * Finds the corresponding closing bracket, ignoring brackets found inside comments, strings, or regex expressions.
 * @param {string} template The string to search.
 * @param {number} index The index to begin the search at.
 * @param {string} open The opening bracket (ex: `'{'` will search for `'}'`).
 * @returns {number | undefined} The index of the closing bracket, or undefined if not found.
 */
function find_matching_bracket(template, index, open) {
	const close = default_brackets[open];
	let brackets = 1;
	let i = index;
	while (brackets > 0 && i < template.length) {
		const char = template[i];
		switch (char) {
			case "'":
			case '"':
			case '`':
				i = find_string_end(template, i + 1, char) + 1;
				continue;
			case '/': {
				const next_char = template[i + 1];
				if (!next_char) continue;
				if (next_char === '/') {
					i = infinity_if_negative(template.indexOf('\n', i + 1)) + '\n'.length;
					continue;
				}
				if (next_char === '*') {
					i = infinity_if_negative(template.indexOf('*/', i + 1)) + '*/'.length;
					continue;
				}
				i = find_regex_end(template, i + 1) + '/'.length;
				continue;
			}
			default: {
				const char = template[i];
				if (char === open) {
					brackets++;
				} else if (char === close) {
					brackets--;
				}
				if (brackets === 0) {
					return i;
				}
				i++;
			}
		}
	}
	return undefined;
}

/** @type {Record<string, string>} */
const default_brackets = {
	'{': '}',
	'(': ')',
	'[': ']'
};

/**
 * @param {Parser} parser
 * @param {number} start
 * @param {Record<string, string>} brackets
 */
function match_bracket(parser, start, brackets = default_brackets) {
	const close = Object.values(brackets);
	const bracket_stack = [];

	let i = start;

	while (i < parser.template.length) {
		let char = parser.template[i++];

		if (char === "'" || char === '"' || char === '`') {
			i = match_quote(parser, i, char);
			continue;
		}

		if (char in brackets) {
			bracket_stack.push(char);
		} else if (close.includes(char)) {
			const popped = /** @type {string} */ (bracket_stack.pop());
			const expected = /** @type {string} */ (brackets[popped]);

			if (char !== expected) {
				expected_token(i - 1, expected);
			}

			if (bracket_stack.length === 0) {
				return i;
			}
		}
	}

	unexpected_eof(parser.template.length);
}

/**
 * @param {Parser} parser
 * @param {number} start
 * @param {string} quote
 */
function match_quote(parser, start, quote) {
	let is_escaped = false;
	let i = start;

	while (i < parser.template.length) {
		const char = parser.template[i++];

		if (is_escaped) {
			is_escaped = false;
			continue;
		}

		if (char === quote) {
			return i;
		}

		if (char === '\\') {
			is_escaped = true;
		}

		if (quote === '`' && char === '$' && parser.template[i] === '{') {
			i = match_bracket(parser, i);
		}
	}

	unterminated_string_constant(start);
}

/** @import { Expression } from 'estree' */
/** @import { Parser } from '../index.js' */

/**
 * @param {Parser} parser
 * @param {string} [opening_token]
 * @returns {Expression | undefined}
 */
function get_loose_identifier(parser, opening_token) {
	// Find the next } and treat it as the end of the expression
	const end = find_matching_bracket(parser.template, parser.index, opening_token ?? '{');
	if (end) {
		const start = parser.index;
		parser.index = end;
		// We don't know what the expression is and signal this by returning an empty identifier
		return {
			type: 'Identifier',
			start,
			end,
			name: ''
		};
	}
}

/**
 * @param {Parser} parser
 * @param {string} [opening_token]
 * @param {boolean} [disallow_loose]
 * @returns {Expression}
 */
function read_expression(parser, opening_token, disallow_loose) {
	try {
		let comment_index = parser.root.comments.length;

		const node = parse_expression_at(
			parser.template,
			parser.root.comments,
			parser.ts,
			parser.index
		);

		let num_parens = 0;

		let i = parser.root.comments.length;
		while (i-- > comment_index) {
			const comment = parser.root.comments[i];
			if (comment.end < node.start) {
				parser.index = comment.end;
				break;
			}
		}

		for (let i = parser.index; i < /** @type {number} */ (node.start); i += 1) {
			if (parser.template[i] === '(') num_parens += 1;
		}

		let index = /** @type {number} */ (node.end);

		const last_comment = parser.root.comments.at(-1);
		if (last_comment && last_comment.end > index) index = last_comment.end;

		while (num_parens > 0) {
			const char = parser.template[index];

			if (char === ')') {
				num_parens -= 1;
			} else if (!regex_whitespace.test(char)) {
				expected_token(index, ')');
			}

			index += 1;
		}

		parser.index = index;

		return /** @type {Expression} */ (node);
	} catch (err) {
		// If we are in an each loop we need the error to be thrown in cases like
		// `as { y = z }` so we still throw and handle the error there
		if (parser.loose && !disallow_loose) {
			const expression = get_loose_identifier(parser, opening_token);
			if (expression) {
				return expression;
			}
		}

		parser.acorn_error(err);
	}
}

/**
 * @param {string} str
 * @returns {string}
 */
function sanitize_template_string(str) {
	return str.replace(/(`|\${|\\)/g, '\\$1');
}

/** @import * as ESTree from 'estree' */

/**
 * @param {Array<ESTree.Expression | ESTree.SpreadElement | null>} elements
 * @returns {ESTree.ArrayExpression}
 */
function array(elements = []) {
	return { type: 'ArrayExpression', elements };
}

/**
 * @param {Array<ESTree.Pattern | null>} elements
 * @returns {ESTree.ArrayPattern}
 */
function array_pattern(elements) {
	return { type: 'ArrayPattern', elements };
}

/**
 * @param {ESTree.Pattern} left
 * @param {ESTree.Expression} right
 * @returns {ESTree.AssignmentPattern}
 */
function assignment_pattern(left, right) {
	return { type: 'AssignmentPattern', left, right };
}

/**
 * @param {Array<ESTree.Pattern>} params
 * @param {ESTree.BlockStatement | ESTree.Expression} body
 * @param {boolean} async
 * @returns {ESTree.ArrowFunctionExpression}
 */
function arrow(params, body, async = false) {
	return {
		type: 'ArrowFunctionExpression',
		params,
		body,
		expression: body.type !== 'BlockStatement',
		generator: false,
		async
	};
}

/**
 * @param {ESTree.AssignmentOperator} operator
 * @param {ESTree.Pattern} left
 * @param {ESTree.Expression} right
 * @returns {ESTree.AssignmentExpression}
 */
function assignment(operator, left, right) {
	return { type: 'AssignmentExpression', operator, left, right };
}

/**
 * @param {ESTree.Expression} argument
 * @returns {ESTree.AwaitExpression}
 */
function await_builder(argument) {
	return { type: 'AwaitExpression', argument };
}

/**
 * @param {ESTree.BinaryOperator} operator
 * @param {ESTree.Expression} left
 * @param {ESTree.Expression} right
 * @returns {ESTree.BinaryExpression}
 */
function binary$1(operator, left, right) {
	return { type: 'BinaryExpression', operator, left, right };
}

/**
 * @param {ESTree.Statement[]} body
 * @returns {ESTree.BlockStatement}
 */
function block(body) {
	return { type: 'BlockStatement', body };
}

/**
 * @param {string} name
 * @param {ESTree.Statement} body
 * @returns {ESTree.LabeledStatement}
 */
function labeled(name, body) {
	return { type: 'LabeledStatement', label: id(name), body };
}

/**
 * @param {string | ESTree.Expression} callee
 * @param {...(ESTree.Expression | ESTree.SpreadElement | false | undefined | null)} args
 * @returns {ESTree.CallExpression}
 */
function call(callee, ...args) {
	if (typeof callee === 'string') callee = id(callee);
	args = args.slice();

	// replacing missing arguments with `void(0)`, unless they're at the end in which case remove them
	let i = args.length;
	let popping = true;
	while (i--) {
		if (!args[i]) {
			if (popping) {
				args.pop();
			} else {
				args[i] = void0;
			}
		} else {
			popping = false;
		}
	}

	return {
		type: 'CallExpression',
		callee,
		arguments: /** @type {Array<ESTree.Expression | ESTree.SpreadElement>} */ (args),
		optional: false
	};
}

/**
 * @param {string | ESTree.Expression} callee
 * @param {...ESTree.Expression} args
 * @returns {ESTree.ChainExpression}
 */
function maybe_call(callee, ...args) {
	const expression = /** @type {ESTree.SimpleCallExpression} */ (call(callee, ...args));
	expression.optional = true;

	return {
		type: 'ChainExpression',
		expression
	};
}

/**
 * @param {ESTree.UnaryOperator} operator
 * @param {ESTree.Expression} argument
 * @returns {ESTree.UnaryExpression}
 */
function unary$1(operator, argument) {
	return { type: 'UnaryExpression', argument, operator, prefix: true };
}

const void0 = unary$1('void', literal(0));

/**
 * @param {ESTree.LogicalOperator} operator
 * @param {ESTree.Expression} left
 * @param {ESTree.Expression} right
 * @returns {ESTree.LogicalExpression}
 */
function logical$1(operator, left, right) {
	return { type: 'LogicalExpression', operator, left, right };
}

/**
 * @param {ESTree.VariableDeclaration['kind']} kind
 * @param {ESTree.VariableDeclarator[]} declarations
 * @returns {ESTree.VariableDeclaration}
 */
function declaration(kind, declarations) {
	return {
		type: 'VariableDeclaration',
		kind,
		declarations
	};
}

/**
 * @param {ESTree.Pattern | string} pattern
 * @param {ESTree.Expression | null} [init]
 * @returns {ESTree.VariableDeclarator}
 */
function declarator(pattern, init) {
	if (typeof pattern === 'string') pattern = id(pattern);
	return { type: 'VariableDeclarator', id: pattern, init };
}

/** @type {ESTree.EmptyStatement} */
const empty = {
	type: 'EmptyStatement'
};

/**
 * @param {ESTree.Expression | ESTree.MaybeNamedClassDeclaration | ESTree.MaybeNamedFunctionDeclaration} declaration
 * @returns {ESTree.ExportDefaultDeclaration}
 */
function export_default(declaration) {
	return { type: 'ExportDefaultDeclaration', declaration };
}

/**
 * @param {ESTree.VariableDeclaration | ESTree.Pattern} left
 * @param {ESTree.Expression} right
 * @param {ESTree.Statement} body
 * @param {boolean} [_await]
 * @returns {ESTree.ForOfStatement}
 */
function for_of(left, right, body, _await = false) {
	return {
		type: 'ForOfStatement',
		left,
		right,
		body,
		await: _await
	};
}

/**
 * @param {ESTree.Identifier} id
 * @param {ESTree.Pattern[]} params
 * @param {ESTree.BlockStatement} body
 * @param {boolean} async
 * @returns {ESTree.FunctionDeclaration}
 */
function function_declaration(id, params, body, async = false) {
	return {
		type: 'FunctionDeclaration',
		id,
		params,
		body,
		generator: false,
		async
	};
}

/**
 * @param {string} name
 * @param {ESTree.Statement[]} body
 * @returns {ESTree.Property & { value: ESTree.FunctionExpression}}}
 */
function get$1(name, body) {
	return prop('get', key(name), function_builder(null, [], block(body)));
}

/**
 * @param {string} name
 * @returns {ESTree.Identifier}
 */
function id(name) {
	return { type: 'Identifier', name };
}

/**
 * @param {string} name
 * @returns {ESTree.PrivateIdentifier}
 */
function private_id(name) {
	return { type: 'PrivateIdentifier', name };
}

/**
 * @param {string} local
 * @returns {ESTree.ImportNamespaceSpecifier}
 */
function import_namespace(local) {
	return {
		type: 'ImportNamespaceSpecifier',
		local: id(local)
	};
}

/**
 * @param {string} name
 * @param {ESTree.Expression} value
 * @returns {ESTree.Property}
 */
function init(name, value) {
	return prop('init', key(name), value);
}

/**
 * @param {string | boolean | null | number | RegExp} value
 * @returns {ESTree.Literal}
 */
function literal(value) {
	// @ts-expect-error we don't want to muck around with bigint here
	return { type: 'Literal', value };
}

/**
 * @param {ESTree.Expression | ESTree.Super} object
 * @param {string | ESTree.Expression | ESTree.PrivateIdentifier} property
 * @param {boolean} computed
 * @param {boolean} optional
 * @returns {ESTree.MemberExpression}
 */
function member(object, property, computed = false, optional = false) {
	if (typeof property === 'string') {
		property = id(property);
	}

	return { type: 'MemberExpression', object, property, computed, optional };
}

/**
 * @param {string} path
 * @returns {ESTree.Identifier | ESTree.MemberExpression}
 */
function member_id(path) {
	const parts = path.split('.');

	/** @type {ESTree.Identifier | ESTree.MemberExpression} */
	let expression = id(parts[0]);

	for (let i = 1; i < parts.length; i += 1) {
		expression = member(expression, id(parts[i]));
	}
	return expression;
}

/**
 * @param {Array<ESTree.Property | ESTree.SpreadElement>} properties
 * @returns {ESTree.ObjectExpression}
 */
function object$2(properties) {
	return { type: 'ObjectExpression', properties };
}

/**
 * @param {Array<ESTree.RestElement | ESTree.AssignmentProperty | ESTree.Property>} properties
 * @returns {ESTree.ObjectPattern}
 */
function object_pattern(properties) {
	// @ts-expect-error the types appear to be wrong
	return { type: 'ObjectPattern', properties };
}

/**
 * @template {ESTree.Expression} Value
 * @param {'init' | 'get' | 'set'} kind
 * @param {ESTree.Expression} key
 * @param {Value} value
 * @param {boolean} computed
 * @returns {ESTree.Property & { value: Value }}
 */
function prop(kind, key, value, computed = false) {
	return { type: 'Property', kind, key, value, method: false, shorthand: false, computed };
}

/**
 * @param {ESTree.Expression | ESTree.PrivateIdentifier} key
 * @param {ESTree.Expression | null | undefined} value
 * @param {boolean} computed
 * @param {boolean} is_static
 * @returns {ESTree.PropertyDefinition}
 */
function prop_def(key, value, computed = false, is_static = false) {
	return {
		type: 'PropertyDefinition',
		decorators: [],
		key,
		value,
		computed,
		static: is_static
	};
}

/**
 * @param {string} cooked
 * @param {boolean} tail
 * @returns {ESTree.TemplateElement}
 */
function quasi(cooked, tail = false) {
	const raw = sanitize_template_string(cooked);
	return { type: 'TemplateElement', value: { raw, cooked }, tail };
}

/**
 * @param {ESTree.Pattern} argument
 * @returns {ESTree.RestElement}
 */
function rest(argument) {
	return { type: 'RestElement', argument };
}

/**
 * @param {ESTree.Expression[]} expressions
 * @returns {ESTree.SequenceExpression}
 */
function sequence(expressions) {
	return { type: 'SequenceExpression', expressions };
}

/**
 * @param {string} name
 * @param {ESTree.Statement[]} body
 * @returns {ESTree.Property & { value: ESTree.FunctionExpression}}
 */
function set(name, body) {
	return prop('set', key(name), function_builder(null, [id('$$value')], block(body)));
}

/**
 * @param {ESTree.Expression} argument
 * @returns {ESTree.SpreadElement}
 */
function spread(argument) {
	return { type: 'SpreadElement', argument };
}

/**
 * @param {ESTree.Expression} expression
 * @returns {ESTree.ExpressionStatement}
 */
function stmt(expression) {
	return { type: 'ExpressionStatement', expression };
}

/**
 * @param {ESTree.TemplateElement[]} elements
 * @param {ESTree.Expression[]} expressions
 * @returns {ESTree.TemplateLiteral}
 */
function template$1(elements, expressions) {
	return { type: 'TemplateLiteral', quasis: elements, expressions };
}

/**
 * @param {ESTree.Expression | ESTree.BlockStatement} expression
 * @param {boolean} [async]
 * @returns {ESTree.Expression}
 */
function thunk(expression, async = false) {
	return unthunk(arrow([], expression, async));
}

/**
 * Replace "(arg) => func(arg)" to "func"
 * @param {ESTree.ArrowFunctionExpression} expression
 * @returns {ESTree.Expression}
 */
function unthunk(expression) {
	// optimize `async () => await x()`, but not `async () => await x(await y)`
	if (expression.async && expression.body.type === 'AwaitExpression') {
		if (!has_await_expression(expression.body.argument)) {
			return unthunk(arrow(expression.params, expression.body.argument));
		}
	}

	if (
		expression.async === false &&
		expression.body.type === 'CallExpression' &&
		expression.body.callee.type === 'Identifier' &&
		expression.params.length === expression.body.arguments.length &&
		expression.params.every((param, index) => {
			const arg = /** @type {ESTree.SimpleCallExpression} */ (expression.body).arguments[index];
			return param.type === 'Identifier' && arg.type === 'Identifier' && param.name === arg.name;
		})
	) {
		return expression.body.callee;
	}
	return expression;
}

/**
 *
 * @param {string | ESTree.Expression} expression
 * @param  {...ESTree.Expression} args
 * @returns {ESTree.NewExpression}
 */
function new_builder(expression, ...args) {
	if (typeof expression === 'string') expression = id(expression);

	return {
		callee: expression,
		arguments: args,
		type: 'NewExpression'
	};
}

/**
 * @param {ESTree.UpdateOperator} operator
 * @param {ESTree.Expression} argument
 * @param {boolean} prefix
 * @returns {ESTree.UpdateExpression}
 */
function update(operator, argument, prefix = false) {
	return { type: 'UpdateExpression', operator, argument, prefix };
}

/**
 * @param {ESTree.Expression} test
 * @param {ESTree.Statement} body
 * @returns {ESTree.DoWhileStatement}
 */
function do_while(test, body) {
	return { type: 'DoWhileStatement', test, body };
}

const true_instance = literal(true);
const false_instance = literal(false);
const null_instance = literal(null);

/** @type {ESTree.DebuggerStatement} */
const debugger_builder = {
	type: 'DebuggerStatement'
};

/** @type {ESTree.ThisExpression} */
const this_instance = {
	type: 'ThisExpression'
};

/**
 * @param {string | ESTree.Pattern} pattern
 * @param {ESTree.Expression | null} [init]
 * @returns {ESTree.VariableDeclaration}
 */
function let_builder(pattern, init) {
	return declaration('let', [declarator(pattern, init)]);
}

/**
 * @param {string | ESTree.Pattern} pattern
 * @param {ESTree.Expression | null} init
 * @returns {ESTree.VariableDeclaration}
 */
function const_builder(pattern, init) {
	return declaration('const', [declarator(pattern, init)]);
}

/**
 * @param {string | ESTree.Pattern} pattern
 * @param {ESTree.Expression | null} [init]
 * @returns {ESTree.VariableDeclaration}
 */
function var_builder(pattern, init) {
	return declaration('var', [declarator(pattern, init)]);
}

/**
 *
 * @param {ESTree.VariableDeclaration | ESTree.Expression | null} init
 * @param {ESTree.Expression} test
 * @param {ESTree.Expression} update
 * @param {ESTree.Statement} body
 * @returns {ESTree.ForStatement}
 */
function for_builder(init, test, update, body) {
	return { type: 'ForStatement', init, test, update, body };
}

/**
 *
 * @param {'constructor' | 'method' | 'get' | 'set'} kind
 * @param {ESTree.Expression | ESTree.PrivateIdentifier} key
 * @param {ESTree.Pattern[]} params
 * @param {ESTree.Statement[]} body
 * @param {boolean} computed
 * @param {boolean} is_static
 * @returns {ESTree.MethodDefinition}
 */
function method(kind, key, params, body, computed = false, is_static = false) {
	return {
		type: 'MethodDefinition',
		decorators: [],
		key,
		kind,
		value: function_builder(null, params, block(body)),
		computed,
		static: is_static
	};
}

/**
 *
 * @param {ESTree.Identifier | null} id
 * @param {ESTree.Pattern[]} params
 * @param {ESTree.BlockStatement} body
 * @returns {ESTree.FunctionExpression}
 */
function function_builder(id, params, body, async = false) {
	return {
		type: 'FunctionExpression',
		id,
		params,
		body,
		generator: false,
		async
	};
}

/**
 * @param {ESTree.Expression} test
 * @param {ESTree.Statement} consequent
 * @param {ESTree.Statement} [alternate]
 * @returns {ESTree.IfStatement}
 */
function if_builder(test, consequent, alternate) {
	return { type: 'IfStatement', test, consequent, alternate };
}

/**
 * @param {string} as
 * @param {string} source
 * @returns {ESTree.ImportDeclaration}
 */
function import_all(as, source) {
	return {
		type: 'ImportDeclaration',
		attributes: [],
		source: literal(source),
		specifiers: [import_namespace(as)]
	};
}

/**
 * @param {Array<[string, string]>} parts
 * @param {string} source
 * @returns {ESTree.ImportDeclaration}
 */
function imports(parts, source) {
	return {
		type: 'ImportDeclaration',
		attributes: [],
		source: literal(source),
		specifiers: parts.map((p) => ({
			type: 'ImportSpecifier',
			imported: id(p[0]),
			local: id(p[1])
		}))
	};
}

/**
 * @param {ESTree.Expression | null} argument
 * @returns {ESTree.ReturnStatement}
 */
function return_builder(argument = null) {
	return { type: 'ReturnStatement', argument };
}

/**
 * @param {string} str
 * @returns {ESTree.ThrowStatement}
 */
function throw_error$1(str) {
	return {
		type: 'ThrowStatement',
		argument: new_builder('Error', literal(str))
	};
}

/**
 * @param {string} name
 * @returns {ESTree.Expression}
 */
function key(name) {
	return regex_is_valid_identifier.test(name) ? id(name) : literal(name);
}

/** @import { AST, Scope } from '#compiler' */
/** @import * as ESTree from 'estree' */

/**
 * Gets the left-most identifier of a member expression or identifier.
 * @param {ESTree.MemberExpression | ESTree.Identifier} expression
 * @returns {ESTree.Identifier | null}
 */
function object$1(expression) {
	while (expression.type === 'MemberExpression') {
		expression = /** @type {ESTree.MemberExpression | ESTree.Identifier} */ (expression.object);
	}

	if (expression.type !== 'Identifier') {
		return null;
	}

	return expression;
}

/**
 * Returns true if the attribute contains a single static text node.
 * @param {AST.Attribute} attribute
 * @returns {attribute is AST.Attribute & { value: [AST.Text] }}
 */
function is_text_attribute(attribute) {
	return (
		Array.isArray(attribute.value) &&
		attribute.value.length === 1 &&
		attribute.value[0].type === 'Text'
	);
}

/**
 * Returns true if the attribute contains a single expression node.
 * In Svelte 5, this also includes a single expression node wrapped in an array.
 * TODO change that in a future version
 * @param {AST.Attribute} attribute
 * @returns {attribute is AST.Attribute & { value: [AST.ExpressionTag] | AST.ExpressionTag }}
 */
function is_expression_attribute(attribute) {
	return (
		(attribute.value !== true && !Array.isArray(attribute.value)) ||
		(Array.isArray(attribute.value) &&
			attribute.value.length === 1 &&
			attribute.value[0].type === 'ExpressionTag')
	);
}

/**
 * Returns the single attribute expression node.
 * In Svelte 5, this also includes a single expression node wrapped in an array.
 * TODO change that in a future version
 * @param { AST.Attribute & { value: [AST.ExpressionTag] | AST.ExpressionTag }} attribute
 * @returns {ESTree.Expression}
 */
function get_attribute_expression(attribute) {
	return Array.isArray(attribute.value)
		? /** @type {AST.ExpressionTag} */ (attribute.value[0]).expression
		: attribute.value.expression;
}

/**
 * Returns the expression chunks of an attribute value
 * @param {AST.Attribute['value']} value
 * @returns {Array<AST.Text | AST.ExpressionTag>}
 */
function get_attribute_chunks(value) {
	return Array.isArray(value) ? value : typeof value === 'boolean' ? [] : [value];
}

/**
 * Returns true if the attribute starts with `on` and contains a single expression node.
 * @param {AST.Attribute} attribute
 * @returns {attribute is AST.Attribute & { value: [AST.ExpressionTag] | AST.ExpressionTag }}
 */
function is_event_attribute(attribute) {
	return is_expression_attribute(attribute) && attribute.name.startsWith('on');
}

/**
 * Extracts all identifiers and member expressions from a pattern.
 * @param {ESTree.Pattern} pattern
 * @param {Array<ESTree.Identifier | ESTree.MemberExpression>} [nodes]
 * @returns {Array<ESTree.Identifier | ESTree.MemberExpression>}
 */
function unwrap_pattern(pattern, nodes = []) {
	switch (pattern.type) {
		case 'Identifier':
			nodes.push(pattern);
			break;

		case 'MemberExpression':
			// member expressions can be part of an assignment pattern, but not a binding pattern
			// see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#binding_and_assignment
			nodes.push(pattern);
			break;

		case 'ObjectPattern':
			for (const prop of pattern.properties) {
				if (prop.type === 'RestElement') {
					unwrap_pattern(prop.argument, nodes);
				} else {
					unwrap_pattern(prop.value, nodes);
				}
			}

			break;

		case 'ArrayPattern':
			for (const element of pattern.elements) {
				if (element) unwrap_pattern(element, nodes);
			}

			break;

		case 'RestElement':
			unwrap_pattern(pattern.argument, nodes);
			break;

		case 'AssignmentPattern':
			unwrap_pattern(pattern.left, nodes);
			break;
	}

	return nodes;
}

/**
 * Extracts all identifiers from a pattern.
 * @param {ESTree.Pattern} pattern
 * @returns {ESTree.Identifier[]}
 */
function extract_identifiers(pattern) {
	return unwrap_pattern(pattern, []).filter((node) => node.type === 'Identifier');
}

/**
 * Extracts all identifiers and a stringified keypath from an expression.
 * TODO replace this with `expression.dependencies`
 * @param {ESTree.Expression} expr
 * @returns {[keypath: string, ids: ESTree.Identifier[]]}
 */
function extract_all_identifiers_from_expression(expr) {
	/** @type {ESTree.Identifier[]} */
	let nodes = [];
	/** @type {string[]} */
	let keypath = [];

	walk$1(
		expr,
		{},
		{
			Identifier(node, { path }) {
				const parent = path.at(-1);
				if (parent?.type !== 'MemberExpression' || parent.property !== node || parent.computed) {
					nodes.push(node);
				}

				if (parent?.type === 'MemberExpression' && parent.computed && parent.property === node) {
					keypath.push(`[${node.name}]`);
				} else {
					keypath.push(node.name);
				}
			},
			Literal(node, { path }) {
				const value = typeof node.value === 'string' ? `"${node.value}"` : String(node.value);
				const parent = path.at(-1);
				if (parent?.type === 'MemberExpression' && parent.computed && parent.property === node) {
					keypath.push(`[${value}]`);
				} else {
					keypath.push(value);
				}
			},
			ThisExpression(_, { next }) {
				keypath.push('this');
				next();
			}
		}
	);

	return [keypath.join('.'), nodes];
}

/**
 * Extracts all leaf identifiers from a destructuring expression.
 * @param {ESTree.Identifier | ESTree.ObjectExpression | ESTree.ArrayExpression} node
 * @param {ESTree.Identifier[]} [nodes]
 * @returns
 */
function extract_identifiers_from_destructuring(node, nodes = []) {
	// TODO This isn't complete, but it should be enough for our purposes
	switch (node.type) {
		case 'Identifier':
			nodes.push(node);
			break;

		case 'ObjectExpression':
			for (const prop of node.properties) {
				if (prop.type === 'Property') {
					extract_identifiers_from_destructuring(/** @type {any} */ (prop.value), nodes);
				} else {
					extract_identifiers_from_destructuring(/** @type {any} */ (prop.argument), nodes);
				}
			}

			break;

		case 'ArrayExpression':
			for (const element of node.elements) {
				if (element) extract_identifiers_from_destructuring(/** @type {any} */ (element), nodes);
			}

			break;
	}

	return nodes;
}

/**
 * Represents the path of a destructured assignment from either a declaration
 * or assignment expression. For example, given `const { foo: { bar: baz } } = quux`,
 * the path of `baz` is `foo.bar`
 * @typedef {Object} DestructuredAssignment
 * @property {ESTree.Identifier | ESTree.MemberExpression} node The node the destructuring path end in. Can be a member expression only for assignment expressions
 * @property {boolean} is_rest `true` if this is a `...rest` destructuring
 * @property {boolean} has_default_value `true` if this has a fallback value like `const { foo = 'bar } = ..`
 * @property {ESTree.Expression} expression The value of the current path
 * This will be a call expression if a rest element or default is involved — e.g. `const { foo: { bar: baz = 42 }, ...rest } = quux` — since we can't represent `baz` or `rest` purely as a path
 * Will be an await expression in case of an async default value (`const { foo = await bar } = ...`)
 * @property {ESTree.Expression} update_expression Like `expression` but without default values.
 */

/**
 * Extracts all destructured assignments from a pattern.
 * For each `id` in the returned `inserts`, make sure to adjust the `name`.
 * @param {ESTree.Node} param
 * @param {ESTree.Expression} initial
 * @returns {{ inserts: Array<{ id: ESTree.Identifier, value: ESTree.Expression }>, paths: DestructuredAssignment[] }}
 */
function extract_paths(param, initial) {
	/**
	 * When dealing with array destructuring patterns (`let [a, b, c] = $derived(blah())`)
	 * we need an intermediate declaration that creates an array, since `blah()` could
	 * return a non-array-like iterator
	 * @type {Array<{ id: ESTree.Identifier, value: ESTree.Expression }>}
	 */
	const inserts = [];

	/** @type {DestructuredAssignment[]} */
	const paths = [];

	_extract_paths(paths, inserts, param, initial, initial, false);

	return { inserts, paths };
}

/**
 * @param {DestructuredAssignment[]} paths
 * @param {Array<{ id: ESTree.Identifier, value: ESTree.Expression }>} inserts
 * @param {ESTree.Node} param
 * @param {ESTree.Expression} expression
 * @param {ESTree.Expression} update_expression
 * @param {boolean} has_default_value
 * @returns {DestructuredAssignment[]}
 */
function _extract_paths(paths, inserts, param, expression, update_expression, has_default_value) {
	switch (param.type) {
		case 'Identifier':
		case 'MemberExpression':
			paths.push({
				node: param,
				is_rest: false,
				has_default_value,
				expression,
				update_expression
			});
			break;

		case 'ObjectPattern':
			for (const prop of param.properties) {
				if (prop.type === 'RestElement') {
					/** @type {ESTree.Expression[]} */
					const props = [];

					for (const p of param.properties) {
						if (p.type === 'Property' && p.key.type !== 'PrivateIdentifier') {
							if (p.key.type === 'Identifier' && !p.computed) {
								props.push(literal(p.key.name));
							} else if (p.key.type === 'Literal') {
								props.push(literal(String(p.key.value)));
							} else {
								props.push(call('String', p.key));
							}
						}
					}

					const rest_expression = call('$.exclude_from_object', expression, array(props));

					if (prop.argument.type === 'Identifier') {
						paths.push({
							node: prop.argument,
							is_rest: true,
							has_default_value,
							expression: rest_expression,
							update_expression: rest_expression
						});
					} else {
						_extract_paths(
							paths,
							inserts,
							prop.argument,
							rest_expression,
							rest_expression,
							has_default_value
						);
					}
				} else {
					const object_expression = member(
						expression,
						prop.key,
						prop.computed || prop.key.type !== 'Identifier'
					);

					_extract_paths(
						paths,
						inserts,
						prop.value,
						object_expression,
						object_expression,
						has_default_value
					);
				}
			}

			break;

		case 'ArrayPattern': {
			// we create an intermediate declaration to convert iterables to arrays if necessary.
			// the consumer is responsible for setting the name of the identifier
			const id$1 = id('#');

			const value = call(
				'$.to_array',
				expression,
				param.elements.at(-1)?.type === 'RestElement' ? undefined : literal(param.elements.length)
			);

			inserts.push({ id: id$1, value });

			for (let i = 0; i < param.elements.length; i += 1) {
				const element = param.elements[i];
				if (element) {
					if (element.type === 'RestElement') {
						const rest_expression = call(member(id$1, 'slice'), literal(i));

						if (element.argument.type === 'Identifier') {
							paths.push({
								node: element.argument,
								is_rest: true,
								has_default_value,
								expression: rest_expression,
								update_expression: rest_expression
							});
						} else {
							_extract_paths(
								paths,
								inserts,
								element.argument,
								rest_expression,
								rest_expression,
								has_default_value
							);
						}
					} else {
						const array_expression = member(id$1, literal(i), true);

						_extract_paths(
							paths,
							inserts,
							element,
							array_expression,
							array_expression,
							has_default_value
						);
					}
				}
			}

			break;
		}

		case 'AssignmentPattern': {
			const fallback_expression = build_fallback(expression, param.right);

			if (param.left.type === 'Identifier') {
				paths.push({
					node: param.left,
					is_rest: false,
					has_default_value: true,
					expression: fallback_expression,
					update_expression
				});
			} else {
				_extract_paths(paths, inserts, param.left, fallback_expression, update_expression, true);
			}

			break;
		}
	}

	return paths;
}

/**
 * Like `path.at(x)`, but skips over `TSNonNullExpression` and `TSAsExpression` nodes and eases assertions a bit
 * by removing the `| undefined` from the resulting type.
 *
 * @template {AST.SvelteNode} T
 * @param {T[]} path
 * @param {number} at
 */
function get_parent(path, at) {
	let node = path.at(at);
	// @ts-expect-error
	if (node.type === 'TSNonNullExpression' || node.type === 'TSAsExpression') {
		return /** @type {T} */ (path.at(at < 0 ? at - 1 : at + 1));
	}
	return /** @type {T} */ (node);
}

/**
 * Returns `true` if the expression is an identifier, a literal, a function expression,
 * or a logical expression that only contains simple expressions. Used to determine whether
 * something needs to be treated as though accessing it could have side-effects (i.e.
 * reading signals prematurely)
 * @param {ESTree.Expression} node
 * @returns {boolean}
 */
function is_simple_expression(node) {
	if (
		node.type === 'Literal' ||
		node.type === 'Identifier' ||
		node.type === 'ArrowFunctionExpression' ||
		node.type === 'FunctionExpression'
	) {
		return true;
	}

	if (node.type === 'ConditionalExpression') {
		return (
			is_simple_expression(node.test) &&
			is_simple_expression(node.consequent) &&
			is_simple_expression(node.alternate)
		);
	}

	if (node.type === 'BinaryExpression' || node.type === 'LogicalExpression') {
		return (
			node.left.type !== 'PrivateIdentifier' &&
			is_simple_expression(node.left) &&
			is_simple_expression(node.right)
		);
	}

	return false;
}

/**
 * @template {ESTree.SimpleCallExpression | ESTree.MemberExpression} T
 * @param {ESTree.ChainExpression & { expression : T } | T} node
 * @returns {T}
 */
function unwrap_optional(node) {
	return node.type === 'ChainExpression' ? node.expression : node;
}

/**
 * @param {ESTree.Expression | ESTree.Pattern} expression
 * @returns {boolean}
 */
function is_expression_async(expression) {
	switch (expression.type) {
		case 'AwaitExpression': {
			return true;
		}
		case 'ArrayPattern': {
			return expression.elements.some((element) => element && is_expression_async(element));
		}
		case 'ArrayExpression': {
			return expression.elements.some((element) => {
				if (!element) {
					return false;
				} else if (element.type === 'SpreadElement') {
					return is_expression_async(element.argument);
				} else {
					return is_expression_async(element);
				}
			});
		}
		case 'AssignmentPattern':
		case 'AssignmentExpression':
		case 'BinaryExpression':
		case 'LogicalExpression': {
			return (
				(expression.left.type !== 'PrivateIdentifier' && is_expression_async(expression.left)) ||
				is_expression_async(expression.right)
			);
		}
		case 'CallExpression':
		case 'NewExpression': {
			return (
				(expression.callee.type !== 'Super' && is_expression_async(expression.callee)) ||
				expression.arguments.some((element) => {
					if (element.type === 'SpreadElement') {
						return is_expression_async(element.argument);
					} else {
						return is_expression_async(element);
					}
				})
			);
		}
		case 'ChainExpression': {
			return is_expression_async(expression.expression);
		}
		case 'ConditionalExpression': {
			return (
				is_expression_async(expression.test) ||
				is_expression_async(expression.alternate) ||
				is_expression_async(expression.consequent)
			);
		}
		case 'ImportExpression': {
			return is_expression_async(expression.source);
		}
		case 'MemberExpression': {
			return (
				(expression.object.type !== 'Super' && is_expression_async(expression.object)) ||
				(expression.property.type !== 'PrivateIdentifier' &&
					is_expression_async(expression.property))
			);
		}
		case 'ObjectPattern':
		case 'ObjectExpression': {
			return expression.properties.some((property) => {
				if (property.type === 'SpreadElement') {
					return is_expression_async(property.argument);
				} else if (property.type === 'Property') {
					return (
						(property.key.type !== 'PrivateIdentifier' && is_expression_async(property.key)) ||
						is_expression_async(property.value)
					);
				}
			});
		}
		case 'RestElement': {
			return is_expression_async(expression.argument);
		}
		case 'SequenceExpression':
		case 'TemplateLiteral': {
			return expression.expressions.some((subexpression) => is_expression_async(subexpression));
		}
		case 'TaggedTemplateExpression': {
			return is_expression_async(expression.tag) || is_expression_async(expression.quasi);
		}
		case 'UnaryExpression':
		case 'UpdateExpression': {
			return is_expression_async(expression.argument);
		}
		case 'YieldExpression': {
			return expression.argument ? is_expression_async(expression.argument) : false;
		}
		default:
			return false;
	}
}

/**
 *
 * @param {ESTree.Expression} expression
 * @param {ESTree.Expression} fallback
 */
function build_fallback(expression, fallback) {
	if (is_simple_expression(fallback)) {
		return call('$.fallback', expression, fallback);
	}

	if (fallback.type === 'AwaitExpression' && is_simple_expression(fallback.argument)) {
		return await_builder(call('$.fallback', expression, fallback.argument));
	}

	return is_expression_async(fallback)
		? await_builder(call('$.fallback', expression, thunk(fallback, true), true_instance))
		: call('$.fallback', expression, thunk(fallback), true_instance);
}

/**
 * @param {ESTree.AssignmentOperator} operator
 * @param {ESTree.Identifier | ESTree.MemberExpression} left
 * @param {ESTree.Expression} right
 */
function build_assignment_value(operator, left, right) {
	return operator === '='
		? right
		: // turn something like x += 1 into x = x + 1
			['||=', '&&=', '??='].includes(operator)
			? logical$1(/** @type {ESTree.LogicalOperator} */ (operator.slice(0, -1)), left, right)
			: binary$1(/** @type {ESTree.BinaryOperator} */ (operator.slice(0, -1)), left, right);
}

/**
 * @param {ESTree.Node} node
 */
function has_await_expression(node) {
	let has_await = false;

	walk$1(node, null, {
		AwaitExpression(_node, context) {
			has_await = true;
			context.stop();
		},
		// don't traverse into these
		FunctionDeclaration() {},
		FunctionExpression() {},
		ArrowFunctionExpression() {}
	});

	return has_await;
}

/**
 * Turns `await ...` to `(await $.save(...))()`
 * @param {ESTree.Expression} expression
 */
function save(expression) {
	return call(await_builder(call('$.save', expression)));
}

/** @import { Program } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { Parser } from '../index.js' */

const regex_closing_script_tag = /<\/script\s*>/;
const regex_starts_with_closing_script_tag = /^<\/script\s*>/;

const RESERVED_ATTRIBUTES = ['server', 'client', 'worker', 'test', 'default'];
const ALLOWED_ATTRIBUTES = ['context', 'generics', 'lang', 'module'];

/**
 * @param {Parser} parser
 * @param {number} start
 * @param {Array<AST.Attribute | AST.SpreadAttribute | AST.Directive | AST.AttachTag>} attributes
 * @returns {AST.Script}
 */
function read_script(parser, start, attributes) {
	const script_start = parser.index;
	const data = parser.read_until(regex_closing_script_tag);
	if (parser.index >= parser.template.length) {
		element_unclosed(parser.template.length, 'script');
	}

	const source =
		parser.template.slice(0, script_start).replace(regex_not_newline_characters, ' ') + data;
	parser.read(regex_starts_with_closing_script_tag);

	/** @type {Program} */
	let ast;

	try {
		ast = parse$3(source, parser.root.comments, parser.ts, true);
	} catch (err) {
		parser.acorn_error(err);
	}

	// TODO is this necessary?
	ast.start = script_start;

	/** @type {'default' | 'module'} */
	let context = 'default';

	for (const attribute of /** @type {AST.Attribute[]} */ (attributes)) {
		if (RESERVED_ATTRIBUTES.includes(attribute.name)) {
			script_reserved_attribute(attribute, attribute.name);
		}

		if (!ALLOWED_ATTRIBUTES.includes(attribute.name)) {
			script_unknown_attribute(attribute);
		}

		if (attribute.name === 'module') {
			if (attribute.value !== true) {
				// Deliberately a generic code to future-proof for potential other attributes
				script_invalid_attribute_value(attribute, attribute.name);
			}

			context = 'module';
		}

		if (attribute.name === 'context') {
			if (attribute.value === true || !is_text_attribute(attribute)) {
				script_invalid_context(attribute);
			}

			const value = attribute.value[0].data;

			if (value !== 'module') {
				script_invalid_context(attribute);
			}

			context = 'module';
		}
	}

	return {
		type: 'Script',
		start,
		end: parser.index,
		context,
		content: ast,
		// @ts-ignore
		attributes
	};
}

/** @import { AST } from '#compiler' */
/** @import { Parser } from '../index.js' */

const REGEX_MATCHER = /^[~^$*|]?=/;
const REGEX_CLOSING_BRACKET = /[\s\]]/;
const REGEX_ATTRIBUTE_FLAGS = /^[a-zA-Z]+/; // only `i` and `s` are valid today, but make it future-proof
const REGEX_COMBINATOR = /^(\+|~|>|\|\|)/;
const REGEX_PERCENTAGE = /^\d+(\.\d+)?%/;
const REGEX_NTH_OF =
	/^(even|odd|\+?(\d+|\d*n(\s*[+-]\s*\d+)?)|-\d*n(\s*\+\s*\d+))((?=\s*[,)])|\s+of\s+)/;
const REGEX_WHITESPACE_OR_COLON = /[\s:]/;
const REGEX_LEADING_HYPHEN_OR_DIGIT = /-?\d/;
const REGEX_VALID_IDENTIFIER_CHAR = /[a-zA-Z0-9_-]/;
const REGEX_UNICODE_SEQUENCE = /^\\[0-9a-fA-F]{1,6}(\r\n|\s)?/;
const REGEX_COMMENT_CLOSE = /\*\//;
const REGEX_HTML_COMMENT_CLOSE = /-->/;

/**
 * @param {Parser} parser
 * @param {number} start
 * @param {Array<AST.Attribute | AST.SpreadAttribute | AST.Directive | AST.AttachTag>} attributes
 * @returns {AST.CSS.StyleSheet}
 */
function read_style(parser, start, attributes) {
	const content_start = parser.index;
	const children = read_body(parser, '</style');
	const content_end = parser.index;

	parser.read(/^<\/style\s*>/);

	return {
		type: 'StyleSheet',
		start,
		end: parser.index,
		attributes,
		children,
		content: {
			start: content_start,
			end: content_end,
			styles: parser.template.slice(content_start, content_end),
			comment: null
		}
	};
}

/**
 * @param {Parser} parser
 * @param {string} close
 * @returns {any[]}
 */
function read_body(parser, close) {
	/** @type {Array<AST.CSS.Rule | AST.CSS.Atrule>} */
	const children = [];

	while (parser.index < parser.template.length) {
		allow_comment_or_whitespace(parser);

		if (parser.match(close)) {
			return children;
		}

		if (parser.match('@')) {
			children.push(read_at_rule(parser));
		} else {
			children.push(read_rule(parser));
		}
	}

	expected_token(parser.template.length, close);
}

/**
 * @param {Parser} parser
 * @returns {AST.CSS.Atrule}
 */
function read_at_rule(parser) {
	const start = parser.index;
	parser.eat('@', true);

	const name = read_identifier(parser);

	const prelude = read_value(parser);

	/** @type {AST.CSS.Block | null} */
	let block = null;

	if (parser.match('{')) {
		// e.g. `@media (...) {...}`
		block = read_block(parser);
	} else {
		// e.g. `@import '...'`
		parser.eat(';', true);
	}

	return {
		type: 'Atrule',
		start,
		end: parser.index,
		name,
		prelude,
		block
	};
}

/**
 * @param {Parser} parser
 * @returns {AST.CSS.Rule}
 */
function read_rule(parser) {
	const start = parser.index;

	return {
		type: 'Rule',
		prelude: read_selector_list(parser),
		block: read_block(parser),
		start,
		end: parser.index,
		metadata: {
			parent_rule: null,
			has_local_selectors: false,
			has_global_selectors: false,
			is_global_block: false
		}
	};
}

/**
 * @param {Parser} parser
 * @param {boolean} [inside_pseudo_class]
 * @returns {AST.CSS.SelectorList}
 */
function read_selector_list(parser, inside_pseudo_class = false) {
	/** @type {AST.CSS.ComplexSelector[]} */
	const children = [];

	allow_comment_or_whitespace(parser);

	const start = parser.index;

	while (parser.index < parser.template.length) {
		children.push(read_selector(parser, inside_pseudo_class));

		const end = parser.index;

		allow_comment_or_whitespace(parser);

		if (inside_pseudo_class ? parser.match(')') : parser.match('{')) {
			return {
				type: 'SelectorList',
				start,
				end,
				children
			};
		} else {
			parser.eat(',', true);
			allow_comment_or_whitespace(parser);
		}
	}

	unexpected_eof(parser.template.length);
}

/**
 * @param {Parser} parser
 * @param {boolean} [inside_pseudo_class]
 * @returns {AST.CSS.ComplexSelector}
 */
function read_selector(parser, inside_pseudo_class = false) {
	const list_start = parser.index;

	/** @type {AST.CSS.RelativeSelector[]} */
	const children = [];

	/**
	 * @param {AST.CSS.Combinator | null} combinator
	 * @param {number} start
	 * @returns {AST.CSS.RelativeSelector}
	 */
	function create_selector(combinator, start) {
		return {
			type: 'RelativeSelector',
			combinator,
			selectors: [],
			start,
			end: -1,
			metadata: {
				is_global: false,
				is_global_like: false,
				scoped: false
			}
		};
	}

	/** @type {AST.CSS.RelativeSelector} */
	let relative_selector = create_selector(null, parser.index);

	while (parser.index < parser.template.length) {
		let start = parser.index;

		if (parser.eat('&')) {
			relative_selector.selectors.push({
				type: 'NestingSelector',
				name: '&',
				start,
				end: parser.index
			});
		} else if (parser.eat('*')) {
			let name = '*';

			if (parser.eat('|')) {
				// * is the namespace (which we ignore)
				name = read_identifier(parser);
			}

			relative_selector.selectors.push({
				type: 'TypeSelector',
				name,
				start,
				end: parser.index
			});
		} else if (parser.eat('#')) {
			relative_selector.selectors.push({
				type: 'IdSelector',
				name: read_identifier(parser),
				start,
				end: parser.index
			});
		} else if (parser.eat('.')) {
			relative_selector.selectors.push({
				type: 'ClassSelector',
				name: read_identifier(parser),
				start,
				end: parser.index
			});
		} else if (parser.eat('::')) {
			relative_selector.selectors.push({
				type: 'PseudoElementSelector',
				name: read_identifier(parser),
				start,
				end: parser.index
			});
			// We read the inner selectors of a pseudo element to ensure it parses correctly,
			// but we don't do anything with the result.
			if (parser.eat('(')) {
				read_selector_list(parser, true);
				parser.eat(')', true);
			}
		} else if (parser.eat(':')) {
			const name = read_identifier(parser);

			/** @type {null | AST.CSS.SelectorList} */
			let args = null;

			if (parser.eat('(')) {
				args = read_selector_list(parser, true);
				parser.eat(')', true);
			}

			relative_selector.selectors.push({
				type: 'PseudoClassSelector',
				name,
				args,
				start,
				end: parser.index
			});
		} else if (parser.eat('[')) {
			parser.allow_whitespace();
			const name = read_identifier(parser);
			parser.allow_whitespace();

			/** @type {string | null} */
			let value = null;

			const matcher = parser.read(REGEX_MATCHER);

			if (matcher) {
				parser.allow_whitespace();
				value = read_attribute_value$1(parser);
			}

			parser.allow_whitespace();

			const flags = parser.read(REGEX_ATTRIBUTE_FLAGS);

			parser.allow_whitespace();
			parser.eat(']', true);

			relative_selector.selectors.push({
				type: 'AttributeSelector',
				start,
				end: parser.index,
				name,
				matcher,
				value,
				flags
			});
		} else if (inside_pseudo_class && parser.match_regex(REGEX_NTH_OF)) {
			// nth of matcher must come before combinator matcher to prevent collision else the '+' in '+2n-1' would be parsed as a combinator

			relative_selector.selectors.push({
				type: 'Nth',
				value: /**@type {string} */ (parser.read(REGEX_NTH_OF)),
				start,
				end: parser.index
			});
		} else if (parser.match_regex(REGEX_PERCENTAGE)) {
			relative_selector.selectors.push({
				type: 'Percentage',
				value: /** @type {string} */ (parser.read(REGEX_PERCENTAGE)),
				start,
				end: parser.index
			});
		} else if (!parser.match_regex(REGEX_COMBINATOR)) {
			let name = read_identifier(parser);

			if (parser.eat('|')) {
				// we ignore the namespace when trying to find matching element classes
				name = read_identifier(parser);
			}

			relative_selector.selectors.push({
				type: 'TypeSelector',
				name,
				start,
				end: parser.index
			});
		}

		const index = parser.index;
		allow_comment_or_whitespace(parser);

		if (parser.match(',') || (inside_pseudo_class ? parser.match(')') : parser.match('{'))) {
			// rewind, so we know whether to continue building the selector list
			parser.index = index;

			relative_selector.end = index;
			children.push(relative_selector);

			return {
				type: 'ComplexSelector',
				start: list_start,
				end: index,
				children,
				metadata: {
					rule: null,
					is_global: false,
					used: false
				}
			};
		}

		parser.index = index;
		const combinator = read_combinator(parser);

		if (combinator) {
			if (relative_selector.selectors.length > 0) {
				relative_selector.end = index;
				children.push(relative_selector);
			}

			// ...and start a new one
			relative_selector = create_selector(combinator, combinator.start);

			parser.allow_whitespace();

			if (parser.match(',') || (inside_pseudo_class ? parser.match(')') : parser.match('{'))) {
				css_selector_invalid(parser.index);
			}
		}
	}

	unexpected_eof(parser.template.length);
}

/**
 * @param {Parser} parser
 * @returns {AST.CSS.Combinator | null}
 */
function read_combinator(parser) {
	const start = parser.index;
	parser.allow_whitespace();

	const index = parser.index;
	const name = parser.read(REGEX_COMBINATOR);

	if (name) {
		const end = parser.index;
		parser.allow_whitespace();

		return {
			type: 'Combinator',
			name,
			start: index,
			end
		};
	}

	if (parser.index !== start) {
		return {
			type: 'Combinator',
			name: ' ',
			start,
			end: parser.index
		};
	}

	return null;
}

/**
 * @param {Parser} parser
 * @returns {AST.CSS.Block}
 */
function read_block(parser) {
	const start = parser.index;

	parser.eat('{', true);

	/** @type {Array<AST.CSS.Declaration | AST.CSS.Rule | AST.CSS.Atrule>} */
	const children = [];

	while (parser.index < parser.template.length) {
		allow_comment_or_whitespace(parser);

		if (parser.match('}')) {
			break;
		} else {
			children.push(read_block_item(parser));
		}
	}

	parser.eat('}', true);

	return {
		type: 'Block',
		start,
		end: parser.index,
		children
	};
}

/**
 * Reads a declaration, rule or at-rule
 *
 * @param {Parser} parser
 * @returns {AST.CSS.Declaration | AST.CSS.Rule | AST.CSS.Atrule}
 */
function read_block_item(parser) {
	if (parser.match('@')) {
		return read_at_rule(parser);
	}

	// read ahead to understand whether we're dealing with a declaration or a nested rule.
	// this involves some duplicated work, but avoids a try-catch that would disguise errors
	const start = parser.index;
	read_value(parser);
	const char = parser.template[parser.index];
	parser.index = start;

	return char === '{' ? read_rule(parser) : read_declaration(parser);
}

/**
 * @param {Parser} parser
 * @returns {AST.CSS.Declaration}
 */
function read_declaration(parser) {
	const start = parser.index;

	const property = parser.read_until(REGEX_WHITESPACE_OR_COLON);
	parser.allow_whitespace();
	parser.eat(':');
	let index = parser.index;
	parser.allow_whitespace();

	const value = read_value(parser);

	if (!value && !property.startsWith('--')) {
		css_empty_declaration({ start, end: index });
	}

	const end = parser.index;

	if (!parser.match('}')) {
		parser.eat(';', true);
	}

	return {
		type: 'Declaration',
		start,
		end,
		property,
		value
	};
}

/**
 * @param {Parser} parser
 * @returns {string}
 */
function read_value(parser) {
	let value = '';
	let escaped = false;
	let in_url = false;

	/** @type {null | '"' | "'"} */
	let quote_mark = null;

	while (parser.index < parser.template.length) {
		const char = parser.template[parser.index];

		if (escaped) {
			value += '\\' + char;
			escaped = false;
		} else if (char === '\\') {
			escaped = true;
		} else if (char === quote_mark) {
			quote_mark = null;
		} else if (char === ')') {
			in_url = false;
		} else if (quote_mark === null && (char === '"' || char === "'")) {
			quote_mark = char;
		} else if (char === '(' && value.slice(-3) === 'url') {
			in_url = true;
		} else if ((char === ';' || char === '{' || char === '}') && !in_url && !quote_mark) {
			return value.trim();
		}

		value += char;

		parser.index++;
	}

	unexpected_eof(parser.template.length);
}

/**
 * Read a property that may or may not be quoted, e.g.
 * `foo` or `'foo bar'` or `"foo bar"`
 * @param {Parser} parser
 */
function read_attribute_value$1(parser) {
	let value = '';
	let escaped = false;
	const quote_mark = parser.eat('"') ? '"' : parser.eat("'") ? "'" : null;

	while (parser.index < parser.template.length) {
		const char = parser.template[parser.index];
		if (escaped) {
			value += '\\' + char;
			escaped = false;
		} else if (char === '\\') {
			escaped = true;
		} else if (quote_mark ? char === quote_mark : REGEX_CLOSING_BRACKET.test(char)) {
			if (quote_mark) {
				parser.eat(quote_mark, true);
			}

			return value.trim();
		} else {
			value += char;
		}

		parser.index++;
	}

	unexpected_eof(parser.template.length);
}

/**
 * https://www.w3.org/TR/css-syntax-3/#ident-token-diagram
 * @param {Parser} parser
 */
function read_identifier(parser) {
	const start = parser.index;

	let identifier = '';

	if (parser.match_regex(REGEX_LEADING_HYPHEN_OR_DIGIT)) {
		css_expected_identifier(start);
	}

	while (parser.index < parser.template.length) {
		const char = parser.template[parser.index];
		if (char === '\\') {
			const sequence = parser.match_regex(REGEX_UNICODE_SEQUENCE);
			if (sequence) {
				identifier += String.fromCodePoint(parseInt(sequence.slice(1), 16));
				parser.index += sequence.length;
			} else {
				identifier += '\\' + parser.template[parser.index + 1];
				parser.index += 2;
			}
		} else if (
			/** @type {number} */ (char.codePointAt(0)) >= 160 ||
			REGEX_VALID_IDENTIFIER_CHAR.test(char)
		) {
			identifier += char;
			parser.index++;
		} else {
			break;
		}
	}

	if (identifier === '') {
		css_expected_identifier(start);
	}

	return identifier;
}

/** @param {Parser} parser */
function allow_comment_or_whitespace(parser) {
	parser.allow_whitespace();
	while (parser.match('/*') || parser.match('<!--')) {
		if (parser.eat('/*')) {
			parser.read_until(REGEX_COMMENT_CLOSE);
			parser.eat('*/', true);
		}

		if (parser.eat('<!--')) {
			parser.read_until(REGEX_HTML_COMMENT_CLOSE);
			parser.eat('-->', true);
		}

		parser.allow_whitespace();
	}
}

// https://html.spec.whatwg.org/entities.json from https://dev.w3.org/html5/html-author/charref
var entities = {
	'CounterClockwiseContourIntegral;': 8755,
	'ClockwiseContourIntegral;': 8754,
	'DoubleLongLeftRightArrow;': 10234,
	'NotNestedGreaterGreater;': 10914,
	'DiacriticalDoubleAcute;': 733,
	'NotSquareSupersetEqual;': 8931,
	'CloseCurlyDoubleQuote;': 8221,
	'DoubleContourIntegral;': 8751,
	'FilledVerySmallSquare;': 9642,
	'NegativeVeryThinSpace;': 8203,
	'NotPrecedesSlantEqual;': 8928,
	'NotRightTriangleEqual;': 8941,
	'NotSucceedsSlantEqual;': 8929,
	'CapitalDifferentialD;': 8517,
	'DoubleLeftRightArrow;': 8660,
	'DoubleLongRightArrow;': 10233,
	'EmptyVerySmallSquare;': 9643,
	'NestedGreaterGreater;': 8811,
	'NotDoubleVerticalBar;': 8742,
	'NotGreaterSlantEqual;': 10878,
	'NotLeftTriangleEqual;': 8940,
	'NotSquareSubsetEqual;': 8930,
	'OpenCurlyDoubleQuote;': 8220,
	'ReverseUpEquilibrium;': 10607,
	'DoubleLongLeftArrow;': 10232,
	'DownLeftRightVector;': 10576,
	'LeftArrowRightArrow;': 8646,
	'NegativeMediumSpace;': 8203,
	'NotGreaterFullEqual;': 8807,
	'NotRightTriangleBar;': 10704,
	'RightArrowLeftArrow;': 8644,
	'SquareSupersetEqual;': 8850,
	'leftrightsquigarrow;': 8621,
	'DownRightTeeVector;': 10591,
	'DownRightVectorBar;': 10583,
	'LongLeftRightArrow;': 10231,
	'Longleftrightarrow;': 10234,
	'NegativeThickSpace;': 8203,
	'NotLeftTriangleBar;': 10703,
	'PrecedesSlantEqual;': 8828,
	'ReverseEquilibrium;': 8651,
	'RightDoubleBracket;': 10215,
	'RightDownTeeVector;': 10589,
	'RightDownVectorBar;': 10581,
	'RightTriangleEqual;': 8885,
	'SquareIntersection;': 8851,
	'SucceedsSlantEqual;': 8829,
	'blacktriangleright;': 9656,
	'longleftrightarrow;': 10231,
	'DoubleUpDownArrow;': 8661,
	'DoubleVerticalBar;': 8741,
	'DownLeftTeeVector;': 10590,
	'DownLeftVectorBar;': 10582,
	'FilledSmallSquare;': 9724,
	'GreaterSlantEqual;': 10878,
	'LeftDoubleBracket;': 10214,
	'LeftDownTeeVector;': 10593,
	'LeftDownVectorBar;': 10585,
	'LeftTriangleEqual;': 8884,
	'NegativeThinSpace;': 8203,
	'NotGreaterGreater;': 8811,
	'NotLessSlantEqual;': 10877,
	'NotNestedLessLess;': 10913,
	'NotReverseElement;': 8716,
	'NotSquareSuperset;': 8848,
	'NotTildeFullEqual;': 8775,
	'RightAngleBracket;': 10217,
	'RightUpDownVector;': 10575,
	'SquareSubsetEqual;': 8849,
	'VerticalSeparator;': 10072,
	'blacktriangledown;': 9662,
	'blacktriangleleft;': 9666,
	'leftrightharpoons;': 8651,
	'rightleftharpoons;': 8652,
	'twoheadrightarrow;': 8608,
	'DiacriticalAcute;': 180,
	'DiacriticalGrave;': 96,
	'DiacriticalTilde;': 732,
	'DoubleRightArrow;': 8658,
	'DownArrowUpArrow;': 8693,
	'EmptySmallSquare;': 9723,
	'GreaterEqualLess;': 8923,
	'GreaterFullEqual;': 8807,
	'LeftAngleBracket;': 10216,
	'LeftUpDownVector;': 10577,
	'LessEqualGreater;': 8922,
	'NonBreakingSpace;': 160,
	'NotPrecedesEqual;': 10927,
	'NotRightTriangle;': 8939,
	'NotSucceedsEqual;': 10928,
	'NotSucceedsTilde;': 8831,
	'NotSupersetEqual;': 8841,
	'RightTriangleBar;': 10704,
	'RightUpTeeVector;': 10588,
	'RightUpVectorBar;': 10580,
	'UnderParenthesis;': 9181,
	'UpArrowDownArrow;': 8645,
	'circlearrowright;': 8635,
	'downharpoonright;': 8642,
	'ntrianglerighteq;': 8941,
	'rightharpoondown;': 8641,
	'rightrightarrows;': 8649,
	'twoheadleftarrow;': 8606,
	'vartriangleright;': 8883,
	'CloseCurlyQuote;': 8217,
	'ContourIntegral;': 8750,
	'DoubleDownArrow;': 8659,
	'DoubleLeftArrow;': 8656,
	'DownRightVector;': 8641,
	'LeftRightVector;': 10574,
	'LeftTriangleBar;': 10703,
	'LeftUpTeeVector;': 10592,
	'LeftUpVectorBar;': 10584,
	'LowerRightArrow;': 8600,
	'NotGreaterEqual;': 8817,
	'NotGreaterTilde;': 8821,
	'NotHumpDownHump;': 8782,
	'NotLeftTriangle;': 8938,
	'NotSquareSubset;': 8847,
	'OverParenthesis;': 9180,
	'RightDownVector;': 8642,
	'ShortRightArrow;': 8594,
	'UpperRightArrow;': 8599,
	'bigtriangledown;': 9661,
	'circlearrowleft;': 8634,
	'curvearrowright;': 8631,
	'downharpoonleft;': 8643,
	'leftharpoondown;': 8637,
	'leftrightarrows;': 8646,
	'nLeftrightarrow;': 8654,
	'nleftrightarrow;': 8622,
	'ntrianglelefteq;': 8940,
	'rightleftarrows;': 8644,
	'rightsquigarrow;': 8605,
	'rightthreetimes;': 8908,
	'straightepsilon;': 1013,
	'trianglerighteq;': 8885,
	'vartriangleleft;': 8882,
	'DiacriticalDot;': 729,
	'DoubleRightTee;': 8872,
	'DownLeftVector;': 8637,
	'GreaterGreater;': 10914,
	'HorizontalLine;': 9472,
	'InvisibleComma;': 8291,
	'InvisibleTimes;': 8290,
	'LeftDownVector;': 8643,
	'LeftRightArrow;': 8596,
	'Leftrightarrow;': 8660,
	'LessSlantEqual;': 10877,
	'LongRightArrow;': 10230,
	'Longrightarrow;': 10233,
	'LowerLeftArrow;': 8601,
	'NestedLessLess;': 8810,
	'NotGreaterLess;': 8825,
	'NotLessGreater;': 8824,
	'NotSubsetEqual;': 8840,
	'NotVerticalBar;': 8740,
	'OpenCurlyQuote;': 8216,
	'ReverseElement;': 8715,
	'RightTeeVector;': 10587,
	'RightVectorBar;': 10579,
	'ShortDownArrow;': 8595,
	'ShortLeftArrow;': 8592,
	'SquareSuperset;': 8848,
	'TildeFullEqual;': 8773,
	'UpperLeftArrow;': 8598,
	'ZeroWidthSpace;': 8203,
	'curvearrowleft;': 8630,
	'doublebarwedge;': 8966,
	'downdownarrows;': 8650,
	'hookrightarrow;': 8618,
	'leftleftarrows;': 8647,
	'leftrightarrow;': 8596,
	'leftthreetimes;': 8907,
	'longrightarrow;': 10230,
	'looparrowright;': 8620,
	'nshortparallel;': 8742,
	'ntriangleright;': 8939,
	'rightarrowtail;': 8611,
	'rightharpoonup;': 8640,
	'trianglelefteq;': 8884,
	'upharpoonright;': 8638,
	'ApplyFunction;': 8289,
	'DifferentialD;': 8518,
	'DoubleLeftTee;': 10980,
	'DoubleUpArrow;': 8657,
	'LeftTeeVector;': 10586,
	'LeftVectorBar;': 10578,
	'LessFullEqual;': 8806,
	'LongLeftArrow;': 10229,
	'Longleftarrow;': 10232,
	'NotEqualTilde;': 8770,
	'NotTildeEqual;': 8772,
	'NotTildeTilde;': 8777,
	'Poincareplane;': 8460,
	'PrecedesEqual;': 10927,
	'PrecedesTilde;': 8830,
	'RightArrowBar;': 8677,
	'RightTeeArrow;': 8614,
	'RightTriangle;': 8883,
	'RightUpVector;': 8638,
	'SucceedsEqual;': 10928,
	'SucceedsTilde;': 8831,
	'SupersetEqual;': 8839,
	'UpEquilibrium;': 10606,
	'VerticalTilde;': 8768,
	'VeryThinSpace;': 8202,
	'bigtriangleup;': 9651,
	'blacktriangle;': 9652,
	'divideontimes;': 8903,
	'fallingdotseq;': 8786,
	'hookleftarrow;': 8617,
	'leftarrowtail;': 8610,
	'leftharpoonup;': 8636,
	'longleftarrow;': 10229,
	'looparrowleft;': 8619,
	'measuredangle;': 8737,
	'ntriangleleft;': 8938,
	'shortparallel;': 8741,
	'smallsetminus;': 8726,
	'triangleright;': 9657,
	'upharpoonleft;': 8639,
	'varsubsetneqq;': 10955,
	'varsupsetneqq;': 10956,
	'DownArrowBar;': 10515,
	'DownTeeArrow;': 8615,
	'ExponentialE;': 8519,
	'GreaterEqual;': 8805,
	'GreaterTilde;': 8819,
	'HilbertSpace;': 8459,
	'HumpDownHump;': 8782,
	'Intersection;': 8898,
	'LeftArrowBar;': 8676,
	'LeftTeeArrow;': 8612,
	'LeftTriangle;': 8882,
	'LeftUpVector;': 8639,
	'NotCongruent;': 8802,
	'NotHumpEqual;': 8783,
	'NotLessEqual;': 8816,
	'NotLessTilde;': 8820,
	'Proportional;': 8733,
	'RightCeiling;': 8969,
	'RoundImplies;': 10608,
	'ShortUpArrow;': 8593,
	'SquareSubset;': 8847,
	'UnderBracket;': 9141,
	'VerticalLine;': 124,
	'blacklozenge;': 10731,
	'exponentiale;': 8519,
	'risingdotseq;': 8787,
	'triangledown;': 9663,
	'triangleleft;': 9667,
	'varsubsetneq;': 8842,
	'varsupsetneq;': 8843,
	'CircleMinus;': 8854,
	'CircleTimes;': 8855,
	'Equilibrium;': 8652,
	'GreaterLess;': 8823,
	'LeftCeiling;': 8968,
	'LessGreater;': 8822,
	'MediumSpace;': 8287,
	'NotLessLess;': 8810,
	'NotPrecedes;': 8832,
	'NotSucceeds;': 8833,
	'NotSuperset;': 8835,
	'OverBracket;': 9140,
	'RightVector;': 8640,
	'Rrightarrow;': 8667,
	'RuleDelayed;': 10740,
	'SmallCircle;': 8728,
	'SquareUnion;': 8852,
	'SubsetEqual;': 8838,
	'UpDownArrow;': 8597,
	'Updownarrow;': 8661,
	'VerticalBar;': 8739,
	'backepsilon;': 1014,
	'blacksquare;': 9642,
	'circledcirc;': 8858,
	'circleddash;': 8861,
	'curlyeqprec;': 8926,
	'curlyeqsucc;': 8927,
	'diamondsuit;': 9830,
	'eqslantless;': 10901,
	'expectation;': 8496,
	'nRightarrow;': 8655,
	'nrightarrow;': 8603,
	'preccurlyeq;': 8828,
	'precnapprox;': 10937,
	'quaternions;': 8461,
	'straightphi;': 981,
	'succcurlyeq;': 8829,
	'succnapprox;': 10938,
	'thickapprox;': 8776,
	'updownarrow;': 8597,
	'Bernoullis;': 8492,
	'CirclePlus;': 8853,
	'EqualTilde;': 8770,
	'Fouriertrf;': 8497,
	'ImaginaryI;': 8520,
	'Laplacetrf;': 8466,
	'LeftVector;': 8636,
	'Lleftarrow;': 8666,
	'NotElement;': 8713,
	'NotGreater;': 8815,
	'Proportion;': 8759,
	'RightArrow;': 8594,
	'RightFloor;': 8971,
	'Rightarrow;': 8658,
	'ThickSpace;': 8287,
	'TildeEqual;': 8771,
	'TildeTilde;': 8776,
	'UnderBrace;': 9183,
	'UpArrowBar;': 10514,
	'UpTeeArrow;': 8613,
	'circledast;': 8859,
	'complement;': 8705,
	'curlywedge;': 8911,
	'eqslantgtr;': 10902,
	'gtreqqless;': 10892,
	'lessapprox;': 10885,
	'lesseqqgtr;': 10891,
	'lmoustache;': 9136,
	'longmapsto;': 10236,
	'mapstodown;': 8615,
	'mapstoleft;': 8612,
	'nLeftarrow;': 8653,
	'nleftarrow;': 8602,
	'nsubseteqq;': 10949,
	'nsupseteqq;': 10950,
	'precapprox;': 10935,
	'rightarrow;': 8594,
	'rmoustache;': 9137,
	'sqsubseteq;': 8849,
	'sqsupseteq;': 8850,
	'subsetneqq;': 10955,
	'succapprox;': 10936,
	'supsetneqq;': 10956,
	'upuparrows;': 8648,
	'varepsilon;': 1013,
	'varnothing;': 8709,
	'Backslash;': 8726,
	'CenterDot;': 183,
	'CircleDot;': 8857,
	'Congruent;': 8801,
	'Coproduct;': 8720,
	'DoubleDot;': 168,
	'DownArrow;': 8595,
	'DownBreve;': 785,
	'Downarrow;': 8659,
	'HumpEqual;': 8783,
	'LeftArrow;': 8592,
	'LeftFloor;': 8970,
	'Leftarrow;': 8656,
	'LessTilde;': 8818,
	'Mellintrf;': 8499,
	'MinusPlus;': 8723,
	'NotCupCap;': 8813,
	'NotExists;': 8708,
	'NotSubset;': 8834,
	'OverBrace;': 9182,
	'PlusMinus;': 177,
	'Therefore;': 8756,
	'ThinSpace;': 8201,
	'TripleDot;': 8411,
	'UnionPlus;': 8846,
	'backprime;': 8245,
	'backsimeq;': 8909,
	'bigotimes;': 10754,
	'centerdot;': 183,
	'checkmark;': 10003,
	'complexes;': 8450,
	'dotsquare;': 8865,
	'downarrow;': 8595,
	'gtrapprox;': 10886,
	'gtreqless;': 8923,
	'gvertneqq;': 8809,
	'heartsuit;': 9829,
	'leftarrow;': 8592,
	'lesseqgtr;': 8922,
	'lvertneqq;': 8808,
	'ngeqslant;': 10878,
	'nleqslant;': 10877,
	'nparallel;': 8742,
	'nshortmid;': 8740,
	'nsubseteq;': 8840,
	'nsupseteq;': 8841,
	'pitchfork;': 8916,
	'rationals;': 8474,
	'spadesuit;': 9824,
	'subseteqq;': 10949,
	'subsetneq;': 8842,
	'supseteqq;': 10950,
	'supsetneq;': 8843,
	'therefore;': 8756,
	'triangleq;': 8796,
	'varpropto;': 8733,
	'DDotrahd;': 10513,
	'DotEqual;': 8784,
	'Integral;': 8747,
	'LessLess;': 10913,
	'NotEqual;': 8800,
	'NotTilde;': 8769,
	'PartialD;': 8706,
	'Precedes;': 8826,
	'RightTee;': 8866,
	'Succeeds;': 8827,
	'SuchThat;': 8715,
	'Superset;': 8835,
	'Uarrocir;': 10569,
	'UnderBar;': 95,
	'andslope;': 10840,
	'angmsdaa;': 10664,
	'angmsdab;': 10665,
	'angmsdac;': 10666,
	'angmsdad;': 10667,
	'angmsdae;': 10668,
	'angmsdaf;': 10669,
	'angmsdag;': 10670,
	'angmsdah;': 10671,
	'angrtvbd;': 10653,
	'approxeq;': 8778,
	'awconint;': 8755,
	'backcong;': 8780,
	'barwedge;': 8965,
	'bbrktbrk;': 9142,
	'bigoplus;': 10753,
	'bigsqcup;': 10758,
	'biguplus;': 10756,
	'bigwedge;': 8896,
	'boxminus;': 8863,
	'boxtimes;': 8864,
	'bsolhsub;': 10184,
	'capbrcup;': 10825,
	'circledR;': 174,
	'circledS;': 9416,
	'cirfnint;': 10768,
	'clubsuit;': 9827,
	'cupbrcap;': 10824,
	'curlyvee;': 8910,
	'cwconint;': 8754,
	'doteqdot;': 8785,
	'dotminus;': 8760,
	'drbkarow;': 10512,
	'dzigrarr;': 10239,
	'elinters;': 9191,
	'emptyset;': 8709,
	'eqvparsl;': 10725,
	'fpartint;': 10765,
	'geqslant;': 10878,
	'gesdotol;': 10884,
	'gnapprox;': 10890,
	'hksearow;': 10533,
	'hkswarow;': 10534,
	'imagline;': 8464,
	'imagpart;': 8465,
	'infintie;': 10717,
	'integers;': 8484,
	'intercal;': 8890,
	'intlarhk;': 10775,
	'laemptyv;': 10676,
	'ldrushar;': 10571,
	'leqslant;': 10877,
	'lesdotor;': 10883,
	'llcorner;': 8990,
	'lnapprox;': 10889,
	'lrcorner;': 8991,
	'lurdshar;': 10570,
	'mapstoup;': 8613,
	'multimap;': 8888,
	'naturals;': 8469,
	'ncongdot;': 10861,
	'notindot;': 8949,
	'otimesas;': 10806,
	'parallel;': 8741,
	'plusacir;': 10787,
	'pointint;': 10773,
	'precneqq;': 10933,
	'precnsim;': 8936,
	'profalar;': 9006,
	'profline;': 8978,
	'profsurf;': 8979,
	'raemptyv;': 10675,
	'realpart;': 8476,
	'rppolint;': 10770,
	'rtriltri;': 10702,
	'scpolint;': 10771,
	'setminus;': 8726,
	'shortmid;': 8739,
	'smeparsl;': 10724,
	'sqsubset;': 8847,
	'sqsupset;': 8848,
	'subseteq;': 8838,
	'succneqq;': 10934,
	'succnsim;': 8937,
	'supseteq;': 8839,
	'thetasym;': 977,
	'thicksim;': 8764,
	'timesbar;': 10801,
	'triangle;': 9653,
	'triminus;': 10810,
	'trpezium;': 9186,
	'ulcorner;': 8988,
	'urcorner;': 8989,
	'varkappa;': 1008,
	'varsigma;': 962,
	'vartheta;': 977,
	'Because;': 8757,
	'Cayleys;': 8493,
	'Cconint;': 8752,
	'Cedilla;': 184,
	'Diamond;': 8900,
	'DownTee;': 8868,
	'Element;': 8712,
	'Epsilon;': 917,
	'Implies;': 8658,
	'LeftTee;': 8867,
	'NewLine;': 10,
	'NoBreak;': 8288,
	'NotLess;': 8814,
	'Omicron;': 927,
	'OverBar;': 8254,
	'Product;': 8719,
	'UpArrow;': 8593,
	'Uparrow;': 8657,
	'Upsilon;': 933,
	'alefsym;': 8501,
	'angrtvb;': 8894,
	'angzarr;': 9084,
	'asympeq;': 8781,
	'backsim;': 8765,
	'because;': 8757,
	'bemptyv;': 10672,
	'between;': 8812,
	'bigcirc;': 9711,
	'bigodot;': 10752,
	'bigstar;': 9733,
	'bnequiv;': 8801,
	'boxplus;': 8862,
	'ccupssm;': 10832,
	'cemptyv;': 10674,
	'cirscir;': 10690,
	'coloneq;': 8788,
	'congdot;': 10861,
	'cudarrl;': 10552,
	'cudarrr;': 10549,
	'cularrp;': 10557,
	'curarrm;': 10556,
	'dbkarow;': 10511,
	'ddagger;': 8225,
	'ddotseq;': 10871,
	'demptyv;': 10673,
	'diamond;': 8900,
	'digamma;': 989,
	'dotplus;': 8724,
	'dwangle;': 10662,
	'epsilon;': 949,
	'eqcolon;': 8789,
	'equivDD;': 10872,
	'gesdoto;': 10882,
	'gtquest;': 10876,
	'gtrless;': 8823,
	'harrcir;': 10568,
	'intprod;': 10812,
	'isindot;': 8949,
	'larrbfs;': 10527,
	'larrsim;': 10611,
	'lbrksld;': 10639,
	'lbrkslu;': 10637,
	'ldrdhar;': 10599,
	'lesdoto;': 10881,
	'lessdot;': 8918,
	'lessgtr;': 8822,
	'lesssim;': 8818,
	'lotimes;': 10804,
	'lozenge;': 9674,
	'ltquest;': 10875,
	'luruhar;': 10598,
	'maltese;': 10016,
	'minusdu;': 10794,
	'napprox;': 8777,
	'natural;': 9838,
	'nearrow;': 8599,
	'nexists;': 8708,
	'notinva;': 8713,
	'notinvb;': 8951,
	'notinvc;': 8950,
	'notniva;': 8716,
	'notnivb;': 8958,
	'notnivc;': 8957,
	'npolint;': 10772,
	'npreceq;': 10927,
	'nsqsube;': 8930,
	'nsqsupe;': 8931,
	'nsubset;': 8834,
	'nsucceq;': 10928,
	'nsupset;': 8835,
	'nvinfin;': 10718,
	'nvltrie;': 8884,
	'nvrtrie;': 8885,
	'nwarrow;': 8598,
	'olcross;': 10683,
	'omicron;': 959,
	'orderof;': 8500,
	'orslope;': 10839,
	'pertenk;': 8241,
	'planckh;': 8462,
	'pluscir;': 10786,
	'plussim;': 10790,
	'plustwo;': 10791,
	'precsim;': 8830,
	'quatint;': 10774,
	'questeq;': 8799,
	'rarrbfs;': 10528,
	'rarrsim;': 10612,
	'rbrksld;': 10638,
	'rbrkslu;': 10640,
	'rdldhar;': 10601,
	'realine;': 8475,
	'rotimes;': 10805,
	'ruluhar;': 10600,
	'searrow;': 8600,
	'simplus;': 10788,
	'simrarr;': 10610,
	'subedot;': 10947,
	'submult;': 10945,
	'subplus;': 10943,
	'subrarr;': 10617,
	'succsim;': 8831,
	'supdsub;': 10968,
	'supedot;': 10948,
	'suphsol;': 10185,
	'suphsub;': 10967,
	'suplarr;': 10619,
	'supmult;': 10946,
	'supplus;': 10944,
	'swarrow;': 8601,
	'topfork;': 10970,
	'triplus;': 10809,
	'tritime;': 10811,
	'uparrow;': 8593,
	'upsilon;': 965,
	'uwangle;': 10663,
	'vzigzag;': 10650,
	'zigrarr;': 8669,
	'Aacute;': 193,
	'Abreve;': 258,
	'Agrave;': 192,
	'Assign;': 8788,
	'Atilde;': 195,
	'Barwed;': 8966,
	'Bumpeq;': 8782,
	'Cacute;': 262,
	'Ccaron;': 268,
	'Ccedil;': 199,
	'Colone;': 10868,
	'Conint;': 8751,
	'CupCap;': 8781,
	'Dagger;': 8225,
	'Dcaron;': 270,
	'DotDot;': 8412,
	'Dstrok;': 272,
	'Eacute;': 201,
	'Ecaron;': 282,
	'Egrave;': 200,
	'Exists;': 8707,
	'ForAll;': 8704,
	'Gammad;': 988,
	'Gbreve;': 286,
	'Gcedil;': 290,
	'HARDcy;': 1066,
	'Hstrok;': 294,
	'Iacute;': 205,
	'Igrave;': 204,
	'Itilde;': 296,
	'Jsercy;': 1032,
	'Kcedil;': 310,
	'Lacute;': 313,
	'Lambda;': 923,
	'Lcaron;': 317,
	'Lcedil;': 315,
	'Lmidot;': 319,
	'Lstrok;': 321,
	'Nacute;': 323,
	'Ncaron;': 327,
	'Ncedil;': 325,
	'Ntilde;': 209,
	'Oacute;': 211,
	'Odblac;': 336,
	'Ograve;': 210,
	'Oslash;': 216,
	'Otilde;': 213,
	'Otimes;': 10807,
	'Racute;': 340,
	'Rarrtl;': 10518,
	'Rcaron;': 344,
	'Rcedil;': 342,
	'SHCHcy;': 1065,
	'SOFTcy;': 1068,
	'Sacute;': 346,
	'Scaron;': 352,
	'Scedil;': 350,
	'Square;': 9633,
	'Subset;': 8912,
	'Supset;': 8913,
	'Tcaron;': 356,
	'Tcedil;': 354,
	'Tstrok;': 358,
	'Uacute;': 218,
	'Ubreve;': 364,
	'Udblac;': 368,
	'Ugrave;': 217,
	'Utilde;': 360,
	'Vdashl;': 10982,
	'Verbar;': 8214,
	'Vvdash;': 8874,
	'Yacute;': 221,
	'Zacute;': 377,
	'Zcaron;': 381,
	'aacute;': 225,
	'abreve;': 259,
	'agrave;': 224,
	'andand;': 10837,
	'angmsd;': 8737,
	'angsph;': 8738,
	'apacir;': 10863,
	'approx;': 8776,
	'atilde;': 227,
	'barvee;': 8893,
	'barwed;': 8965,
	'becaus;': 8757,
	'bernou;': 8492,
	'bigcap;': 8898,
	'bigcup;': 8899,
	'bigvee;': 8897,
	'bkarow;': 10509,
	'bottom;': 8869,
	'bowtie;': 8904,
	'boxbox;': 10697,
	'bprime;': 8245,
	'brvbar;': 166,
	'bullet;': 8226,
	'bumpeq;': 8783,
	'cacute;': 263,
	'capand;': 10820,
	'capcap;': 10827,
	'capcup;': 10823,
	'capdot;': 10816,
	'ccaron;': 269,
	'ccedil;': 231,
	'circeq;': 8791,
	'cirmid;': 10991,
	'colone;': 8788,
	'commat;': 64,
	'compfn;': 8728,
	'conint;': 8750,
	'coprod;': 8720,
	'copysr;': 8471,
	'cularr;': 8630,
	'cupcap;': 10822,
	'cupcup;': 10826,
	'cupdot;': 8845,
	'curarr;': 8631,
	'curren;': 164,
	'cylcty;': 9005,
	'dagger;': 8224,
	'daleth;': 8504,
	'dcaron;': 271,
	'dfisht;': 10623,
	'divide;': 247,
	'divonx;': 8903,
	'dlcorn;': 8990,
	'dlcrop;': 8973,
	'dollar;': 36,
	'drcorn;': 8991,
	'drcrop;': 8972,
	'dstrok;': 273,
	'eacute;': 233,
	'easter;': 10862,
	'ecaron;': 283,
	'ecolon;': 8789,
	'egrave;': 232,
	'egsdot;': 10904,
	'elsdot;': 10903,
	'emptyv;': 8709,
	'emsp13;': 8196,
	'emsp14;': 8197,
	'eparsl;': 10723,
	'eqcirc;': 8790,
	'equals;': 61,
	'equest;': 8799,
	'female;': 9792,
	'ffilig;': 64259,
	'ffllig;': 64260,
	'forall;': 8704,
	'frac12;': 189,
	'frac13;': 8531,
	'frac14;': 188,
	'frac15;': 8533,
	'frac16;': 8537,
	'frac18;': 8539,
	'frac23;': 8532,
	'frac25;': 8534,
	'frac34;': 190,
	'frac35;': 8535,
	'frac38;': 8540,
	'frac45;': 8536,
	'frac56;': 8538,
	'frac58;': 8541,
	'frac78;': 8542,
	'gacute;': 501,
	'gammad;': 989,
	'gbreve;': 287,
	'gesdot;': 10880,
	'gesles;': 10900,
	'gtlPar;': 10645,
	'gtrarr;': 10616,
	'gtrdot;': 8919,
	'gtrsim;': 8819,
	'hairsp;': 8202,
	'hamilt;': 8459,
	'hardcy;': 1098,
	'hearts;': 9829,
	'hellip;': 8230,
	'hercon;': 8889,
	'homtht;': 8763,
	'horbar;': 8213,
	'hslash;': 8463,
	'hstrok;': 295,
	'hybull;': 8259,
	'hyphen;': 8208,
	'iacute;': 237,
	'igrave;': 236,
	'iiiint;': 10764,
	'iinfin;': 10716,
	'incare;': 8453,
	'inodot;': 305,
	'intcal;': 8890,
	'iquest;': 191,
	'isinsv;': 8947,
	'itilde;': 297,
	'jsercy;': 1112,
	'kappav;': 1008,
	'kcedil;': 311,
	'kgreen;': 312,
	'lAtail;': 10523,
	'lacute;': 314,
	'lagran;': 8466,
	'lambda;': 955,
	'langle;': 10216,
	'larrfs;': 10525,
	'larrhk;': 8617,
	'larrlp;': 8619,
	'larrpl;': 10553,
	'larrtl;': 8610,
	'latail;': 10521,
	'lbrace;': 123,
	'lbrack;': 91,
	'lcaron;': 318,
	'lcedil;': 316,
	'ldquor;': 8222,
	'lesdot;': 10879,
	'lesges;': 10899,
	'lfisht;': 10620,
	'lfloor;': 8970,
	'lharul;': 10602,
	'llhard;': 10603,
	'lmidot;': 320,
	'lmoust;': 9136,
	'loplus;': 10797,
	'lowast;': 8727,
	'lowbar;': 95,
	'lparlt;': 10643,
	'lrhard;': 10605,
	'lsaquo;': 8249,
	'lsquor;': 8218,
	'lstrok;': 322,
	'lthree;': 8907,
	'ltimes;': 8905,
	'ltlarr;': 10614,
	'ltrPar;': 10646,
	'mapsto;': 8614,
	'marker;': 9646,
	'mcomma;': 10793,
	'midast;': 42,
	'midcir;': 10992,
	'middot;': 183,
	'minusb;': 8863,
	'minusd;': 8760,
	'mnplus;': 8723,
	'models;': 8871,
	'mstpos;': 8766,
	'nVDash;': 8879,
	'nVdash;': 8878,
	'nacute;': 324,
	'nbumpe;': 8783,
	'ncaron;': 328,
	'ncedil;': 326,
	'nearhk;': 10532,
	'nequiv;': 8802,
	'nesear;': 10536,
	'nexist;': 8708,
	'nltrie;': 8940,
	'notinE;': 8953,
	'nparsl;': 11005,
	'nprcue;': 8928,
	'nrarrc;': 10547,
	'nrarrw;': 8605,
	'nrtrie;': 8941,
	'nsccue;': 8929,
	'nsimeq;': 8772,
	'ntilde;': 241,
	'numero;': 8470,
	'nvDash;': 8877,
	'nvHarr;': 10500,
	'nvdash;': 8876,
	'nvlArr;': 10498,
	'nvrArr;': 10499,
	'nwarhk;': 10531,
	'nwnear;': 10535,
	'oacute;': 243,
	'odblac;': 337,
	'odsold;': 10684,
	'ograve;': 242,
	'ominus;': 8854,
	'origof;': 8886,
	'oslash;': 248,
	'otilde;': 245,
	'otimes;': 8855,
	'parsim;': 10995,
	'percnt;': 37,
	'period;': 46,
	'permil;': 8240,
	'phmmat;': 8499,
	'planck;': 8463,
	'plankv;': 8463,
	'plusdo;': 8724,
	'plusdu;': 10789,
	'plusmn;': 177,
	'preceq;': 10927,
	'primes;': 8473,
	'prnsim;': 8936,
	'propto;': 8733,
	'prurel;': 8880,
	'puncsp;': 8200,
	'qprime;': 8279,
	'rAtail;': 10524,
	'racute;': 341,
	'rangle;': 10217,
	'rarrap;': 10613,
	'rarrfs;': 10526,
	'rarrhk;': 8618,
	'rarrlp;': 8620,
	'rarrpl;': 10565,
	'rarrtl;': 8611,
	'ratail;': 10522,
	'rbrace;': 125,
	'rbrack;': 93,
	'rcaron;': 345,
	'rcedil;': 343,
	'rdquor;': 8221,
	'rfisht;': 10621,
	'rfloor;': 8971,
	'rharul;': 10604,
	'rmoust;': 9137,
	'roplus;': 10798,
	'rpargt;': 10644,
	'rsaquo;': 8250,
	'rsquor;': 8217,
	'rthree;': 8908,
	'rtimes;': 8906,
	'sacute;': 347,
	'scaron;': 353,
	'scedil;': 351,
	'scnsim;': 8937,
	'searhk;': 10533,
	'seswar;': 10537,
	'sfrown;': 8994,
	'shchcy;': 1097,
	'sigmaf;': 962,
	'sigmav;': 962,
	'simdot;': 10858,
	'smashp;': 10803,
	'softcy;': 1100,
	'solbar;': 9023,
	'spades;': 9824,
	'sqcaps;': 8851,
	'sqcups;': 8852,
	'sqsube;': 8849,
	'sqsupe;': 8850,
	'square;': 9633,
	'squarf;': 9642,
	'ssetmn;': 8726,
	'ssmile;': 8995,
	'sstarf;': 8902,
	'subdot;': 10941,
	'subset;': 8834,
	'subsim;': 10951,
	'subsub;': 10965,
	'subsup;': 10963,
	'succeq;': 10928,
	'supdot;': 10942,
	'supset;': 8835,
	'supsim;': 10952,
	'supsub;': 10964,
	'supsup;': 10966,
	'swarhk;': 10534,
	'swnwar;': 10538,
	'target;': 8982,
	'tcaron;': 357,
	'tcedil;': 355,
	'telrec;': 8981,
	'there4;': 8756,
	'thetav;': 977,
	'thinsp;': 8201,
	'thksim;': 8764,
	'timesb;': 8864,
	'timesd;': 10800,
	'topbot;': 9014,
	'topcir;': 10993,
	'tprime;': 8244,
	'tridot;': 9708,
	'tstrok;': 359,
	'uacute;': 250,
	'ubreve;': 365,
	'udblac;': 369,
	'ufisht;': 10622,
	'ugrave;': 249,
	'ulcorn;': 8988,
	'ulcrop;': 8975,
	'urcorn;': 8989,
	'urcrop;': 8974,
	'utilde;': 361,
	'vangrt;': 10652,
	'varphi;': 981,
	'varrho;': 1009,
	'veebar;': 8891,
	'vellip;': 8942,
	'verbar;': 124,
	'vsubnE;': 10955,
	'vsubne;': 8842,
	'vsupnE;': 10956,
	'vsupne;': 8843,
	'wedbar;': 10847,
	'wedgeq;': 8793,
	'weierp;': 8472,
	'wreath;': 8768,
	'xoplus;': 10753,
	'xotime;': 10754,
	'xsqcup;': 10758,
	'xuplus;': 10756,
	'xwedge;': 8896,
	'yacute;': 253,
	'zacute;': 378,
	'zcaron;': 382,
	'zeetrf;': 8488,
	'AElig;': 198,
	Aacute: 193,
	'Acirc;': 194,
	Agrave: 192,
	'Alpha;': 913,
	'Amacr;': 256,
	'Aogon;': 260,
	'Aring;': 197,
	Atilde: 195,
	'Breve;': 728,
	Ccedil: 199,
	'Ccirc;': 264,
	'Colon;': 8759,
	'Cross;': 10799,
	'Dashv;': 10980,
	'Delta;': 916,
	Eacute: 201,
	'Ecirc;': 202,
	Egrave: 200,
	'Emacr;': 274,
	'Eogon;': 280,
	'Equal;': 10869,
	'Gamma;': 915,
	'Gcirc;': 284,
	'Hacek;': 711,
	'Hcirc;': 292,
	'IJlig;': 306,
	Iacute: 205,
	'Icirc;': 206,
	Igrave: 204,
	'Imacr;': 298,
	'Iogon;': 302,
	'Iukcy;': 1030,
	'Jcirc;': 308,
	'Jukcy;': 1028,
	'Kappa;': 922,
	Ntilde: 209,
	'OElig;': 338,
	Oacute: 211,
	'Ocirc;': 212,
	Ograve: 210,
	'Omacr;': 332,
	'Omega;': 937,
	Oslash: 216,
	Otilde: 213,
	'Prime;': 8243,
	'RBarr;': 10512,
	'Scirc;': 348,
	'Sigma;': 931,
	'THORN;': 222,
	'TRADE;': 8482,
	'TSHcy;': 1035,
	'Theta;': 920,
	'Tilde;': 8764,
	Uacute: 218,
	'Ubrcy;': 1038,
	'Ucirc;': 219,
	Ugrave: 217,
	'Umacr;': 362,
	'Union;': 8899,
	'Uogon;': 370,
	'UpTee;': 8869,
	'Uring;': 366,
	'VDash;': 8875,
	'Vdash;': 8873,
	'Wcirc;': 372,
	'Wedge;': 8896,
	Yacute: 221,
	'Ycirc;': 374,
	aacute: 225,
	'acirc;': 226,
	'acute;': 180,
	'aelig;': 230,
	agrave: 224,
	'aleph;': 8501,
	'alpha;': 945,
	'amacr;': 257,
	'amalg;': 10815,
	'angle;': 8736,
	'angrt;': 8735,
	'angst;': 197,
	'aogon;': 261,
	'aring;': 229,
	'asymp;': 8776,
	atilde: 227,
	'awint;': 10769,
	'bcong;': 8780,
	'bdquo;': 8222,
	'bepsi;': 1014,
	'blank;': 9251,
	'blk12;': 9618,
	'blk14;': 9617,
	'blk34;': 9619,
	'block;': 9608,
	'boxDL;': 9559,
	'boxDR;': 9556,
	'boxDl;': 9558,
	'boxDr;': 9555,
	'boxHD;': 9574,
	'boxHU;': 9577,
	'boxHd;': 9572,
	'boxHu;': 9575,
	'boxUL;': 9565,
	'boxUR;': 9562,
	'boxUl;': 9564,
	'boxUr;': 9561,
	'boxVH;': 9580,
	'boxVL;': 9571,
	'boxVR;': 9568,
	'boxVh;': 9579,
	'boxVl;': 9570,
	'boxVr;': 9567,
	'boxdL;': 9557,
	'boxdR;': 9554,
	'boxdl;': 9488,
	'boxdr;': 9484,
	'boxhD;': 9573,
	'boxhU;': 9576,
	'boxhd;': 9516,
	'boxhu;': 9524,
	'boxuL;': 9563,
	'boxuR;': 9560,
	'boxul;': 9496,
	'boxur;': 9492,
	'boxvH;': 9578,
	'boxvL;': 9569,
	'boxvR;': 9566,
	'boxvh;': 9532,
	'boxvl;': 9508,
	'boxvr;': 9500,
	'breve;': 728,
	brvbar: 166,
	'bsemi;': 8271,
	'bsime;': 8909,
	'bsolb;': 10693,
	'bumpE;': 10926,
	'bumpe;': 8783,
	'caret;': 8257,
	'caron;': 711,
	'ccaps;': 10829,
	ccedil: 231,
	'ccirc;': 265,
	'ccups;': 10828,
	'cedil;': 184,
	'check;': 10003,
	'clubs;': 9827,
	'colon;': 58,
	'comma;': 44,
	'crarr;': 8629,
	'cross;': 10007,
	'csube;': 10961,
	'csupe;': 10962,
	'ctdot;': 8943,
	'cuepr;': 8926,
	'cuesc;': 8927,
	'cupor;': 10821,
	curren: 164,
	'cuvee;': 8910,
	'cuwed;': 8911,
	'cwint;': 8753,
	'dashv;': 8867,
	'dblac;': 733,
	'ddarr;': 8650,
	'delta;': 948,
	'dharl;': 8643,
	'dharr;': 8642,
	'diams;': 9830,
	'disin;': 8946,
	divide: 247,
	'doteq;': 8784,
	'dtdot;': 8945,
	'dtrif;': 9662,
	'duarr;': 8693,
	'duhar;': 10607,
	'eDDot;': 10871,
	eacute: 233,
	'ecirc;': 234,
	'efDot;': 8786,
	egrave: 232,
	'emacr;': 275,
	'empty;': 8709,
	'eogon;': 281,
	'eplus;': 10865,
	'epsiv;': 1013,
	'eqsim;': 8770,
	'equiv;': 8801,
	'erDot;': 8787,
	'erarr;': 10609,
	'esdot;': 8784,
	'exist;': 8707,
	'fflig;': 64256,
	'filig;': 64257,
	'fjlig;': 102,
	'fllig;': 64258,
	'fltns;': 9649,
	'forkv;': 10969,
	frac12: 189,
	frac14: 188,
	frac34: 190,
	'frasl;': 8260,
	'frown;': 8994,
	'gamma;': 947,
	'gcirc;': 285,
	'gescc;': 10921,
	'gimel;': 8503,
	'gneqq;': 8809,
	'gnsim;': 8935,
	'grave;': 96,
	'gsime;': 10894,
	'gsiml;': 10896,
	'gtcir;': 10874,
	'gtdot;': 8919,
	'harrw;': 8621,
	'hcirc;': 293,
	'hoarr;': 8703,
	iacute: 237,
	'icirc;': 238,
	'iexcl;': 161,
	igrave: 236,
	'iiint;': 8749,
	'iiota;': 8489,
	'ijlig;': 307,
	'imacr;': 299,
	'image;': 8465,
	'imath;': 305,
	'imped;': 437,
	'infin;': 8734,
	'iogon;': 303,
	'iprod;': 10812,
	iquest: 191,
	'isinE;': 8953,
	'isins;': 8948,
	'isinv;': 8712,
	'iukcy;': 1110,
	'jcirc;': 309,
	'jmath;': 567,
	'jukcy;': 1108,
	'kappa;': 954,
	'lAarr;': 8666,
	'lBarr;': 10510,
	'langd;': 10641,
	'laquo;': 171,
	'larrb;': 8676,
	'lates;': 10925,
	'lbarr;': 10508,
	'lbbrk;': 10098,
	'lbrke;': 10635,
	'lceil;': 8968,
	'ldquo;': 8220,
	'lescc;': 10920,
	'lhard;': 8637,
	'lharu;': 8636,
	'lhblk;': 9604,
	'llarr;': 8647,
	'lltri;': 9722,
	'lneqq;': 8808,
	'lnsim;': 8934,
	'loang;': 10220,
	'loarr;': 8701,
	'lobrk;': 10214,
	'lopar;': 10629,
	'lrarr;': 8646,
	'lrhar;': 8651,
	'lrtri;': 8895,
	'lsime;': 10893,
	'lsimg;': 10895,
	'lsquo;': 8216,
	'ltcir;': 10873,
	'ltdot;': 8918,
	'ltrie;': 8884,
	'ltrif;': 9666,
	'mDDot;': 8762,
	'mdash;': 8212,
	'micro;': 181,
	middot: 183,
	'minus;': 8722,
	'mumap;': 8888,
	'nabla;': 8711,
	'napid;': 8779,
	'napos;': 329,
	'natur;': 9838,
	'nbump;': 8782,
	'ncong;': 8775,
	'ndash;': 8211,
	'neArr;': 8663,
	'nearr;': 8599,
	'nedot;': 8784,
	'nesim;': 8770,
	'ngeqq;': 8807,
	'ngsim;': 8821,
	'nhArr;': 8654,
	'nharr;': 8622,
	'nhpar;': 10994,
	'nlArr;': 8653,
	'nlarr;': 8602,
	'nleqq;': 8806,
	'nless;': 8814,
	'nlsim;': 8820,
	'nltri;': 8938,
	'notin;': 8713,
	'notni;': 8716,
	'npart;': 8706,
	'nprec;': 8832,
	'nrArr;': 8655,
	'nrarr;': 8603,
	'nrtri;': 8939,
	'nsime;': 8772,
	'nsmid;': 8740,
	'nspar;': 8742,
	'nsubE;': 10949,
	'nsube;': 8840,
	'nsucc;': 8833,
	'nsupE;': 10950,
	'nsupe;': 8841,
	ntilde: 241,
	'numsp;': 8199,
	'nvsim;': 8764,
	'nwArr;': 8662,
	'nwarr;': 8598,
	oacute: 243,
	'ocirc;': 244,
	'odash;': 8861,
	'oelig;': 339,
	'ofcir;': 10687,
	ograve: 242,
	'ohbar;': 10677,
	'olarr;': 8634,
	'olcir;': 10686,
	'oline;': 8254,
	'omacr;': 333,
	'omega;': 969,
	'operp;': 10681,
	'oplus;': 8853,
	'orarr;': 8635,
	'order;': 8500,
	oslash: 248,
	otilde: 245,
	'ovbar;': 9021,
	'parsl;': 11005,
	'phone;': 9742,
	'plusb;': 8862,
	'pluse;': 10866,
	plusmn: 177,
	'pound;': 163,
	'prcue;': 8828,
	'prime;': 8242,
	'prnap;': 10937,
	'prsim;': 8830,
	'quest;': 63,
	'rAarr;': 8667,
	'rBarr;': 10511,
	'radic;': 8730,
	'rangd;': 10642,
	'range;': 10661,
	'raquo;': 187,
	'rarrb;': 8677,
	'rarrc;': 10547,
	'rarrw;': 8605,
	'ratio;': 8758,
	'rbarr;': 10509,
	'rbbrk;': 10099,
	'rbrke;': 10636,
	'rceil;': 8969,
	'rdquo;': 8221,
	'reals;': 8477,
	'rhard;': 8641,
	'rharu;': 8640,
	'rlarr;': 8644,
	'rlhar;': 8652,
	'rnmid;': 10990,
	'roang;': 10221,
	'roarr;': 8702,
	'robrk;': 10215,
	'ropar;': 10630,
	'rrarr;': 8649,
	'rsquo;': 8217,
	'rtrie;': 8885,
	'rtrif;': 9656,
	'sbquo;': 8218,
	'sccue;': 8829,
	'scirc;': 349,
	'scnap;': 10938,
	'scsim;': 8831,
	'sdotb;': 8865,
	'sdote;': 10854,
	'seArr;': 8664,
	'searr;': 8600,
	'setmn;': 8726,
	'sharp;': 9839,
	'sigma;': 963,
	'simeq;': 8771,
	'simgE;': 10912,
	'simlE;': 10911,
	'simne;': 8774,
	'slarr;': 8592,
	'smile;': 8995,
	'smtes;': 10924,
	'sqcap;': 8851,
	'sqcup;': 8852,
	'sqsub;': 8847,
	'sqsup;': 8848,
	'srarr;': 8594,
	'starf;': 9733,
	'strns;': 175,
	'subnE;': 10955,
	'subne;': 8842,
	'supnE;': 10956,
	'supne;': 8843,
	'swArr;': 8665,
	'swarr;': 8601,
	'szlig;': 223,
	'theta;': 952,
	'thkap;': 8776,
	'thorn;': 254,
	'tilde;': 732,
	'times;': 215,
	'trade;': 8482,
	'trisb;': 10701,
	'tshcy;': 1115,
	'twixt;': 8812,
	uacute: 250,
	'ubrcy;': 1118,
	'ucirc;': 251,
	'udarr;': 8645,
	'udhar;': 10606,
	ugrave: 249,
	'uharl;': 8639,
	'uharr;': 8638,
	'uhblk;': 9600,
	'ultri;': 9720,
	'umacr;': 363,
	'uogon;': 371,
	'uplus;': 8846,
	'upsih;': 978,
	'uring;': 367,
	'urtri;': 9721,
	'utdot;': 8944,
	'utrif;': 9652,
	'uuarr;': 8648,
	'vBarv;': 10985,
	'vDash;': 8872,
	'varpi;': 982,
	'vdash;': 8866,
	'veeeq;': 8794,
	'vltri;': 8882,
	'vnsub;': 8834,
	'vnsup;': 8835,
	'vprop;': 8733,
	'vrtri;': 8883,
	'wcirc;': 373,
	'wedge;': 8743,
	'xcirc;': 9711,
	'xdtri;': 9661,
	'xhArr;': 10234,
	'xharr;': 10231,
	'xlArr;': 10232,
	'xlarr;': 10229,
	'xodot;': 10752,
	'xrArr;': 10233,
	'xrarr;': 10230,
	'xutri;': 9651,
	yacute: 253,
	'ycirc;': 375,
	AElig: 198,
	Acirc: 194,
	'Aopf;': 120120,
	Aring: 197,
	'Ascr;': 119964,
	'Auml;': 196,
	'Barv;': 10983,
	'Beta;': 914,
	'Bopf;': 120121,
	'Bscr;': 8492,
	'CHcy;': 1063,
	'COPY;': 169,
	'Cdot;': 266,
	'Copf;': 8450,
	'Cscr;': 119966,
	'DJcy;': 1026,
	'DScy;': 1029,
	'DZcy;': 1039,
	'Darr;': 8609,
	'Dopf;': 120123,
	'Dscr;': 119967,
	Ecirc: 202,
	'Edot;': 278,
	'Eopf;': 120124,
	'Escr;': 8496,
	'Esim;': 10867,
	'Euml;': 203,
	'Fopf;': 120125,
	'Fscr;': 8497,
	'GJcy;': 1027,
	'Gdot;': 288,
	'Gopf;': 120126,
	'Gscr;': 119970,
	'Hopf;': 8461,
	'Hscr;': 8459,
	'IEcy;': 1045,
	'IOcy;': 1025,
	Icirc: 206,
	'Idot;': 304,
	'Iopf;': 120128,
	'Iota;': 921,
	'Iscr;': 8464,
	'Iuml;': 207,
	'Jopf;': 120129,
	'Jscr;': 119973,
	'KHcy;': 1061,
	'KJcy;': 1036,
	'Kopf;': 120130,
	'Kscr;': 119974,
	'LJcy;': 1033,
	'Lang;': 10218,
	'Larr;': 8606,
	'Lopf;': 120131,
	'Lscr;': 8466,
	'Mopf;': 120132,
	'Mscr;': 8499,
	'NJcy;': 1034,
	'Nopf;': 8469,
	'Nscr;': 119977,
	Ocirc: 212,
	'Oopf;': 120134,
	'Oscr;': 119978,
	'Ouml;': 214,
	'Popf;': 8473,
	'Pscr;': 119979,
	'QUOT;': 34,
	'Qopf;': 8474,
	'Qscr;': 119980,
	'Rang;': 10219,
	'Rarr;': 8608,
	'Ropf;': 8477,
	'Rscr;': 8475,
	'SHcy;': 1064,
	'Sopf;': 120138,
	'Sqrt;': 8730,
	'Sscr;': 119982,
	'Star;': 8902,
	THORN: 222,
	'TScy;': 1062,
	'Topf;': 120139,
	'Tscr;': 119983,
	'Uarr;': 8607,
	Ucirc: 219,
	'Uopf;': 120140,
	'Upsi;': 978,
	'Uscr;': 119984,
	'Uuml;': 220,
	'Vbar;': 10987,
	'Vert;': 8214,
	'Vopf;': 120141,
	'Vscr;': 119985,
	'Wopf;': 120142,
	'Wscr;': 119986,
	'Xopf;': 120143,
	'Xscr;': 119987,
	'YAcy;': 1071,
	'YIcy;': 1031,
	'YUcy;': 1070,
	'Yopf;': 120144,
	'Yscr;': 119988,
	'Yuml;': 376,
	'ZHcy;': 1046,
	'Zdot;': 379,
	'Zeta;': 918,
	'Zopf;': 8484,
	'Zscr;': 119989,
	acirc: 226,
	acute: 180,
	aelig: 230,
	'andd;': 10844,
	'andv;': 10842,
	'ange;': 10660,
	'aopf;': 120146,
	'apid;': 8779,
	'apos;': 39,
	aring: 229,
	'ascr;': 119990,
	'auml;': 228,
	'bNot;': 10989,
	'bbrk;': 9141,
	'beta;': 946,
	'beth;': 8502,
	'bnot;': 8976,
	'bopf;': 120147,
	'boxH;': 9552,
	'boxV;': 9553,
	'boxh;': 9472,
	'boxv;': 9474,
	'bscr;': 119991,
	'bsim;': 8765,
	'bsol;': 92,
	'bull;': 8226,
	'bump;': 8782,
	'caps;': 8745,
	'cdot;': 267,
	cedil: 184,
	'cent;': 162,
	'chcy;': 1095,
	'cirE;': 10691,
	'circ;': 710,
	'cire;': 8791,
	'comp;': 8705,
	'cong;': 8773,
	'copf;': 120148,
	'copy;': 169,
	'cscr;': 119992,
	'csub;': 10959,
	'csup;': 10960,
	'cups;': 8746,
	'dArr;': 8659,
	'dHar;': 10597,
	'darr;': 8595,
	'dash;': 8208,
	'diam;': 8900,
	'djcy;': 1106,
	'dopf;': 120149,
	'dscr;': 119993,
	'dscy;': 1109,
	'dsol;': 10742,
	'dtri;': 9663,
	'dzcy;': 1119,
	'eDot;': 8785,
	'ecir;': 8790,
	ecirc: 234,
	'edot;': 279,
	'emsp;': 8195,
	'ensp;': 8194,
	'eopf;': 120150,
	'epar;': 8917,
	'epsi;': 949,
	'escr;': 8495,
	'esim;': 8770,
	'euml;': 235,
	'euro;': 8364,
	'excl;': 33,
	'flat;': 9837,
	'fnof;': 402,
	'fopf;': 120151,
	'fork;': 8916,
	'fscr;': 119995,
	'gdot;': 289,
	'geqq;': 8807,
	'gesl;': 8923,
	'gjcy;': 1107,
	'gnap;': 10890,
	'gneq;': 10888,
	'gopf;': 120152,
	'gscr;': 8458,
	'gsim;': 8819,
	'gtcc;': 10919,
	'gvnE;': 8809,
	'hArr;': 8660,
	'half;': 189,
	'harr;': 8596,
	'hbar;': 8463,
	'hopf;': 120153,
	'hscr;': 119997,
	icirc: 238,
	'iecy;': 1077,
	iexcl: 161,
	'imof;': 8887,
	'iocy;': 1105,
	'iopf;': 120154,
	'iota;': 953,
	'iscr;': 119998,
	'isin;': 8712,
	'iuml;': 239,
	'jopf;': 120155,
	'jscr;': 119999,
	'khcy;': 1093,
	'kjcy;': 1116,
	'kopf;': 120156,
	'kscr;': 120000,
	'lArr;': 8656,
	'lHar;': 10594,
	'lang;': 10216,
	laquo: 171,
	'larr;': 8592,
	'late;': 10925,
	'lcub;': 123,
	'ldca;': 10550,
	'ldsh;': 8626,
	'leqq;': 8806,
	'lesg;': 8922,
	'ljcy;': 1113,
	'lnap;': 10889,
	'lneq;': 10887,
	'lopf;': 120157,
	'lozf;': 10731,
	'lpar;': 40,
	'lscr;': 120001,
	'lsim;': 8818,
	'lsqb;': 91,
	'ltcc;': 10918,
	'ltri;': 9667,
	'lvnE;': 8808,
	'macr;': 175,
	'male;': 9794,
	'malt;': 10016,
	micro: 181,
	'mlcp;': 10971,
	'mldr;': 8230,
	'mopf;': 120158,
	'mscr;': 120002,
	'nGtv;': 8811,
	'nLtv;': 8810,
	'nang;': 8736,
	'napE;': 10864,
	'nbsp;': 160,
	'ncap;': 10819,
	'ncup;': 10818,
	'ngeq;': 8817,
	'nges;': 10878,
	'ngtr;': 8815,
	'nisd;': 8954,
	'njcy;': 1114,
	'nldr;': 8229,
	'nleq;': 8816,
	'nles;': 10877,
	'nmid;': 8740,
	'nopf;': 120159,
	'npar;': 8742,
	'npre;': 10927,
	'nsce;': 10928,
	'nscr;': 120003,
	'nsim;': 8769,
	'nsub;': 8836,
	'nsup;': 8837,
	'ntgl;': 8825,
	'ntlg;': 8824,
	'nvap;': 8781,
	'nvge;': 8805,
	'nvgt;': 62,
	'nvle;': 8804,
	'nvlt;': 60,
	'oast;': 8859,
	'ocir;': 8858,
	ocirc: 244,
	'odiv;': 10808,
	'odot;': 8857,
	'ogon;': 731,
	'oint;': 8750,
	'omid;': 10678,
	'oopf;': 120160,
	'opar;': 10679,
	'ordf;': 170,
	'ordm;': 186,
	'oror;': 10838,
	'oscr;': 8500,
	'osol;': 8856,
	'ouml;': 246,
	'para;': 182,
	'part;': 8706,
	'perp;': 8869,
	'phiv;': 981,
	'plus;': 43,
	'popf;': 120161,
	pound: 163,
	'prap;': 10935,
	'prec;': 8826,
	'prnE;': 10933,
	'prod;': 8719,
	'prop;': 8733,
	'pscr;': 120005,
	'qint;': 10764,
	'qopf;': 120162,
	'qscr;': 120006,
	'quot;': 34,
	'rArr;': 8658,
	'rHar;': 10596,
	'race;': 8765,
	'rang;': 10217,
	raquo: 187,
	'rarr;': 8594,
	'rcub;': 125,
	'rdca;': 10551,
	'rdsh;': 8627,
	'real;': 8476,
	'rect;': 9645,
	'rhov;': 1009,
	'ring;': 730,
	'ropf;': 120163,
	'rpar;': 41,
	'rscr;': 120007,
	'rsqb;': 93,
	'rtri;': 9657,
	'scap;': 10936,
	'scnE;': 10934,
	'sdot;': 8901,
	'sect;': 167,
	'semi;': 59,
	'sext;': 10038,
	'shcy;': 1096,
	'sime;': 8771,
	'simg;': 10910,
	'siml;': 10909,
	'smid;': 8739,
	'smte;': 10924,
	'solb;': 10692,
	'sopf;': 120164,
	'spar;': 8741,
	'squf;': 9642,
	'sscr;': 120008,
	'star;': 9734,
	'subE;': 10949,
	'sube;': 8838,
	'succ;': 8827,
	'sung;': 9834,
	'sup1;': 185,
	'sup2;': 178,
	'sup3;': 179,
	'supE;': 10950,
	'supe;': 8839,
	szlig: 223,
	'tbrk;': 9140,
	'tdot;': 8411,
	thorn: 254,
	times: 215,
	'tint;': 8749,
	'toea;': 10536,
	'topf;': 120165,
	'tosa;': 10537,
	'trie;': 8796,
	'tscr;': 120009,
	'tscy;': 1094,
	'uArr;': 8657,
	'uHar;': 10595,
	'uarr;': 8593,
	ucirc: 251,
	'uopf;': 120166,
	'upsi;': 965,
	'uscr;': 120010,
	'utri;': 9653,
	'uuml;': 252,
	'vArr;': 8661,
	'vBar;': 10984,
	'varr;': 8597,
	'vert;': 124,
	'vopf;': 120167,
	'vscr;': 120011,
	'wopf;': 120168,
	'wscr;': 120012,
	'xcap;': 8898,
	'xcup;': 8899,
	'xmap;': 10236,
	'xnis;': 8955,
	'xopf;': 120169,
	'xscr;': 120013,
	'xvee;': 8897,
	'yacy;': 1103,
	'yicy;': 1111,
	'yopf;': 120170,
	'yscr;': 120014,
	'yucy;': 1102,
	'yuml;': 255,
	'zdot;': 380,
	'zeta;': 950,
	'zhcy;': 1078,
	'zopf;': 120171,
	'zscr;': 120015,
	'zwnj;': 8204,
	'AMP;': 38,
	'Acy;': 1040,
	'Afr;': 120068,
	'And;': 10835,
	Auml: 196,
	'Bcy;': 1041,
	'Bfr;': 120069,
	COPY: 169,
	'Cap;': 8914,
	'Cfr;': 8493,
	'Chi;': 935,
	'Cup;': 8915,
	'Dcy;': 1044,
	'Del;': 8711,
	'Dfr;': 120071,
	'Dot;': 168,
	'ENG;': 330,
	'ETH;': 208,
	'Ecy;': 1069,
	'Efr;': 120072,
	'Eta;': 919,
	Euml: 203,
	'Fcy;': 1060,
	'Ffr;': 120073,
	'Gcy;': 1043,
	'Gfr;': 120074,
	'Hat;': 94,
	'Hfr;': 8460,
	'Icy;': 1048,
	'Ifr;': 8465,
	'Int;': 8748,
	Iuml: 207,
	'Jcy;': 1049,
	'Jfr;': 120077,
	'Kcy;': 1050,
	'Kfr;': 120078,
	'Lcy;': 1051,
	'Lfr;': 120079,
	'Lsh;': 8624,
	'Map;': 10501,
	'Mcy;': 1052,
	'Mfr;': 120080,
	'Ncy;': 1053,
	'Nfr;': 120081,
	'Not;': 10988,
	'Ocy;': 1054,
	'Ofr;': 120082,
	Ouml: 214,
	'Pcy;': 1055,
	'Pfr;': 120083,
	'Phi;': 934,
	'Psi;': 936,
	QUOT: 34,
	'Qfr;': 120084,
	'REG;': 174,
	'Rcy;': 1056,
	'Rfr;': 8476,
	'Rho;': 929,
	'Rsh;': 8625,
	'Scy;': 1057,
	'Sfr;': 120086,
	'Sub;': 8912,
	'Sum;': 8721,
	'Sup;': 8913,
	'Tab;': 9,
	'Tau;': 932,
	'Tcy;': 1058,
	'Tfr;': 120087,
	'Ucy;': 1059,
	'Ufr;': 120088,
	Uuml: 220,
	'Vcy;': 1042,
	'Vee;': 8897,
	'Vfr;': 120089,
	'Wfr;': 120090,
	'Xfr;': 120091,
	'Ycy;': 1067,
	'Yfr;': 120092,
	'Zcy;': 1047,
	'Zfr;': 8488,
	'acE;': 8766,
	'acd;': 8767,
	'acy;': 1072,
	'afr;': 120094,
	'amp;': 38,
	'and;': 8743,
	'ang;': 8736,
	'apE;': 10864,
	'ape;': 8778,
	'ast;': 42,
	auml: 228,
	'bcy;': 1073,
	'bfr;': 120095,
	'bne;': 61,
	'bot;': 8869,
	'cap;': 8745,
	cent: 162,
	'cfr;': 120096,
	'chi;': 967,
	'cir;': 9675,
	copy: 169,
	'cup;': 8746,
	'dcy;': 1076,
	'deg;': 176,
	'dfr;': 120097,
	'die;': 168,
	'div;': 247,
	'dot;': 729,
	'ecy;': 1101,
	'efr;': 120098,
	'egs;': 10902,
	'ell;': 8467,
	'els;': 10901,
	'eng;': 331,
	'eta;': 951,
	'eth;': 240,
	euml: 235,
	'fcy;': 1092,
	'ffr;': 120099,
	'gEl;': 10892,
	'gap;': 10886,
	'gcy;': 1075,
	'gel;': 8923,
	'geq;': 8805,
	'ges;': 10878,
	'gfr;': 120100,
	'ggg;': 8921,
	'glE;': 10898,
	'gla;': 10917,
	'glj;': 10916,
	'gnE;': 8809,
	'gne;': 10888,
	'hfr;': 120101,
	'icy;': 1080,
	'iff;': 8660,
	'ifr;': 120102,
	'int;': 8747,
	iuml: 239,
	'jcy;': 1081,
	'jfr;': 120103,
	'kcy;': 1082,
	'kfr;': 120104,
	'lEg;': 10891,
	'lap;': 10885,
	'lat;': 10923,
	'lcy;': 1083,
	'leg;': 8922,
	'leq;': 8804,
	'les;': 10877,
	'lfr;': 120105,
	'lgE;': 10897,
	'lnE;': 8808,
	'lne;': 10887,
	'loz;': 9674,
	'lrm;': 8206,
	'lsh;': 8624,
	macr: 175,
	'map;': 8614,
	'mcy;': 1084,
	'mfr;': 120106,
	'mho;': 8487,
	'mid;': 8739,
	'nGg;': 8921,
	'nGt;': 8811,
	'nLl;': 8920,
	'nLt;': 8810,
	'nap;': 8777,
	nbsp: 160,
	'ncy;': 1085,
	'nfr;': 120107,
	'ngE;': 8807,
	'nge;': 8817,
	'ngt;': 8815,
	'nis;': 8956,
	'niv;': 8715,
	'nlE;': 8806,
	'nle;': 8816,
	'nlt;': 8814,
	'not;': 172,
	'npr;': 8832,
	'nsc;': 8833,
	'num;': 35,
	'ocy;': 1086,
	'ofr;': 120108,
	'ogt;': 10689,
	'ohm;': 937,
	'olt;': 10688,
	'ord;': 10845,
	ordf: 170,
	ordm: 186,
	'orv;': 10843,
	ouml: 246,
	'par;': 8741,
	para: 182,
	'pcy;': 1087,
	'pfr;': 120109,
	'phi;': 966,
	'piv;': 982,
	'prE;': 10931,
	'pre;': 10927,
	'psi;': 968,
	'qfr;': 120110,
	quot: 34,
	'rcy;': 1088,
	'reg;': 174,
	'rfr;': 120111,
	'rho;': 961,
	'rlm;': 8207,
	'rsh;': 8625,
	'scE;': 10932,
	'sce;': 10928,
	'scy;': 1089,
	sect: 167,
	'sfr;': 120112,
	'shy;': 173,
	'sim;': 8764,
	'smt;': 10922,
	'sol;': 47,
	'squ;': 9633,
	'sub;': 8834,
	'sum;': 8721,
	sup1: 185,
	sup2: 178,
	sup3: 179,
	'sup;': 8835,
	'tau;': 964,
	'tcy;': 1090,
	'tfr;': 120113,
	'top;': 8868,
	'ucy;': 1091,
	'ufr;': 120114,
	'uml;': 168,
	uuml: 252,
	'vcy;': 1074,
	'vee;': 8744,
	'vfr;': 120115,
	'wfr;': 120116,
	'xfr;': 120117,
	'ycy;': 1099,
	'yen;': 165,
	'yfr;': 120118,
	yuml: 255,
	'zcy;': 1079,
	'zfr;': 120119,
	'zwj;': 8205,
	AMP: 38,
	'DD;': 8517,
	ETH: 208,
	'GT;': 62,
	'Gg;': 8921,
	'Gt;': 8811,
	'Im;': 8465,
	'LT;': 60,
	'Ll;': 8920,
	'Lt;': 8810,
	'Mu;': 924,
	'Nu;': 925,
	'Or;': 10836,
	'Pi;': 928,
	'Pr;': 10939,
	REG: 174,
	'Re;': 8476,
	'Sc;': 10940,
	'Xi;': 926,
	'ac;': 8766,
	'af;': 8289,
	amp: 38,
	'ap;': 8776,
	'dd;': 8518,
	deg: 176,
	'ee;': 8519,
	'eg;': 10906,
	'el;': 10905,
	eth: 240,
	'gE;': 8807,
	'ge;': 8805,
	'gg;': 8811,
	'gl;': 8823,
	'gt;': 62,
	'ic;': 8291,
	'ii;': 8520,
	'in;': 8712,
	'it;': 8290,
	'lE;': 8806,
	'le;': 8804,
	'lg;': 8822,
	'll;': 8810,
	'lt;': 60,
	'mp;': 8723,
	'mu;': 956,
	'ne;': 8800,
	'ni;': 8715,
	not: 172,
	'nu;': 957,
	'oS;': 9416,
	'or;': 8744,
	'pi;': 960,
	'pm;': 177,
	'pr;': 8826,
	reg: 174,
	'rx;': 8478,
	'sc;': 8827,
	shy: 173,
	uml: 168,
	'wp;': 8472,
	'wr;': 8768,
	'xi;': 958,
	yen: 165,
	GT: 62,
	LT: 60,
	gt: 62,
	lt: 60
};

const windows_1252 = [
	8364, 129, 8218, 402, 8222, 8230, 8224, 8225, 710, 8240, 352, 8249, 338, 141, 381, 143, 144, 8216,
	8217, 8220, 8221, 8226, 8211, 8212, 732, 8482, 353, 8250, 339, 157, 382, 376
];

/**
 * @param {string} entity_name
 * @param {boolean} is_attribute_value
 */
function reg_exp_entity(entity_name, is_attribute_value) {
	// https://html.spec.whatwg.org/multipage/parsing.html#named-character-reference-state
	// doesn't decode the html entity which not ends with ; and next character is =, number or alphabet in attribute value.
	if (is_attribute_value && !entity_name.endsWith(';')) {
		return `${entity_name}\\b(?!=)`;
	}
	return entity_name;
}

/** @param {boolean} is_attribute_value */
function get_entity_pattern(is_attribute_value) {
	const reg_exp_num = '#(?:x[a-fA-F\\d]+|\\d+)(?:;)?';
	const reg_exp_entities = Object.keys(entities).map(
		/** @param {any} entity_name */ (entity_name) => reg_exp_entity(entity_name, is_attribute_value)
	);

	const entity_pattern = new RegExp(`&(${reg_exp_num}|${reg_exp_entities.join('|')})`, 'g');

	return entity_pattern;
}

const entity_pattern_content = get_entity_pattern(false);
const entity_pattern_attr_value = get_entity_pattern(true);

/**
 * @param {string} html
 * @param {boolean} is_attribute_value
 */
function decode_character_references(html, is_attribute_value) {
	const entity_pattern = is_attribute_value ? entity_pattern_attr_value : entity_pattern_content;
	return html.replace(
		entity_pattern,
		/**
		 * @param {any} match
		 * @param {keyof typeof entities} entity
		 */ (match, entity) => {
			let code;

			// Handle named entities
			if (entity[0] !== '#') {
				code = entities[entity];
			} else if (entity[1] === 'x') {
				code = parseInt(entity.substring(2), 16);
			} else {
				code = parseInt(entity.substring(1), 10);
			}

			if (!code) {
				return match;
			}

			return String.fromCodePoint(validate_code(code));
		}
	);
}

const NUL = 0;

// some code points are verboten. If we were inserting HTML, the browser would replace the illegal
// code points with alternatives in some cases - since we're bypassing that mechanism, we need
// to replace them ourselves
//
// Source: http://en.wikipedia.org/wiki/Character_encodings_in_HTML#Illegal_characters
// Also see: https://en.wikipedia.org/wiki/Plane_(Unicode)
// Also see: https://html.spec.whatwg.org/multipage/parsing.html#preprocessing-the-input-stream

/** @param {number} code */
function validate_code(code) {
	// line feed becomes generic whitespace
	if (code === 10) {
		return 32;
	}

	// ASCII range. (Why someone would use HTML entities for ASCII characters I don't know, but...)
	if (code < 128) {
		return code;
	}

	// code points 128-159 are dealt with leniently by browsers, but they're incorrect. We need
	// to correct the mistake or we'll end up with missing € signs and so on
	if (code <= 159) {
		return windows_1252[code - 128];
	}

	// basic multilingual plane
	if (code < 55296) {
		return code;
	}

	// UTF-16 surrogate halves
	if (code <= 57343) {
		return NUL;
	}

	// rest of the basic multilingual plane
	if (code <= 65535) {
		return code;
	}

	// supplementary multilingual plane 0x10000 - 0x1ffff
	if (code >= 65536 && code <= 131071) {
		return code;
	}

	// supplementary ideographic plane 0x20000 - 0x2ffff
	if (code >= 131072 && code <= 196607) {
		return code;
	}

	// supplementary special-purpose plane 0xe0000 - 0xe07f and 0xe0100 - 0xe01ef
	if ((code >= 917504 && code <= 917631) || (code >= 917760 && code <= 917999)) {
		return code;
	}

	return NUL;
}

/** @import { AST } from '#compiler' */

/**
 * @param {any} transparent
 * @returns {AST.Fragment}
 */
function create_fragment(transparent = false) {
	return {
		type: 'Fragment',
		nodes: [],
		metadata: {
			transparent,
			dynamic: false
		}
	};
}

/** @import { Expression, PrivateIdentifier } from 'estree' */
/** @import { AST, Binding } from '#compiler' */

/**
 * All nodes that can appear elsewhere than the top level, have attributes and can contain children
 */
const element_nodes = [
	'SvelteElement',
	'RegularElement',
	'SvelteFragment',
	'Component',
	'SvelteComponent',
	'SvelteSelf',
	'SlotElement'
];

/**
 * Returns true for all nodes that can appear elsewhere than the top level, have attributes and can contain children
 * @param {AST.SvelteNode} node
 * @returns {node is AST.Component | AST.RegularElement | AST.SlotElement | AST.SvelteComponent | AST.SvelteElement | AST.SvelteFragment | AST.SvelteSelf}
 */
function is_element_node(node) {
	return element_nodes.includes(node.type);
}

/**
 * Returns true for all component-like nodes
 * @param {AST.SvelteNode} node
 * @returns {node is AST.Component |  AST.SvelteComponent | AST.SvelteSelf}
 */
function is_component_node(node) {
	return ['Component', 'SvelteComponent', 'SvelteSelf'].includes(node.type);
}

/**
 * @param {AST.RegularElement | AST.SvelteElement} node
 * @returns {boolean}
 */
function is_custom_element_node(node) {
	return (
		node.type === 'RegularElement' &&
		(node.name.includes('-') ||
			node.attributes.some((attr) => attr.type === 'Attribute' && attr.name === 'is'))
	);
}

/**
 * @param {string} name
 * @param {number} start
 * @param {number} end
 * @param {AST.Attribute['value']} value
 * @returns {AST.Attribute}
 */
function create_attribute(name, start, end, value) {
	return {
		type: 'Attribute',
		start,
		end,
		name,
		value,
		metadata: {
			delegated: false,
			needs_clsx: false
		}
	};
}
class ExpressionMetadata {
	/** True if the expression references state directly, or _might_ (via member/call expressions) */
	has_state = false;

	/** True if the expression involves a call expression (often, it will need to be wrapped in a derived) */
	has_call = false;

	/** True if the expression contains `await` */
	has_await = false;

	/** True if the expression includes a member expression */
	has_member_expression = false;

	/** True if the expression includes an assignment or an update */
	has_assignment = false;

	/**
	 * All the bindings that are referenced eagerly (not inside functions) in this expression
	 * @type {Set<Binding>}
	 */
	dependencies = new Set();

	/**
	 * True if the expression references state directly, or _might_ (via member/call expressions)
	 * @type {Set<Binding>}
	 */
	references = new Set();

	/** @type {null | Set<Expression>} */
	#blockers = null;

	#get_blockers() {
		if (!this.#blockers) {
			this.#blockers = new Set();

			for (const d of this.dependencies) {
				if (d.blocker) this.#blockers.add(d.blocker);
			}
		}

		return this.#blockers;
	}

	blockers() {
		return array([...this.#get_blockers()]);
	}

	has_blockers() {
		return this.#get_blockers().size > 0;
	}

	is_async() {
		return this.has_await || this.#get_blockers().size > 0;
	}

	/**
	 * @param {ExpressionMetadata} source
	 */
	merge(source) {
		this.has_state ||= source.has_state;
		this.has_call ||= source.has_call;
		this.has_await ||= source.has_await;
		this.has_member_expression ||= source.has_member_expression;
		this.has_assignment ||= source.has_assignment;
		this.#blockers = null; // so that blockers are recalculated

		for (const r of source.references) this.references.add(r);
		for (const b of source.dependencies) this.dependencies.add(b);
	}
}

/**
 * @param {Expression | PrivateIdentifier} node
 */
function get_name(node) {
	if (node.type === 'Literal') return String(node.value);
	if (node.type === 'PrivateIdentifier') return '#' + node.name;
	if (node.type === 'Identifier') return node.name;

	return null;
}

/**
 * @param {string[]} strings
 * @param {string} conjunction
 */
function list$1(strings, conjunction = 'or') {
	if (strings.length === 1) return strings[0];
	if (strings.length === 2) return `${strings[0]} ${conjunction} ${strings[1]}`;
	return `${strings.slice(0, -1).join(', ')} ${conjunction} ${strings[strings.length - 1]}`;
}

/** @import { Expression } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { Parser } from '../index.js' */

const regex_invalid_unquoted_attribute_value = /^(\/>|[\s"'=<>`])/;
const regex_closing_textarea_tag = /^<\/textarea(\s[^>]*)?>/i;
const regex_closing_comment = /-->/;
const regex_whitespace_or_slash_or_closing_tag = /(\s|\/|>)/;
const regex_token_ending_character = /[\s=/>"']/;
const regex_starts_with_quote_characters = /^["']/;
const regex_attribute_value = /^(?:"([^"]*)"|'([^'])*'|([^>\s]+))/;
const regex_valid_element_name =
	/^(?:![a-zA-Z]+|[a-zA-Z](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?|[a-zA-Z][a-zA-Z0-9]*:[a-zA-Z][a-zA-Z0-9-]*[a-zA-Z0-9])$/;
const regex_valid_component_name =
	// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#identifiers adjusted for our needs
	// (must start with uppercase letter if no dots, can contain dots)
	/^(?:\p{Lu}[$\u200c\u200d\p{ID_Continue}.]*|\p{ID_Start}[$\u200c\u200d\p{ID_Continue}]*(?:\.[$\u200c\u200d\p{ID_Continue}]+)+)$/u;

/** @type {Map<string, AST.ElementLike['type']>} */
const root_only_meta_tags = new Map([
	['svelte:head', 'SvelteHead'],
	['svelte:options', 'SvelteOptions'],
	['svelte:window', 'SvelteWindow'],
	['svelte:document', 'SvelteDocument'],
	['svelte:body', 'SvelteBody']
]);

/** @type {Map<string, AST.ElementLike['type']>} */
const meta_tags = new Map([
	...root_only_meta_tags,
	['svelte:element', 'SvelteElement'],
	['svelte:component', 'SvelteComponent'],
	['svelte:self', 'SvelteSelf'],
	['svelte:fragment', 'SvelteFragment'],
	['svelte:boundary', 'SvelteBoundary']
]);

/** @param {Parser} parser */
function element(parser) {
	const start = parser.index++;

	let parent = parser.current();

	if (parser.eat('!--')) {
		const data = parser.read_until(regex_closing_comment);
		parser.eat('-->', true);

		parser.append({
			type: 'Comment',
			start,
			end: parser.index,
			data
		});

		return;
	}

	const is_closing_tag = parser.eat('/');
	const name = parser.read_until(regex_whitespace_or_slash_or_closing_tag);

	if (is_closing_tag) {
		parser.allow_whitespace();
		parser.eat('>', true);

		if (is_void(name)) {
			void_element_invalid_content(start);
		}

		// close any elements that don't have their own closing tags, e.g. <div><p></div>
		while (/** @type {AST.RegularElement} */ (parent).name !== name) {
			if (parser.loose) {
				// If the previous element did interpret the next opening tag as an attribute, backtrack
				if (is_element_node(parent)) {
					const last = parent.attributes.at(-1);
					if (last?.type === 'Attribute' && last.name === `<${name}`) {
						parser.index = last.start;
						parent.attributes.pop();
						break;
					}
				}
			}

			if (parent.type === 'RegularElement') {
				if (!parser.last_auto_closed_tag || parser.last_auto_closed_tag.tag !== name) {
					const end = parent.fragment.nodes[0]?.start ?? start;
					element_implicitly_closed(
						{ start: parent.start, end },
						`</${name}>`,
						`</${parent.name}>`
					);
				}
			} else if (!parser.loose) {
				if (parser.last_auto_closed_tag && parser.last_auto_closed_tag.tag === name) {
					element_invalid_closing_tag_autoclosed(start, name, parser.last_auto_closed_tag.reason);
				} else {
					element_invalid_closing_tag(start, name);
				}
			}

			parent.end = start;
			parser.pop();

			parent = parser.current();
		}

		parent.end = parser.index;
		parser.pop();

		if (parser.last_auto_closed_tag && parser.stack.length < parser.last_auto_closed_tag.depth) {
			parser.last_auto_closed_tag = undefined;
		}

		return;
	}

	if (name.startsWith('svelte:') && !meta_tags.has(name)) {
		const bounds = { start: start + 1, end: start + 1 + name.length };
		svelte_meta_invalid_tag(bounds, list$1(Array.from(meta_tags.keys())));
	}

	if (!regex_valid_element_name.test(name) && !regex_valid_component_name.test(name)) {
		// <div. -> in the middle of typing -> allow in loose mode
		if (!parser.loose || !name.endsWith('.')) {
			const bounds = { start: start + 1, end: start + 1 + name.length };
			tag_invalid_name(bounds);
		}
	}

	if (root_only_meta_tags.has(name)) {
		if (name in parser.meta_tags) {
			svelte_meta_duplicate(start, name);
		}

		if (parent.type !== 'Root') {
			svelte_meta_invalid_placement(start, name);
		}

		parser.meta_tags[name] = true;
	}

	const type = meta_tags.has(name)
		? meta_tags.get(name)
		: regex_valid_component_name.test(name) || (parser.loose && name.endsWith('.'))
			? 'Component'
			: name === 'title' && parent_is_head(parser.stack)
				? 'TitleElement'
				: // TODO Svelte 6/7: once slots are removed in favor of snippets, always keep slot as a regular element
					name === 'slot' && !parent_is_shadowroot_template(parser.stack)
					? 'SlotElement'
					: 'RegularElement';

	/** @type {AST.ElementLike} */
	const element =
		type === 'RegularElement'
			? {
					type,
					start,
					end: -1,
					name,
					attributes: [],
					fragment: create_fragment(true),
					metadata: {
						svg: false,
						mathml: false,
						scoped: false,
						has_spread: false,
						path: [],
						synthetic_value_node: null
					}
				}
			: /** @type {AST.ElementLike} */ ({
					type,
					start,
					end: -1,
					name,
					attributes: [],
					fragment: create_fragment(true),
					metadata: {
						// unpopulated at first, differs between types
					}
				});

	parser.allow_whitespace();

	if (parent.type === 'RegularElement' && closing_tag_omitted(parent.name, name)) {
		const end = parent.fragment.nodes[0]?.start ?? start;
		element_implicitly_closed({ start: parent.start, end }, `<${name}>`, `</${parent.name}>`);
		parent.end = start;
		parser.pop();
		parser.last_auto_closed_tag = {
			tag: parent.name,
			reason: name,
			depth: parser.stack.length
		};
	}

	/** @type {string[]} */
	const unique_names = [];

	const current = parser.current();
	const is_top_level_script_or_style =
		(name === 'script' || name === 'style') && current.type === 'Root';

	const read = is_top_level_script_or_style ? read_static_attribute : read_attribute;

	let attribute;
	while ((attribute = read(parser))) {
		// animate and transition can only be specified once per element so no need
		// to check here, use can be used multiple times, same for the on directive
		// finally let already has error handling in case of duplicate variable names
		if (
			attribute.type === 'Attribute' ||
			attribute.type === 'BindDirective' ||
			attribute.type === 'StyleDirective' ||
			attribute.type === 'ClassDirective'
		) {
			// `bind:attribute` and `attribute` are just the same but `class:attribute`,
			// `style:attribute` and `attribute` are different and should be allowed together
			// so we concatenate the type while normalizing the type for BindDirective
			const type = attribute.type === 'BindDirective' ? 'Attribute' : attribute.type;
			if (unique_names.includes(type + attribute.name)) {
				attribute_duplicate(attribute);
				// <svelte:element bind:this this=..> is allowed
			} else if (attribute.name !== 'this') {
				unique_names.push(type + attribute.name);
			}
		}

		element.attributes.push(attribute);
		parser.allow_whitespace();
	}

	if (element.type === 'Component') {
		element.metadata.expression = new ExpressionMetadata();
	}

	if (element.type === 'SvelteComponent') {
		const index = element.attributes.findIndex(
			/** @param {any} attr */
			(attr) => attr.type === 'Attribute' && attr.name === 'this'
		);
		if (index === -1) {
			svelte_component_missing_this(start);
		}

		const definition = /** @type {AST.Attribute} */ (element.attributes.splice(index, 1)[0]);
		if (!is_expression_attribute(definition)) {
			svelte_component_invalid_this(definition.start);
		}

		element.expression = get_attribute_expression(definition);
		element.metadata.expression = new ExpressionMetadata();
	}

	if (element.type === 'SvelteElement') {
		const index = element.attributes.findIndex(
			/** @param {any} attr */
			(attr) => attr.type === 'Attribute' && attr.name === 'this'
		);
		if (index === -1) {
			svelte_element_missing_this(start);
		}

		const definition = /** @type {AST.Attribute} */ (element.attributes.splice(index, 1)[0]);

		if (definition.value === true) {
			svelte_element_missing_this(definition);
		}

		if (!is_expression_attribute(definition)) {
			svelte_element_invalid_this(definition);

			// note that this is wrong, in the case of e.g. `this="h{n}"` — it will result in `<h>`.
			// it would be much better to just error here, but we are preserving the existing buggy
			// Svelte 4 behaviour out of an overabundance of caution regarding breaking changes.
			// TODO in 6.0, error
			const chunk = /** @type {Array<AST.ExpressionTag | AST.Text>} */ (definition.value)[0];
			element.tag =
				chunk.type === 'Text'
					? {
							type: 'Literal',
							value: chunk.data,
							raw: `'${chunk.raw}'`,
							start: chunk.start,
							end: chunk.end
						}
					: chunk.expression;
		} else {
			element.tag = get_attribute_expression(definition);
		}

		element.metadata.expression = new ExpressionMetadata();
	}

	if (is_top_level_script_or_style) {
		parser.eat('>', true);

		/** @type {AST.Comment | null} */
		let prev_comment = null;
		for (let i = current.fragment.nodes.length - 1; i >= 0; i--) {
			const node = current.fragment.nodes[i];

			if (i === current.fragment.nodes.length - 1 && node.end !== start) {
				break;
			}

			if (node.type === 'Comment') {
				prev_comment = node;
				break;
			} else if (node.type !== 'Text' || node.data.trim()) {
				break;
			}
		}

		if (name === 'script') {
			const content = read_script(parser, start, element.attributes);
			if (prev_comment) {
				// We take advantage of the fact that the root will never have leadingComments set,
				// and set the previous comment to it so that the warning mechanism can later
				// inspect the root and see if there was a html comment before it silencing specific warnings.
				content.content.leadingComments = [{ type: 'Line', value: prev_comment.data }];
			}

			if (content.context === 'module') {
				if (current.module) script_duplicate(start);
				current.module = content;
			} else {
				if (current.instance) script_duplicate(start);
				current.instance = content;
			}
		} else {
			const content = read_style(parser, start, element.attributes);
			content.content.comment = prev_comment;

			if (current.css) style_duplicate(start);
			current.css = content;
		}
		return;
	}

	parser.append(element);

	const self_closing = parser.eat('/') || is_void(name);
	const closed = parser.eat('>', true, false);

	// Loose parsing mode
	if (!closed) {
		// We may have eaten an opening `<` of the next element and treated it as an attribute...
		const last = element.attributes.at(-1);
		if (last?.type === 'Attribute' && last.name === '<') {
			parser.index = last.start;
			element.attributes.pop();
		} else {
			// ... or we may have eaten part of a following block ...
			const prev_1 = parser.template[parser.index - 1];
			const prev_2 = parser.template[parser.index - 2];
			const current = parser.template[parser.index];
			if (prev_2 === '{' && prev_1 === '/') {
				parser.index -= 2;
			} else if (prev_1 === '{' && (current === '#' || current === '@' || current === ':')) {
				parser.index -= 1;
			} else {
				// ... or we're followed by whitespace, for example near the end of the template,
				// which we want to take in so that language tools has more room to work with
				parser.allow_whitespace();
			}
		}
	}

	if (self_closing || !closed) {
		// don't push self-closing elements onto the stack
		element.end = parser.index;
	} else if (name === 'textarea') {
		// special case
		element.fragment.nodes = read_sequence(
			parser,
			() => regex_closing_textarea_tag.test(parser.template.slice(parser.index)),
			'inside <textarea>'
		);
		parser.read(regex_closing_textarea_tag);
		element.end = parser.index;
	} else if (name === 'script' || name === 'style') {
		// special case
		const start = parser.index;
		const data = parser.read_until(new RegExp(`</${name}>`));
		const end = parser.index;

		/** @type {AST.Text} */
		const node = {
			start,
			end,
			type: 'Text',
			data,
			raw: data
		};

		element.fragment.nodes.push(node);
		parser.eat(`</${name}>`, true);
		element.end = parser.index;
	} else {
		parser.stack.push(element);
		parser.fragments.push(element.fragment);
	}
}

/** @param {AST.TemplateNode[]} stack */
function parent_is_head(stack) {
	let i = stack.length;
	while (i--) {
		const { type } = stack[i];
		if (type === 'SvelteHead') return true;
		if (type === 'RegularElement' || type === 'Component') return false;
	}
	return false;
}

/** @param {AST.TemplateNode[]} stack */
function parent_is_shadowroot_template(stack) {
	// https://developer.chrome.com/docs/css-ui/declarative-shadow-dom#building_a_declarative_shadow_root
	let i = stack.length;
	while (i--) {
		if (
			stack[i].type === 'RegularElement' &&
			/** @type {AST.RegularElement} */ (stack[i]).attributes.some(
				(a) => a.type === 'Attribute' && a.name === 'shadowrootmode'
			)
		) {
			return true;
		}
	}
	return false;
}

/**
 * @param {Parser} parser
 * @returns {AST.Attribute | null}
 */
function read_static_attribute(parser) {
	const start = parser.index;

	const name = parser.read_until(regex_token_ending_character);
	if (!name) return null;

	/** @type {true | Array<AST.Text | AST.ExpressionTag>} */
	let value = true;

	if (parser.eat('=')) {
		parser.allow_whitespace();
		let raw = parser.match_regex(regex_attribute_value);
		if (!raw) {
			expected_attribute_value(parser.index);
		}

		parser.index += raw.length;

		const quoted = raw[0] === '"' || raw[0] === "'";
		if (quoted) {
			raw = raw.slice(1, -1);
		}

		value = [
			{
				start: parser.index - raw.length - (quoted ? 1 : 0),
				end: quoted ? parser.index - 1 : parser.index,
				type: 'Text',
				raw: raw,
				data: decode_character_references(raw, true)
			}
		];
	}

	if (parser.match_regex(regex_starts_with_quote_characters)) {
		expected_token(parser.index, '=');
	}

	return create_attribute(name, start, parser.index, value);
}

/**
 * @param {Parser} parser
 * @returns {AST.Attribute | AST.SpreadAttribute | AST.Directive | AST.AttachTag | null}
 */
function read_attribute(parser) {
	const start = parser.index;

	if (parser.eat('{')) {
		parser.allow_whitespace();

		if (parser.eat('@attach')) {
			parser.require_whitespace();

			const expression = read_expression(parser);
			parser.allow_whitespace();
			parser.eat('}', true);

			/** @type {AST.AttachTag} */
			const attachment = {
				type: 'AttachTag',
				start,
				end: parser.index,
				expression,
				metadata: {
					expression: new ExpressionMetadata()
				}
			};

			return attachment;
		}

		if (parser.eat('...')) {
			const expression = read_expression(parser);

			parser.allow_whitespace();
			parser.eat('}', true);

			/** @type {AST.SpreadAttribute} */
			const spread = {
				type: 'SpreadAttribute',
				start,
				end: parser.index,
				expression,
				metadata: {
					expression: new ExpressionMetadata()
				}
			};

			return spread;
		} else {
			const value_start = parser.index;
			let name = parser.read_identifier();

			if (name === null) {
				if (
					parser.loose &&
					(parser.match('#') || parser.match('/') || parser.match('@') || parser.match(':'))
				) {
					// We're likely in an unclosed opening tag and did read part of a block.
					// Return null to not crash the parser so it can continue with closing the tag.
					return null;
				} else if (parser.loose && parser.match('}')) {
					// Likely in the middle of typing, just created the shorthand
					name = '';
				} else {
					attribute_empty_shorthand(start);
				}
			}

			parser.allow_whitespace();
			parser.eat('}', true);

			/** @type {AST.ExpressionTag} */
			const expression = {
				type: 'ExpressionTag',
				start: value_start,
				end: value_start + name.length,
				expression: {
					start: value_start,
					end: value_start + name.length,
					type: 'Identifier',
					name
				},
				metadata: {
					expression: new ExpressionMetadata()
				}
			};

			return create_attribute(name, start, parser.index, expression);
		}
	}

	const name = parser.read_until(regex_token_ending_character);
	if (!name) return null;

	let end = parser.index;

	parser.allow_whitespace();

	const colon_index = name.indexOf(':');
	const type = colon_index !== -1 && get_directive_type(name.slice(0, colon_index));

	/** @type {true | AST.ExpressionTag | Array<AST.Text | AST.ExpressionTag>} */
	let value = true;
	if (parser.eat('=')) {
		parser.allow_whitespace();

		if (parser.template[parser.index] === '/' && parser.template[parser.index + 1] === '>') {
			const char_start = parser.index;
			parser.index++; // consume '/'
			value = [
				{
					start: char_start,
					end: char_start + 1,
					type: 'Text',
					raw: '/',
					data: '/'
				}
			];
			end = parser.index;
		} else {
			value = read_attribute_value(parser);
			end = parser.index;
		}
	} else if (parser.match_regex(regex_starts_with_quote_characters)) {
		expected_token(parser.index, '=');
	}

	if (type) {
		const [directive_name, ...modifiers] = name.slice(colon_index + 1).split('|');

		if (directive_name === '') {
			directive_missing_name({ start, end: start + colon_index + 1 }, name);
		}

		if (type === 'StyleDirective') {
			return {
				start,
				end,
				type,
				name: directive_name,
				modifiers: /** @type {Array<'important'>} */ (modifiers),
				value,
				metadata: {
					expression: new ExpressionMetadata()
				}
			};
		}

		const first_value = value === true ? undefined : Array.isArray(value) ? value[0] : value;

		/** @type {Expression | null} */
		let expression = null;

		if (first_value) {
			const attribute_contains_text =
				/** @type {any[]} */ (value).length > 1 || first_value.type === 'Text';
			if (attribute_contains_text) {
				directive_invalid_value(/** @type {number} */ (first_value.start));
			} else {
				// TODO throw a parser error in a future version here if this `[ExpressionTag]` instead of `ExpressionTag`,
				// which means stringified value, which isn't allowed for some directives?
				expression = first_value.expression;
			}
		}

		const directive = /** @type {AST.Directive} */ ({
			start,
			end,
			type,
			name: directive_name,
			expression,
			metadata: {
				expression: new ExpressionMetadata()
			}
		});

		// @ts-expect-error we do this separately from the declaration to avoid upsetting typescript
		directive.modifiers = modifiers;

		if (directive.type === 'TransitionDirective') {
			const direction = name.slice(0, colon_index);
			directive.intro = direction === 'in' || direction === 'transition';
			directive.outro = direction === 'out' || direction === 'transition';
		}

		// Directive name is expression, e.g. <p class:isRed />
		if (
			(directive.type === 'BindDirective' || directive.type === 'ClassDirective') &&
			!directive.expression
		) {
			directive.expression = /** @type {any} */ ({
				start: start + colon_index + 1,
				end,
				type: 'Identifier',
				name: directive.name
			});
		}

		return directive;
	}

	return create_attribute(name, start, end, value);
}

/**
 * @param {string} name
 * @returns {any}
 */
function get_directive_type(name) {
	if (name === 'use') return 'UseDirective';
	if (name === 'animate') return 'AnimateDirective';
	if (name === 'bind') return 'BindDirective';
	if (name === 'class') return 'ClassDirective';
	if (name === 'style') return 'StyleDirective';
	if (name === 'on') return 'OnDirective';
	if (name === 'let') return 'LetDirective';
	if (name === 'in' || name === 'out' || name === 'transition') return 'TransitionDirective';
	return false;
}

/**
 * @param {Parser} parser
 * @return {AST.ExpressionTag | Array<AST.ExpressionTag | AST.Text>}
 */
function read_attribute_value(parser) {
	const quote_mark = parser.eat("'") ? "'" : parser.eat('"') ? '"' : null;
	if (quote_mark && parser.eat(quote_mark)) {
		return [
			{
				start: parser.index - 1,
				end: parser.index - 1,
				type: 'Text',
				raw: '',
				data: ''
			}
		];
	}

	/** @type {Array<AST.ExpressionTag | AST.Text>} */
	let value;
	try {
		value = read_sequence(
			parser,
			() => {
				// handle common case of quote marks existing outside of regex for performance reasons
				if (quote_mark) return parser.match(quote_mark);
				return !!parser.match_regex(regex_invalid_unquoted_attribute_value);
			},
			'in attribute value'
		);
	} catch (/** @type {any} */ error) {
		if (error.code === 'js_parse_error') {
			// if the attribute value didn't close + self-closing tag
			// eg: `<Component test={{a:1} />`
			// acorn may throw a `Unterminated regular expression` because of `/>`
			const pos = error.position?.[0];
			if (pos !== undefined && parser.template.slice(pos - 1, pos + 1) === '/>') {
				parser.index = pos;
				expected_token(pos, quote_mark || '}');
			}
		}
		throw error;
	}

	if (value.length === 0 && !quote_mark) {
		expected_attribute_value(parser.index);
	}

	if (quote_mark) parser.index += 1;

	if (quote_mark || value.length > 1 || value[0].type === 'Text') {
		return value;
	} else {
		return value[0];
	}
}

/**
 * @param {Parser} parser
 * @param {() => boolean} done
 * @param {string} location
 * @returns {any[]}
 */
function read_sequence(parser, done, location) {
	/** @type {AST.Text} */
	let current_chunk = {
		start: parser.index,
		end: -1,
		type: 'Text',
		raw: '',
		data: ''
	};

	/** @type {Array<AST.Text | AST.ExpressionTag>} */
	const chunks = [];

	/** @param {number} end */
	function flush(end) {
		if (current_chunk.raw) {
			current_chunk.data = decode_character_references(current_chunk.raw, true);
			current_chunk.end = end;
			chunks.push(current_chunk);
		}
	}

	while (parser.index < parser.template.length) {
		const index = parser.index;

		if (done()) {
			flush(parser.index);
			return chunks;
		} else if (parser.eat('{')) {
			if (parser.match('#')) {
				const index = parser.index - 1;
				parser.eat('#');
				const name = parser.read_until(/[^a-z]/);
				block_invalid_placement(index, name, location);
			} else if (parser.match('@')) {
				const index = parser.index - 1;
				parser.eat('@');
				const name = parser.read_until(/[^a-z]/);
				tag_invalid_placement(index, name, location);
			}

			flush(parser.index - 1);

			parser.allow_whitespace();
			const expression = read_expression(parser);
			parser.allow_whitespace();
			parser.eat('}', true);

			/** @type {AST.ExpressionTag} */
			const chunk = {
				type: 'ExpressionTag',
				start: index,
				end: parser.index,
				expression,
				metadata: {
					expression: new ExpressionMetadata()
				}
			};

			chunks.push(chunk);

			current_chunk = {
				start: parser.index,
				end: -1,
				type: 'Text',
				raw: '',
				data: ''
			};
		} else {
			current_chunk.raw += parser.template[parser.index++];
		}
	}

	if (parser.loose) {
		return chunks;
	} else {
		unexpected_eof(parser.template.length);
	}
}

/** @import { Location } from 'locate-character' */
/** @import { Pattern } from 'estree' */
/** @import { Parser } from '../index.js' */

/**
 * @param {Parser} parser
 * @returns {Pattern}
 */
function read_pattern(parser) {
	const start = parser.index;
	let i = parser.index;

	const name = parser.read_identifier();

	if (name !== null) {
		const annotation = read_type_annotation(parser);

		return {
			type: 'Identifier',
			name,
			start,
			loc: {
				start: /** @type {Location} */ (locator(start)),
				end: /** @type {Location} */ (locator(parser.index))
			},
			end: parser.index,
			typeAnnotation: annotation
		};
	}

	const char = parser.template[i];

	if (char !== '{' && char !== '[') {
		expected_pattern(i);
	}

	i = match_bracket(parser, start);
	parser.index = i;

	const pattern_string = parser.template.slice(start, i);

	try {
		// the length of the `space_with_newline` has to be start - 1
		// because we added a `(` in front of the pattern_string,
		// which shifted the entire string to right by 1
		// so we offset it by removing 1 character in the `space_with_newline`
		// to achieve that, we remove the 1st space encountered,
		// so it will not affect the `column` of the node
		let space_with_newline = parser.template
			.slice(0, start)
			.replace(regex_not_newline_characters, ' ');
		const first_space = space_with_newline.indexOf(' ');
		space_with_newline =
			space_with_newline.slice(0, first_space) + space_with_newline.slice(first_space + 1);

		const expression = /** @type {any} */ (
			parse_expression_at(
				`${space_with_newline}(${pattern_string} = 1)`,
				parser.root.comments,
				parser.ts,
				start - 1
			)
		).left;

		expression.typeAnnotation = read_type_annotation(parser);
		if (expression.typeAnnotation) {
			expression.end = expression.typeAnnotation.end;
		}

		return expression;
	} catch (error) {
		parser.acorn_error(error);
	}
}

/**
 * @param {Parser} parser
 * @returns {any}
 */
function read_type_annotation(parser) {
	const start = parser.index;
	parser.allow_whitespace();

	if (!parser.eat(':')) {
		parser.index = start;
		return undefined;
	}

	// we need to trick Acorn into parsing the type annotation
	const insert = '_ as ';
	let a = parser.index - insert.length;
	const template =
		parser.template.slice(0, a).replace(/[^\n]/g, ' ') +
		insert +
		// If this is a type annotation for a function parameter, Acorn-TS will treat subsequent
		// parameters as part of a sequence expression instead, and will then error on optional
		// parameters (`?:`). Therefore replace that sequence with something that will not error.
		parser.template.slice(parser.index).replace(/\?\s*:/g, ':');
	let expression = parse_expression_at(template, parser.root.comments, parser.ts, a);

	// `foo: bar = baz` gets mangled — fix it
	if (expression.type === 'AssignmentExpression') {
		let b = expression.right.start;
		while (template[b] !== '=') b -= 1;
		expression = parse_expression_at(template.slice(0, b), parser.root.comments, parser.ts, a);
	}

	// `array as item: string, index` becomes `string, index`, which is mistaken as a sequence expression - fix that
	if (expression.type === 'SequenceExpression') {
		expression = expression.expressions[0];
	}

	parser.index = /** @type {number} */ (expression.end);
	return {
		type: 'TSTypeAnnotation',
		start,
		end: parser.index,
		typeAnnotation: /** @type {any} */ (expression).typeAnnotation
	};
}

/** @import { ArrowFunctionExpression, Expression, Identifier, Pattern } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { Parser } from '../index.js' */

const regex_whitespace_with_closing_curly_brace = /^\s*}/;

const pointy_bois = { '<': '>' };

/** @param {Parser} parser */
function tag(parser) {
	const start = parser.index;
	parser.index += 1;

	parser.allow_whitespace();

	if (parser.eat('#')) return open(parser);
	if (parser.eat(':')) return next(parser);
	if (parser.eat('@')) return special(parser);
	if (parser.match('/')) {
		if (!parser.match('/*') && !parser.match('//')) {
			parser.eat('/');
			return close(parser);
		}
	}

	const expression = read_expression(parser);

	parser.allow_whitespace();
	parser.eat('}', true);

	parser.append({
		type: 'ExpressionTag',
		start,
		end: parser.index,
		expression,
		metadata: {
			expression: new ExpressionMetadata()
		}
	});
}

/** @param {Parser} parser */
function open(parser) {
	let start = parser.index - 2;
	while (parser.template[start] !== '{') start -= 1;

	if (parser.eat('if')) {
		parser.require_whitespace();

		/** @type {AST.IfBlock} */
		const block = parser.append({
			type: 'IfBlock',
			elseif: false,
			start,
			end: -1,
			test: read_expression(parser),
			consequent: create_fragment(),
			alternate: null,
			metadata: {
				expression: new ExpressionMetadata()
			}
		});

		parser.allow_whitespace();
		parser.eat('}', true);

		parser.stack.push(block);
		parser.fragments.push(block.consequent);

		return;
	}

	if (parser.eat('each')) {
		parser.require_whitespace();

		const template = parser.template;
		let end = parser.template.length;

		/** @type {Expression | undefined} */
		let expression;

		// we have to do this loop because `{#each x as { y = z }}` fails to parse —
		// the `as { y = z }` is treated as an Expression but it's actually a Pattern.
		// the 'fix' is to backtrack and hide everything from the `as` onwards, until
		// we get a valid expression
		while (!expression) {
			try {
				expression = read_expression(parser, undefined, true);
			} catch (err) {
				end = /** @type {any} */ (err).position[0] - 2;

				while (end > start && parser.template.slice(end, end + 2) !== 'as') {
					end -= 1;
				}

				if (end <= start) {
					if (parser.loose) {
						expression = get_loose_identifier(parser);
						if (expression) {
							break;
						}
					}
					throw err;
				}

				// @ts-expect-error parser.template is meant to be readonly, this is a special case
				parser.template = template.slice(0, end);
			}
		}

		// @ts-expect-error
		parser.template = template;

		parser.allow_whitespace();

		// {#each} blocks must declare a context – {#each list as item}
		if (!parser.match('as')) {
			// this could be a TypeScript assertion that was erroneously eaten.

			if (expression.type === 'SequenceExpression') {
				expression = expression.expressions[0];
			}

			let assertion = null;
			let end = expression.end;

			expression = walk$1(expression, null, {
				// @ts-expect-error
				TSAsExpression(node, context) {
					if (node.end === /** @type {Expression} */ (expression).end) {
						assertion = node;
						end = node.expression.end;
						return node.expression;
					}

					context.next();
				}
			});

			expression.end = end;

			if (assertion) {
				// we can't reset `parser.index` to `expression.expression.end` because
				// it will ignore any parentheses — we need to jump through this hoop
				let end = /** @type {any} */ (/** @type {any} */ (assertion).typeAnnotation).start - 2;
				while (parser.template.slice(end, end + 2) !== 'as') end -= 1;

				parser.index = end;
			}
		}

		/** @type {Pattern | null} */
		let context = null;
		let index;
		let key;

		if (parser.eat('as')) {
			parser.require_whitespace();

			context = read_pattern(parser);
		} else {
			// {#each Array.from({ length: 10 }), i} is read as a sequence expression,
			// which is set back above - we now gotta reset the index as a consequence
			// to properly read the , i part
			parser.index = /** @type {number} */ (expression.end);
		}

		parser.allow_whitespace();

		if (parser.eat(',')) {
			parser.allow_whitespace();
			index = parser.read_identifier();
			if (!index) {
				expected_identifier(parser.index);
			}

			parser.allow_whitespace();
		}

		if (parser.eat('(')) {
			parser.allow_whitespace();

			key = read_expression(parser, '(');
			parser.allow_whitespace();
			parser.eat(')', true);
			parser.allow_whitespace();
		}

		const matches = parser.eat('}', true, false);

		if (!matches) {
			// Parser may have read the `as` as part of the expression (e.g. in `{#each foo. as x}`)
			if (parser.template.slice(parser.index - 4, parser.index) === ' as ') {
				const prev_index = parser.index;
				context = read_pattern(parser);
				parser.eat('}', true);
				expression = {
					type: 'Identifier',
					name: '',
					start: expression.start,
					end: prev_index - 4
				};
			} else {
				parser.eat('}', true); // rerun to produce the parser error
			}
		}

		/** @type {AST.EachBlock} */
		const block = parser.append({
			type: 'EachBlock',
			start,
			end: -1,
			expression,
			body: create_fragment(),
			context,
			index,
			key,
			metadata: /** @type {any} */ (null) // filled in later
		});

		parser.stack.push(block);
		parser.fragments.push(block.body);

		return;
	}

	if (parser.eat('await')) {
		parser.require_whitespace();
		const expression = read_expression(parser);
		parser.allow_whitespace();

		/** @type {AST.AwaitBlock} */
		const block = parser.append({
			type: 'AwaitBlock',
			start,
			end: -1,
			expression,
			value: null,
			error: null,
			pending: null,
			then: null,
			catch: null,
			metadata: {
				expression: new ExpressionMetadata()
			}
		});

		if (parser.eat('then')) {
			if (parser.match_regex(regex_whitespace_with_closing_curly_brace)) {
				parser.allow_whitespace();
			} else {
				parser.require_whitespace();
				block.value = read_pattern(parser);
				parser.allow_whitespace();
			}

			block.then = create_fragment();
			parser.fragments.push(block.then);
		} else if (parser.eat('catch')) {
			if (parser.match_regex(regex_whitespace_with_closing_curly_brace)) {
				parser.allow_whitespace();
			} else {
				parser.require_whitespace();
				block.error = read_pattern(parser);
				parser.allow_whitespace();
			}

			block.catch = create_fragment();
			parser.fragments.push(block.catch);
		} else {
			block.pending = create_fragment();
			parser.fragments.push(block.pending);
		}

		const matches = parser.eat('}', true, false);

		// Parser may have read the `then/catch` as part of the expression (e.g. in `{#await foo. then x}`)
		if (!matches) {
			if (parser.template.slice(parser.index - 6, parser.index) === ' then ') {
				const prev_index = parser.index;
				block.value = read_pattern(parser);
				parser.eat('}', true);
				block.expression = {
					type: 'Identifier',
					name: '',
					start: expression.start,
					end: prev_index - 6
				};
				block.then = block.pending;
				block.pending = null;
			} else if (parser.template.slice(parser.index - 7, parser.index) === ' catch ') {
				const prev_index = parser.index;
				block.error = read_pattern(parser);
				parser.eat('}', true);
				block.expression = {
					type: 'Identifier',
					name: '',
					start: expression.start,
					end: prev_index - 7
				};
				block.catch = block.pending;
				block.pending = null;
			} else {
				parser.eat('}', true); // rerun to produce the parser error
			}
		}

		parser.stack.push(block);

		return;
	}

	if (parser.eat('key')) {
		parser.require_whitespace();

		const expression = read_expression(parser);
		parser.allow_whitespace();

		parser.eat('}', true);

		/** @type {AST.KeyBlock} */
		const block = parser.append({
			type: 'KeyBlock',
			start,
			end: -1,
			expression,
			fragment: create_fragment(),
			metadata: {
				expression: new ExpressionMetadata()
			}
		});

		parser.stack.push(block);
		parser.fragments.push(block.fragment);

		return;
	}

	if (parser.eat('snippet')) {
		parser.require_whitespace();

		const name_start = parser.index;
		let name = parser.read_identifier();
		const name_end = parser.index;

		if (name === null) {
			if (parser.loose) {
				name = '';
			} else {
				expected_identifier(parser.index);
			}
		}

		parser.allow_whitespace();

		const params_start = parser.index;

		// snippets could have a generic signature, e.g. `#snippet foo<T>(...)`
		/** @type {string | undefined} */
		let type_params;

		// if we match a generic opening
		if (parser.ts && parser.match('<')) {
			const start = parser.index;
			const end = match_bracket(parser, start, pointy_bois);

			type_params = parser.template.slice(start + 1, end - 1);

			parser.index = end;
		}

		parser.allow_whitespace();

		const matched = parser.eat('(', true, false);

		if (matched) {
			let parentheses = 1;

			while (parser.index < parser.template.length && (!parser.match(')') || parentheses !== 1)) {
				if (parser.match('(')) parentheses++;
				if (parser.match(')')) parentheses--;
				parser.index += 1;
			}

			parser.eat(')', true);
		}

		const prelude = parser.template.slice(0, params_start).replace(/\S/g, ' ');
		const params = parser.template.slice(params_start, parser.index);

		let function_expression = matched
			? /** @type {ArrowFunctionExpression} */ (
					parse_expression_at(
						prelude + `${params} => {}`,
						parser.root.comments,
						parser.ts,
						params_start
					)
				)
			: { params: [] };

		parser.allow_whitespace();
		parser.eat('}', true);

		/** @type {AST.SnippetBlock} */
		const block = parser.append({
			type: 'SnippetBlock',
			start,
			end: -1,
			expression: {
				type: 'Identifier',
				start: name_start,
				end: name_end,
				name
			},
			typeParams: type_params,
			parameters: function_expression.params,
			body: create_fragment(),
			metadata: {
				can_hoist: false,
				sites: new Set()
			}
		});
		parser.stack.push(block);
		parser.fragments.push(block.body);

		return;
	}

	expected_block_type(parser.index);
}

/** @param {Parser} parser */
function next(parser) {
	const start = parser.index - 1;

	const block = parser.current(); // TODO type should not be TemplateNode, that's much too broad

	if (block.type === 'IfBlock') {
		if (!parser.eat('else')) expected_token(start, '{:else} or {:else if}');
		if (parser.eat('if')) block_invalid_elseif(start);

		parser.allow_whitespace();

		parser.fragments.pop();

		block.alternate = create_fragment();
		parser.fragments.push(block.alternate);

		// :else if
		if (parser.eat('if')) {
			parser.require_whitespace();

			const expression = read_expression(parser);

			parser.allow_whitespace();
			parser.eat('}', true);

			let elseif_start = start - 1;
			while (parser.template[elseif_start] !== '{') elseif_start -= 1;

			/** @type {AST.IfBlock} */
			const child = parser.append({
				start: elseif_start,
				end: -1,
				type: 'IfBlock',
				elseif: true,
				test: expression,
				consequent: create_fragment(),
				alternate: null,
				metadata: {
					expression: new ExpressionMetadata()
				}
			});

			parser.stack.push(child);
			parser.fragments.pop();
			parser.fragments.push(child.consequent);
		} else {
			// :else
			parser.allow_whitespace();
			parser.eat('}', true);
		}

		return;
	}

	if (block.type === 'EachBlock') {
		if (!parser.eat('else')) expected_token(start, '{:else}');

		parser.allow_whitespace();
		parser.eat('}', true);

		block.fallback = create_fragment();

		parser.fragments.pop();
		parser.fragments.push(block.fallback);

		return;
	}

	if (block.type === 'AwaitBlock') {
		if (parser.eat('then')) {
			if (block.then) {
				block_duplicate_clause(start, '{:then}');
			}

			if (!parser.eat('}')) {
				parser.require_whitespace();
				block.value = read_pattern(parser);
				parser.allow_whitespace();
				parser.eat('}', true);
			}

			block.then = create_fragment();
			parser.fragments.pop();
			parser.fragments.push(block.then);

			return;
		}

		if (parser.eat('catch')) {
			if (block.catch) {
				block_duplicate_clause(start, '{:catch}');
			}

			if (!parser.eat('}')) {
				parser.require_whitespace();
				block.error = read_pattern(parser);
				parser.allow_whitespace();
				parser.eat('}', true);
			}

			block.catch = create_fragment();
			parser.fragments.pop();
			parser.fragments.push(block.catch);

			return;
		}

		expected_token(start, '{:then ...} or {:catch ...}');
	}

	block_invalid_continuation_placement(start);
}

/** @param {Parser} parser */
function close(parser) {
	const start = parser.index - 1;

	let block = parser.current();
	/** Only relevant/reached for loose parsing mode */
	let matched;

	switch (block.type) {
		case 'IfBlock':
			matched = parser.eat('if', true, false);

			if (!matched) {
				block.end = start - 1;
				parser.pop();
				close(parser);
				return;
			}

			parser.allow_whitespace();
			parser.eat('}', true);

			while (block.elseif) {
				block.end = parser.index;
				parser.stack.pop();
				block = /** @type {AST.IfBlock} */ (parser.current());
			}

			block.end = parser.index;
			parser.pop();
			return;

		case 'EachBlock':
			matched = parser.eat('each', true, false);
			break;
		case 'KeyBlock':
			matched = parser.eat('key', true, false);
			break;
		case 'AwaitBlock':
			matched = parser.eat('await', true, false);
			break;
		case 'SnippetBlock':
			matched = parser.eat('snippet', true, false);
			break;

		case 'RegularElement':
			if (parser.loose) {
				matched = false;
			} else {
				// TODO handle implicitly closed elements
				block_unexpected_close(start);
			}
			break;

		default:
			block_unexpected_close(start);
	}

	if (!matched) {
		block.end = start - 1;
		parser.pop();
		close(parser);
		return;
	}

	parser.allow_whitespace();
	parser.eat('}', true);
	block.end = parser.index;
	parser.pop();
}

/** @param {Parser} parser */
function special(parser) {
	let start = parser.index;
	while (parser.template[start] !== '{') start -= 1;

	if (parser.eat('html')) {
		// {@html content} tag
		parser.require_whitespace();

		const expression = read_expression(parser);

		parser.allow_whitespace();
		parser.eat('}', true);

		parser.append({
			type: 'HtmlTag',
			start,
			end: parser.index,
			expression,
			metadata: {
				expression: new ExpressionMetadata()
			}
		});

		return;
	}

	if (parser.eat('debug')) {
		/** @type {Identifier[]} */
		let identifiers;

		// Implies {@debug} which indicates "debug all"
		if (parser.read(regex_whitespace_with_closing_curly_brace)) {
			identifiers = [];
		} else {
			const expression = read_expression(parser);

			identifiers =
				expression.type === 'SequenceExpression'
					? /** @type {Identifier[]} */ (expression.expressions)
					: [/** @type {Identifier} */ (expression)];

			identifiers.forEach(
				/** @param {any} node */ (node) => {
					if (node.type !== 'Identifier') {
						debug_tag_invalid_arguments(/** @type {number} */ (node.start));
					}
				}
			);

			parser.allow_whitespace();
			parser.eat('}', true);
		}

		parser.append({
			type: 'DebugTag',
			start,
			end: parser.index,
			identifiers
		});

		return;
	}

	if (parser.eat('const')) {
		parser.require_whitespace();

		const id = read_pattern(parser);
		parser.allow_whitespace();

		parser.eat('=', true);
		parser.allow_whitespace();

		const expression_start = parser.index;
		const init = read_expression(parser);
		if (
			init.type === 'SequenceExpression' &&
			!parser.template.substring(expression_start, init.start).includes('(')
		) {
			// const a = (b, c) is allowed but a = b, c = d is not;
			const_tag_invalid_expression(init);
		}
		parser.allow_whitespace();

		parser.eat('}', true);

		parser.append({
			type: 'ConstTag',
			start,
			end: parser.index,
			declaration: {
				type: 'VariableDeclaration',
				kind: 'const',
				declarations: [{ type: 'VariableDeclarator', id, init, start: id.start, end: init.end }],
				start: start + 2, // start at const, not at @const
				end: parser.index - 1
			},
			metadata: {
				expression: new ExpressionMetadata()
			}
		});
	}

	if (parser.eat('render')) {
		// {@render foo(...)}
		parser.require_whitespace();

		const expression = read_expression(parser);

		if (
			expression.type !== 'CallExpression' &&
			(expression.type !== 'ChainExpression' || expression.expression.type !== 'CallExpression')
		) {
			render_tag_invalid_expression(expression);
		}

		parser.allow_whitespace();
		parser.eat('}', true);

		parser.append({
			type: 'RenderTag',
			start,
			end: parser.index,
			expression: /** @type {AST.RenderTag['expression']} */ (expression),
			metadata: {
				expression: new ExpressionMetadata(),
				dynamic: false,
				arguments: [],
				path: [],
				snippets: new Set()
			}
		});
	}
}

/** @import { AST } from '#compiler' */
/** @import { Parser } from '../index.js' */

/** @param {Parser} parser */
function text(parser) {
	const start = parser.index;

	let data = '';

	while (parser.index < parser.template.length && !parser.match('<') && !parser.match('{')) {
		data += parser.template[parser.index++];
	}

	/** @type {AST.Text} */
	parser.append({
		type: 'Text',
		start,
		end: parser.index,
		raw: data,
		data: decode_character_references(data, false)
	});
}

/** @import { Parser } from '../index.js' */

/** @param {Parser} parser */
function fragment(parser) {
	if (parser.match('<')) {
		return element;
	}

	if (parser.match('{')) {
		return tag;
	}

	return text;
}

/** @import { ObjectExpression } from 'estree' */
/** @import { AST } from '#compiler' */

/**
 * @param {AST.SvelteOptionsRaw} node
 * @returns {AST.Root['options']}
 */
function read_options(node) {
	/** @type {AST.SvelteOptions} */
	const component_options = {
		start: node.start,
		end: node.end,
		// @ts-ignore
		attributes: node.attributes
	};

	if (!node) {
		return component_options;
	}

	for (const attribute of node.attributes) {
		if (attribute.type !== 'Attribute') {
			svelte_options_invalid_attribute(attribute);
		}

		const { name } = attribute;

		switch (name) {
			case 'runes': {
				component_options.runes = get_boolean_value(attribute);
				break;
			}
			case 'tag': {
				svelte_options_deprecated_tag(attribute);
				break; // eslint doesn't know this is unnecessary
			}
			case 'customElement': {
				/** @type {AST.SvelteOptions['customElement']} */
				const ce = {};
				const { value: v } = attribute;
				const value = v === true || Array.isArray(v) ? v : [v];

				if (value === true) {
					svelte_options_invalid_customelement(attribute);
				} else if (value[0].type === 'Text') {
					const tag = get_static_value$1(attribute);
					validate_tag(attribute, tag);
					ce.tag = tag;
					component_options.customElement = ce;
					break;
				} else if (value[0].expression.type !== 'ObjectExpression') {
					// Before Svelte 4 it was necessary to explicitly set customElement to null or else you'd get a warning.
					// This is no longer necessary, but for backwards compat just skip in this case now.
					if (value[0].expression.type === 'Literal' && value[0].expression.value === null) {
						break;
					}
					svelte_options_invalid_customelement(attribute);
				}

				/** @type {Array<[string, any]>} */
				const properties = [];
				for (const property of value[0].expression.properties) {
					if (
						property.type !== 'Property' ||
						property.computed ||
						property.key.type !== 'Identifier'
					) {
						svelte_options_invalid_customelement(attribute);
					}
					properties.push([property.key.name, property.value]);
				}

				const tag = properties.find(([name]) => name === 'tag');
				if (tag) {
					const tag_value = tag[1]?.value;
					validate_tag(tag, tag_value);
					ce.tag = tag_value;
				}

				const props = properties.find(([name]) => name === 'props')?.[1];
				if (props) {
					if (props.type !== 'ObjectExpression') {
						svelte_options_invalid_customelement_props(attribute);
					}
					ce.props = {};
					for (const property of /** @type {ObjectExpression} */ (props).properties) {
						if (
							property.type !== 'Property' ||
							property.computed ||
							property.key.type !== 'Identifier' ||
							property.value.type !== 'ObjectExpression'
						) {
							svelte_options_invalid_customelement_props(attribute);
						}
						ce.props[property.key.name] = {};
						for (const prop of property.value.properties) {
							if (
								prop.type !== 'Property' ||
								prop.computed ||
								prop.key.type !== 'Identifier' ||
								prop.value.type !== 'Literal'
							) {
								svelte_options_invalid_customelement_props(attribute);
							}

							if (prop.key.name === 'type') {
								if (
									['String', 'Number', 'Boolean', 'Array', 'Object'].indexOf(
										/** @type {string} */ (prop.value.value)
									) === -1
								) {
									svelte_options_invalid_customelement_props(attribute);
								}
								ce.props[property.key.name].type = /** @type {any} */ (prop.value.value);
							} else if (prop.key.name === 'reflect') {
								if (typeof prop.value.value !== 'boolean') {
									svelte_options_invalid_customelement_props(attribute);
								}
								ce.props[property.key.name].reflect = prop.value.value;
							} else if (prop.key.name === 'attribute') {
								if (typeof prop.value.value !== 'string') {
									svelte_options_invalid_customelement_props(attribute);
								}
								ce.props[property.key.name].attribute = prop.value.value;
							} else {
								svelte_options_invalid_customelement_props(attribute);
							}
						}
					}
				}

				const shadow = properties.find(([name]) => name === 'shadow')?.[1];
				if (shadow) {
					const shadowdom = shadow?.value;
					if (shadowdom !== 'open' && shadowdom !== 'none') {
						svelte_options_invalid_customelement_shadow(shadow);
					}
					ce.shadow = shadowdom;
				}

				const extend = properties.find(([name]) => name === 'extend')?.[1];
				if (extend) {
					ce.extend = extend;
				}

				component_options.customElement = ce;
				break;
			}
			case 'namespace': {
				const value = get_static_value$1(attribute);

				if (value === NAMESPACE_SVG) {
					component_options.namespace = 'svg';
				} else if (value === NAMESPACE_MATHML) {
					component_options.namespace = 'mathml';
				} else if (value === 'html' || value === 'mathml' || value === 'svg') {
					component_options.namespace = value;
				} else {
					svelte_options_invalid_attribute_value(attribute, `"html", "mathml" or "svg"`);
				}

				break;
			}
			case 'css': {
				const value = get_static_value$1(attribute);

				if (value === 'injected') {
					component_options.css = value;
				} else {
					svelte_options_invalid_attribute_value(attribute, `"injected"`);
				}

				break;
			}
			case 'immutable': {
				component_options.immutable = get_boolean_value(attribute);
				break;
			}
			case 'preserveWhitespace': {
				component_options.preserveWhitespace = get_boolean_value(attribute);
				break;
			}
			case 'accessors': {
				component_options.accessors = get_boolean_value(attribute);
				break;
			}
			default:
				svelte_options_unknown_attribute(attribute, name);
		}
	}

	return component_options;
}

/**
 * @param {any} attribute
 */
function get_static_value$1(attribute) {
	const { value } = attribute;

	if (value === true) return true;

	const chunk = Array.isArray(value) ? value[0] : value;

	if (!chunk) return true;
	if (value.length > 1) {
		return null;
	}
	if (chunk.type === 'Text') return chunk.data;
	if (chunk.expression.type !== 'Literal') {
		return null;
	}

	return chunk.expression.value;
}

/**
 * @param {any} attribute
 */
function get_boolean_value(attribute) {
	const value = get_static_value$1(attribute);
	if (typeof value !== 'boolean') {
		svelte_options_invalid_attribute_value(attribute, 'true or false');
	}
	return value;
}

// https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name
const tag_name_char =
	'[a-z0-9_.\xB7\xC0-\xD6\xD8-\xF6\xF8-\u037D\u037F-\u1FFF\u200C-\u200D\u203F-\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\u{10000}-\u{EFFFF}-]';
const regex_valid_tag_name = new RegExp(`^[a-z]${tag_name_char}*-${tag_name_char}*$`, 'u');
const reserved_tag_names = [
	'annotation-xml',
	'color-profile',
	'font-face',
	'font-face-src',
	'font-face-uri',
	'font-face-format',
	'font-face-name',
	'missing-glyph'
];

/**
 * @param {any} attribute
 * @param {string | null} tag
 * @returns {asserts tag is string}
 */
function validate_tag(attribute, tag) {
	if (typeof tag !== 'string') {
		svelte_options_invalid_tagname(attribute);
	}
	if (tag) {
		if (!regex_valid_tag_name.test(tag)) {
			svelte_options_invalid_tagname(attribute);
		} else if (reserved_tag_names.includes(tag)) {
			svelte_options_reserved_tagname(attribute);
		}
	}
}

/** @import { AST } from '#compiler' */

/**
 * @param {AST.SvelteBody | AST.SvelteDocument | AST.SvelteOptionsRaw | AST.SvelteWindow} node
 */
function disallow_children(node) {
	const { nodes } = node.fragment;

	if (nodes.length > 0) {
		const first = nodes[0];
		const last = nodes[nodes.length - 1];

		svelte_meta_invalid_content({ start: first.start, end: last.end }, node.name);
	}
}

/** @import { AST } from '#compiler' */
// @ts-expect-error acorn type definitions are borked in the release we use

const regex_position_indicator = / \(\d+:\d+\)$/;

const regex_lang_attribute =
	/<!--[^]*?-->|<script\s+(?:[^>]*|(?:[^=>'"/]+=(?:"[^"]*"|'[^']*'|[^>\s]+)\s+)*)lang=(["'])?([^"' >]+)\1[^>]*>/g;

class Parser {
	/**
	 * @readonly
	 * @type {string}
	 */
	template;

	/**
	 * Whether or not we're in loose parsing mode, in which
	 * case we try to continue parsing as much as possible
	 * @type {boolean}
	 */
	loose;

	/** */
	index = 0;

	/** Whether we're parsing in TypeScript mode */
	ts = false;

	/** @type {AST.TemplateNode[]} */
	stack = [];

	/** @type {AST.Fragment[]} */
	fragments = [];

	/** @type {AST.Root} */
	root;

	/** @type {Record<string, boolean>} */
	meta_tags = {};

	/** @type {LastAutoClosedTag | undefined} */
	last_auto_closed_tag;

	/**
	 * @param {string} template
	 * @param {boolean} loose
	 */
	constructor(template, loose) {
		if (typeof template !== 'string') {
			throw new TypeError('Template must be a string');
		}

		this.loose = loose;
		this.template = template.trimEnd();

		let match_lang;

		do match_lang = regex_lang_attribute.exec(template);
		while (match_lang && match_lang[0][1] !== 's'); // ensure it starts with '<s' to match script tags

		regex_lang_attribute.lastIndex = 0; // reset matched index to pass tests - otherwise declare the regex inside the constructor

		this.ts = match_lang?.[2] === 'ts';

		this.root = {
			css: null,
			js: [],
			// @ts-ignore
			start: null,
			// @ts-ignore
			end: null,
			type: 'Root',
			fragment: create_fragment(),
			options: null,
			comments: [],
			metadata: {
				ts: this.ts
			}
		};

		this.stack.push(this.root);
		this.fragments.push(this.root.fragment);

		/** @type {ParserState} */
		let state = fragment;

		while (this.index < this.template.length) {
			state = state(this) || fragment;
		}

		if (this.stack.length > 1) {
			const current = this.current();

			if (this.loose) {
				current.end = this.template.length;
			} else if (current.type === 'RegularElement') {
				current.end = current.start + 1;
				element_unclosed(current, current.name);
			} else {
				current.end = current.start + 1;
				block_unclosed(current);
			}
		}

		if (state !== fragment) {
			unexpected_eof(this.index);
		}

		if (this.root.fragment.nodes.length) {
			let start = /** @type {number} */ (this.root.fragment.nodes[0].start);
			while (regex_whitespace.test(template[start])) start += 1;

			let end = /** @type {number} */ (
				this.root.fragment.nodes[this.root.fragment.nodes.length - 1].end
			);
			while (regex_whitespace.test(template[end - 1])) end -= 1;

			this.root.start = start;
			this.root.end = end;
		} else {
			// @ts-ignore
			this.root.start = this.root.end = null;
		}

		const options_index = this.root.fragment.nodes.findIndex(
			/** @param {any} thing */
			(thing) => thing.type === 'SvelteOptions'
		);
		if (options_index !== -1) {
			const options = /** @type {AST.SvelteOptionsRaw} */ (this.root.fragment.nodes[options_index]);
			this.root.fragment.nodes.splice(options_index, 1);
			this.root.options = read_options(options);

			disallow_children(options);

			// We need this for the old AST format
			Object.defineProperty(this.root.options, '__raw__', {
				value: options,
				enumerable: false
			});
		}
	}

	current() {
		return this.stack[this.stack.length - 1];
	}

	/**
	 * @param {any} err
	 * @returns {never}
	 */
	acorn_error(err) {
		js_parse_error(err.pos, err.message.replace(regex_position_indicator, ''));
	}

	/**
	 * @param {string} str
	 * @param {boolean} required
	 * @param {boolean} required_in_loose
	 */
	eat(str, required = false, required_in_loose = true) {
		if (this.match(str)) {
			this.index += str.length;
			return true;
		}

		if (required && (!this.loose || required_in_loose)) {
			expected_token(this.index, str);
		}

		return false;
	}

	/** @param {string} str */
	match(str) {
		const length = str.length;
		if (length === 1) {
			// more performant than slicing
			return this.template[this.index] === str;
		}

		return this.template.slice(this.index, this.index + length) === str;
	}

	/**
	 * Match a regex at the current index
	 * @param {RegExp} pattern  Should have a ^ anchor at the start so the regex doesn't search past the beginning, resulting in worse performance
	 */
	match_regex(pattern) {
		const match = pattern.exec(this.template.slice(this.index));
		if (!match || match.index !== 0) return null;

		return match[0];
	}

	allow_whitespace() {
		while (this.index < this.template.length && regex_whitespace.test(this.template[this.index])) {
			this.index++;
		}
	}

	/**
	 * Search for a regex starting at the current index and return the result if it matches
	 * @param {RegExp} pattern  Should have a ^ anchor at the start so the regex doesn't search past the beginning, resulting in worse performance
	 */
	read(pattern) {
		const result = this.match_regex(pattern);
		if (result) this.index += result.length;
		return result;
	}

	/** @param {any} allow_reserved */
	read_identifier(allow_reserved = false) {
		const start = this.index;

		let i = this.index;

		const code = /** @type {number} */ (this.template.codePointAt(i));
		if (!isIdentifierStart(code, true)) return null;

		i += code <= 0xffff ? 1 : 2;

		while (i < this.template.length) {
			const code = /** @type {number} */ (this.template.codePointAt(i));

			if (!isIdentifierChar(code, true)) break;
			i += code <= 0xffff ? 1 : 2;
		}

		const identifier = this.template.slice(this.index, (this.index = i));

		if (!allow_reserved && is_reserved(identifier)) {
			unexpected_reserved_word(start, identifier);
		}

		return identifier;
	}

	/** @param {RegExp} pattern */
	read_until(pattern) {
		if (this.index >= this.template.length) {
			if (this.loose) return '';
			unexpected_eof(this.template.length);
		}

		const start = this.index;
		const match = pattern.exec(this.template.slice(start));

		if (match) {
			this.index = start + match.index;
			return this.template.slice(start, this.index);
		}

		this.index = this.template.length;
		return this.template.slice(start);
	}

	require_whitespace() {
		if (!regex_whitespace.test(this.template[this.index])) {
			expected_whitespace(this.index);
		}

		this.allow_whitespace();
	}

	pop() {
		this.fragments.pop();
		return this.stack.pop();
	}

	/**
	 * @template {AST.Fragment['nodes'][number]} T
	 * @param {T} node
	 * @returns {T}
	 */
	append(node) {
		this.fragments.at(-1)?.nodes.push(node);
		return node;
	}
}

/**
 * @param {string} template
 * @param {boolean} [loose]
 * @returns {AST.Root}
 */
function parse$2(template, loose = false) {
	set_source(template);

	const parser = new Parser(template, loose);
	return parser.root;
}

/** @typedef {(parser: Parser) => ParserState | void} ParserState */

/** @typedef {Object} LastAutoClosedTag
 * @property {string} tag
 * @property {string} reason
 * @property {number} depth
 */

/** @import { Context, Visitors } from 'zimmerframe' */
/** @import { FunctionExpression, FunctionDeclaration } from 'estree' */

/**
 * @param {FunctionExpression | FunctionDeclaration} node
 * @param {Context<any, any>} context
 */
function remove_this_param(node, context) {
	if (node.params[0]?.type === 'Identifier' && node.params[0].name === 'this') {
		node.params.shift();
	}
	return context.next();
}

/** @type {Visitors<any, null>} */
const visitors$4 = {
	_(node, context) {
		const n = context.next() ?? node;

		// TODO there may come a time when we decide to preserve type annotations.
		// until that day comes, we just delete them so they don't confuse esrap
		delete n.typeAnnotation;
		delete n.typeParameters;
		delete n.typeArguments;
		delete n.returnType;
		delete n.accessibility;
	},
	Decorator(node) {
		typescript_invalid_feature(node, 'decorators (related TSC proposal is not stage 4 yet)');
	},
	ImportDeclaration(node) {
		if (node.importKind === 'type') return empty;

		if (node.specifiers?.length > 0) {
			const specifiers = node.specifiers.filter((/** @type {any} */ s) => s.importKind !== 'type');
			if (specifiers.length === 0) return empty;

			return { ...node, specifiers };
		}

		return node;
	},
	ExportNamedDeclaration(node, context) {
		if (node.exportKind === 'type') return empty;

		if (node.declaration) {
			const result = context.next();
			if (result?.declaration?.type === 'EmptyStatement') {
				return empty;
			}
			return result;
		}

		if (node.specifiers) {
			const specifiers = node.specifiers.filter((/** @type {any} */ s) => s.exportKind !== 'type');
			if (specifiers.length === 0) return empty;

			return { ...node, specifiers };
		}

		return node;
	},
	ExportDefaultDeclaration(node) {
		if (node.exportKind === 'type') return empty;
		return node;
	},
	ExportAllDeclaration(node) {
		if (node.exportKind === 'type') return empty;
		return node;
	},
	PropertyDefinition(node, { next }) {
		if (node.accessor) {
			typescript_invalid_feature(
				node,
				'accessor fields (related TSC proposal is not stage 4 yet)'
			);
		}
		return next();
	},
	TSAsExpression(node, context) {
		return context.visit(node.expression);
	},
	TSSatisfiesExpression(node, context) {
		return context.visit(node.expression);
	},
	TSNonNullExpression(node, context) {
		return context.visit(node.expression);
	},
	TSInterfaceDeclaration() {
		return empty;
	},
	TSTypeAliasDeclaration() {
		return empty;
	},
	TSTypeAssertion(node, context) {
		return context.visit(node.expression);
	},
	TSEnumDeclaration(node) {
		typescript_invalid_feature(node, 'enums');
	},
	TSParameterProperty(node, context) {
		if ((node.readonly || node.accessibility) && context.path.at(-2)?.kind === 'constructor') {
			typescript_invalid_feature(node, 'accessibility modifiers on constructor parameters');
		}
		return context.visit(node.parameter);
	},
	TSInstantiationExpression(node, context) {
		return context.visit(node.expression);
	},
	FunctionExpression: remove_this_param,
	FunctionDeclaration: remove_this_param,
	TSDeclareFunction() {
		return empty;
	},
	ClassBody(node, context) {
		const body = [];
		for (const _child of node.body) {
			const child = context.visit(_child);
			if (child.type !== 'PropertyDefinition' || !child.declare) {
				body.push(child);
			}
		}
		return {
			...node,
			body
		};
	},
	ClassDeclaration(node, context) {
		if (node.declare) {
			return empty;
		}
		delete node.implements;
		return context.next();
	},
	MethodDefinition(node, context) {
		if (node.abstract) {
			return empty;
		}
		return context.next();
	},
	VariableDeclaration(node, context) {
		if (node.declare) {
			return empty;
		}
		return context.next();
	},
	TSModuleDeclaration(node, context) {
		if (!node.body) return empty;

		// namespaces can contain non-type nodes
		const cleaned = /** @type {any[]} */ (node.body.body).map((entry) => context.visit(entry));
		if (cleaned.some((entry) => entry !== empty)) {
			typescript_invalid_feature(node, 'namespaces with non-type nodes');
		}

		return empty;
	}
};

/**
 * @template T
 * @param {T} ast
 * @returns {T}
 */
function remove_typescript_nodes(ast) {
	return walk$1(ast, null, visitors$4);
}

/** @import { Node } from 'estree' */

/**
 * @param {Node} node
 * @param {Node} parent
 * @returns {boolean}
 */
function is_reference(node, parent) {
	if (node.type === 'MemberExpression') {
		return !node.computed && is_reference(node.object, node);
	}

	if (node.type !== 'Identifier') return false;

	switch (parent?.type) {
		// disregard `bar` in `foo.bar`
		case 'MemberExpression':
			return parent.computed || node === parent.object;

		// disregard the `foo` in `class {foo(){}}` but keep it in `class {[foo](){}}`
		case 'MethodDefinition':
			return parent.computed;

		// disregard the `meta` in `import.meta`
		case 'MetaProperty':
			return parent.meta === node;

		// disregard the `foo` in `class {foo=bar}` but keep it in `class {[foo]=bar}` and `class {bar=foo}`
		case 'PropertyDefinition':
			return parent.computed || node === parent.value;

		// disregard the `bar` in `{ bar: foo }`, but keep it in `{ [bar]: foo }`
		case 'Property':
			return parent.computed || node === parent.value;

		// disregard the `bar` in `export { foo as bar }` or
		// the foo in `import { foo as bar }`
		case 'ExportSpecifier':
		case 'ImportSpecifier':
			return node === parent.local;

		// disregard the `foo` in `foo: while (...) { ... break foo; ... continue foo;}`
		case 'LabeledStatement':
		case 'BreakStatement':
		case 'ContinueStatement':
			return false;

		default:
			return true;
	}
}

/** @import { AST } from '#compiler' */

/**
 * @param {AST.SvelteNode} node
 */
function determine_slot(node) {
	if (!is_element_node(node)) return null;

	for (const attribute of node.attributes) {
		if (attribute.type !== 'Attribute') continue;
		if (attribute.name !== 'slot') continue;
		if (!is_text_attribute(attribute)) continue;

		return /** @type {string} */ (attribute.value[0].data);
	}

	return null;
}

/** @import { AssignmentExpression, Expression, Literal, Node, Pattern, Super, UpdateExpression, VariableDeclarator } from 'estree' */
/** @import { AST, Binding } from '#compiler' */
/** @import { AnalysisState, Context } from '../../types' */
/** @import { Scope } from '../../../scope' */
/** @import { NodeLike } from '../../../../errors.js' */

/**
 * @param {AssignmentExpression | UpdateExpression | AST.BindDirective} node
 * @param {Pattern | Expression} argument
 * @param {Context} context
 */
function validate_assignment(node, argument, context) {
	validate_no_const_assignment(node, argument, context.state.scope, node.type === 'BindDirective');

	if (argument.type === 'Identifier') {
		const binding = context.state.scope.get(argument.name);

		if (context.state.analysis.runes) {
			if (
				context.state.analysis.props_id != null &&
				binding?.node === context.state.analysis.props_id
			) {
				constant_assignment(node, '$props.id()');
			}

			if (binding?.kind === 'each') {
				each_item_invalid_assignment(node);
			}
		}

		if (binding?.kind === 'snippet') {
			snippet_parameter_assignment(node);
		}
	}

	if (argument.type === 'MemberExpression' && argument.object.type === 'ThisExpression') {
		const name =
			argument.computed && argument.property.type !== 'Literal'
				? null
				: get_name(argument.property);

		const field = name !== null && context.state.state_fields?.get(name);

		// check we're not assigning to a state field before its declaration in the constructor
		if (field && field.node.type === 'AssignmentExpression' && node !== field.node) {
			let i = context.path.length;
			while (i--) {
				const parent = context.path[i];

				if (
					parent.type === 'FunctionDeclaration' ||
					parent.type === 'FunctionExpression' ||
					parent.type === 'ArrowFunctionExpression'
				) {
					const grandparent = get_parent(context.path, i - 1);

					if (
						grandparent.type === 'MethodDefinition' &&
						grandparent.kind === 'constructor' &&
						/** @type {number} */ (node.start) < /** @type {number} */ (field.node.start)
					) {
						state_field_invalid_assignment(node);
					}

					break;
				}
			}
		}
	}
}

/**
 * @param {NodeLike} node
 * @param {Pattern | Expression} argument
 * @param {Scope} scope
 * @param {boolean} is_binding
 */
function validate_no_const_assignment(node, argument, scope, is_binding) {
	if (argument.type === 'ArrayPattern') {
		for (const element of argument.elements) {
			if (element) {
				validate_no_const_assignment(node, element, scope, is_binding);
			}
		}
	} else if (argument.type === 'ObjectPattern') {
		for (const element of argument.properties) {
			if (element.type === 'Property') {
				validate_no_const_assignment(node, element.value, scope, is_binding);
			}
		}
	} else if (argument.type === 'Identifier') {
		const binding = scope.get(argument.name);
		if (
			binding?.declaration_kind === 'import' ||
			(binding?.declaration_kind === 'const' && binding.kind !== 'each')
		) {
			// e.invalid_const_assignment(
			// 	node,
			// 	is_binding,
			// 	// This takes advantage of the fact that we don't assign initial for let directives and then/catch variables.
			// 	// If we start doing that, we need another property on the binding to differentiate, or give up on the more precise error message.
			// 	binding.kind !== 'state' &&
			// 		binding.kind !== 'raw_state' &&
			// 		(binding.kind !== 'normal' || !binding.initial)
			// );

			// TODO have a more specific error message for assignments to things like `{:then foo}`
			const thing = binding.declaration_kind === 'import' ? 'import' : 'constant';

			if (is_binding) {
				constant_binding(node, thing);
			} else {
				constant_assignment(node, thing);
			}
		}
	}
}

/**
 * Validates that the opening of a control flow block is `{` immediately followed by the expected character.
 * In legacy mode whitespace is allowed inbetween. TODO remove once legacy mode is gone and move this into parser instead.
 * @param {{start: number; end: number}} node
 * @param {AnalysisState} state
 * @param {string} expected
 */
function validate_opening_tag(node, state, expected) {
	if (state.analysis.source[node.start + 1] !== expected) {
		// avoid a sea of red and only mark the first few characters
		block_unexpected_character({ start: node.start, end: node.start + 5 }, expected);
	}
}

/**
 * @param {AST.Fragment | null | undefined} node
 * @param {Context} context
 */
function validate_block_not_empty(node, context) {
	if (!node) return;
	// Assumption: If the block has zero elements, someone's in the middle of typing it out,
	// so don't warn in that case because it would be distracting.
	if (node.nodes.length === 1 && node.nodes[0].type === 'Text' && !node.nodes[0].raw.trim()) {
		block_empty(node.nodes[0]);
	}
}

/**
 * @param {VariableDeclarator} node
 * @param {AnalysisState} state
 */
function ensure_no_module_import_conflict(node, state) {
	const ids = extract_identifiers(node.id);
	for (const id of ids) {
		if (
			state.ast_type === 'instance' &&
			state.scope === state.analysis.instance.scope &&
			state.analysis.module.scope.get(id.name)?.declaration_kind === 'import'
		) {
			// TODO fix the message here
			declaration_duplicate_module_import(node.id);
		}
	}
}

/**
 * A 'safe' identifier means that the `foo` in `foo.bar` or `foo()` will not
 * call functions that require component context to exist
 * @param {Expression | Super} expression
 * @param {Scope} scope
 */
function is_safe_identifier(expression, scope) {
	let node = expression;
	while (node.type === 'MemberExpression') node = node.object;

	if (node.type !== 'Identifier') return false;

	const binding = scope.get(node.name);
	if (!binding) return true;

	if (binding.kind === 'store_sub') {
		return is_safe_identifier({ name: node.name.slice(1), type: 'Identifier' }, scope);
	}

	return (
		binding.declaration_kind !== 'import' &&
		binding.kind !== 'prop' &&
		binding.kind !== 'bindable_prop' &&
		binding.kind !== 'rest_prop'
	);
}

/**
 * @param {Expression | Literal | Super} node
 * @param {Context} context
 * @returns {boolean}
 */
function is_pure(node, context) {
	if (node.type === 'Literal') {
		return true;
	}

	if (node.type === 'CallExpression') {
		if (!is_pure(node.callee, context)) {
			return false;
		}
		for (let arg of node.arguments) {
			if (!is_pure(arg.type === 'SpreadElement' ? arg.argument : arg, context)) {
				return false;
			}
		}
		return true;
	}

	if (node.type !== 'Identifier' && node.type !== 'MemberExpression') {
		return false;
	}

	if (get_rune(call(node), context.state.scope) === '$effect.tracking') {
		return false;
	}

	/** @type {Expression | Super | null} */
	let left = node;
	while (left.type === 'MemberExpression') {
		left = left.object;
	}

	if (!left) return false;

	if (left.type === 'Identifier') {
		const binding = context.state.scope.get(left.name);
		if (binding === null) return true; // globals are assumed to be safe
	} else if (is_pure(left, context)) {
		return true;
	}

	// TODO add more cases (safe Svelte imports, etc)
	return false;
}

/**
 * Checks if the name is valid, which it is when it's not starting with (or is) a dollar sign or if it's a function parameter.
 * The second argument is the depth of the scope, which is there for backwards compatibility reasons: In Svelte 4, you
 * were allowed to define `$`-prefixed variables anywhere below the top level of components. Once legacy mode is gone, this
 * argument can be removed / the call sites adjusted accordingly.
 * @param {Binding | null} binding
 * @param {number | undefined} [function_depth]
 */
function validate_identifier_name(binding, function_depth) {
	if (!binding) return;

	const declaration_kind = binding.declaration_kind;

	if (
		declaration_kind !== 'synthetic' &&
		declaration_kind !== 'param' &&
		declaration_kind !== 'rest_param' &&
		(!function_depth || function_depth <= 1)
	) {
		const node = binding.node;

		if (node.name === '$') {
			dollar_binding_invalid(node);
		} else if (
			node.name.startsWith('$') &&
			// import type { $Type } from "" - these are normally already filtered out,
			// but for the migration they aren't, and throwing here is preventing the migration to complete
			// TODO -> once migration script is gone we can remove this check
			!(
				binding.initial?.type === 'ImportDeclaration' &&
				/** @type {any} */ (binding.initial).importKind === 'type'
			)
		) {
			dollar_prefix_invalid(node);
		}
	}
}

/**
 * Checks that the exported name is not a derived or reassigned state variable.
 * @param {Node} node
 * @param {Scope} scope
 * @param {string} name
 */
function validate_export(node, scope, name) {
	const binding = scope.get(name);
	if (!binding) return;

	if (binding.kind === 'derived') {
		derived_invalid_export(node);
	}

	if ((binding.kind === 'state' || binding.kind === 'raw_state') && binding.reassigned) {
		state_invalid_export(node);
	}
}

/** @import { BinaryOperator, ClassDeclaration, Expression, FunctionDeclaration, Identifier, ImportDeclaration, MemberExpression, LogicalOperator, Node, Pattern, UnaryOperator, VariableDeclarator, Super, SimpleLiteral, FunctionExpression, ArrowFunctionExpression } from 'estree' */
/** @import { Context, Visitor } from 'zimmerframe' */
/** @import { AST, BindingKind, DeclarationKind } from '#compiler' */

const UNKNOWN$1 = Symbol('unknown');
/** Includes `BigInt` */
const NUMBER = Symbol('number');
const STRING = Symbol('string');
const FUNCTION = Symbol('string');

/** @type {Record<string, [type: typeof NUMBER | typeof  STRING | typeof  UNKNOWN, fn?: Function]>} */
const globals = {
	BigInt: [NUMBER],
	'Math.min': [NUMBER, Math.min],
	'Math.max': [NUMBER, Math.max],
	'Math.random': [NUMBER],
	'Math.floor': [NUMBER, Math.floor],
	// @ts-ignore
	'Math.f16round': [NUMBER, Math.f16round],
	'Math.round': [NUMBER, Math.round],
	'Math.abs': [NUMBER, Math.abs],
	'Math.acos': [NUMBER, Math.acos],
	'Math.asin': [NUMBER, Math.asin],
	'Math.atan': [NUMBER, Math.atan],
	'Math.atan2': [NUMBER, Math.atan2],
	'Math.ceil': [NUMBER, Math.ceil],
	'Math.cos': [NUMBER, Math.cos],
	'Math.sin': [NUMBER, Math.sin],
	'Math.tan': [NUMBER, Math.tan],
	'Math.exp': [NUMBER, Math.exp],
	'Math.log': [NUMBER, Math.log],
	'Math.pow': [NUMBER, Math.pow],
	'Math.sqrt': [NUMBER, Math.sqrt],
	'Math.clz32': [NUMBER, Math.clz32],
	'Math.imul': [NUMBER, Math.imul],
	'Math.sign': [NUMBER, Math.sign],
	'Math.log10': [NUMBER, Math.log10],
	'Math.log2': [NUMBER, Math.log2],
	'Math.log1p': [NUMBER, Math.log1p],
	'Math.expm1': [NUMBER, Math.expm1],
	'Math.cosh': [NUMBER, Math.cosh],
	'Math.sinh': [NUMBER, Math.sinh],
	'Math.tanh': [NUMBER, Math.tanh],
	'Math.acosh': [NUMBER, Math.acosh],
	'Math.asinh': [NUMBER, Math.asinh],
	'Math.atanh': [NUMBER, Math.atanh],
	'Math.trunc': [NUMBER, Math.trunc],
	'Math.fround': [NUMBER, Math.fround],
	'Math.cbrt': [NUMBER, Math.cbrt],
	Number: [NUMBER, Number],
	'Number.isInteger': [NUMBER, Number.isInteger],
	'Number.isFinite': [NUMBER, Number.isFinite],
	'Number.isNaN': [NUMBER, Number.isNaN],
	'Number.isSafeInteger': [NUMBER, Number.isSafeInteger],
	'Number.parseFloat': [NUMBER, Number.parseFloat],
	'Number.parseInt': [NUMBER, Number.parseInt],
	String: [STRING, String],
	'String.fromCharCode': [STRING, String.fromCharCode],
	'String.fromCodePoint': [STRING, String.fromCodePoint]
};

/** @type {Record<string, any>} */
const global_constants = {
	'Math.PI': Math.PI,
	'Math.E': Math.E,
	'Math.LN10': Math.LN10,
	'Math.LN2': Math.LN2,
	'Math.LOG10E': Math.LOG10E,
	'Math.LOG2E': Math.LOG2E,
	'Math.SQRT2': Math.SQRT2,
	'Math.SQRT1_2': Math.SQRT1_2
};

class Binding {
	/** @type {Scope} */
	scope;

	/** @type {Identifier} */
	node;

	/** @type {BindingKind} */
	kind;

	/** @type {DeclarationKind} */
	declaration_kind;

	/**
	 * What the value was initialized with.
	 * For destructured props such as `let { foo = 'bar' } = $props()` this is `'bar'` and not `$props()`
	 * @type {null | Expression | FunctionDeclaration | ClassDeclaration | ImportDeclaration | AST.EachBlock | AST.SnippetBlock}
	 */
	initial = null;

	/** @type {Array<{ node: Identifier; path: AST.SvelteNode[] }>} */
	references = [];

	/**
	 * (Re)assignments of this binding. Includes declarations such as `function x() {}`.
	 * @type {Array<{ value: Expression; scope: Scope }>}
	 */
	assignments = [];

	/**
	 * For `legacy_reactive`: its reactive dependencies
	 * @type {Binding[]}
	 */
	legacy_dependencies = [];

	/**
	 * Legacy props: the `class` in `{ export klass as class}`. $props(): The `class` in { class: klass } = $props()
	 * @type {string | null}
	 */
	prop_alias = null;

	/**
	 * Additional metadata, varies per binding type
	 * @type {null | { inside_rest?: boolean; is_template_declaration?: boolean; exclude_props?: string[] }}
	 */
	metadata = null;

	mutated = false;
	reassigned = false;

	/**
	 * Instance-level declarations may follow (or contain) a top-level `await`. In these cases,
	 * any reads that occur in the template must wait for the corresponding promise to resolve
	 * otherwise the initial value will not have been assigned.
	 * It is a member expression of the form `$$blockers[n]`.
	 * TODO the blocker is set during transform which feels a bit grubby
	 * @type {MemberExpression | null}
	 */
	blocker = null;

	/**
	 *
	 * @param {Scope} scope
	 * @param {Identifier} node
	 * @param {BindingKind} kind
	 * @param {DeclarationKind} declaration_kind
	 * @param {Binding['initial']} initial
	 */
	constructor(scope, node, kind, declaration_kind, initial) {
		this.scope = scope;
		this.node = node;
		this.initial = initial;
		this.kind = kind;
		this.declaration_kind = declaration_kind;

		if (initial) {
			this.assignments.push({ value: /** @type {Expression} */ (initial), scope });
		}
	}

	get updated() {
		return this.mutated || this.reassigned;
	}

	/**
	 * @returns {this is Binding & { initial: ArrowFunctionExpression | FunctionDeclaration | FunctionExpression }}
	 */
	is_function() {
		if (this.updated) {
			// even if it's reassigned to another function,
			// we can't use it directly as e.g. an event handler
			return false;
		}

		const type = this.initial?.type;

		return (
			type === 'ArrowFunctionExpression' ||
			type === 'FunctionExpression' ||
			type === 'FunctionDeclaration'
		);
	}
}

class Evaluation {
	/** @type {Set<any>} */
	values;

	/**
	 * True if there is exactly one possible value
	 * @readonly
	 * @type {boolean}
	 */
	is_known = true;

	/**
	 * True if the possible values contains `UNKNOWN`
	 * @readonly
	 * @type {boolean}
	 */
	has_unknown = false;

	/**
	 * True if the value is known to not be null/undefined
	 * @readonly
	 * @type {boolean}
	 */
	is_defined = true;

	/**
	 * True if the value is known to be a string
	 * @readonly
	 * @type {boolean}
	 */
	is_string = true;

	/**
	 * True if the value is known to be a number
	 * @readonly
	 * @type {boolean}
	 */
	is_number = true;

	/**
	 * True if the value is known to be a function
	 * @readonly
	 * @type {boolean}
	 */
	is_function = true;

	/**
	 * @readonly
	 * @type {any}
	 */
	value = undefined;

	/**
	 *
	 * @param {Scope} scope
	 * @param {Expression | FunctionDeclaration} expression
	 * @param {Set<any>} values
	 */
	constructor(scope, expression, values) {
		current_evaluations.set(expression, this);

		this.values = values;

		switch (expression.type) {
			case 'Literal': {
				this.values.add(expression.value);
				break;
			}

			case 'Identifier': {
				const binding = scope.get(expression.name);

				if (binding) {
					if (
						binding.initial?.type === 'CallExpression' &&
						get_rune(binding.initial, scope) === '$props.id'
					) {
						this.values.add(STRING);
						break;
					}

					const is_prop =
						binding.kind === 'prop' ||
						binding.kind === 'rest_prop' ||
						binding.kind === 'bindable_prop';

					if (binding.initial?.type === 'EachBlock' && binding.initial.index === expression.name) {
						this.values.add(NUMBER);
						break;
					}

					if (binding.initial?.type === 'SnippetBlock') {
						this.is_defined = true;
						this.is_known = false;
						this.values.add(UNKNOWN$1);
						break;
					}

					if (!binding.updated && binding.initial !== null && !is_prop) {
						binding.scope.evaluate(/** @type {Expression} */ (binding.initial), this.values);
						break;
					}
				} else if (expression.name === 'undefined') {
					this.values.add(undefined);
					break;
				}

				// TODO glean what we can from reassignments
				// TODO one day, expose props and imports somehow

				this.values.add(UNKNOWN$1);
				break;
			}

			case 'BinaryExpression': {
				const a = scope.evaluate(/** @type {Expression} */ (expression.left)); // `left` cannot be `PrivateIdentifier` unless operator is `in`
				const b = scope.evaluate(expression.right);

				if (a.is_known && b.is_known) {
					this.values.add(binary[expression.operator](a.value, b.value));
					break;
				}

				switch (expression.operator) {
					case '!=':
					case '!==':
					case '<':
					case '<=':
					case '>':
					case '>=':
					case '==':
					case '===':
					case 'in':
					case 'instanceof':
						this.values.add(true);
						this.values.add(false);
						break;

					case '%':
					case '&':
					case '*':
					case '**':
					case '-':
					case '/':
					case '<<':
					case '>>':
					case '>>>':
					case '^':
					case '|':
						this.values.add(NUMBER);
						break;

					case '+':
						if (a.is_string || b.is_string) {
							this.values.add(STRING);
						} else if (a.is_number && b.is_number) {
							this.values.add(NUMBER);
						} else {
							this.values.add(STRING);
							this.values.add(NUMBER);
						}
						break;

					default:
						this.values.add(UNKNOWN$1);
				}
				break;
			}

			case 'ConditionalExpression': {
				const test = scope.evaluate(expression.test);
				const consequent = scope.evaluate(expression.consequent);
				const alternate = scope.evaluate(expression.alternate);

				if (test.is_known) {
					for (const value of (test.value ? consequent : alternate).values) {
						this.values.add(value);
					}
				} else {
					for (const value of consequent.values) {
						this.values.add(value);
					}

					for (const value of alternate.values) {
						this.values.add(value);
					}
				}
				break;
			}

			case 'LogicalExpression': {
				const a = scope.evaluate(expression.left);
				const b = scope.evaluate(expression.right);

				if (a.is_known) {
					if (b.is_known) {
						this.values.add(logical[expression.operator](a.value, b.value));
						break;
					}

					if (
						(expression.operator === '&&' && !a.value) ||
						(expression.operator === '||' && a.value) ||
						(expression.operator === '??' && a.value != null)
					) {
						this.values.add(a.value);
					} else {
						for (const value of b.values) {
							this.values.add(value);
						}
					}

					break;
				}

				for (const value of a.values) {
					this.values.add(value);
				}

				for (const value of b.values) {
					this.values.add(value);
				}
				break;
			}

			case 'UnaryExpression': {
				const argument = scope.evaluate(expression.argument);

				if (argument.is_known) {
					this.values.add(unary[expression.operator](argument.value));
					break;
				}

				switch (expression.operator) {
					case '!':
					case 'delete':
						this.values.add(false);
						this.values.add(true);
						break;

					case '+':
					case '-':
					case '~':
						this.values.add(NUMBER);
						break;

					case 'typeof':
						this.values.add(STRING);
						break;

					case 'void':
						this.values.add(undefined);
						break;

					default:
						this.values.add(UNKNOWN$1);
				}
				break;
			}

			case 'CallExpression': {
				const keypath = get_global_keypath(expression.callee, scope);

				if (keypath) {
					if (is_rune(keypath)) {
						const arg = /** @type {Expression | undefined} */ (expression.arguments[0]);

						switch (keypath) {
							case '$state':
							case '$state.raw':
							case '$derived':
								if (arg) {
									scope.evaluate(arg, this.values);
								} else {
									this.values.add(undefined);
								}
								break;

							case '$props.id':
								this.values.add(STRING);
								break;

							case '$effect.tracking':
								this.values.add(false);
								this.values.add(true);
								break;

							case '$derived.by':
								if (arg?.type === 'ArrowFunctionExpression' && arg.body.type !== 'BlockStatement') {
									scope.evaluate(arg.body, this.values);
									break;
								}

								this.values.add(UNKNOWN$1);
								break;

							default: {
								this.values.add(UNKNOWN$1);
							}
						}

						break;
					}

					if (
						Object.hasOwn(globals, keypath) &&
						expression.arguments.every((arg) => arg.type !== 'SpreadElement')
					) {
						const [type, fn] = globals[keypath];
						const values = expression.arguments.map((arg) => scope.evaluate(arg));

						if (fn && values.every((e) => e.is_known)) {
							this.values.add(fn(...values.map((e) => e.value)));
						} else {
							this.values.add(type);
						}

						break;
					}
				}

				this.values.add(UNKNOWN$1);
				break;
			}

			case 'TemplateLiteral': {
				let result = expression.quasis[0].value.cooked;

				for (let i = 0; i < expression.expressions.length; i += 1) {
					const e = scope.evaluate(expression.expressions[i]);

					if (e.is_known) {
						result += e.value + expression.quasis[i + 1].value.cooked;
					} else {
						this.values.add(STRING);
						break;
					}
				}

				this.values.add(result);
				break;
			}

			case 'MemberExpression': {
				const keypath = get_global_keypath(expression, scope);

				if (keypath && Object.hasOwn(global_constants, keypath)) {
					this.values.add(global_constants[keypath]);
					break;
				}

				this.values.add(UNKNOWN$1);
				break;
			}

			case 'ArrowFunctionExpression':
			case 'FunctionExpression':
			case 'FunctionDeclaration': {
				this.values.add(FUNCTION);
				break;
			}

			default: {
				this.values.add(UNKNOWN$1);
			}
		}

		for (const value of this.values) {
			this.value = value; // saves having special logic for `size === 1`

			if (value !== STRING && typeof value !== 'string') {
				this.is_string = false;
			}

			if (value !== NUMBER && typeof value !== 'number') {
				this.is_number = false;
			}

			if (value !== FUNCTION) {
				this.is_function = false;
			}

			if (value == null || value === UNKNOWN$1) {
				this.is_defined = false;
			}

			if (value === UNKNOWN$1) {
				this.has_unknown = true;
			}
		}

		if (this.values.size > 1 || typeof this.value === 'symbol') {
			this.is_known = false;
		}

		current_evaluations.delete(expression);
	}
}

class Scope {
	/** @type {ScopeRoot} */
	root;

	/**
	 * The immediate parent scope
	 * @type {Scope | null}
	 */
	parent;

	/**
	 * Whether or not `var` declarations are contained by this scope
	 * @type {boolean}
	 */
	#porous;

	/**
	 * A map of every identifier declared by this scope, and all the
	 * identifiers that reference it
	 * @type {Map<string, Binding>}
	 */
	declarations = new Map();

	/**
	 * A map of declarators to the bindings they declare
	 * @type {Map<VariableDeclarator | AST.LetDirective, Binding[]>}
	 */
	declarators = new Map();

	/**
	 * A set of all the names referenced with this scope
	 * — useful for generating unique names
	 * @type {Map<string, { node: Identifier; path: AST.SvelteNode[] }[]>}
	 */
	references = new Map();

	/**
	 * The scope depth allows us to determine if a state variable is referenced in its own scope,
	 * which is usually an error. Block statements do not increase this value
	 */
	function_depth = 0;

	/**
	 * If tracing of reactive dependencies is enabled for this scope
	 * @type {null | Expression}
	 */
	tracing = null;

	/**
	 *
	 * @param {ScopeRoot} root
	 * @param {Scope | null} parent
	 * @param {boolean} porous
	 */
	constructor(root, parent, porous) {
		this.root = root;
		this.parent = parent;
		this.#porous = porous;
		this.function_depth = parent ? parent.function_depth + (porous ? 0 : 1) : 0;
	}

	/**
	 * @param {Identifier} node
	 * @param {Binding['kind']} kind
	 * @param {DeclarationKind} declaration_kind
	 * @param {null | Expression | FunctionDeclaration | ClassDeclaration | ImportDeclaration | AST.EachBlock | AST.SnippetBlock} initial
	 * @returns {Binding}
	 */
	declare(node, kind, declaration_kind, initial = null) {
		if (this.parent) {
			if (declaration_kind === 'var' && this.#porous) {
				return this.parent.declare(node, kind, declaration_kind);
			}

			if (declaration_kind === 'import') {
				return this.parent.declare(node, kind, declaration_kind, initial);
			}
		}

		if (this.declarations.has(node.name)) {
			const binding = this.declarations.get(node.name);
			if (binding && binding.declaration_kind !== 'var' && declaration_kind !== 'var') {
				// This also errors on function types, but that's arguably a good thing
				// declaring function twice is also caught by acorn in the parse phase
				declaration_duplicate(node, node.name);
			}
		}

		const binding = new Binding(this, node, kind, declaration_kind, initial);

		validate_identifier_name(binding, this.function_depth);

		this.declarations.set(node.name, binding);
		this.root.conflicts.add(node.name);
		return binding;
	}

	child(porous = false) {
		return new Scope(this.root, this, porous);
	}

	/**
	 * @param {string} preferred_name
	 * @returns {string}
	 */
	generate(preferred_name) {
		if (this.#porous) {
			return /** @type {Scope} */ (this.parent).generate(preferred_name);
		}

		preferred_name = preferred_name.replace(/[^a-zA-Z0-9_$]/g, '_').replace(/^[0-9]/, '_');
		let name = preferred_name;
		let n = 1;

		while (
			this.references.has(name) ||
			this.declarations.has(name) ||
			this.root.conflicts.has(name) ||
			is_reserved(name)
		) {
			name = `${preferred_name}_${n++}`;
		}

		this.references.set(name, []);
		this.root.conflicts.add(name);
		return name;
	}

	/**
	 * @param {string} name
	 * @returns {Binding | null}
	 */
	get(name) {
		return this.declarations.get(name) ?? this.parent?.get(name) ?? null;
	}

	/**
	 * @param {VariableDeclarator | AST.LetDirective} node
	 * @returns {Binding[]}
	 */
	get_bindings(node) {
		const bindings = this.declarators.get(node);
		if (!bindings) {
			throw new Error('No binding found for declarator');
		}
		return bindings;
	}

	/**
	 * @param {string} name
	 * @returns {Scope | null}
	 */
	owner(name) {
		return this.declarations.has(name) ? this : this.parent && this.parent.owner(name);
	}

	/**
	 * @param {Identifier} node
	 * @param {AST.SvelteNode[]} path
	 */
	reference(node, path) {
		path = [...path]; // ensure that mutations to path afterwards don't affect this reference
		let references = this.references.get(node.name);

		if (!references) this.references.set(node.name, (references = []));

		references.push({ node, path });

		const binding = this.declarations.get(node.name);
		if (binding) {
			binding.references.push({ node, path });
		} else if (this.parent) {
			this.parent.reference(node, path);
		} else {
			// no binding was found, and this is the top level scope,
			// which means this is a global
			this.root.conflicts.add(node.name);
		}
	}

	/**
	 * Does partial evaluation to find an exact value or at least the rough type of the expression.
	 * Only call this once scope has been fully generated in a first pass,
	 * else this evaluates on incomplete data and may yield wrong results.
	 * @param {Expression} expression
	 * @param {Set<any>} [values]
	 */
	evaluate(expression, values = new Set()) {
		const current = current_evaluations.get(expression);
		if (current) return current;

		return new Evaluation(this, expression, values);
	}
}

/**
 * Track which expressions are currently being evaluated — this allows
 * us to prevent cyclical evaluations without passing the map around
 * @type {Map<Expression | FunctionDeclaration, Evaluation>}
 */
const current_evaluations = new Map();

/** @type {Record<BinaryOperator, (left: any, right: any) => any>} */
const binary = {
	'!=': (left, right) => left != right,
	'!==': (left, right) => left !== right,
	'<': (left, right) => left < right,
	'<=': (left, right) => left <= right,
	'>': (left, right) => left > right,
	'>=': (left, right) => left >= right,
	'==': (left, right) => left == right,
	'===': (left, right) => left === right,
	in: (left, right) => left in right,
	instanceof: (left, right) => left instanceof right,
	'%': (left, right) => left % right,
	'&': (left, right) => left & right,
	'*': (left, right) => left * right,
	'**': (left, right) => left ** right,
	'+': (left, right) => left + right,
	'-': (left, right) => left - right,
	'/': (left, right) => left / right,
	'<<': (left, right) => left << right,
	'>>': (left, right) => left >> right,
	'>>>': (left, right) => left >>> right,
	'^': (left, right) => left ^ right,
	'|': (left, right) => left | right
};

/** @type {Record<UnaryOperator, (argument: any) => any>} */
const unary = {
	'-': (argument) => -argument,
	'+': (argument) => +argument,
	'!': (argument) => !argument,
	'~': (argument) => ~argument,
	typeof: (argument) => typeof argument,
	void: () => undefined,
	delete: () => true
};

/** @type {Record<LogicalOperator, (left: any, right: any) => any>} */
const logical = {
	'||': (left, right) => left || right,
	'&&': (left, right) => left && right,
	'??': (left, right) => left ?? right
};

class ScopeRoot {
	/** @type {Set<string>} */
	conflicts = new Set();

	/**
	 * @param {string} preferred_name
	 */
	unique(preferred_name) {
		preferred_name = preferred_name.replace(/[^a-zA-Z0-9_$]/g, '_');
		let final_name = preferred_name;
		let n = 1;

		while (this.conflicts.has(final_name)) {
			final_name = `${preferred_name}_${n++}`;
		}

		this.conflicts.add(final_name);
		const id$1 = id(final_name);
		return id$1;
	}
}

/**
 * @param {AST.SvelteNode} ast
 * @param {ScopeRoot} root
 * @param {boolean} allow_reactive_declarations
 * @param {Scope | null} parent
 */
function create_scopes(ast, root, allow_reactive_declarations, parent) {
	/** @typedef {{ scope: Scope }} State */

	/**
	 * A map of node->associated scope. A node appearing in this map does not necessarily mean that it created a scope
	 * @type {Map<AST.SvelteNode, Scope>}
	 */
	const scopes = new Map();
	const scope = new Scope(root, parent, false);
	scopes.set(ast, scope);

	/** @type {State} */
	const state = { scope };

	/** @type {[Scope, { node: Identifier; path: AST.SvelteNode[] }][]} */
	const references = [];

	/** @type {[Scope, Pattern | MemberExpression, Expression][]} */
	const updates = [];

	/**
	 * An array of reactive declarations, i.e. the `a` in `$: a = b * 2`
	 * @type {Identifier[]}
	 */
	const possible_implicit_declarations = [];

	/**
	 * @param {Scope} scope
	 * @param {Pattern[]} params
	 */
	function add_params(scope, params) {
		for (const param of params) {
			for (const node of extract_identifiers(param)) {
				scope.declare(node, 'normal', param.type === 'RestElement' ? 'rest_param' : 'param');
			}
		}
	}

	/**
	 * @type {Visitor<Node, State, AST.SvelteNode>}
	 */
	const create_block_scope = (node, { state, next }) => {
		const scope = state.scope.child(true);
		scopes.set(node, scope);

		next({ scope });
	};

	/**
	 * @type {Visitor<AST.ElementLike, State, AST.SvelteNode>}
	 */
	const SvelteFragment = (node, { state, next }) => {
		const scope = state.scope.child();
		scopes.set(node, scope);
		next({ scope });
	};

	/**
	 * @type {Visitor<AST.Component | AST.SvelteComponent | AST.SvelteSelf, State, AST.SvelteNode>}
	 */
	const Component = (node, context) => {
		node.metadata.scopes = {
			default: context.state.scope.child()
		};

		if (node.type === 'SvelteComponent') {
			context.visit(node.expression);
		}

		const default_state = determine_slot(node)
			? context.state
			: { scope: node.metadata.scopes.default };

		for (const attribute of node.attributes) {
			if (attribute.type === 'LetDirective') {
				context.visit(attribute, default_state);
			} else {
				context.visit(attribute);
			}
		}

		for (const child of node.fragment.nodes) {
			let state = default_state;

			const slot_name = determine_slot(child);

			if (slot_name !== null) {
				node.metadata.scopes[slot_name] = context.state.scope.child();

				state = {
					scope: node.metadata.scopes[slot_name]
				};
			}

			context.visit(child, state);
		}
	};

	/**
	 * @type {Visitor<AST.AnimateDirective | AST.TransitionDirective | AST.UseDirective, State, AST.SvelteNode>}
	 */
	const SvelteDirective = (node, { state, path, visit }) => {
		state.scope.reference(id(node.name.split('.')[0]), path);

		if (node.expression) {
			visit(node.expression);
		}
	};

	let has_await = false;

	walk$1(ast, state, {
		AwaitExpression(node, context) {
			// this doesn't _really_ belong here, but it allows us to
			// automatically opt into runes mode on encountering
			// blocking awaits, without doing an additional walk
			// before the analysis occurs
			// TODO remove this in Svelte 7.0 or whenever we get rid of legacy support
			has_await ||= context.path.every(
				({ type }) =>
					type !== 'ArrowFunctionExpression' &&
					type !== 'FunctionExpression' &&
					type !== 'FunctionDeclaration'
			);

			context.next();
		},

		// references
		Identifier(node, { path, state }) {
			const parent = path.at(-1);
			if (
				parent &&
				is_reference(node, /** @type {Node} */ (parent)) &&
				// TSTypeAnnotation, TSInterfaceDeclaration etc - these are normally already filtered out,
				// but for the migration they aren't, so we need to filter them out here
				// TODO -> once migration script is gone we can remove this check
				!parent.type.startsWith('TS')
			) {
				references.push([state.scope, { node, path: path.slice() }]);
			}
		},
		LabeledStatement(node, { path, next }) {
			if (path.length > 1 || !allow_reactive_declarations) return next();
			if (node.label.name !== '$') return next();

			// create a scope for the $: block
			const scope = state.scope.child();
			scopes.set(node, scope);

			if (
				node.body.type === 'ExpressionStatement' &&
				node.body.expression.type === 'AssignmentExpression'
			) {
				for (const id of extract_identifiers(node.body.expression.left)) {
					if (!id.name.startsWith('$')) {
						possible_implicit_declarations.push(id);
					}
				}
			}

			next({ scope });
		},

		SvelteFragment,
		SlotElement: SvelteFragment,
		SvelteElement: SvelteFragment,
		RegularElement: SvelteFragment,

		LetDirective(node, context) {
			const scope = context.state.scope;

			/** @type {Binding[]} */
			const bindings = [];
			scope.declarators.set(node, bindings);

			if (node.expression) {
				for (const id of extract_identifiers_from_destructuring(node.expression)) {
					const binding = scope.declare(id, 'template', 'const');
					scope.reference(id, [context.path[context.path.length - 1], node]);
					bindings.push(binding);
				}
			} else {
				/** @type {Identifier} */
				const id = {
					name: node.name,
					type: 'Identifier',
					start: node.start,
					end: node.end
				};
				const binding = scope.declare(id, 'template', 'const');
				scope.reference(id, [context.path[context.path.length - 1], node]);
				bindings.push(binding);
			}
		},

		Component: (node, context) => {
			context.state.scope.reference(id(node.name.split('.')[0]), context.path);
			Component(node, context);
		},
		SvelteSelf: Component,
		SvelteComponent: Component,

		// updates
		AssignmentExpression(node, { state, next }) {
			updates.push([state.scope, node.left, node.right]);
			next();
		},

		UpdateExpression(node, { state, next }) {
			const expression = /** @type {Identifier | MemberExpression} */ (node.argument);
			updates.push([state.scope, expression, expression]);
			next();
		},

		ImportDeclaration(node, { state }) {
			for (const specifier of node.specifiers) {
				state.scope.declare(specifier.local, 'normal', 'import', node);
			}
		},

		FunctionExpression(node, { state, next }) {
			const scope = state.scope.child();
			scopes.set(node, scope);

			if (node.id) scope.declare(node.id, 'normal', 'function');

			add_params(scope, node.params);
			next({ scope });
		},

		FunctionDeclaration(node, { state, next }) {
			if (node.id) state.scope.declare(node.id, 'normal', 'function', node);

			const scope = state.scope.child();
			scopes.set(node, scope);

			add_params(scope, node.params);
			next({ scope });
		},

		ArrowFunctionExpression(node, { state, next }) {
			const scope = state.scope.child();
			scopes.set(node, scope);

			add_params(scope, node.params);
			next({ scope });
		},

		ForStatement: create_block_scope,
		ForInStatement: create_block_scope,
		ForOfStatement: create_block_scope,
		SwitchStatement: create_block_scope,
		BlockStatement(node, context) {
			const parent = context.path.at(-1);
			if (
				parent?.type === 'FunctionDeclaration' ||
				parent?.type === 'FunctionExpression' ||
				parent?.type === 'ArrowFunctionExpression'
			) {
				// We already created a new scope for the function
				context.next();
			} else {
				create_block_scope(node, context);
			}
		},

		ClassDeclaration(node, { state, next }) {
			if (node.id) state.scope.declare(node.id, 'normal', 'let', node);
			next();
		},

		VariableDeclaration(node, { state, path, next }) {
			const is_parent_const_tag = path.at(-1)?.type === 'ConstTag';
			for (const declarator of node.declarations) {
				/** @type {Binding[]} */
				const bindings = [];

				state.scope.declarators.set(declarator, bindings);

				for (const id of extract_identifiers(declarator.id)) {
					const binding = state.scope.declare(
						id,
						is_parent_const_tag ? 'template' : 'normal',
						node.kind,
						declarator.init
					);
					binding.metadata = { is_template_declaration: true };
					bindings.push(binding);
				}
			}

			next();
		},

		CatchClause(node, { state, next }) {
			if (node.param) {
				const scope = state.scope.child(true);
				scopes.set(node, scope);

				for (const id of extract_identifiers(node.param)) {
					scope.declare(id, 'normal', 'let');
				}

				next({ scope });
			} else {
				next();
			}
		},

		EachBlock(node, { state, visit }) {
			visit(node.expression);

			// context and children are a new scope
			const scope = state.scope.child();
			scopes.set(node, scope);

			if (node.context) {
				// declarations
				for (const id of extract_identifiers(node.context)) {
					const binding = scope.declare(id, 'each', 'const');

					let inside_rest = false;
					let is_rest_id = false;
					walk$1(node.context, null, {
						Identifier(node) {
							if (inside_rest && node === id) {
								is_rest_id = true;
							}
						},
						RestElement(_, { next }) {
							const prev = inside_rest;
							inside_rest = true;
							next();
							inside_rest = prev;
						}
					});

					binding.metadata = { inside_rest: is_rest_id };
				}

				// Visit to pick up references from default initializers
				visit(node.context, { scope });
			}

			if (node.index) {
				const is_keyed =
					node.key &&
					(node.key.type !== 'Identifier' || !node.index || node.key.name !== node.index);
				scope.declare(id(node.index), is_keyed ? 'template' : 'static', 'const', node);
			}
			if (node.key) visit(node.key, { scope });

			// children
			for (const child of node.body.nodes) {
				visit(child, { scope });
			}
			if (node.fallback) visit(node.fallback, { scope });

			node.metadata = {
				expression: new ExpressionMetadata(),
				keyed: false,
				contains_group_binding: false,
				index: scope.root.unique('$$index'),
				declarations: scope.declarations,
				is_controlled: false,
				// filled in during analysis
				transitive_deps: new Set()
			};
		},

		AwaitBlock(node, context) {
			context.visit(node.expression);

			if (node.pending) {
				context.visit(node.pending);
			}

			if (node.then) {
				context.visit(node.then);
				if (node.value) {
					const then_scope = /** @type {Scope} */ (scopes.get(node.then));
					const value_scope = context.state.scope.child();
					scopes.set(node.value, value_scope);
					context.visit(node.value, { scope: value_scope });
					for (const id of extract_identifiers(node.value)) {
						then_scope.declare(id, 'template', 'const');
						value_scope.declare(id, 'normal', 'const');
					}
				}
			}

			if (node.catch) {
				context.visit(node.catch);
				if (node.error) {
					const catch_scope = /** @type {Scope} */ (scopes.get(node.catch));
					const error_scope = context.state.scope.child();
					scopes.set(node.error, error_scope);
					context.visit(node.error, { scope: error_scope });
					for (const id of extract_identifiers(node.error)) {
						catch_scope.declare(id, 'template', 'const');
						error_scope.declare(id, 'normal', 'const');
					}
				}
			}
		},

		SnippetBlock(node, context) {
			const state = context.state;
			let scope = state.scope;

			scope.declare(node.expression, 'normal', 'function', node);

			const child_scope = state.scope.child();
			scopes.set(node, child_scope);

			for (const param of node.parameters) {
				for (const id of extract_identifiers(param)) {
					child_scope.declare(id, 'snippet', 'let');
				}
			}

			context.next({ scope: child_scope });
		},

		Fragment: (node, context) => {
			const scope = context.state.scope.child(node.metadata.transparent);
			scopes.set(node, scope);
			context.next({ scope });
		},

		BindDirective(node, context) {
			if (node.expression.type !== 'SequenceExpression') {
				const expression = /** @type {Identifier | MemberExpression} */ (node.expression);
				updates.push([context.state.scope, expression, expression]);
			}

			context.next();
		},

		TransitionDirective: SvelteDirective,
		AnimateDirective: SvelteDirective,
		UseDirective: SvelteDirective,
		// using it's own function instead of `SvelteDirective` because
		// StyleDirective doesn't have expressions and are generally already
		// handled by `Identifier`. This is the special case for the shorthand
		// eg <button style:height /> where the variable has the same name of
		// the css property
		StyleDirective(node, { path, state, next }) {
			if (node.value === true) {
				state.scope.reference(id(node.name), path.concat(node));
			}
			next();
		}

		// TODO others
	});

	for (const id of possible_implicit_declarations) {
		const binding = scope.get(id.name);
		if (binding) continue; // TODO can also be legacy_reactive if declared outside of reactive statement

		scope.declare(id, 'legacy_reactive', 'let');
	}

	// we do this after the fact, so that we don't need to worry
	// about encountering references before their declarations
	for (const [scope, { node, path }] of references) {
		scope.reference(node, path);
	}

	for (const [scope, node, value] of updates) {
		for (const expression of unwrap_pattern(node)) {
			const left = object$1(expression);
			const binding = left && scope.get(left.name);

			if (binding !== null && left !== binding.node) {
				if (left === expression) {
					binding.reassigned = true;
					binding.assignments.push({ value, scope });
				} else {
					binding.mutated = true;
				}
			}
		}
	}

	return {
		has_await,
		scope,
		scopes
	};
}

/**
 * @template {{ scope: Scope, scopes: Map<AST.SvelteNode, Scope> }} State
 * @param {AST.SvelteNode} node
 * @param {Context<AST.SvelteNode, State>} context
 */
function set_scope(node, { next, state }) {
	const scope = state.scopes.get(node);
	next(scope !== undefined && scope !== state.scope ? { ...state, scope } : state);
}

/**
 * Returns the name of the rune if the given expression is a `CallExpression` using a rune.
 * @param {Node | null | undefined} node
 * @param {Scope} scope
 */
function get_rune(node, scope) {
	if (!node) return null;
	if (node.type !== 'CallExpression') return null;

	const keypath = get_global_keypath(node.callee, scope);

	if (!keypath || !is_rune(keypath)) return null;
	return keypath;
}

/**
 * Returns the name of the rune if the given expression is a `CallExpression` using a rune.
 * @param {Expression | Super} node
 * @param {Scope} scope
 */
function get_global_keypath(node, scope) {
	let n = node;

	let joined = '';

	while (n.type === 'MemberExpression') {
		if (n.computed) return null;
		if (n.property.type !== 'Identifier') return null;
		joined = '.' + n.property.name + joined;
		n = n.object;
	}

	if (n.type === 'CallExpression' && n.callee.type === 'Identifier') {
		joined = '()' + joined;
		n = n.callee;
	}

	if (n.type !== 'Identifier') return null;

	const binding = scope.get(n.name);
	if (binding !== null) return null; // rune name, but references a variable or store

	return n.name + joined;
}

/**
 * @template T
 * @param {Array<[T, T]>} edges
 * @returns {Array<T>|undefined}
 */
function check_graph_for_cycles(edges) {
	/** @type {Map<T, T[]>} */
	const graph = edges.reduce((g, edge) => {
		const [u, v] = edge;
		if (!g.has(u)) g.set(u, []);
		if (!g.has(v)) g.set(v, []);
		g.get(u).push(v);
		return g;
	}, new Map());

	const visited = new Set();
	/** @type {Set<T>} */
	const on_stack = new Set();
	/** @type {Array<Array<T>>} */
	const cycles = [];

	/**
	 * @param {T} v
	 */
	function visit(v) {
		visited.add(v);
		on_stack.add(v);

		graph.get(v)?.forEach((w) => {
			if (!visited.has(w)) {
				visit(w);
			} else if (on_stack.has(w)) {
				cycles.push([...on_stack, w]);
			}
		});

		on_stack.delete(v);
	}

	graph.forEach((_, v) => {
		if (!visited.has(v)) {
			visit(v);
		}
	});

	return cycles[0];
}

/** @import { AST } from '#compiler' */
const regex_css_browser_prefix = /^-((webkit)|(moz)|(o)|(ms))-/;
const regex_css_name_boundary = /^[\s,;}]$/;

/**
 * @param {string} name
 * @returns {string}
 */
function remove_css_prefix(name) {
	return name.replace(regex_css_browser_prefix, '');
}

/** @param {AST.CSS.Atrule} node */
const is_keyframes_node = (node) => remove_css_prefix(node.name) === 'keyframes';

/** @import { AST } from '#compiler' */
/** @import { Node } from 'estree' */
const UNKNOWN = {};

/**
 * @param {Node} node
 * @param {boolean} is_class
 * @param {Set<any>} set
 * @param {boolean} is_nested
 */
function gather_possible_values(node, is_class, set, is_nested = false) {
	if (set.has(UNKNOWN)) {
		// no point traversing any further
		return;
	}

	if (node.type === 'Literal') {
		set.add(String(node.value));
	} else if (node.type === 'ConditionalExpression') {
		gather_possible_values(node.consequent, is_class, set, is_nested);
		gather_possible_values(node.alternate, is_class, set, is_nested);
	} else if (node.type === 'LogicalExpression') {
		if (node.operator === '&&') {
			// && is a special case, because the only way the left
			// hand value can be included is if it's falsy. this is
			// a bit of extra work but it's worth it because
			// `class={[condition && 'blah']}` is common,
			// and we don't want to deopt on `condition`
			const left = new Set();
			gather_possible_values(node.left, is_class, left, is_nested);

			if (left.has(UNKNOWN)) {
				// add all non-nullish falsy values, unless this is a `class` attribute that
				// will be processed by cslx, in which case falsy values are removed, unless
				// they're not inside an array/object (TODO 6.0 remove that last part)
				if (!is_class || !is_nested) {
					set.add('');
					set.add(false);
					set.add(NaN);
					set.add(0); // -0 and 0n are also falsy, but stringify to '0'
				}
			} else {
				for (const value of left) {
					if (!value && value != undefined && (!is_class || !is_nested)) {
						set.add(value);
					}
				}
			}

			gather_possible_values(node.right, is_class, set, is_nested);
		} else {
			gather_possible_values(node.left, is_class, set, is_nested);
			gather_possible_values(node.right, is_class, set, is_nested);
		}
	} else if (is_class && node.type === 'ArrayExpression') {
		for (const entry of node.elements) {
			if (entry) {
				gather_possible_values(entry, is_class, set, true);
			}
		}
	} else if (is_class && node.type === 'ObjectExpression') {
		for (const property of node.properties) {
			if (
				property.type === 'Property' &&
				!property.computed &&
				(property.key.type === 'Identifier' || property.key.type === 'Literal')
			) {
				set.add(
					property.key.type === 'Identifier' ? property.key.name : String(property.key.value)
				);
			} else {
				set.add(UNKNOWN);
			}
		}
	} else {
		set.add(UNKNOWN);
	}
}

/**
 * @param {AST.Text | AST.ExpressionTag} chunk
 * @param {boolean} is_class
 * @returns {string[] | null}
 */
function get_possible_values(chunk, is_class) {
	const values = new Set();

	if (chunk.type === 'Text') {
		values.add(chunk.data);
	} else {
		gather_possible_values(chunk.expression, is_class, values);
	}

	if (values.has(UNKNOWN)) return null;
	return [...values].map((value) => String(value));
}

/**
 * Returns all parent rules; root is last
 * @param {AST.CSS.Rule | null} rule
 */
function get_parent_rules(rule) {
	const rules = [];

	while (rule) {
		rules.push(rule);
		rule = rule.metadata.parent_rule;
	}

	return rules;
}

/**
 * True if is `:global(...)` or `:global` and no pseudo class that is scoped.
 * @param {AST.CSS.RelativeSelector} relative_selector
 * @returns {relative_selector is AST.CSS.RelativeSelector & { selectors: [AST.CSS.PseudoClassSelector, ...Array<AST.CSS.PseudoClassSelector | AST.CSS.PseudoElementSelector>] }}
 */
function is_global$1(relative_selector) {
	const first = relative_selector.selectors[0];

	return (
		first.type === 'PseudoClassSelector' &&
		first.name === 'global' &&
		(first.args === null ||
			// Only these two selector types keep the whole selector global, because e.g.
			// :global(button).x means that the selector is still scoped because of the .x
			relative_selector.selectors.every(
				(selector) =>
					is_unscoped_pseudo_class(selector) || selector.type === 'PseudoElementSelector'
			))
	);
}

/**
 * `true` if is a pseudo class that cannot be or is not scoped
 * @param {AST.CSS.SimpleSelector} selector
 */
function is_unscoped_pseudo_class(selector) {
	return (
		selector.type === 'PseudoClassSelector' &&
		// These make the selector scoped
		((selector.name !== 'has' &&
			selector.name !== 'is' &&
			selector.name !== 'where' &&
			// Not is special because we want to scope as specific as possible, but because :not
			// inverses the result, we want to leave the unscoped, too. The exception is more than
			// one selector in the :not (.e.g :not(.x .y)), then .x and .y should be scoped
			(selector.name !== 'not' ||
				selector.args === null ||
				selector.args.children.every((c) => c.children.length === 1))) ||
			// selectors with has/is/where/not can also be global if all their children are global
			selector.args === null ||
			selector.args.children.every((c) => c.children.every((r) => is_global$1(r))))
	);
}

/**
 * True if is `:global(...)` or `:global`, irrespective of whether or not there are any pseudo classes that are scoped.
 * Difference to `is_global`: `:global(x):has(y)` is `true` for `is_outer_global` but `false` for `is_global`.
 * @param {AST.CSS.RelativeSelector} relative_selector
 * @returns {relative_selector is AST.CSS.RelativeSelector & { selectors: [AST.CSS.PseudoClassSelector, ...Array<AST.CSS.PseudoClassSelector | AST.CSS.PseudoElementSelector>] }}
 */
function is_outer_global(relative_selector) {
	const first = relative_selector.selectors[0];

	return (
		first.type === 'PseudoClassSelector' &&
		first.name === 'global' &&
		(first.args === null ||
			// Only these two selector types can keep the whole selector global, because e.g.
			// :global(button).x means that the selector is still scoped because of the .x
			relative_selector.selectors.every(
				(selector) =>
					selector.type === 'PseudoClassSelector' || selector.type === 'PseudoElementSelector'
			))
	);
}

/** @import { ComponentAnalysis } from '../../types.js' */
/** @import { AST } from '#compiler' */
/** @import { Visitors } from 'zimmerframe' */

/**
 * @typedef {{
 *   keyframes: string[];
 *   rule: AST.CSS.Rule | null;
 *   analysis: ComponentAnalysis;
 * }} CssState
 */

/**
 * @typedef {Visitors<AST.CSS.Node, CssState>} CssVisitors
 */

/**
 * True if is `:global`
 * @param {AST.CSS.SimpleSelector} simple_selector
 */
function is_global_block_selector(simple_selector) {
	return (
		simple_selector.type === 'PseudoClassSelector' &&
		simple_selector.name === 'global' &&
		simple_selector.args === null
	);
}

/**
 * @param {AST.SvelteNode[]} path
 */
function is_unscoped(path) {
	return path
		.filter((node) => node.type === 'Rule')
		.every((node) => node.metadata.has_global_selectors);
}

/**
 *
 * @param {Array<AST.CSS.Node>} path
 */
function is_in_global_block$1(path) {
	return path.some((node) => node.type === 'Rule' && node.metadata.is_global_block);
}

/** @type {CssVisitors} */
const css_visitors = {
	Atrule(node, context) {
		if (is_keyframes_node(node)) {
			if (!node.prelude.startsWith('-global-') && !is_in_global_block$1(context.path)) {
				context.state.keyframes.push(node.prelude);
			} else if (node.prelude.startsWith('-global-')) {
				// we don't check if the block.children.length because the keyframe is still added even if empty
				context.state.analysis.css.has_global ||= is_unscoped(context.path);
			}
		}

		context.next();
	},
	ComplexSelector(node, context) {
		context.next(); // analyse relevant selectors first

		{
			const global = node.children.find(is_global$1);

			if (global) {
				const is_nested = context.path.at(-2)?.type === 'PseudoClassSelector';
				if (is_nested && !global.selectors[0].args) {
					css_global_block_invalid_placement(global.selectors[0]);
				}

				const idx = node.children.indexOf(global);
				if (global.selectors[0].args !== null && idx !== 0 && idx !== node.children.length - 1) {
					// ensure `:global(...)` is not used in the middle of a selector (but multiple `global(...)` in sequence are ok)
					for (let i = idx + 1; i < node.children.length; i++) {
						if (!is_global$1(node.children[i])) {
							css_global_invalid_placement(global.selectors[0]);
						}
					}
				}
			}
		}

		// ensure `:global(...)` do not lead to invalid css after `:global()` is removed
		for (const relative_selector of node.children) {
			for (let i = 0; i < relative_selector.selectors.length; i++) {
				const selector = relative_selector.selectors[i];

				if (selector.type === 'PseudoClassSelector' && selector.name === 'global') {
					const child = selector.args?.children[0].children[0];
					// ensure `:global(element)` to be at the first position in a compound selector
					if (child?.selectors[0].type === 'TypeSelector' && i !== 0) {
						css_global_invalid_selector_list(selector);
					}

					// ensure `:global(.class)` is not followed by a type selector, eg: `:global(.class)element`
					if (relative_selector.selectors[i + 1]?.type === 'TypeSelector') {
						css_type_selector_invalid_placement(relative_selector.selectors[i + 1]);
					}

					// ensure `:global(...)`contains a single selector
					// (standalone :global() with multiple selectors is OK)
					if (
						selector.args !== null &&
						selector.args.children.length > 1 &&
						(node.children.length > 1 || relative_selector.selectors.length > 1)
					) {
						css_global_invalid_selector(selector);
					}
				}
			}
		}

		node.metadata.rule = context.state.rule;

		node.metadata.is_global = node.children.every(
			({ metadata }) => metadata.is_global || metadata.is_global_like
		);

		node.metadata.used ||= node.metadata.is_global;

		if (
			node.metadata.rule?.metadata.parent_rule &&
			node.children[0]?.selectors[0]?.type === 'NestingSelector'
		) {
			const first = node.children[0]?.selectors[1];
			const no_nesting_scope =
				first?.type !== 'PseudoClassSelector' || is_unscoped_pseudo_class(first);
			const parent_is_global = node.metadata.rule.metadata.parent_rule.prelude.children.some(
				(child) => child.children.length === 1 && child.children[0].metadata.is_global
			);
			// mark `&:hover` in `:global(.foo) { &:hover { color: green }}` as used
			if (no_nesting_scope && parent_is_global) {
				node.metadata.used = true;
			}
		}
	},
	RelativeSelector(node, context) {
		const parent = /** @type {AST.CSS.ComplexSelector} */ (context.path.at(-1));

		if (
			node.combinator != null &&
			!context.state.rule?.metadata.parent_rule &&
			parent.children[0] === node &&
			context.path.at(-3)?.type !== 'PseudoClassSelector'
		) {
			css_selector_invalid(node.combinator);
		}

		node.metadata.is_global = node.selectors.length >= 1 && is_global$1(node);

		if (
			node.selectors.length >= 1 &&
			node.selectors.every(
				(selector) =>
					selector.type === 'PseudoClassSelector' || selector.type === 'PseudoElementSelector'
			)
		) {
			const first = node.selectors[0];
			node.metadata.is_global_like ||=
				(first.type === 'PseudoClassSelector' && first.name === 'host') ||
				(first.type === 'PseudoElementSelector' &&
					[
						'view-transition',
						'view-transition-group',
						'view-transition-old',
						'view-transition-new',
						'view-transition-image-pair'
					].includes(first.name));
		}

		node.metadata.is_global_like ||=
			node.selectors.some(
				(child) => child.type === 'PseudoClassSelector' && child.name === 'root'
			) &&
			// :root.y:has(.x) is not a global selector because while .y is unscoped, .x inside `:has(...)` should be scoped
			!node.selectors.some((child) => child.type === 'PseudoClassSelector' && child.name === 'has');

		if (node.metadata.is_global_like || node.metadata.is_global) {
			// So that nested selectors like `:root:not(.x)` are not marked as unused
			for (const child of node.selectors) {
				walk$1(/** @type {AST.CSS.Node} */ (child), null, {
					ComplexSelector(node, context) {
						node.metadata.used = true;
						context.next();
					}
				});
			}
		}

		context.next();
	},
	Rule(node, context) {
		node.metadata.parent_rule = context.state.rule;

		// We gotta allow :global x, :global y because CSS preprocessors might generate that from :global { x, y {...} }
		for (const complex_selector of node.prelude.children) {
			let is_global_block = false;

			for (let selector_idx = 0; selector_idx < complex_selector.children.length; selector_idx++) {
				const child = complex_selector.children[selector_idx];
				const idx = child.selectors.findIndex(is_global_block_selector);

				if (is_global_block) {
					// All selectors after :global are unscoped
					child.metadata.is_global_like = true;
				}

				if (idx === 0) {
					if (
						child.selectors.length > 1 &&
						selector_idx === 0 &&
						node.metadata.parent_rule === null
					) {
						css_global_block_invalid_modifier_start(child.selectors[1]);
					} else {
						// `child` starts with `:global`
						node.metadata.is_global_block = is_global_block = true;

						for (let i = 1; i < child.selectors.length; i++) {
							walk$1(/** @type {AST.CSS.Node} */ (child.selectors[i]), null, {
								ComplexSelector(node) {
									node.metadata.used = true;
								}
							});
						}

						if (child.combinator && child.combinator.name !== ' ') {
							css_global_block_invalid_combinator(child, child.combinator.name);
						}

						const declaration = node.block.children.find((child) => child.type === 'Declaration');
						const is_lone_global =
							complex_selector.children.length === 1 &&
							complex_selector.children[0].selectors.length === 1; // just `:global`, not e.g. `:global x`

						if (is_lone_global && node.prelude.children.length > 1) {
							// `:global, :global x { z { ... } }` would become `x { z { ... } }` which means `z` is always
							// constrained by `x`, which is not what the user intended
							css_global_block_invalid_list(node.prelude);
						}

						if (
							declaration &&
							// :global { color: red; } is invalid, but foo :global { color: red; } is valid
							node.prelude.children.length === 1 &&
							is_lone_global
						) {
							css_global_block_invalid_declaration(declaration);
						}
					}
				} else if (idx !== -1) {
					css_global_block_invalid_modifier(child.selectors[idx]);
				}
			}

			if (node.metadata.is_global_block && !is_global_block) {
				css_global_block_invalid_list(node.prelude);
			}
		}

		const state = { ...context.state, rule: node };

		// visit selector list first, to populate child selector metadata
		context.visit(node.prelude, state);

		for (const selector of node.prelude.children) {
			node.metadata.has_global_selectors ||= selector.metadata.is_global;
			node.metadata.has_local_selectors ||= !selector.metadata.is_global;
		}

		// if this rule has a ComplexSelector whose RelativeSelector children are all
		// `:global(...)`, and the rule contains declarations (rather than just
		// nested rules) then the component as a whole includes global CSS
		context.state.analysis.css.has_global ||=
			node.metadata.has_global_selectors &&
			node.block.children.filter((child) => child.type === 'Declaration').length > 0 &&
			is_unscoped(context.path);

		// visit block list, so parent rule metadata is populated
		context.visit(node.block, state);
	},
	NestingSelector(node, context) {
		const rule = /** @type {AST.CSS.Rule} */ (context.state.rule);
		const parent_rule = rule.metadata.parent_rule;

		if (!parent_rule) {
			// https://developer.mozilla.org/en-US/docs/Web/CSS/Nesting_selector#using_outside_nested_rule
			const children = rule.prelude.children;
			const selectors = children[0].children[0].selectors;
			if (
				children.length > 1 ||
				selectors.length > 1 ||
				selectors[0].type !== 'PseudoClassSelector' ||
				selectors[0].name !== 'global' ||
				selectors[0].args?.children[0]?.children[0].selectors[0] !== node
			) {
				css_nesting_selector_invalid_placement(node);
			}
		} else if (
			// :global { &.foo { ... } } is invalid
			parent_rule.metadata.is_global_block &&
			!parent_rule.metadata.parent_rule &&
			parent_rule.prelude.children[0].children.length === 1 &&
			parent_rule.prelude.children[0].children[0].selectors.length === 1
		) {
			css_global_block_invalid_modifier_start(node);
		}

		context.next();
	}
};

/**
 * @param {AST.CSS.StyleSheet} stylesheet
 * @param {ComponentAnalysis} analysis
 */
function analyze_css(stylesheet, analysis) {
	/** @type {CssState} */
	const css_state = {
		keyframes: analysis.css.keyframes,
		rule: null,
		analysis
	};

	walk$1(stylesheet, css_state, css_visitors);
}

/** @import * as Compiler from '#compiler' */

/** @typedef {typeof NODE_PROBABLY_EXISTS | typeof NODE_DEFINITELY_EXISTS} NodeExistsValue */
/** @typedef {typeof FORWARD | typeof BACKWARD} Direction */

const NODE_PROBABLY_EXISTS = 0;
const NODE_DEFINITELY_EXISTS = 1;
const FORWARD = 0;
const BACKWARD = 1;

const whitelist_attribute_selector = new Map([
	['details', ['open']],
	['dialog', ['open']]
]);

/** @type {Compiler.AST.CSS.Combinator} */
const descendant_combinator = {
	type: 'Combinator',
	name: ' ',
	start: -1,
	end: -1
};

/** @type {Compiler.AST.CSS.RelativeSelector} */
const nesting_selector = {
	type: 'RelativeSelector',
	start: -1,
	end: -1,
	combinator: null,
	selectors: [
		{
			type: 'NestingSelector',
			name: '&',
			start: -1,
			end: -1
		}
	],
	metadata: {
		is_global: false,
		is_global_like: false,
		scoped: false
	}
};

/** @type {Compiler.AST.CSS.RelativeSelector} */
const any_selector = {
	type: 'RelativeSelector',
	start: -1,
	end: -1,
	combinator: null,
	selectors: [
		{
			type: 'TypeSelector',
			name: '*',
			start: -1,
			end: -1
		}
	],
	metadata: {
		is_global: false,
		is_global_like: false,
		scoped: false
	}
};

/**
 * Snippets encountered already (avoids infinite loops)
 * @type {Set<Compiler.AST.SnippetBlock>}
 */
const seen = new Set();

/**
 *
 * @param {Compiler.AST.CSS.StyleSheet} stylesheet
 * @param {Compiler.AST.RegularElement | Compiler.AST.SvelteElement} element
 */
function prune(stylesheet, element) {
	walk$1(/** @type {Compiler.AST.CSS.Node} */ (stylesheet), null, {
		Rule(node, context) {
			if (node.metadata.is_global_block) {
				context.visit(node.prelude);
			} else {
				context.next();
			}
		},
		ComplexSelector(node) {
			const selectors = get_relative_selectors(node);

			seen.clear();

			if (
				apply_selector(
					selectors,
					/** @type {Compiler.AST.CSS.Rule} */ (node.metadata.rule),
					element,
					BACKWARD
				)
			) {
				node.metadata.used = true;
			}

			// note: we don't call context.next() here, we only recurse into
			// selectors that don't belong to rules (i.e. inside `:is(...)` etc)
			// when we encounter them below
		}
	});
}

/**
 * Retrieves the relative selectors (minus the trailing globals) from a complex selector.
 * Also searches them for any existing `&` selectors and adds one if none are found.
 * This ensures we traverse up to the parent rule when the inner selectors match and we're
 * trying to see if the parent rule also matches.
 * @param {Compiler.AST.CSS.ComplexSelector} node
 */
function get_relative_selectors(node) {
	const selectors = truncate(node);

	if (node.metadata.rule?.metadata.parent_rule && selectors.length > 0) {
		let has_explicit_nesting_selector = false;

		// nesting could be inside pseudo classes like :is, :has or :where
		for (let selector of selectors) {
			walk$1(selector, null, {
				// @ts-ignore
				NestingSelector() {
					has_explicit_nesting_selector = true;
				}
			});

			// if we found one we can break from the others
			if (has_explicit_nesting_selector) break;
		}

		if (!has_explicit_nesting_selector) {
			if (selectors[0].combinator === null) {
				selectors[0] = {
					...selectors[0],
					combinator: descendant_combinator
				};
			}

			selectors.unshift(nesting_selector);
		}
	}

	return selectors;
}

/**
 * Discard trailing `:global(...)` selectors, these are unused for scoping purposes
 * @param {Compiler.AST.CSS.ComplexSelector} node
 */
function truncate(node) {
	const i = node.children.findLastIndex(({ metadata, selectors }) => {
		const first = selectors[0];
		return (
			// not after a :global selector
			!metadata.is_global_like &&
			!(first.type === 'PseudoClassSelector' && first.name === 'global' && first.args === null) &&
			// not a :global(...) without a :has/is/where(...) modifier that is scoped
			!metadata.is_global
		);
	});

	return node.children.slice(0, i + 1).map((child) => {
		// In case of `:root.y:has(...)`, `y` is unscoped, but everything in `:has(...)` should be scoped (if not global).
		// To properly accomplish that, we gotta filter out all selector types except `:has`.
		const root = child.selectors.find((s) => s.type === 'PseudoClassSelector' && s.name === 'root');
		if (!root || child.metadata.is_global_like) return child;

		return {
			...child,
			selectors: child.selectors.filter((s) => s.type === 'PseudoClassSelector' && s.name === 'has')
		};
	});
}

/**
 * @param {Compiler.AST.CSS.RelativeSelector[]} relative_selectors
 * @param {Compiler.AST.CSS.Rule} rule
 * @param {Compiler.AST.RegularElement | Compiler.AST.SvelteElement} element
 * @param {Direction} direction
 * @returns {boolean}
 */
function apply_selector(relative_selectors, rule, element, direction) {
	const rest_selectors = relative_selectors.slice();
	const relative_selector = direction === FORWARD ? rest_selectors.shift() : rest_selectors.pop();

	const matched =
		!!relative_selector &&
		relative_selector_might_apply_to_node(relative_selector, rule, element, direction) &&
		apply_combinator(relative_selector, rest_selectors, rule, element, direction);

	if (matched) {
		if (!is_outer_global(relative_selector)) {
			relative_selector.metadata.scoped = true;
		}

		element.metadata.scoped = true;
	}

	return matched;
}

/**
 * @param {Compiler.AST.CSS.RelativeSelector} relative_selector
 * @param {Compiler.AST.CSS.RelativeSelector[]} rest_selectors
 * @param {Compiler.AST.CSS.Rule} rule
 * @param {Compiler.AST.RegularElement | Compiler.AST.SvelteElement | Compiler.AST.RenderTag | Compiler.AST.Component | Compiler.AST.SvelteComponent | Compiler.AST.SvelteSelf} node
 * @param {Direction} direction
 * @returns {boolean}
 */
function apply_combinator(relative_selector, rest_selectors, rule, node, direction) {
	const combinator =
		direction == FORWARD ? rest_selectors[0]?.combinator : relative_selector.combinator;
	if (!combinator) return true;

	switch (combinator.name) {
		case ' ':
		case '>': {
			const is_adjacent = combinator.name === '>';
			const parents =
				direction === FORWARD
					? get_descendant_elements(node, is_adjacent)
					: get_ancestor_elements(node, is_adjacent);
			let parent_matched = false;

			for (const parent of parents) {
				if (apply_selector(rest_selectors, rule, parent, direction)) {
					parent_matched = true;
				}
			}

			return (
				parent_matched ||
				(direction === BACKWARD &&
					(!is_adjacent || parents.length === 0) &&
					rest_selectors.every((selector) => is_global(selector, rule)))
			);
		}

		case '+':
		case '~': {
			const siblings = get_possible_element_siblings(node, direction, combinator.name === '+');

			let sibling_matched = false;

			for (const possible_sibling of siblings.keys()) {
				if (
					possible_sibling.type === 'RenderTag' ||
					possible_sibling.type === 'SlotElement' ||
					possible_sibling.type === 'Component'
				) {
					// `{@render foo()}<p>foo</p>` with `:global(.x) + p` is a match
					if (rest_selectors.length === 1 && rest_selectors[0].metadata.is_global) {
						sibling_matched = true;
					}
				} else if (apply_selector(rest_selectors, rule, possible_sibling, direction)) {
					sibling_matched = true;
				}
			}

			return (
				sibling_matched ||
				(direction === BACKWARD &&
					get_element_parent(node) === null &&
					rest_selectors.every((selector) => is_global(selector, rule)))
			);
		}

		default:
			// TODO other combinators
			return true;
	}
}

/**
 * Returns `true` if the relative selector is global, meaning
 * it's a `:global(...)` or unscopeable selector, or
 * is an `:is(...)` or `:where(...)` selector that contains
 * a global selector
 * @param {Compiler.AST.CSS.RelativeSelector} selector
 * @param {Compiler.AST.CSS.Rule} rule
 * @returns {boolean}
 */
function is_global(selector, rule) {
	if (selector.metadata.is_global || selector.metadata.is_global_like) {
		return true;
	}

	let explicitly_global = false;

	for (const s of selector.selectors) {
		/** @type {Compiler.AST.CSS.SelectorList | null} */
		let selector_list = null;
		let can_be_global = false;
		let owner = rule;

		if (s.type === 'PseudoClassSelector') {
			if ((s.name === 'is' || s.name === 'where') && s.args) {
				selector_list = s.args;
			} else {
				can_be_global = is_unscoped_pseudo_class(s);
			}
		}

		if (s.type === 'NestingSelector') {
			owner = /** @type {Compiler.AST.CSS.Rule} */ (rule.metadata.parent_rule);
			selector_list = owner.prelude;
		}

		const has_global_selectors = !!selector_list?.children.some((complex_selector) => {
			return complex_selector.children.every((relative_selector) =>
				is_global(relative_selector, owner)
			);
		});
		explicitly_global ||= has_global_selectors;

		if (!has_global_selectors && !can_be_global) {
			return false;
		}
	}

	return explicitly_global || selector.selectors.length === 0;
}

const regex_backslash_and_following_character = /\\(.)/g;

/**
 * Ensure that `element` satisfies each simple selector in `relative_selector`
 *
 * @param {Compiler.AST.CSS.RelativeSelector} relative_selector
 * @param {Compiler.AST.CSS.Rule} rule
 * @param {Compiler.AST.RegularElement | Compiler.AST.SvelteElement} element
 * @param {Direction} direction
 * @returns {boolean}
 */
function relative_selector_might_apply_to_node(relative_selector, rule, element, direction) {
	// Sort :has(...) selectors in one bucket and everything else into another
	const has_selectors = [];
	const other_selectors = [];

	for (const selector of relative_selector.selectors) {
		if (selector.type === 'PseudoClassSelector' && selector.name === 'has' && selector.args) {
			has_selectors.push(selector);
		} else {
			other_selectors.push(selector);
		}
	}

	// If we're called recursively from a :has(...) selector, we're on the way of checking if the other selectors match.
	// In that case ignore this check (because we just came from this) to avoid an infinite loop.
	if (has_selectors.length > 0) {
		// If this is a :has inside a global selector, we gotta include the element itself, too,
		// because the global selector might be for an element that's outside the component,
		// e.g. :root:has(.scoped), :global(.foo):has(.scoped), or :root { &:has(.scoped) {} }
		const rules = get_parent_rules(rule);
		const include_self =
			rules.some((r) => r.prelude.children.some((c) => c.children.some((s) => is_global(s, r)))) ||
			rules[rules.length - 1].prelude.children.some((c) =>
				c.children.some((r) =>
					r.selectors.some(
						(s) =>
							s.type === 'PseudoClassSelector' &&
							(s.name === 'root' || (s.name === 'global' && s.args))
					)
				)
			);

		// :has(...) is special in that it means "look downwards in the CSS tree". Since our matching algorithm goes
		// upwards and back-to-front, we need to first check the selectors inside :has(...), then check the rest of the
		// selector in a way that is similar to ancestor matching. In a sense, we're treating `.x:has(.y)` as `.x .y`.
		for (const has_selector of has_selectors) {
			const complex_selectors = /** @type {Compiler.AST.CSS.SelectorList} */ (has_selector.args)
				.children;
			let matched = false;

			for (const complex_selector of complex_selectors) {
				const [first, ...rest] = truncate(complex_selector);
				// if it was just a :global(...)
				if (!first) {
					complex_selector.metadata.used = true;
					matched = true;
					continue;
				}

				if (include_self) {
					const selector_including_self = [
						first.combinator ? { ...first, combinator: null } : first,
						...rest
					];
					if (apply_selector(selector_including_self, rule, element, FORWARD)) {
						complex_selector.metadata.used = true;
						matched = true;
					}
				}

				const selector_excluding_self = [
					any_selector,
					first.combinator ? first : { ...first, combinator: descendant_combinator },
					...rest
				];
				if (apply_selector(selector_excluding_self, rule, element, FORWARD)) {
					complex_selector.metadata.used = true;
					matched = true;
				}
			}

			if (!matched) {
				return false;
			}
		}
	}

	for (const selector of other_selectors) {
		if (selector.type === 'Percentage' || selector.type === 'Nth') continue;

		const name = selector.name.replace(regex_backslash_and_following_character, '$1');

		switch (selector.type) {
			case 'PseudoClassSelector': {
				if (name === 'host' || name === 'root') return false;

				if (
					name === 'global' &&
					selector.args !== null &&
					relative_selector.selectors.length === 1
				) {
					const args = selector.args;
					const complex_selector = args.children[0];
					return apply_selector(complex_selector.children, rule, element, BACKWARD);
				}

				// We came across a :global, everything beyond it is global and therefore a potential match
				if (name === 'global' && selector.args === null) return true;

				// :not(...) contents should stay unscoped. Scoping them would achieve the opposite of what we want,
				// because they are then _more_ likely to bleed out of the component. The exception is complex selectors
				// with descendants, in which case we scope them all.
				if (name === 'not' && selector.args) {
					for (const complex_selector of selector.args.children) {
						walk$1(complex_selector, null, {
							ComplexSelector(node, context) {
								node.metadata.used = true;
								context.next();
							}
						});
						const relative = truncate(complex_selector);

						if (complex_selector.children.length > 1) {
							// foo:not(bar foo) means that bar is an ancestor of foo (side note: ending with foo is the only way the selector make sense).
							// We can't fully check if that actually matches with our current algorithm, so we just assume it does.
							// The result may not match a real element, so the only drawback is the missing prune.
							for (const selector of relative) {
								selector.metadata.scoped = true;
							}

							/** @type {Compiler.AST.RegularElement | Compiler.AST.SvelteElement | null} */
							let el = element;
							while (el) {
								el.metadata.scoped = true;
								el = get_element_parent(el);
							}
						}
					}

					break;
				}

				if ((name === 'is' || name === 'where') && selector.args) {
					let matched = false;

					for (const complex_selector of selector.args.children) {
						const relative = truncate(complex_selector);
						const is_global = relative.length === 0;

						if (is_global) {
							complex_selector.metadata.used = true;
							matched = true;
						} else if (apply_selector(relative, rule, element, BACKWARD)) {
							complex_selector.metadata.used = true;
							matched = true;
						} else if (complex_selector.children.length > 1 && (name == 'is' || name == 'where')) {
							// foo :is(bar baz) can also mean that bar is an ancestor of foo, and baz a descendant.
							// We can't fully check if that actually matches with our current algorithm, so we just assume it does.
							// The result may not match a real element, so the only drawback is the missing prune.
							complex_selector.metadata.used = true;
							matched = true;
							for (const selector of relative) {
								selector.metadata.scoped = true;
							}
						}
					}

					if (!matched) {
						return false;
					}
				}

				break;
			}

			case 'PseudoElementSelector': {
				break;
			}

			case 'AttributeSelector': {
				const whitelisted = whitelist_attribute_selector.get(element.name.toLowerCase());
				if (
					!whitelisted?.includes(selector.name.toLowerCase()) &&
					!attribute_matches(
						element,
						selector.name,
						selector.value && unquote(selector.value),
						selector.matcher,
						selector.flags?.includes('i') ?? false
					)
				) {
					return false;
				}
				break;
			}

			case 'ClassSelector': {
				if (!attribute_matches(element, 'class', name, '~=', false)) {
					return false;
				}

				break;
			}

			case 'IdSelector': {
				if (!attribute_matches(element, 'id', name, '=', false)) {
					return false;
				}

				break;
			}

			case 'TypeSelector': {
				if (
					element.name.toLowerCase() !== name.toLowerCase() &&
					name !== '*' &&
					element.type !== 'SvelteElement'
				) {
					return false;
				}

				break;
			}

			case 'NestingSelector': {
				let matched = false;

				const parent = /** @type {Compiler.AST.CSS.Rule} */ (rule.metadata.parent_rule);

				for (const complex_selector of parent.prelude.children) {
					if (
						apply_selector(get_relative_selectors(complex_selector), parent, element, direction) ||
						complex_selector.children.every((s) => is_global(s, parent))
					) {
						complex_selector.metadata.used = true;
						matched = true;
					}
				}

				if (!matched) {
					return false;
				}

				break;
			}
		}
	}

	// possible match
	return true;
}

/**
 * @param {any} operator
 * @param {any} expected_value
 * @param {any} case_insensitive
 * @param {any} value
 */
function test_attribute(operator, expected_value, case_insensitive, value) {
	if (case_insensitive) {
		expected_value = expected_value.toLowerCase();
		value = value.toLowerCase();
	}
	switch (operator) {
		case '=':
			return value === expected_value;
		case '~=':
			return value.split(/\s/).includes(expected_value);
		case '|=':
			return `${value}-`.startsWith(`${expected_value}-`);
		case '^=':
			return value.startsWith(expected_value);
		case '$=':
			return value.endsWith(expected_value);
		case '*=':
			return value.includes(expected_value);
		default:
			throw new Error("this shouldn't happen");
	}
}

/**
 * @param {Compiler.AST.RegularElement | Compiler.AST.SvelteElement} node
 * @param {string} name
 * @param {string | null} expected_value
 * @param {string | null} operator
 * @param {boolean} case_insensitive
 */
function attribute_matches(node, name, expected_value, operator, case_insensitive) {
	for (const attribute of node.attributes) {
		if (attribute.type === 'SpreadAttribute') return true;
		if (attribute.type === 'BindDirective' && attribute.name === name) return true;

		const name_lower = name.toLowerCase();
		// match attributes against the corresponding directive but bail out on exact matching
		if (attribute.type === 'StyleDirective' && name_lower === 'style') return true;
		if (attribute.type === 'ClassDirective' && name_lower === 'class') {
			if (operator === '~=') {
				if (attribute.name === expected_value) return true;
			} else {
				return true;
			}
		}

		if (attribute.type !== 'Attribute') continue;
		if (attribute.name.toLowerCase() !== name_lower) continue;

		if (attribute.value === true) return operator === null;
		if (expected_value === null) return true;

		if (is_text_attribute(attribute)) {
			const matches = test_attribute(
				operator,
				expected_value,
				case_insensitive,
				attribute.value[0].data
			);
			// continue if we still may match against a class/style directive
			if (!matches && (name_lower === 'class' || name_lower === 'style')) continue;
			return matches;
		}

		const chunks = get_attribute_chunks(attribute.value);
		const possible_values = new Set();

		/** @type {string[]} */
		let prev_values = [];
		for (const chunk of chunks) {
			const current_possible_values = get_possible_values(chunk, name_lower === 'class');

			// impossible to find out all combinations
			if (!current_possible_values) return true;

			if (prev_values.length > 0) {
				/** @type {string[]} */
				const start_with_space = [];

				/** @type {string[]} */
				const remaining = [];

				current_possible_values.forEach((current_possible_value) => {
					if (regex_starts_with_whitespace.test(current_possible_value)) {
						start_with_space.push(current_possible_value);
					} else {
						remaining.push(current_possible_value);
					}
				});
				if (remaining.length > 0) {
					if (start_with_space.length > 0) {
						prev_values.forEach((prev_value) => possible_values.add(prev_value));
					}

					/** @type {string[]} */
					const combined = [];

					prev_values.forEach((prev_value) => {
						remaining.forEach((value) => {
							combined.push(prev_value + value);
						});
					});
					prev_values = combined;
					start_with_space.forEach((value) => {
						if (regex_ends_with_whitespace.test(value)) {
							possible_values.add(value);
						} else {
							prev_values.push(value);
						}
					});
					continue;
				} else {
					prev_values.forEach((prev_value) => possible_values.add(prev_value));
					prev_values = [];
				}
			}
			current_possible_values.forEach((current_possible_value) => {
				if (regex_ends_with_whitespace.test(current_possible_value)) {
					possible_values.add(current_possible_value);
				} else {
					prev_values.push(current_possible_value);
				}
			});
			if (prev_values.length < current_possible_values.length) {
				prev_values.push(' ');
			}
			if (prev_values.length > 20) {
				// might grow exponentially, bail out
				return true;
			}
		}
		prev_values.forEach((prev_value) => possible_values.add(prev_value));

		for (const value of possible_values) {
			if (test_attribute(operator, expected_value, case_insensitive, value)) return true;
		}
	}

	return false;
}

/** @param {string} str */
function unquote(str) {
	if ((str[0] === str[str.length - 1] && str[0] === "'") || str[0] === '"') {
		return str.slice(1, str.length - 1);
	}
	return str;
}

/**
 * @param {Compiler.AST.RegularElement | Compiler.AST.SvelteElement | Compiler.AST.RenderTag | Compiler.AST.Component | Compiler.AST.SvelteComponent | Compiler.AST.SvelteSelf} node
 * @param {boolean} adjacent_only
 * @param {Set<Compiler.AST.SnippetBlock>} seen
 */
function get_ancestor_elements(node, adjacent_only, seen = new Set()) {
	/** @type {Array<Compiler.AST.RegularElement | Compiler.AST.SvelteElement>} */
	const ancestors = [];

	const path = node.metadata.path;
	let i = path.length;

	while (i--) {
		const parent = path[i];

		if (parent.type === 'SnippetBlock') {
			if (!seen.has(parent)) {
				seen.add(parent);

				for (const site of parent.metadata.sites) {
					ancestors.push(...get_ancestor_elements(site, adjacent_only, seen));
				}
			}

			break;
		}

		if (parent.type === 'RegularElement' || parent.type === 'SvelteElement') {
			ancestors.push(parent);
			if (adjacent_only) {
				break;
			}
		}
	}

	return ancestors;
}

/**
 * @param {Compiler.AST.RegularElement | Compiler.AST.SvelteElement | Compiler.AST.RenderTag | Compiler.AST.Component | Compiler.AST.SvelteComponent | Compiler.AST.SvelteSelf} node
 * @param {boolean} adjacent_only
 * @param {Set<Compiler.AST.SnippetBlock>} seen
 */
function get_descendant_elements(node, adjacent_only, seen = new Set()) {
	/** @type {Array<Compiler.AST.RegularElement | Compiler.AST.SvelteElement>} */
	const descendants = [];

	/**
	 * @param {Compiler.AST.SvelteNode} node
	 */
	function walk_children(node) {
		walk$1(node, null, {
			_(node, context) {
				if (node.type === 'RegularElement' || node.type === 'SvelteElement') {
					descendants.push(node);

					if (!adjacent_only) {
						context.next();
					}
				} else if (node.type === 'RenderTag') {
					for (const snippet of node.metadata.snippets) {
						if (seen.has(snippet)) continue;

						seen.add(snippet);
						walk_children(snippet.body);
					}
				} else {
					context.next();
				}
			}
		});
	}

	walk_children(node.type === 'RenderTag' ? node : node.fragment);

	return descendants;
}

/**
 * @param {Compiler.AST.RegularElement | Compiler.AST.SvelteElement | Compiler.AST.RenderTag | Compiler.AST.Component | Compiler.AST.SvelteComponent | Compiler.AST.SvelteSelf} node
 * @returns {Compiler.AST.RegularElement | Compiler.AST.SvelteElement | null}
 */
function get_element_parent(node) {
	let path = node.metadata.path;
	let i = path.length;

	while (i--) {
		const parent = path[i];

		if (parent.type === 'RegularElement' || parent.type === 'SvelteElement') {
			return parent;
		}
	}

	return null;
}

/**
 * @param {Compiler.AST.RegularElement | Compiler.AST.SvelteElement | Compiler.AST.RenderTag | Compiler.AST.Component | Compiler.AST.SvelteComponent | Compiler.AST.SvelteSelf} node
 * @param {Direction} direction
 * @param {boolean} adjacent_only
 * @param {Set<Compiler.AST.SnippetBlock>} seen
 * @returns {Map<Compiler.AST.RegularElement | Compiler.AST.SvelteElement | Compiler.AST.SlotElement | Compiler.AST.RenderTag | Compiler.AST.Component, NodeExistsValue>}
 */
function get_possible_element_siblings(node, direction, adjacent_only, seen = new Set()) {
	/** @type {Map<Compiler.AST.RegularElement | Compiler.AST.SvelteElement | Compiler.AST.SlotElement | Compiler.AST.RenderTag | Compiler.AST.Component, NodeExistsValue>} */
	const result = new Map();
	const path = node.metadata.path;

	/** @type {Compiler.AST.SvelteNode} */
	let current = node;

	let i = path.length;

	while (i--) {
		const fragment = /** @type {Compiler.AST.Fragment} */ (path[i--]);
		let j = fragment.nodes.indexOf(current) + (direction === FORWARD ? 1 : -1);

		while (j >= 0 && j < fragment.nodes.length) {
			const node = fragment.nodes[j];

			if (node.type === 'RegularElement') {
				const has_slot_attribute = node.attributes.some(
					(attr) => attr.type === 'Attribute' && attr.name.toLowerCase() === 'slot'
				);

				if (!has_slot_attribute) {
					result.set(node, NODE_DEFINITELY_EXISTS);

					if (adjacent_only) {
						return result;
					}
				}
				// Special case: slots, render tags and svelte:element tags could resolve to no siblings,
				// so we want to continue until we find a definite sibling even with the adjacent-only combinator
			} else if (is_block(node) || node.type === 'Component') {
				if (node.type === 'SlotElement' || node.type === 'Component') {
					result.set(node, NODE_PROBABLY_EXISTS);
				}

				const possible_last_child = get_possible_nested_siblings(node, direction, adjacent_only);
				add_to_map(possible_last_child, result);
				if (
					adjacent_only &&
					node.type !== 'Component' &&
					has_definite_elements(possible_last_child)
				) {
					return result;
				}
			} else if (node.type === 'SvelteElement') {
				result.set(node, NODE_PROBABLY_EXISTS);
			} else if (node.type === 'RenderTag') {
				result.set(node, NODE_PROBABLY_EXISTS);
				for (const snippet of node.metadata.snippets) {
					add_to_map(get_possible_nested_siblings(snippet, direction, adjacent_only), result);
				}
			}

			j = direction === FORWARD ? j + 1 : j - 1;
		}

		current = path[i];

		if (!current) break;

		if (
			current.type === 'Component' ||
			current.type === 'SvelteComponent' ||
			current.type === 'SvelteSelf'
		) {
			continue;
		}

		if (current.type === 'SnippetBlock') {
			if (seen.has(current)) break;
			seen.add(current);

			for (const site of current.metadata.sites) {
				const siblings = get_possible_element_siblings(site, direction, adjacent_only, seen);
				add_to_map(siblings, result);

				if (adjacent_only && current.metadata.sites.size === 1 && has_definite_elements(siblings)) {
					return result;
				}
			}
		}

		if (!is_block(current)) break;

		if (current.type === 'EachBlock' && fragment === current.body) {
			// `{#each ...}<a /><b />{/each}` — `<b>` can be previous sibling of `<a />`
			add_to_map(get_possible_nested_siblings(current, direction, adjacent_only), result);
		}
	}

	return result;
}

/**
 * @param {Compiler.AST.EachBlock | Compiler.AST.IfBlock | Compiler.AST.AwaitBlock | Compiler.AST.KeyBlock | Compiler.AST.SlotElement | Compiler.AST.SnippetBlock | Compiler.AST.Component} node
 * @param {Direction} direction
 * @param {boolean} adjacent_only
 * @param {Set<Compiler.AST.SnippetBlock>} seen
 * @returns {Map<Compiler.AST.RegularElement | Compiler.AST.SvelteElement, NodeExistsValue>}
 */
function get_possible_nested_siblings(node, direction, adjacent_only, seen = new Set()) {
	/** @type {Array<Compiler.AST.Fragment | undefined | null>} */
	let fragments = [];

	switch (node.type) {
		case 'EachBlock':
			fragments.push(node.body, node.fallback);
			break;

		case 'IfBlock':
			fragments.push(node.consequent, node.alternate);
			break;

		case 'AwaitBlock':
			fragments.push(node.pending, node.then, node.catch);
			break;

		case 'KeyBlock':
		case 'SlotElement':
			fragments.push(node.fragment);
			break;

		case 'SnippetBlock':
			if (seen.has(node)) {
				return new Map();
			}
			seen.add(node);
			fragments.push(node.body);
			break;

		case 'Component':
			fragments.push(node.fragment, ...[...node.metadata.snippets].map((s) => s.body));
			break;
	}

	/** @type {Map<Compiler.AST.RegularElement | Compiler.AST.SvelteElement, NodeExistsValue>} NodeMap */
	const result = new Map();

	let exhaustive = node.type !== 'SlotElement' && node.type !== 'SnippetBlock';

	for (const fragment of fragments) {
		if (fragment == null) {
			exhaustive = false;
			continue;
		}

		const map = loop_child(fragment.nodes, direction, adjacent_only, seen);
		exhaustive &&= has_definite_elements(map);

		add_to_map(map, result);
	}

	if (!exhaustive) {
		for (const key of result.keys()) {
			result.set(key, NODE_PROBABLY_EXISTS);
		}
	}

	return result;
}

/**
 * @param {Map<unknown, NodeExistsValue>} result
 * @returns {boolean}
 */
function has_definite_elements(result) {
	if (result.size === 0) return false;
	for (const exist of result.values()) {
		if (exist === NODE_DEFINITELY_EXISTS) {
			return true;
		}
	}
	return false;
}

/**
 * @template T2
 * @template {T2} T1
 * @param {Map<T1, NodeExistsValue>} from
 * @param {Map<T2, NodeExistsValue>} to
 * @returns {void}
 */
function add_to_map(from, to) {
	from.forEach((exist, element) => {
		to.set(element, higher_existence(exist, to.get(element)));
	});
}

/**
 * @param {NodeExistsValue} exist1
 * @param {NodeExistsValue | undefined} exist2
 * @returns {NodeExistsValue}
 */
function higher_existence(exist1, exist2) {
	if (exist2 === undefined) return exist1;
	return exist1 > exist2 ? exist1 : exist2;
}

/**
 * @param {Compiler.AST.SvelteNode[]} children
 * @param {Direction} direction
 * @param {boolean} adjacent_only
 * @param {Set<Compiler.AST.SnippetBlock>} seen
 */
function loop_child(children, direction, adjacent_only, seen) {
	/** @type {Map<Compiler.AST.RegularElement | Compiler.AST.SvelteElement, NodeExistsValue>} */
	const result = new Map();

	let i = direction === FORWARD ? 0 : children.length - 1;

	while (i >= 0 && i < children.length) {
		const child = children[i];

		if (child.type === 'RegularElement') {
			result.set(child, NODE_DEFINITELY_EXISTS);
			if (adjacent_only) {
				break;
			}
		} else if (child.type === 'SvelteElement') {
			result.set(child, NODE_PROBABLY_EXISTS);
		} else if (child.type === 'RenderTag') {
			for (const snippet of child.metadata.snippets) {
				add_to_map(get_possible_nested_siblings(snippet, direction, adjacent_only, seen), result);
			}
		} else if (is_block(child)) {
			const child_result = get_possible_nested_siblings(child, direction, adjacent_only, seen);
			add_to_map(child_result, result);
			if (adjacent_only && has_definite_elements(child_result)) {
				break;
			}
		}

		i = direction === FORWARD ? i + 1 : i - 1;
	}

	return result;
}

/**
 * @param {Compiler.AST.SvelteNode} node
 * @returns {node is Compiler.AST.IfBlock | Compiler.AST.EachBlock | Compiler.AST.AwaitBlock | Compiler.AST.KeyBlock | Compiler.AST.SlotElement}
 */
function is_block(node) {
	return (
		node.type === 'IfBlock' ||
		node.type === 'EachBlock' ||
		node.type === 'AwaitBlock' ||
		node.type === 'KeyBlock' ||
		node.type === 'SlotElement'
	);
}

/** @import { Visitors } from 'zimmerframe' */
/** @import { AST } from '#compiler' */

/**
 * @param {AST.CSS.StyleSheet} stylesheet
 */
function warn_unused(stylesheet) {
	walk$1(stylesheet, { stylesheet }, visitors$3);
}

/** @type {Visitors<AST.CSS.Node, { stylesheet: AST.CSS.StyleSheet }>} */
const visitors$3 = {
	Atrule(node, context) {
		if (!is_keyframes_node(node)) {
			context.next();
		}
	},
	PseudoClassSelector(node, context) {
		if (node.name === 'is' || node.name === 'where') {
			context.next();
		}
	},
	ComplexSelector(node, context) {
		if (
			!node.metadata.used &&
			// prevent double-marking of `.unused:is(.unused)`
			(context.path.at(-2)?.type !== 'PseudoClassSelector' ||
				/** @type {AST.CSS.ComplexSelector} */ (context.path.at(-4))?.metadata.used)
		) {
			const content = context.state.stylesheet.content;
			const text = content.styles.substring(node.start - content.start, node.end - content.start);
			css_unused_selector(node, text);
		}

		context.next();
	},
	Rule(node, context) {
		if (node.metadata.is_global_block) {
			context.visit(node.prelude);
		} else {
			context.next();
		}
	}
};

/** @import { ArrowFunctionExpression, FunctionDeclaration, FunctionExpression } from 'estree' */
/** @import { Context } from '../../types' */

/**
 * @param {ArrowFunctionExpression | FunctionExpression | FunctionDeclaration} node
 * @param {Context} context
 */
function visit_function$1(node, context) {
	if (context.state.expression) {
		for (const [name] of context.state.scope.references) {
			const binding = context.state.scope.get(name);

			if (binding && binding.scope.function_depth < context.state.scope.function_depth) {
				context.state.expression.references.add(binding);
			}
		}
	}

	context.next({
		...context.state,
		function_depth: context.state.function_depth + 1,
		expression: null
	});
}

/** @import { ArrowFunctionExpression } from 'estree' */
/** @import { Context } from '../types' */

/**
 * @param {ArrowFunctionExpression} node
 * @param {Context} context
 */
function ArrowFunctionExpression$1(node, context) {
	visit_function$1(node, context);
}

/** @import { AssignmentExpression } from 'estree' */
/** @import { Context } from '../types' */

/**
 * @param {AssignmentExpression} node
 * @param {Context} context
 */
function AssignmentExpression$2(node, context) {
	validate_assignment(node, node.left, context);

	if (context.state.reactive_statement) {
		const id = node.left.type === 'MemberExpression' ? object$1(node.left) : node.left;
		if (id !== null) {
			for (const id of extract_identifiers(node.left)) {
				const binding = context.state.scope.get(id.name);

				if (binding) {
					context.state.reactive_statement.assignments.add(binding);
				}
			}
		}
	}

	if (context.state.expression) {
		context.state.expression.has_assignment = true;
	}

	context.next();
}

/** @import { Context } from '../types' */
/** @import { AST } from '#compiler'; */

/**
 * @param {AST.AnimateDirective} node
 * @param {Context} context
 */
function AnimateDirective$1(node, context) {
	context.next({ ...context.state, expression: node.metadata.expression });

	if (node.metadata.expression.has_await) {
		illegal_await_expression(node);
	}
}

/** @import { AST } from '#compiler' */

/**
 * @param {AST.SvelteNode[]} path
 */
function mark_subtree_dynamic(path) {
	let i = path.length;
	while (i--) {
		const node = path[i];
		if (node.type === 'Fragment') {
			if (node.metadata.dynamic) return;
			node.metadata.dynamic = true;
		}
	}
}

/** @import { AST } from '#compiler' */
/** @import { Context } from '../types' */

/**
 * @param {AST.AttachTag} node
 * @param {Context} context
 */
function AttachTag$1(node, context) {
	mark_subtree_dynamic(context.path);
	context.next({ ...context.state, expression: node.metadata.expression });

	if (node.metadata.expression.has_await) {
		illegal_await_expression(node);
	}
}

/** @import { AST } from '#compiler' */
/** @import { Context } from '../types' */

/**
 * @param {AST.Attribute} node
 * @param {Context} context
 */
function Attribute$1(node, context) {
	context.next();

	const parent = /** @type {AST.SvelteNode} */ (context.path.at(-1));

	if (parent.type === 'RegularElement') {
		// special case <option value="" />
		if (node.name === 'value' && parent.name === 'option') {
			mark_subtree_dynamic(context.path);
		}
	}

	if (is_event_attribute(node)) {
		mark_subtree_dynamic(context.path);
	}

	if (cannot_be_set_statically(node.name)) {
		mark_subtree_dynamic(context.path);
	}

	// class={[...]} or class={{...}} or `class={x}` need clsx to resolve the classes
	if (
		node.name === 'class' &&
		!Array.isArray(node.value) &&
		node.value !== true &&
		node.value.expression.type !== 'Literal' &&
		node.value.expression.type !== 'TemplateLiteral' &&
		node.value.expression.type !== 'BinaryExpression'
	) {
		mark_subtree_dynamic(context.path);
		node.metadata.needs_clsx = true;
	}

	if (node.value !== true) {
		for (const chunk of get_attribute_chunks(node.value)) {
			if (chunk.type !== 'ExpressionTag') continue;

			if (
				chunk.expression.type === 'FunctionExpression' ||
				chunk.expression.type === 'ArrowFunctionExpression'
			) {
				continue;
			}
		}

		if (is_event_attribute(node)) {
			const parent = context.path.at(-1);
			if (parent?.type === 'RegularElement' || parent?.type === 'SvelteElement') {
				context.state.analysis.uses_event_attributes = true;
			}

			node.metadata.delegated =
				parent?.type === 'RegularElement' && can_delegate_event(node.name.slice(2));
		}
	}
}

/** @import { AST } from '#compiler' */
/** @import { Context } from '../types' */

/**
 * @param {AST.AwaitBlock} node
 * @param {Context} context
 */
function AwaitBlock$2(node, context) {
	validate_block_not_empty(node.pending);
	validate_block_not_empty(node.then);
	validate_block_not_empty(node.catch);

	if (context.state.analysis.runes) {
		validate_opening_tag(node, context.state, '#');

		if (node.value) {
			const start = /** @type {number} */ (node.value.start);
			const match = context.state.analysis.source
				.substring(start - 10, start)
				.match(/{(\s*):then\s+$/);

			if (match && match[1] !== '') {
				block_unexpected_character({ start: start - 10, end: start }, ':');
			}
		}

		if (node.error) {
			const start = /** @type {number} */ (node.error.start);
			const match = context.state.analysis.source
				.substring(start - 10, start)
				.match(/{(\s*):catch\s+$/);

			if (match && match[1] !== '') {
				block_unexpected_character({ start: start - 10, end: start }, ':');
			}
		}
	}

	mark_subtree_dynamic(context.path);

	context.visit(node.expression, { ...context.state, expression: node.metadata.expression });
	if (node.pending) context.visit(node.pending);
	if (node.then) context.visit(node.then);
	if (node.catch) context.visit(node.catch);
}

/** @import { AwaitExpression, Expression, SpreadElement, Property } from 'estree' */
/** @import { Context } from '../types' */
/** @import { AST } from '#compiler' */

/**
 * @param {AwaitExpression} node
 * @param {Context} context
 */
function AwaitExpression$2(node, context) {
	const tla = context.state.ast_type === 'instance' && context.state.function_depth === 1;

	// preserve context for awaits that precede other expressions in template or `$derived(...)`
	if (
		is_reactive_expression(
			context.path,
			context.state.derived_function_depth === context.state.function_depth
		) &&
		!is_last_evaluated_expression(context.path, node)
	) {
		context.state.analysis.pickled_awaits.add(node);
	}

	let suspend = tla;

	if (context.state.expression) {
		context.state.expression.has_await = true;

		suspend = true;
	}

	// disallow top-level `await` or `await` in template expressions
	// unless a) in runes mode and b) opted into `experimental.async`
	if (suspend) {
		if (!context.state.options.experimental.async) {
			experimental_async(node);
		}

		if (!context.state.analysis.runes) {
			legacy_await_invalid(node);
		}
	}

	context.next();
}

/**
 * @param {AST.SvelteNode[]} path
 * @param {boolean} in_derived
 */
function is_reactive_expression(path, in_derived) {
	if (in_derived) return true;

	let i = path.length;

	while (i--) {
		const parent = path[i];

		if (
			parent.type === 'ArrowFunctionExpression' ||
			parent.type === 'FunctionExpression' ||
			parent.type === 'FunctionDeclaration'
		) {
			// No reactive expression found between function and await
			return false;
		}

		// @ts-expect-error we could probably use a neater/more robust mechanism
		if (parent.metadata) {
			return true;
		}
	}

	return false;
}

/**
 * @param {AST.SvelteNode[]} path
 * @param {Expression | SpreadElement | Property} node
 */
function is_last_evaluated_expression(path, node) {
	let i = path.length;

	while (i--) {
		const parent = path[i];

		if (parent.type === 'ConstTag') {
			// {@const ...} tags are treated as deriveds and its contents should all get the preserve-reactivity treatment
			return false;
		}

		// @ts-expect-error we could probably use a neater/more robust mechanism
		if (parent.metadata) {
			return true;
		}

		switch (parent.type) {
			case 'ArrayExpression':
				if (node !== parent.elements.at(-1)) return false;
				break;

			case 'AssignmentExpression':
			case 'BinaryExpression':
			case 'LogicalExpression':
				if (node === parent.left) return false;
				break;

			case 'CallExpression':
			case 'NewExpression':
				if (node !== parent.arguments.at(-1)) return false;
				break;

			case 'ConditionalExpression':
				if (node === parent.test) return false;
				break;

			case 'MemberExpression':
				if (parent.computed && node === parent.object) return false;
				break;

			case 'ObjectExpression':
				if (node !== parent.properties.at(-1)) return false;
				break;

			case 'Property':
				if (node === parent.key) return false;
				break;

			case 'SequenceExpression':
				if (node !== parent.expressions.at(-1)) return false;
				break;

			case 'TaggedTemplateExpression':
				if (node !== parent.quasi.expressions.at(-1)) return false;
				break;

			case 'TemplateLiteral':
				if (node !== parent.expressions.at(-1)) return false;
				break;

			case 'VariableDeclarator':
				return true;

			default:
				return false;
		}

		node = parent;
	}
}

/**
 * @typedef BindingProperty
 * @property {string} [event] This is set if the binding corresponds to the property name on the dom element it's bound to
 * 							  and there's an event that notifies of a change to that property
 * @property {boolean} [bidirectional] Set this to `true` if updates are written to the dom property
 * @property {boolean} [omit_in_ssr] Set this to true if the binding should not be included in SSR
 * @property {string[]} [valid_elements] If this is set, the binding is only valid on the given elements
 * @property {string[]} [invalid_elements] If this is set, the binding is invalid on the given elements
 */

/**
 * @type {Record<string, BindingProperty>}
 */
const binding_properties = {
	// media
	currentTime: {
		valid_elements: ['audio', 'video'],
		omit_in_ssr: true,
		bidirectional: true
	},
	duration: {
		valid_elements: ['audio', 'video'],
		event: 'durationchange',
		omit_in_ssr: true
	},
	focused: {},
	paused: {
		valid_elements: ['audio', 'video'],
		omit_in_ssr: true,
		bidirectional: true
	},
	buffered: {
		valid_elements: ['audio', 'video'],
		omit_in_ssr: true
	},
	seekable: {
		valid_elements: ['audio', 'video'],
		omit_in_ssr: true
	},
	played: {
		valid_elements: ['audio', 'video'],
		omit_in_ssr: true
	},
	volume: {
		valid_elements: ['audio', 'video'],
		omit_in_ssr: true,
		bidirectional: true
	},
	muted: {
		valid_elements: ['audio', 'video'],
		omit_in_ssr: true,
		bidirectional: true
	},
	playbackRate: {
		valid_elements: ['audio', 'video'],
		omit_in_ssr: true,
		bidirectional: true
	},
	seeking: {
		valid_elements: ['audio', 'video'],
		omit_in_ssr: true
	},
	ended: {
		valid_elements: ['audio', 'video'],
		omit_in_ssr: true
	},
	readyState: {
		valid_elements: ['audio', 'video'],
		omit_in_ssr: true
	},
	// video
	videoHeight: {
		valid_elements: ['video'],
		event: 'resize',
		omit_in_ssr: true
	},
	videoWidth: {
		valid_elements: ['video'],
		event: 'resize',
		omit_in_ssr: true
	},
	// img
	naturalWidth: {
		valid_elements: ['img'],
		event: 'load',
		omit_in_ssr: true
	},
	naturalHeight: {
		valid_elements: ['img'],
		event: 'load',
		omit_in_ssr: true
	},
	// document
	activeElement: {
		valid_elements: ['svelte:document'],
		omit_in_ssr: true
	},
	fullscreenElement: {
		valid_elements: ['svelte:document'],
		event: 'fullscreenchange',
		omit_in_ssr: true
	},
	pointerLockElement: {
		valid_elements: ['svelte:document'],
		event: 'pointerlockchange',
		omit_in_ssr: true
	},
	visibilityState: {
		valid_elements: ['svelte:document'],
		event: 'visibilitychange',
		omit_in_ssr: true
	},
	// window
	innerWidth: {
		valid_elements: ['svelte:window'],
		omit_in_ssr: true
	},
	innerHeight: {
		valid_elements: ['svelte:window'],
		omit_in_ssr: true
	},
	outerWidth: {
		valid_elements: ['svelte:window'],
		omit_in_ssr: true
	},
	outerHeight: {
		valid_elements: ['svelte:window'],
		omit_in_ssr: true
	},
	scrollX: {
		valid_elements: ['svelte:window'],
		omit_in_ssr: true,
		bidirectional: true
	},
	scrollY: {
		valid_elements: ['svelte:window'],
		omit_in_ssr: true,
		bidirectional: true
	},
	online: {
		valid_elements: ['svelte:window'],
		omit_in_ssr: true
	},
	devicePixelRatio: {
		valid_elements: ['svelte:window'],
		event: 'resize',
		omit_in_ssr: true
	},
	// dimensions
	clientWidth: {
		omit_in_ssr: true,
		invalid_elements: ['svelte:window', 'svelte:document']
	},
	clientHeight: {
		omit_in_ssr: true,
		invalid_elements: ['svelte:window', 'svelte:document']
	},
	offsetWidth: {
		omit_in_ssr: true,
		invalid_elements: ['svelte:window', 'svelte:document']
	},
	offsetHeight: {
		omit_in_ssr: true,
		invalid_elements: ['svelte:window', 'svelte:document']
	},
	contentRect: {
		omit_in_ssr: true,
		invalid_elements: ['svelte:window', 'svelte:document']
	},
	contentBoxSize: {
		omit_in_ssr: true,
		invalid_elements: ['svelte:window', 'svelte:document']
	},
	borderBoxSize: {
		omit_in_ssr: true,
		invalid_elements: ['svelte:window', 'svelte:document']
	},
	devicePixelContentBoxSize: {
		omit_in_ssr: true,
		invalid_elements: ['svelte:window', 'svelte:document']
	},
	// checkbox/radio
	indeterminate: {
		event: 'change',
		bidirectional: true,
		valid_elements: ['input'],
		omit_in_ssr: true // no corresponding attribute
	},
	checked: {
		valid_elements: ['input'],
		bidirectional: true
	},
	group: {
		valid_elements: ['input'],
		bidirectional: true
	},
	// various
	this: {
		omit_in_ssr: true
	},
	innerText: {
		invalid_elements: ['svelte:window', 'svelte:document'],
		bidirectional: true
	},
	innerHTML: {
		invalid_elements: ['svelte:window', 'svelte:document'],
		bidirectional: true
	},
	textContent: {
		invalid_elements: ['svelte:window', 'svelte:document'],
		bidirectional: true
	},
	open: {
		event: 'toggle',
		bidirectional: true,
		valid_elements: ['details']
	},
	value: {
		valid_elements: ['input', 'textarea', 'select'],
		bidirectional: true
	},
	files: {
		valid_elements: ['input'],
		omit_in_ssr: true,
		bidirectional: true
	}
};

/** @import { AST } from '#compiler' */
/** @import { Context } from '../types' */

/**
 * @param {AST.BindDirective} node
 * @param {Context} context
 */
function BindDirective$1(node, context) {
	const parent = context.path.at(-1);

	if (
		parent?.type === 'RegularElement' ||
		parent?.type === 'SvelteElement' ||
		parent?.type === 'SvelteWindow' ||
		parent?.type === 'SvelteDocument' ||
		parent?.type === 'SvelteBody'
	) {
		if (node.name in binding_properties) {
			const property = binding_properties[node.name];
			if (property.valid_elements && !property.valid_elements.includes(parent.name)) {
				bind_invalid_target(
					node,
					node.name,
					property.valid_elements.map((valid_element) => `\`<${valid_element}>\``).join(', ')
				);
			}

			if (property.invalid_elements && property.invalid_elements.includes(parent.name)) {
				const valid_bindings = Object.entries(binding_properties)
					.filter(([_, binding_property]) => {
						return (
							binding_property.valid_elements?.includes(parent.name) ||
							(!binding_property.valid_elements &&
								!binding_property.invalid_elements?.includes(parent.name))
						);
					})
					.map(([property_name]) => property_name)
					.sort();

				bind_invalid_name(
					node,
					node.name,
					`Possible bindings for <${parent.name}> are ${valid_bindings.join(', ')}`
				);
			}

			if (parent.name === 'input' && node.name !== 'this') {
				const type = /** @type {AST.Attribute | undefined} */ (
					parent.attributes.find((a) => a.type === 'Attribute' && a.name === 'type')
				);

				if (type && !is_text_attribute(type)) {
					if (node.name !== 'value' || type.value === true) {
						attribute_invalid_type(type);
					}
				} else {
					if (node.name === 'checked' && type?.value[0].data !== 'checkbox') {
						bind_invalid_target(
							node,
							node.name,
							`\`<input type="checkbox">\`${type?.value[0].data === 'radio' ? ` — for \`<input type="radio">\`, use \`bind:group\`` : ''}`
						);
					}

					if (node.name === 'files' && type?.value[0].data !== 'file') {
						bind_invalid_target(node, node.name, '`<input type="file">`');
					}
				}
			}

			if (parent.name === 'select' && node.name !== 'this') {
				const multiple = parent.attributes.find(
					(a) =>
						a.type === 'Attribute' &&
						a.name === 'multiple' &&
						!is_text_attribute(a) &&
						a.value !== true
				);

				if (multiple) {
					attribute_invalid_multiple(multiple);
				}
			}

			if (node.name === 'offsetWidth' && is_svg(parent.name)) {
				bind_invalid_target(
					node,
					node.name,
					`non-\`<svg>\` elements. Use \`bind:clientWidth\` for \`<svg>\` instead`
				);
			}

			if (is_content_editable_binding(node.name)) {
				const contenteditable = /** @type {AST.Attribute} */ (
					parent.attributes.find((a) => a.type === 'Attribute' && a.name === 'contenteditable')
				);

				if (!contenteditable) {
					attribute_contenteditable_missing(node);
				} else if (!is_text_attribute(contenteditable) && contenteditable.value !== true) {
					attribute_contenteditable_dynamic(contenteditable);
				}
			}
		} else {
			const match = fuzzymatch(node.name, Object.keys(binding_properties));

			if (match) {
				const property = binding_properties[match];
				if (!property.valid_elements || property.valid_elements.includes(parent.name)) {
					bind_invalid_name(node, node.name, `Did you mean '${match}'?`);
				}
			}

			bind_invalid_name(node, node.name);
		}
	}

	// When dealing with bind getters/setters skip the specific binding validation
	// Group bindings aren't supported for getter/setters so we don't need to handle
	// the metadata
	if (node.expression.type === 'SequenceExpression') {
		if (node.name === 'group') {
			bind_group_invalid_expression(node);
		}

		let i = /** @type {number} */ (node.expression.start);
		let leading_comments_start = /**@type {any}*/ (node.expression.leadingComments?.at(0))?.start;
		let leading_comments_end = /**@type {any}*/ (node.expression.leadingComments?.at(-1))?.end;
		while (context.state.analysis.source[--i] !== '{') {
			if (
				context.state.analysis.source[i] === '(' &&
				// if the parenthesis is in a leading comment we don't need to throw the error
				!(
					leading_comments_start &&
					leading_comments_end &&
					i <= leading_comments_end &&
					i >= leading_comments_start
				)
			) {
				bind_invalid_parens(node, node.name);
			}
		}

		if (node.expression.expressions.length !== 2) {
			bind_invalid_expression(node);
		}

		mark_subtree_dynamic(context.path);

		const [get, set] = node.expression.expressions;
		// We gotta jump across the getter/setter functions to avoid the expression metadata field being reset to null
		// as we want to collect the functions' blocker/async info
		context.visit(get.type === 'ArrowFunctionExpression' ? get.body : get, {
			...context.state,
			expression: node.metadata.expression
		});
		context.visit(set.type === 'ArrowFunctionExpression' ? set.body : set, {
			...context.state,
			expression: node.metadata.expression
		});

		if (node.metadata.expression.has_await) {
			illegal_await_expression(node);
		}

		return;
	}

	validate_assignment(node, node.expression, context);

	const assignee = node.expression;
	const left = object$1(assignee);

	if (left === null) {
		bind_invalid_expression(node);
	}

	const binding = context.state.scope.get(left.name);
	node.metadata.binding = binding;

	if (assignee.type === 'Identifier') {
		// reassignment
		if (
			node.name !== 'this' && // bind:this also works for regular variables
			(!binding ||
				(binding.kind !== 'state' &&
					binding.kind !== 'raw_state' &&
					binding.kind !== 'prop' &&
					binding.kind !== 'bindable_prop' &&
					binding.kind !== 'each' &&
					binding.kind !== 'store_sub' &&
					!binding.updated)) // TODO wut?
		) {
			bind_invalid_value(node.expression);
		}
	}

	if (node.name === 'group') {
		if (!binding) {
			throw new Error('Cannot find declaration for bind:group');
		}

		if (binding.kind === 'snippet') {
			bind_group_invalid_snippet_parameter(node);
		}

		// Traverse the path upwards and find all EachBlocks who are (indirectly) contributing to bind:group,
		// i.e. one of their declarations is referenced in the binding. This allows group bindings to work
		// correctly when referencing a variable declared in an EachBlock by using the index of the each block
		// entries as keys.
		const each_blocks = [];
		const [keypath, expression_ids] = extract_all_identifiers_from_expression(node.expression);
		let ids = expression_ids;

		let i = context.path.length;
		while (i--) {
			const parent = context.path[i];

			if (parent.type === 'EachBlock') {
				const references = ids.filter((id) => parent.metadata.declarations.has(id.name));

				if (references.length > 0) {
					parent.metadata.contains_group_binding = true;

					each_blocks.push(parent);
					ids = ids.filter((id) => !references.includes(id));
					ids.push(...extract_all_identifiers_from_expression(parent.expression)[1]);
				}
			}
		}

		// The identifiers that make up the binding expression form they key for the binding group.
		// If the same identifiers in the same order are used in another bind:group, they will be in the same group.
		// (there's an edge case where `bind:group={a[i]}` will be in a different group than `bind:group={a[j]}` even when i == j,
		//  but this is a limitation of the current static analysis we do; it also never worked in Svelte 4)
		const bindings = expression_ids.map((id) => context.state.scope.get(id.name));
		let group_name;

		outer: for (const [[key, b], group] of context.state.analysis.binding_groups) {
			if (b.length !== bindings.length || key !== keypath) continue;
			for (let i = 0; i < bindings.length; i++) {
				if (bindings[i] !== b[i]) continue outer;
			}
			group_name = group;
		}

		if (!group_name) {
			group_name = context.state.scope.root.unique('binding_group');
			context.state.analysis.binding_groups.set([keypath, bindings], group_name);
		}

		node.metadata = {
			binding_group_name: group_name,
			parent_each_blocks: each_blocks,
			expression: node.metadata.expression
		};
	}

	if (binding?.kind === 'each' && binding.metadata?.inside_rest) {
		bind_invalid_each_rest(binding.node, binding.node.name);
	}

	context.next({ ...context.state, expression: node.metadata.expression });

	if (node.metadata.expression.has_await) {
		illegal_await_expression(node);
	}
}

/** @import { ArrowFunctionExpression, CallExpression, Expression, FunctionDeclaration, FunctionExpression, Identifier, VariableDeclarator } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { Context } from '../types' */

/**
 * @param {CallExpression} node
 * @param {Context} context
 */
function CallExpression$2(node, context) {
	const parent = /** @type {AST.SvelteNode} */ (get_parent(context.path, -1));

	const rune = get_rune(node, context.state.scope);

	if (rune && rune !== '$inspect') {
		for (const arg of node.arguments) {
			if (arg.type === 'SpreadElement') {
				rune_invalid_spread(node, rune);
			}
		}
	}

	switch (rune) {
		case null:
			if (!is_safe_identifier(node.callee, context.state.scope)) {
				context.state.analysis.needs_context = true;
			}

			break;

		case '$bindable':
			if (node.arguments.length > 1) {
				rune_invalid_arguments_length(node, '$bindable', 'zero or one arguments');
			}

			if (
				parent.type !== 'AssignmentPattern' ||
				context.path.at(-3)?.type !== 'ObjectPattern' ||
				context.path.at(-4)?.type !== 'VariableDeclarator' ||
				get_rune(
					/** @type {VariableDeclarator} */ (context.path.at(-4)).init,
					context.state.scope
				) !== '$props'
			) {
				bindable_invalid_location(node);
			}

			// We need context in case the bound prop is stale
			context.state.analysis.needs_context = true;

			break;

		case '$host':
			if (node.arguments.length > 0) {
				rune_invalid_arguments(node, '$host');
			} else if (context.state.ast_type === 'module' || !context.state.analysis.custom_element) {
				host_invalid_placement(node);
			}

			break;

		case '$props':
			if (context.state.has_props_rune) {
				props_duplicate(node, rune);
			}

			context.state.has_props_rune = true;

			if (
				parent.type !== 'VariableDeclarator' ||
				context.state.ast_type !== 'instance' ||
				context.state.scope !== context.state.analysis.instance.scope
			) {
				props_invalid_placement(node);
			}

			if (node.arguments.length > 0) {
				rune_invalid_arguments(node, rune);
			}

			break;

		case '$props.id': {
			const grand_parent = get_parent(context.path, -2);

			if (context.state.analysis.props_id) {
				props_duplicate(node, rune);
			}

			if (
				parent.type !== 'VariableDeclarator' ||
				parent.id.type !== 'Identifier' ||
				context.state.ast_type !== 'instance' ||
				context.state.scope !== context.state.analysis.instance.scope ||
				grand_parent.type !== 'VariableDeclaration'
			) {
				props_id_invalid_placement(node);
			}

			if (node.arguments.length > 0) {
				rune_invalid_arguments(node, rune);
			}

			context.state.analysis.props_id = parent.id;

			break;
		}

		case '$state':
		case '$state.raw':
		case '$derived':
		case '$derived.by': {
			const valid =
				is_variable_declaration(parent, context) ||
				is_class_property_definition(parent) ||
				is_class_property_assignment_at_constructor_root(parent, context);

			if (!valid) {
				state_invalid_placement(node, rune);
			}

			if ((rune === '$derived' || rune === '$derived.by') && node.arguments.length !== 1) {
				rune_invalid_arguments_length(node, rune, 'exactly one argument');
			} else if (node.arguments.length > 1) {
				rune_invalid_arguments_length(node, rune, 'zero or one arguments');
			}

			break;
		}

		case '$effect':
		case '$effect.pre':
			if (parent.type !== 'ExpressionStatement') {
				effect_invalid_placement(node);
			}

			if (node.arguments.length !== 1) {
				rune_invalid_arguments_length(node, rune, 'exactly one argument');
			}

			// `$effect` needs context because Svelte needs to know whether it should re-run
			// effects that invalidate themselves, and that's determined by whether we're in runes mode
			context.state.analysis.needs_context = true;

			break;

		case '$effect.tracking':
			if (node.arguments.length !== 0) {
				rune_invalid_arguments(node, rune);
			}

			break;

		case '$effect.root':
			if (node.arguments.length !== 1) {
				rune_invalid_arguments_length(node, rune, 'exactly one argument');
			}

			break;

		case '$effect.pending':
			if (context.state.expression) {
				context.state.expression.has_state = true;
			}

			break;

		case '$inspect':
			if (node.arguments.length < 1) {
				rune_invalid_arguments_length(node, rune, 'one or more arguments');
			}

			break;

		case '$inspect().with':
			if (node.arguments.length !== 1) {
				rune_invalid_arguments_length(node, rune, 'exactly one argument');
			}

			break;

		case '$inspect.trace': {
			if (node.arguments.length > 1) {
				rune_invalid_arguments_length(node, rune, 'zero or one arguments');
			}

			const grand_parent = context.path.at(-2);
			const fn = context.path.at(-3);

			if (
				parent.type !== 'ExpressionStatement' ||
				grand_parent?.type !== 'BlockStatement' ||
				!(
					fn?.type === 'FunctionDeclaration' ||
					fn?.type === 'FunctionExpression' ||
					fn?.type === 'ArrowFunctionExpression'
				) ||
				grand_parent.body[0] !== parent
			) {
				inspect_trace_invalid_placement(node);
			}

			if (fn.generator) {
				inspect_trace_generator(node);
			}

			if (dev) {
				if (node.arguments[0]) {
					context.state.scope.tracing = thunk(/** @type {Expression} */ (node.arguments[0]));
				} else {
					const label = get_function_label(context.path.slice(0, -2)) ?? 'trace';
					const loc = `(${locate_node(fn)})`;

					context.state.scope.tracing = thunk(literal(label + ' ' + loc));
				}

				context.state.analysis.tracing = true;
			}

			break;
		}

		case '$state.eager':
			if (node.arguments.length !== 1) {
				rune_invalid_arguments_length(node, rune, 'exactly one argument');
			}

			break;

		case '$state.snapshot':
			if (node.arguments.length !== 1) {
				rune_invalid_arguments_length(node, rune, 'exactly one argument');
			}

			break;
	}

	// `$inspect(foo)` or `$derived(foo) should not trigger the `static-state-reference` warning
	if (rune === '$derived') {
		const expression = new ExpressionMetadata();

		context.next({
			...context.state,
			function_depth: context.state.function_depth + 1,
			derived_function_depth: context.state.function_depth + 1,
			expression
		});

		if (expression.has_await) {
			context.state.analysis.async_deriveds.add(node);
		}
	} else if (rune === '$inspect') {
		context.next({ ...context.state, function_depth: context.state.function_depth + 1 });
	} else {
		context.next();
	}

	if (context.state.expression) {
		// TODO We assume that any dependencies are stateful, which isn't necessarily the case — see
		// https://github.com/sveltejs/svelte/issues/13266. This check also includes dependencies
		// outside the call expression itself (e.g. `{blah && pure()}`) resulting in additional
		// false positives, but for now we accept that trade-off
		if (!is_pure(node.callee, context) || context.state.expression.dependencies.size > 0) {
			context.state.expression.has_call = true;
			context.state.expression.has_state = true;
		}
	}
}

/**
 * @param {AST.SvelteNode[]} nodes
 */
function get_function_label(nodes) {
	const fn = /** @type {FunctionExpression | FunctionDeclaration | ArrowFunctionExpression} */ (
		nodes.at(-1)
	);

	if ((fn.type === 'FunctionDeclaration' || fn.type === 'FunctionExpression') && fn.id != null) {
		return fn.id.name;
	}

	const parent = nodes.at(-2);
	if (!parent) return;

	if (parent.type === 'CallExpression') {
		return source.slice(parent.callee.start, parent.callee.end) + '(...)';
	}

	if (parent.type === 'Property' && !parent.computed) {
		return /** @type {Identifier} */ (parent.key).name;
	}

	if (parent.type === 'VariableDeclarator' && parent.id.type === 'Identifier') {
		return parent.id.name;
	}
}

/**
 * @param {AST.SvelteNode} parent
 * @param {Context} context
 */
function is_variable_declaration(parent, context) {
	return parent.type === 'VariableDeclarator' && get_parent(context.path, -3).type !== 'ConstTag';
}

/**
 * @param {AST.SvelteNode} parent
 */
function is_class_property_definition(parent) {
	return parent.type === 'PropertyDefinition' && !parent.static && !parent.computed;
}

/**
 * @param {AST.SvelteNode} node
 * @param {Context} context
 */
function is_class_property_assignment_at_constructor_root(node, context) {
	if (
		node.type === 'AssignmentExpression' &&
		node.operator === '=' &&
		node.left.type === 'MemberExpression' &&
		node.left.object.type === 'ThisExpression' &&
		((node.left.property.type === 'Identifier' && !node.left.computed) ||
			node.left.property.type === 'PrivateIdentifier' ||
			node.left.property.type === 'Literal')
	) {
		// MethodDefinition (-5) -> FunctionExpression (-4) -> BlockStatement (-3) -> ExpressionStatement (-2) -> AssignmentExpression (-1)
		const parent = get_parent(context.path, -5);
		return parent?.type === 'MethodDefinition' && parent.kind === 'constructor';
	}

	return false;
}

/** @import { AssignmentExpression, CallExpression, ClassBody, PropertyDefinition, Expression, PrivateIdentifier, MethodDefinition } from 'estree' */
/** @import { StateField } from '#compiler' */
/** @import { Context } from '../types' */

/**
 * @param {ClassBody} node
 * @param {Context} context
 */
function ClassBody$2(node, context) {
	if (!context.state.analysis.runes) {
		context.next();
		return;
	}

	/** @type {string[]} */
	const private_ids = [];

	for (const prop of node.body) {
		if (
			(prop.type === 'MethodDefinition' || prop.type === 'PropertyDefinition') &&
			prop.key.type === 'PrivateIdentifier'
		) {
			private_ids.push(prop.key.name);
		}
	}

	/** @type {Map<string, StateField>} */
	const state_fields = new Map();

	/** @type {Map<string, Array<MethodDefinition['kind'] | 'prop' | 'assigned_prop'>>} */
	const fields = new Map();

	context.state.analysis.classes.set(node, state_fields);

	/** @type {MethodDefinition | null} */
	let constructor = null;

	/**
	 * @param {PropertyDefinition | AssignmentExpression} node
	 * @param {Expression | PrivateIdentifier} key
	 * @param {Expression | null | undefined} value
	 */
	function handle(node, key, value) {
		const name = get_name(key);
		if (name === null) return;

		const rune = get_rune(value, context.state.scope);

		if (rune && is_state_creation_rune(rune)) {
			if (state_fields.has(name)) {
				state_field_duplicate(node, name);
			}

			const _key = (node.type === 'AssignmentExpression' || !node.static ? '' : '@') + name;
			const field = fields.get(_key);

			// if there's already a method or assigned field, error
			if (field && !(field.length === 1 && field[0] === 'prop')) {
				duplicate_class_field(node, _key);
			}

			state_fields.set(name, {
				node,
				type: rune,
				// @ts-expect-error for public state this is filled out in a moment
				key: key.type === 'PrivateIdentifier' ? key : null,
				value: /** @type {CallExpression} */ (value)
			});
		}
	}

	for (const child of node.body) {
		if (child.type === 'PropertyDefinition' && !child.computed && !child.static) {
			handle(child, child.key, child.value);
			const key = /** @type {string} */ (get_name(child.key));
			const field = fields.get(key);
			if (!field) {
				fields.set(key, [child.value ? 'assigned_prop' : 'prop']);
				continue;
			}
			duplicate_class_field(child, key);
		}

		if (child.type === 'MethodDefinition') {
			if (child.kind === 'constructor') {
				constructor = child;
			} else if (!child.computed) {
				const key = (child.static ? '@' : '') + get_name(child.key);
				const field = fields.get(key);
				if (!field) {
					fields.set(key, [child.kind]);
					continue;
				}
				if (
					field.includes(child.kind) ||
					field.includes('prop') ||
					field.includes('assigned_prop')
				) {
					duplicate_class_field(child, key);
				}
				if (child.kind === 'get') {
					if (field.length === 1 && field[0] === 'set') {
						field.push('get');
						continue;
					}
				} else if (child.kind === 'set') {
					if (field.length === 1 && field[0] === 'get') {
						field.push('set');
						continue;
					}
				} else {
					field.push(child.kind);
					continue;
				}
				duplicate_class_field(child, key);
			}
		}
	}

	if (constructor) {
		for (const statement of constructor.value.body.body) {
			if (statement.type !== 'ExpressionStatement') continue;
			if (statement.expression.type !== 'AssignmentExpression') continue;

			const { left, right } = statement.expression;

			if (left.type !== 'MemberExpression') continue;
			if (left.object.type !== 'ThisExpression') continue;
			if (left.computed && left.property.type !== 'Literal') continue;

			handle(statement.expression, left.property, right);
		}
	}

	for (const [name, field] of state_fields) {
		if (name[0] === '#') {
			continue;
		}

		let deconflicted = name.replace(regex_invalid_identifier_chars, '_');
		while (private_ids.includes(deconflicted)) {
			deconflicted = '_' + deconflicted;
		}

		private_ids.push(deconflicted);
		field.key = private_id(deconflicted);
	}

	context.next({ ...context.state, state_fields });
}

/** @import { ClassDeclaration } from 'estree' */
/** @import { Context } from '../types' */

/**
 * @param {ClassDeclaration} node
 * @param {Context} context
 */
function ClassDeclaration(node, context) {
	if (context.state.analysis.runes && node.id !== null) {
		validate_identifier_name(context.state.scope.get(node.id.name));
	}

	// In modules, we allow top-level module scope only, in components, we allow the component scope,
	// which is function_depth of 1. With the exception of `new class` which is also not allowed at
	// component scope level either.
	const allowed_depth = context.state.ast_type === 'module' ? 0 : 1;

	if (context.state.scope.function_depth > allowed_depth) {
		perf_avoid_nested_class(node);
	}

	context.next();
}

/** @import { AST } from '#compiler' */
/** @import { Context } from '../types' */


/**
 * @param {AST.ClassDirective} node
 * @param {Context} context
 */
function ClassDirective(node, context) {
	mark_subtree_dynamic(context.path);
	context.next({ ...context.state, expression: node.metadata.expression });
}

/** @import { AST } from '#compiler' */
/** @import { Context } from '../../types' */

/**
 * @param {AST.Attribute} attribute
 */
function validate_attribute_name(attribute) {
	if (
		attribute.name.includes(':') &&
		!attribute.name.startsWith('xmlns:') &&
		!attribute.name.startsWith('xlink:') &&
		!attribute.name.startsWith('xml:')
	) {
		attribute_illegal_colon(attribute);
	}
}

/**
 * @param {AST.Attribute} attribute
 * @param {AST.ElementLike} parent
 */
function validate_attribute(attribute, parent) {
	if (
		Array.isArray(attribute.value) &&
		attribute.value.length === 1 &&
		attribute.value[0].type === 'ExpressionTag' &&
		(parent.type === 'Component' ||
			parent.type === 'SvelteComponent' ||
			parent.type === 'SvelteSelf' ||
			(parent.type === 'RegularElement' && is_custom_element_node(parent)))
	) {
		attribute_quoted(attribute);
	}

	if (attribute.value === true || !Array.isArray(attribute.value) || attribute.value.length === 1) {
		return;
	}

	const is_quoted = attribute.value.at(-1)?.end !== attribute.end;

	if (!is_quoted) {
		attribute_unquoted_sequence(attribute);
	}
}

/**
 * @param {Context} context
 * @param {AST.Attribute} attribute
 * @param {boolean} is_component
 */
function validate_slot_attribute(context, attribute, is_component = false) {
	const parent = context.path.at(-2);
	let owner = undefined;

	if (parent?.type === 'SnippetBlock') {
		if (!is_text_attribute(attribute)) {
			slot_attribute_invalid(attribute);
		}
		return;
	}

	let i = context.path.length;
	while (i--) {
		const ancestor = context.path[i];
		if (
			!owner &&
			(ancestor.type === 'Component' ||
				ancestor.type === 'SvelteComponent' ||
				ancestor.type === 'SvelteSelf' ||
				ancestor.type === 'SvelteElement' ||
				(ancestor.type === 'RegularElement' && is_custom_element_node(ancestor)))
		) {
			owner = ancestor;
		}
	}

	if (owner) {
		if (
			owner.type === 'Component' ||
			owner.type === 'SvelteComponent' ||
			owner.type === 'SvelteSelf'
		) {
			if (owner !== parent) {
				if (!is_component) {
					slot_attribute_invalid_placement(attribute);
				}
			} else {
				if (!is_text_attribute(attribute)) {
					slot_attribute_invalid(attribute);
				}

				const name = attribute.value[0].data;

				if (context.state.component_slots.has(name)) {
					slot_attribute_duplicate(attribute, name, owner.name);
				}

				context.state.component_slots.add(name);

				if (name === 'default') {
					for (const node of owner.fragment.nodes) {
						if (node.type === 'Text' && regex_only_whitespaces.test(node.data)) {
							continue;
						}

						if (node.type === 'RegularElement' || node.type === 'SvelteFragment') {
							if (node.attributes.some((a) => a.type === 'Attribute' && a.name === 'slot')) {
								continue;
							}
						}

						slot_default_duplicate(node);
					}
				}
			}
		}
	} else if (!is_component) {
		slot_attribute_invalid_placement(attribute);
	}
}

/** @import { Binding } from '#compiler' */

/**
 * Returns `true` if a binding unambiguously resolves to a specific
 * snippet declaration, or is external to the current component
 * @param {Binding | null} binding
 */
function is_resolved_snippet(binding) {
	return (
		!binding ||
		binding.declaration_kind === 'import' ||
		binding.kind === 'prop' ||
		binding.kind === 'rest_prop' ||
		binding.kind === 'bindable_prop' ||
		binding?.initial?.type === 'SnippetBlock'
	);
}

/** @import { Expression } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { AnalysisState, Context } from '../../types' */

/**
 * @param {AST.Component | AST.SvelteComponent | AST.SvelteSelf} node
 * @param {Context} context
 */
function visit_component(node, context) {
	node.metadata.path = [...context.path];

	// link this node to all the snippets that it could render, so that we can prune CSS correctly
	node.metadata.snippets = new Set();

	// 'resolved' means we know which snippets this component might render. if it is `false`,
	// then `node.metadata.snippets` is populated with every locally defined snippet
	// once analysis is complete
	let resolved = true;

	for (const attribute of node.attributes) {
		if (attribute.type === 'SpreadAttribute' || attribute.type === 'BindDirective') {
			resolved = false;
			continue;
		}

		if (attribute.type !== 'Attribute' || !is_expression_attribute(attribute)) {
			continue;
		}

		const expression = get_attribute_expression(attribute);

		// given an attribute like `foo={bar}`, if `bar` resolves to an import or a prop
		// then we know it doesn't reference a locally defined snippet. if it resolves
		// to a `{#snippet bar()}` then we know _which_ snippet it resolves to. in all
		// other cases, we can't know (without much more complex static analysis) which
		// snippets the component might render, so we treat the component as unresolved
		if (expression.type === 'Identifier') {
			const binding = context.state.scope.get(expression.name);

			resolved &&= is_resolved_snippet(binding);

			if (binding?.initial?.type === 'SnippetBlock') {
				node.metadata.snippets.add(binding.initial);
			}
		} else if (expression.type !== 'Literal') {
			resolved = false;
		}
	}

	if (resolved) {
		for (const child of node.fragment.nodes) {
			if (child.type === 'SnippetBlock') {
				node.metadata.snippets.add(child);
			}
		}
	}

	context.state.analysis.snippet_renderers.set(node, resolved);

	mark_subtree_dynamic(context.path);

	for (const attribute of node.attributes) {
		if (
			attribute.type !== 'Attribute' &&
			attribute.type !== 'SpreadAttribute' &&
			attribute.type !== 'LetDirective' &&
			attribute.type !== 'OnDirective' &&
			attribute.type !== 'BindDirective' &&
			attribute.type !== 'AttachTag'
		) {
			component_invalid_directive(attribute);
		}

		if (
			attribute.type === 'OnDirective' &&
			(attribute.modifiers.length > 1 || attribute.modifiers.some((m) => m !== 'once'))
		) {
			event_handler_invalid_component_modifier(attribute);
		}

		if (attribute.type === 'Attribute') {
			if (context.state.analysis.runes) {
				validate_attribute(attribute, node);

				if (is_expression_attribute(attribute)) {
					disallow_unparenthesized_sequences(
						get_attribute_expression(attribute),
						context.state.analysis.source
					);
				}
			}

			validate_attribute_name(attribute);

			if (attribute.name === 'slot') {
				validate_slot_attribute(context, attribute, true);
			}
		}

		if (attribute.type === 'BindDirective' && attribute.name !== 'this') {
			context.state.analysis.uses_component_bindings = true;
		}

		if (attribute.type === 'AttachTag') {
			disallow_unparenthesized_sequences(attribute.expression, context.state.analysis.source);
		}
	}

	// If the component has a slot attribute — `<Foo slot="whatever" .../>` —
	// then `let:` directives apply to other attributes, instead of just the
	// top-level contents of the component. Yes, this is very weird.
	const default_state = determine_slot(node)
		? context.state
		: { ...context.state, scope: node.metadata.scopes.default };

	for (const attribute of node.attributes) {
		context.visit(attribute, attribute.type === 'LetDirective' ? default_state : context.state);
	}

	/** @type {AST.Comment[]} */
	let comments = [];

	/** @type {Record<string, AST.Fragment['nodes']>} */
	const nodes = { default: [] };

	for (const child of node.fragment.nodes) {
		if (child.type === 'Comment') {
			comments.push(child);
			continue;
		}

		const slot_name = determine_slot(child) ?? 'default';
		(nodes[slot_name] ??= []).push(...comments, child);

		if (slot_name !== 'default') comments = [];
	}

	/** @type {Set<string>} */
	const component_slots = new Set();

	for (const slot_name in nodes) {
		/** @type {AnalysisState} */
		const state = {
			...context.state,
			scope: node.metadata.scopes[slot_name],
			parent_element: null,
			component_slots
		};

		context.visit({ ...node.fragment, nodes: nodes[slot_name] }, state);
	}
}

/**
 * @param {Expression} expression
 * @param {string} source
 */
function disallow_unparenthesized_sequences(expression, source) {
	if (expression.type === 'SequenceExpression') {
		let i = /** @type {number} */ (expression.start);
		while (--i > 0) {
			const char = source[i];
			if (char === '(') break; // parenthesized sequence expressions are ok
			if (char === '{') attribute_invalid_sequence_expression(expression);
		}
	}
}

/** @import { AST } from '#compiler' */
/** @import { Context } from '../types' */

/**
 * @param {AST.Component} node
 * @param {Context} context
 */
function Component$2(node, context) {
	const binding = context.state.scope.get(
		node.name.includes('.') ? node.name.slice(0, node.name.indexOf('.')) : node.name
	);

	node.metadata.dynamic =
		context.state.analysis.runes && // Svelte 4 required you to use svelte:component to switch components
		binding !== null &&
		(binding.kind !== 'normal' || node.name.includes('.'));

	if (binding) {
		node.metadata.expression.has_state = node.metadata.dynamic;
		node.metadata.expression.dependencies.add(binding);
		node.metadata.expression.references.add(binding);
	}

	visit_component(node, context);
}

/** @import { AST } from '#compiler' */
/** @import { Context } from '../types' */

/**
 * @param {AST.ConstTag} node
 * @param {Context} context
 */
function ConstTag$2(node, context) {
	if (context.state.analysis.runes) {
		validate_opening_tag(node, context.state, '@');
	}

	const parent = context.path.at(-1);
	const grand_parent = context.path.at(-2);

	if (
		parent?.type !== 'Fragment' ||
		(grand_parent?.type !== 'IfBlock' &&
			grand_parent?.type !== 'SvelteFragment' &&
			grand_parent?.type !== 'Component' &&
			grand_parent?.type !== 'SvelteComponent' &&
			grand_parent?.type !== 'EachBlock' &&
			grand_parent?.type !== 'AwaitBlock' &&
			grand_parent?.type !== 'SnippetBlock' &&
			grand_parent?.type !== 'SvelteBoundary' &&
			grand_parent?.type !== 'KeyBlock' &&
			((grand_parent?.type !== 'RegularElement' && grand_parent?.type !== 'SvelteElement') ||
				!grand_parent.attributes.some((a) => a.type === 'Attribute' && a.name === 'slot')))
	) {
		const_tag_invalid_placement(node);
	}

	const declaration = node.declaration.declarations[0];

	context.visit(declaration.id);
	context.visit(declaration.init, {
		...context.state,
		expression: node.metadata.expression,
		// We're treating this like a $derived under the hood
		function_depth: context.state.function_depth + 1,
		derived_function_depth: context.state.function_depth + 1
	});
}

/** @import { AST } from '#compiler' */
/** @import { Context } from '../types' */

/**
 * @param {AST.DebugTag} node
 * @param {Context} context
 */
function DebugTag$2(node, context) {
	if (context.state.analysis.runes) {
		validate_opening_tag(node, context.state, '@');
	}

	context.next();
}

/** @import { Expression } from 'estree' */
/** @import { AST, Binding } from '#compiler' */
/** @import { Context } from '../types' */
/** @import { Scope } from '../../scope' */

/**
 * @param {AST.EachBlock} node
 * @param {Context} context
 */
function EachBlock$2(node, context) {
	validate_opening_tag(node, context.state, '#');

	validate_block_not_empty(node.body);
	validate_block_not_empty(node.fallback);

	const id = node.context;
	if (id?.type === 'Identifier' && (id.name === '$state' || id.name === '$derived')) {
		// TODO weird that this is necessary
		state_invalid_placement(node, id.name);
	}

	if (node.key) {
		// treat `{#each items as item, i (i)}` as a normal indexed block, everything else as keyed
		node.metadata.keyed =
			node.key.type !== 'Identifier' || !node.index || node.key.name !== node.index;
	}

	if (node.metadata.keyed && !node.context) {
		each_key_without_as(/** @type {Expression} */ (node.key));
	}

	// evaluate expression in parent scope
	context.visit(node.expression, {
		...context.state,
		expression: node.metadata.expression,
		scope: /** @type {Scope} */ (context.state.scope.parent)
	});

	context.visit(node.body);
	if (node.key) context.visit(node.key);
	if (node.fallback) context.visit(node.fallback);

	if (!context.state.analysis.runes) {
		let mutated =
			!!node.context &&
			extract_identifiers(node.context).some((id) => {
				const binding = context.state.scope.get(id.name);
				return !!binding?.mutated;
			});

		// collect transitive dependencies...
		for (const binding of node.metadata.expression.dependencies) {
			collect_transitive_dependencies(binding, node.metadata.transitive_deps);
		}

		// ...and ensure they are marked as state, so they can be turned
		// into mutable sources and invalidated
		if (mutated) {
			for (const binding of node.metadata.transitive_deps) {
				if (
					binding.kind === 'normal' &&
					(binding.declaration_kind === 'const' ||
						binding.declaration_kind === 'let' ||
						binding.declaration_kind === 'var')
				) {
					binding.kind = 'state';
				}
			}
		}
	}

	mark_subtree_dynamic(context.path);
}

/**
 * @param {Binding} binding
 * @param {Set<Binding>} bindings
 * @returns {void}
 */
function collect_transitive_dependencies(binding, bindings) {
	if (bindings.has(binding)) {
		return;
	}
	bindings.add(binding);

	if (binding.kind === 'legacy_reactive') {
		for (const dep of binding.legacy_dependencies) {
			collect_transitive_dependencies(dep, bindings);
		}
	}
}

/** @import { ExportDefaultDeclaration } from 'estree' */
/** @import { Context } from '../types' */

/**
 * @param {ExportDefaultDeclaration} node
 * @param {Context} context
 */
function ExportDefaultDeclaration(node, context) {
	if (!context.state.ast_type /* .svelte.js module */) {
		if (node.declaration.type === 'Identifier') {
			validate_export(node, context.state.scope, node.declaration.name);
		}
	} else {
		module_illegal_default_export(node);
	}

	context.next();
}

/** @import { ExportNamedDeclaration, Identifier } from 'estree' */
/** @import { Context } from '../types' */

/**
 * @param {ExportNamedDeclaration} node
 * @param {Context} context
 */
function ExportNamedDeclaration$1(node, context) {
	// visit children, so bindings are correctly initialised
	context.next();

	if (
		context.state.ast_type &&
		node.specifiers.some((specifier) =>
			specifier.exported.type === 'Identifier'
				? specifier.exported.name === 'default'
				: specifier.exported.value === 'default'
		)
	) {
		module_illegal_default_export(node);
	}

	if (node.declaration?.type === 'VariableDeclaration') {
		// in runes mode, forbid `export let`
		if (
			context.state.analysis.runes &&
			context.state.ast_type === 'instance' &&
			node.declaration.kind === 'let'
		) {
			legacy_export_invalid(node);
		}

		for (const declarator of node.declaration.declarations) {
			for (const id of extract_identifiers(declarator.id)) {
				const binding = context.state.scope.get(id.name);
				if (!binding) continue;

				if (binding.kind === 'derived') {
					derived_invalid_export(node);
				}

				if ((binding.kind === 'state' || binding.kind === 'raw_state') && binding.reassigned) {
					state_invalid_export(node);
				}
			}
		}
	}

	if (context.state.analysis.runes) {
		if (node.declaration && context.state.ast_type === 'instance') {
			if (
				node.declaration.type === 'FunctionDeclaration' ||
				node.declaration.type === 'ClassDeclaration'
			) {
				context.state.analysis.exports.push({
					name: /** @type {Identifier} */ (node.declaration.id).name,
					alias: null
				});
			} else if (node.declaration.kind === 'const') {
				for (const declarator of node.declaration.declarations) {
					for (const node of extract_identifiers(declarator.id)) {
						context.state.analysis.exports.push({ name: node.name, alias: null });
					}
				}
			}
		}
	}
}

/** @import { ExportSpecifier } from 'estree' */
/** @import { Context } from '../types' */

/**
 * @param {ExportSpecifier} node
 * @param {Context} context
 */
function ExportSpecifier(node, context) {
	const local_name =
		node.local.type === 'Identifier' ? node.local.name : /** @type {string} */ (node.local.value);
	const exported_name =
		node.exported.type === 'Identifier'
			? node.exported.name
			: /** @type {string} */ (node.exported.value);

	if (context.state.ast_type === 'instance') {
		if (context.state.analysis.runes) {
			context.state.analysis.exports.push({
				name: local_name,
				alias: exported_name
			});

			const binding = context.state.scope.get(local_name);
			if (binding) binding.reassigned = true;
		}
	} else {
		validate_export(node, context.state.scope, local_name);
	}
}

/** @import { ExpressionStatement, ImportDeclaration } from 'estree' */
/** @import { Context } from '../types' */

/**
 * @param {ExpressionStatement} node
 * @param {Context} context
 */
function ExpressionStatement$2(node, context) {
	// warn on `new Component({ target: ... })` if imported from a `.svelte` file
	if (
		node.expression.type === 'NewExpression' &&
		node.expression.callee.type === 'Identifier' &&
		node.expression.arguments.length === 1 &&
		node.expression.arguments[0].type === 'ObjectExpression' &&
		node.expression.arguments[0].properties.some(
			(p) => p.type === 'Property' && p.key.type === 'Identifier' && p.key.name === 'target'
		)
	) {
		const binding = context.state.scope.get(node.expression.callee.name);

		if (binding?.kind === 'normal' && binding.declaration_kind === 'import') {
			const declaration = /** @type {ImportDeclaration} */ (binding.initial);

			// Theoretically someone could import a class from a `.svelte.js` module, but that's too rare to worry about
			if (
				/** @type {string} */ (declaration.source.value).endsWith('.svelte') &&
				declaration.specifiers.find(
					(s) => s.local.name === binding.node.name && s.type === 'ImportDefaultSpecifier'
				)
			) {
				legacy_component_creation(node.expression);
			}
		}
	}

	context.next();
}

/** @import { AST } from '#compiler' */
/** @import { Context } from '../types' */

/**
 * @param {AST.ExpressionTag} node
 * @param {Context} context
 */
function ExpressionTag(node, context) {
	const in_template = context.path.at(-1)?.type === 'Fragment';

	if (in_template && context.state.parent_element) {
		const message = is_tag_valid_with_parent('#text', context.state.parent_element);
		if (message) {
			node_invalid_placement(node, message);
		}
	}

	// TODO ideally we wouldn't do this here, we'd just do it on encountering
	// an `Identifier` within the tag. But we currently need to handle `{42}` etc
	mark_subtree_dynamic(context.path);

	context.next({ ...context.state, expression: node.metadata.expression });
}

/** @import { AST } from '#compiler' */
/** @import { Context } from '../types.js' */

/**
 * @param {AST.Fragment} node
 * @param {Context} context
 */
function Fragment$2(node, context) {
	context.next({ ...context.state, fragment: node });
}

/** @import { FunctionDeclaration } from 'estree' */
/** @import { Context } from '../types' */

/**
 * @param {FunctionDeclaration} node
 * @param {Context} context
 */
function FunctionDeclaration$1(node, context) {
	if (context.state.analysis.runes && node.id !== null) {
		validate_identifier_name(context.state.scope.get(node.id.name));
	}

	visit_function$1(node, context);
}

/** @import { FunctionExpression } from 'estree' */
/** @import { Context } from '../types' */

/**
 * @param {FunctionExpression} node
 * @param {Context} context
 */
function FunctionExpression$1(node, context) {
	visit_function$1(node, context);
}

/** @import { AST } from '#compiler' */
/** @import { Context } from '../types' */

/**
 * @param {AST.HtmlTag} node
 * @param {Context} context
 */
function HtmlTag$2(node, context) {
	if (context.state.analysis.runes) {
		validate_opening_tag(node, context.state, '@');
	}

	// unfortunately this is necessary in order to fix invalid HTML
	mark_subtree_dynamic(context.path);

	context.next({ ...context.state, expression: node.metadata.expression });
}

/** @import { BlockStatement, Expression, Identifier } from 'estree' */
/** @import { Binding } from '#compiler' */
/** @import { ClientTransformState, ComponentClientTransformState } from './types.js' */
/** @import { Analysis } from '../../types.js' */
/** @import { Scope } from '../../scope.js' */

/**
 * @param {Binding} binding
 * @param {Analysis} analysis
 * @returns {boolean}
 */
function is_state_source(binding, analysis) {
	return (
		(binding.kind === 'state' || binding.kind === 'raw_state') &&
		(!analysis.immutable || binding.reassigned || analysis.accessors)
	);
}

/**
 * @param {Identifier} node
 * @param {ClientTransformState} state
 * @returns {Expression}
 */
function build_getter$1(node, state) {
	if (Object.hasOwn(state.transform, node.name)) {
		const binding = state.scope.get(node.name);

		// don't transform the declaration itself
		if (node !== binding?.node) {
			return state.transform[node.name].read(node);
		}
	}

	return node;
}

/**
 * @param {Binding} binding
 * @param {ComponentClientTransformState} state
 * @param {string} name
 * @param {Expression | null} [initial]
 * @returns
 */
function get_prop_source(binding, state, name, initial) {
	/** @type {Expression[]} */
	const args = [id('$$props'), literal(name)];

	let flags = 0;

	if (binding.kind === 'bindable_prop') {
		flags |= PROPS_IS_BINDABLE;
	}

	if (state.analysis.immutable) {
		flags |= PROPS_IS_IMMUTABLE;
	}

	if (state.analysis.runes) {
		flags |= PROPS_IS_RUNES;
	}

	if (
		state.analysis.accessors ||
		(state.analysis.immutable
			? binding.reassigned || (state.analysis.runes && binding.mutated)
			: binding.updated)
	) {
		flags |= PROPS_IS_UPDATED;
	}

	/** @type {Expression | undefined} */
	let arg;

	if (initial) {
		// To avoid eagerly evaluating the right-hand-side, we wrap it in a thunk if necessary
		if (is_simple_expression(initial)) {
			arg = initial;
		} else {
			if (
				initial.type === 'CallExpression' &&
				initial.callee.type === 'Identifier' &&
				initial.arguments.length === 0
			) {
				arg = initial.callee;
			} else {
				arg = thunk(initial);
			}

			flags |= PROPS_IS_LAZY_INITIAL;
		}
	}

	if (flags || arg) {
		args.push(literal(flags));
		if (arg) args.push(arg);
	}

	return call('$.prop', ...args);
}

/**
 *
 * @param {Binding} binding
 * @param {ClientTransformState} state
 * @returns
 */
function is_prop_source(binding, state) {
	return (
		(binding.kind === 'prop' || binding.kind === 'bindable_prop') &&
		(!state.analysis.runes ||
			state.analysis.accessors ||
			binding.reassigned ||
			binding.initial ||
			// Until legacy mode is gone, we also need to use the prop source when only mutated is true,
			// because the parent could be a legacy component which needs coarse-grained reactivity
			binding.updated)
	);
}

/**
 * @param {Expression} node
 * @param {Scope | null} scope
 */
function should_proxy(node, scope) {
	if (
		!node ||
		node.type === 'Literal' ||
		node.type === 'TemplateLiteral' ||
		node.type === 'ArrowFunctionExpression' ||
		node.type === 'FunctionExpression' ||
		node.type === 'UnaryExpression' ||
		node.type === 'BinaryExpression' ||
		(node.type === 'Identifier' && node.name === 'undefined')
	) {
		return false;
	}

	if (node.type === 'Identifier' && scope !== null) {
		const binding = scope.get(node.name);
		// Let's see if the reference is something that can be proxied
		if (
			binding !== null &&
			!binding.reassigned &&
			binding.initial !== null &&
			binding.initial.type !== 'FunctionDeclaration' &&
			binding.initial.type !== 'ClassDeclaration' &&
			binding.initial.type !== 'ImportDeclaration' &&
			binding.initial.type !== 'EachBlock' &&
			binding.initial.type !== 'SnippetBlock'
		) {
			return should_proxy(binding.initial, null);
		}
	}

	return true;
}

/**
 * Svelte legacy mode should use safe equals in most places, runes mode shouldn't
 * @param {ComponentClientTransformState} state
 * @param {Expression | BlockStatement} expression
 * @param {boolean} [async]
 */
function create_derived(state, expression, async = false) {
	const thunk$1 = thunk(expression, async);

	if (async) {
		return save(call('$.async_derived', thunk$1));
	} else {
		return call(state.analysis.runes ? '$.derived' : '$.derived_safe_equal', thunk$1);
	}
}

/** @import { Expression, Identifier } from 'estree' */
/** @import { Context } from '../types' */

/**
 * @param {Identifier} node
 * @param {Context} context
 */
function Identifier$2(node, context) {
	let i = context.path.length;
	let parent = /** @type {Expression} */ (context.path[--i]);

	if (!is_reference(node, parent)) {
		return;
	}

	mark_subtree_dynamic(context.path);

	// If we are using arguments outside of a function, then throw an error
	if (
		node.name === 'arguments' &&
		!context.path.some((n) => n.type === 'FunctionDeclaration' || n.type === 'FunctionExpression')
	) {
		invalid_arguments_usage(node);
	}

	// `$$slots` exists even in runes mode
	if (node.name === '$$slots') {
		context.state.analysis.uses_slots = true;
	}

	if (context.state.analysis.runes) {
		if (
			is_rune(node.name) &&
			context.state.scope.get(node.name) === null &&
			context.state.scope.get(node.name.slice(1))?.kind !== 'store_sub'
		) {
			/** @type {Expression} */
			let current = node;
			let name = node.name;

			while (parent.type === 'MemberExpression') {
				if (parent.computed) rune_invalid_computed_property(parent);
				name += `.${/** @type {Identifier} */ (parent.property).name}`;

				current = parent;
				parent = /** @type {Expression} */ (context.path[--i]);

				if (!is_rune(name)) {
					if (name === '$effect.active') {
						rune_renamed(parent, '$effect.active', '$effect.tracking');
					}

					if (name === '$state.frozen') {
						rune_renamed(parent, '$state.frozen', '$state.raw');
					}

					if (name === '$state.is') {
						rune_removed(parent, '$state.is');
					}

					rune_invalid_name(parent, name);
				}
			}

			if (parent.type !== 'CallExpression') {
				rune_missing_parentheses(current);
			}
		}
	}

	let binding = context.state.scope.get(node.name);

	if (!context.state.analysis.runes) {
		if (node.name === '$$props') {
			context.state.analysis.uses_props = true;
		}

		if (node.name === '$$restProps') {
			context.state.analysis.uses_rest_props = true;
		}
	}

	if (binding) {
		if (context.state.expression) {
			context.state.expression.dependencies.add(binding);
			context.state.expression.references.add(binding);
			context.state.expression.has_state ||=
				binding.kind !== 'static' &&
				(binding.kind === 'prop' ||
					binding.kind === 'bindable_prop' ||
					binding.kind === 'rest_prop' ||
					!binding.is_function()) &&
				!context.state.scope.evaluate(node).is_known;
		}

		if (
			context.state.analysis.runes &&
			node !== binding.node &&
			context.state.function_depth === binding.scope.function_depth &&
			// If we have $state that can be proxied or frozen and isn't re-assigned, then that means
			// it's likely not using a primitive value and thus this warning isn't that helpful.
			((binding.kind === 'state' &&
				(binding.reassigned ||
					(binding.initial?.type === 'CallExpression' &&
						binding.initial.arguments.length === 1 &&
						binding.initial.arguments[0].type !== 'SpreadElement' &&
						!should_proxy(binding.initial.arguments[0], context.state.scope)))) ||
				binding.kind === 'raw_state' ||
				binding.kind === 'derived') &&
			// We're only concerned with reads here
			(parent.type !== 'AssignmentExpression' || parent.left !== node) &&
			parent.type !== 'UpdateExpression'
		) {
			let type = 'closure';

			let i = context.path.length;
			while (i--) {
				const parent = context.path[i];

				if (
					parent.type === 'ArrowFunctionExpression' ||
					parent.type === 'FunctionDeclaration' ||
					parent.type === 'FunctionExpression'
				) {
					break;
				}

				if (
					parent.type === 'CallExpression' &&
					parent.arguments.includes(/** @type {any} */ (context.path[i + 1]))
				) {
					const rune = get_rune(parent, context.state.scope);

					if (rune === '$state' || rune === '$state.raw') {
						type = 'derived';
						break;
					}
				}
			}

			state_referenced_locally(node, node.name, type);
		}

		if (
			context.state.reactive_statement &&
			binding.scope === context.state.analysis.module.scope &&
			binding.reassigned
		) {
			reactive_declaration_module_script_dependency(node);
		}

		if (binding.metadata?.is_template_declaration && context.state.options.experimental.async) {
			let snippet_name;

			// Find out if this references a {@const ...} declaration of an implicit children snippet
			// when it is itself inside a snippet block at the same level. If so, error.
			for (let i = context.path.length - 1; i >= 0; i--) {
				const parent = context.path[i];
				const grand_parent = context.path[i - 1];

				if (parent.type === 'SnippetBlock') {
					snippet_name = parent.expression.name;
				} else if (
					snippet_name &&
					grand_parent &&
					parent.type === 'Fragment' &&
					(is_component_node(grand_parent) ||
						(grand_parent.type === 'SvelteBoundary' &&
							(snippet_name === 'failed' || snippet_name === 'pending')))
				) {
					if (
						is_component_node(grand_parent)
							? grand_parent.metadata.scopes.default === binding.scope
							: context.state.scopes.get(parent) === binding.scope
					) {
						const_tag_invalid_reference(node, node.name);
					} else {
						break;
					}
				}
			}
		}
	}
}

/** @import { AST } from '#compiler' */
/** @import { Context } from '../types' */

/**
 * @param {AST.IfBlock} node
 * @param {Context} context
 */
function IfBlock$2(node, context) {
	validate_block_not_empty(node.consequent);
	validate_block_not_empty(node.alternate);

	if (context.state.analysis.runes) {
		validate_opening_tag(node, context.state, node.elseif ? ':' : '#');
	}

	mark_subtree_dynamic(context.path);

	context.visit(node.test, {
		...context.state,
		expression: node.metadata.expression
	});

	context.visit(node.consequent);
	if (node.alternate) context.visit(node.alternate);
}

/** @import { ImportDeclaration } from 'estree' */
/** @import { Context } from '../types' */

/**
 * @param {ImportDeclaration} node
 * @param {Context} context
 */
function ImportDeclaration(node, context) {
	if (context.state.analysis.runes) {
		const source = /** @type {string} */ (node.source.value);

		if (source.startsWith('svelte/internal')) {
			import_svelte_internal_forbidden(node);
		}

		if (source === 'svelte') {
			for (const specifier of node.specifiers) {
				if (specifier.type === 'ImportSpecifier') {
					if (
						specifier.imported.type === 'Identifier' &&
						(specifier.imported.name === 'beforeUpdate' ||
							specifier.imported.name === 'afterUpdate')
					) {
						runes_mode_invalid_import(specifier, specifier.imported.name);
					}
				}
			}
		}
	}
}

/** @import { AST } from '#compiler' */
/** @import { Context } from '../types' */

/**
 * @param {AST.KeyBlock} node
 * @param {Context} context
 */
function KeyBlock$2(node, context) {
	validate_block_not_empty(node.fragment);

	if (context.state.analysis.runes) {
		validate_opening_tag(node, context.state, '#');
	}

	mark_subtree_dynamic(context.path);

	context.visit(node.expression, { ...context.state, expression: node.metadata.expression });
	context.visit(node.fragment);
}

/** @import { Expression, LabeledStatement } from 'estree' */
/** @import { AST, ReactiveStatement } from '#compiler' */
/** @import { Context } from '../types' */

/**
 * @param {LabeledStatement} node
 * @param {Context} context
 */
function LabeledStatement$2(node, context) {
	if (node.label.name === '$') {
		const parent = /** @type {AST.SvelteNode} */ (context.path.at(-1));

		const is_reactive_statement =
			context.state.ast_type === 'instance' && parent.type === 'Program';

		if (is_reactive_statement) {
			if (context.state.analysis.runes) {
				legacy_reactive_statement_invalid(node);
			}

			// Find all dependencies of this `$: {...}` statement
			/** @type {ReactiveStatement} */
			const reactive_statement = {
				assignments: new Set(),
				dependencies: []
			};

			context.next({
				...context.state,
				reactive_statement,
				function_depth: context.state.scope.function_depth + 1
			});

			// Every referenced binding becomes a dependency, unless it's on
			// the left-hand side of an `=` assignment
			for (const [name, nodes] of context.state.scope.references) {
				const binding = context.state.scope.get(name);
				if (binding === null) continue;

				for (const { node, path } of nodes) {
					/** @type {Expression} */
					let left = node;

					let i = path.length - 1;
					let parent = /** @type {Expression} */ (path.at(i));
					while (parent.type === 'MemberExpression') {
						left = parent;
						parent = /** @type {Expression} */ (path.at(--i));
					}

					if (
						parent.type === 'AssignmentExpression' &&
						parent.operator === '=' &&
						parent.left === left
					) {
						continue;
					}

					reactive_statement.dependencies.push(binding);
					break;
				}
			}

			context.state.analysis.reactive_statements.set(node, reactive_statement);

			if (
				node.body.type === 'ExpressionStatement' &&
				node.body.expression.type === 'AssignmentExpression'
			) {
				let ids = extract_identifiers(node.body.expression.left);
				if (node.body.expression.left.type === 'MemberExpression') {
					const id = object$1(node.body.expression.left);
					if (id !== null) {
						ids = [id];
					}
				}

				for (const id of ids) {
					const binding = context.state.scope.get(id.name);
					if (binding?.kind === 'legacy_reactive') {
						// TODO does this include `let double; $: double = x * 2`?
						binding.legacy_dependencies = Array.from(reactive_statement.dependencies);
					}
				}
			}
		} else if (!context.state.analysis.runes) {
			reactive_declaration_invalid_placement(node);
		}
	}

	context.next();
}

/** @import { AST } from '#compiler' */
/** @import { Context } from '../types' */

/**
 * @param {AST.LetDirective} node
 * @param {Context} context
 */
function LetDirective$1(node, context) {
	const parent = context.path.at(-1);

	if (
		parent === undefined ||
		(parent.type !== 'Component' &&
			parent.type !== 'RegularElement' &&
			parent.type !== 'SlotElement' &&
			parent.type !== 'SvelteElement' &&
			parent.type !== 'SvelteComponent' &&
			parent.type !== 'SvelteSelf' &&
			parent.type !== 'SvelteFragment')
	) {
		let_directive_invalid_placement(node);
	}
}

/** @import { Literal } from 'estree' */

/**
 * @param {Literal} node
 */
function Literal(node) {
	if (typeof node.value === 'string') {
		if (regex_bidirectional_control_characters.test(node.value)) {
			bidirectional_control_characters(node);
		}
	}
}

/** @import { MemberExpression } from 'estree' */
/** @import { Context } from '../types' */

/**
 * @param {MemberExpression} node
 * @param {Context} context
 */
function MemberExpression$2(node, context) {
	if (node.object.type === 'Identifier' && node.property.type === 'Identifier') {
		const binding = context.state.scope.get(node.object.name);
		if (binding?.kind === 'rest_prop' && node.property.name.startsWith('$$')) {
			props_illegal_name(node.property);
		}
	}

	if (context.state.expression) {
		context.state.expression.has_member_expression = true;
		context.state.expression.has_state ||= !is_pure(node, context);
	}

	if (!is_safe_identifier(node, context.state.scope)) {
		context.state.analysis.needs_context = true;
	}

	context.next();
}

/** @import { NewExpression } from 'estree' */
/** @import { Context } from '../types' */

/**
 * @param {NewExpression} node
 * @param {Context} context
 */
function NewExpression(node, context) {
	if (node.callee.type === 'ClassExpression' && context.state.scope.function_depth > 0) {
		perf_avoid_inline_class(node);
	}

	context.state.analysis.needs_context = true;

	context.next();
}

/** @import { AST } from '#compiler' */
/** @import { Context } from '../types' */

/**
 * @param {AST.OnDirective} node
 * @param {Context} context
 */
function OnDirective$1(node, context) {
	if (context.state.analysis.runes) {
		const parent_type = context.path.at(-1)?.type;

		// Don't warn on component events; these might not be under the author's control so the warning would be unactionable
		if (parent_type === 'RegularElement' || parent_type === 'SvelteElement') {
			event_directive_deprecated(node, node.name);
		}
	}

	const parent = context.path.at(-1);
	if (parent?.type === 'SvelteElement' || parent?.type === 'RegularElement') {
		context.state.analysis.event_directive_node ??= node;
	}

	mark_subtree_dynamic(context.path);

	context.next({ ...context.state, expression: node.metadata.expression });
}

/** @import { PropertyDefinition } from 'estree' */
/** @import { Context } from '../types' */

/**
 * @param {PropertyDefinition} node
 * @param {Context} context
 */
function PropertyDefinition$1(node, context) {
	const name = get_name(node.key);
	const field = name && context.state.state_fields.get(name);

	if (field && node !== field.node && node.value) {
		if (/** @type {number} */ (node.start) < /** @type {number} */ (field.node.start)) {
			state_field_invalid_assignment(node);
		}
	}

	context.next();
}

var lib$1 = {};

var ariaPropsMap = {};

var iterationDecorator$1 = {};

var iteratorProxy$1 = {};

var hasRequiredIteratorProxy$1;

function requireIteratorProxy$1 () {
	if (hasRequiredIteratorProxy$1) return iteratorProxy$1;
	hasRequiredIteratorProxy$1 = 1;

	Object.defineProperty(iteratorProxy$1, "__esModule", {
	  value: true
	});
	iteratorProxy$1.default = void 0;
	// eslint-disable-next-line no-unused-vars
	function iteratorProxy() {
	  var values = this;
	  var index = 0;
	  var iter = {
	    '@@iterator': function iterator() {
	      return iter;
	    },
	    next: function next() {
	      if (index < values.length) {
	        var value = values[index];
	        index = index + 1;
	        return {
	          done: false,
	          value: value
	        };
	      } else {
	        return {
	          done: true
	        };
	      }
	    }
	  };
	  return iter;
	}
	iteratorProxy$1.default = iteratorProxy;
	return iteratorProxy$1;
}

var hasRequiredIterationDecorator$1;

function requireIterationDecorator$1 () {
	if (hasRequiredIterationDecorator$1) return iterationDecorator$1;
	hasRequiredIterationDecorator$1 = 1;

	Object.defineProperty(iterationDecorator$1, "__esModule", {
	  value: true
	});
	iterationDecorator$1.default = iterationDecorator;
	var _iteratorProxy = _interopRequireDefault(requireIteratorProxy$1());
	function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
	function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
	function iterationDecorator(collection, entries) {
	  if (typeof Symbol === 'function' && _typeof(Symbol.iterator) === 'symbol') {
	    Object.defineProperty(collection, Symbol.iterator, {
	      value: _iteratorProxy.default.bind(entries)
	    });
	  }
	  return collection;
	}
	return iterationDecorator$1;
}

var hasRequiredAriaPropsMap;

function requireAriaPropsMap () {
	if (hasRequiredAriaPropsMap) return ariaPropsMap;
	hasRequiredAriaPropsMap = 1;

	Object.defineProperty(ariaPropsMap, "__esModule", {
	  value: true
	});
	ariaPropsMap.default = void 0;
	var _iterationDecorator = _interopRequireDefault(requireIterationDecorator$1());
	function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
	function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
	function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
	function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
	function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
	function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = true, o = false; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = true, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
	function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
	var properties = [['aria-activedescendant', {
	  'type': 'id'
	}], ['aria-atomic', {
	  'type': 'boolean'
	}], ['aria-autocomplete', {
	  'type': 'token',
	  'values': ['inline', 'list', 'both', 'none']
	}], ['aria-braillelabel', {
	  'type': 'string'
	}], ['aria-brailleroledescription', {
	  'type': 'string'
	}], ['aria-busy', {
	  'type': 'boolean'
	}], ['aria-checked', {
	  'type': 'tristate'
	}], ['aria-colcount', {
	  type: 'integer'
	}], ['aria-colindex', {
	  type: 'integer'
	}], ['aria-colspan', {
	  type: 'integer'
	}], ['aria-controls', {
	  'type': 'idlist'
	}], ['aria-current', {
	  type: 'token',
	  values: ['page', 'step', 'location', 'date', 'time', true, false]
	}], ['aria-describedby', {
	  'type': 'idlist'
	}], ['aria-description', {
	  'type': 'string'
	}], ['aria-details', {
	  'type': 'id'
	}], ['aria-disabled', {
	  'type': 'boolean'
	}], ['aria-dropeffect', {
	  'type': 'tokenlist',
	  'values': ['copy', 'execute', 'link', 'move', 'none', 'popup']
	}], ['aria-errormessage', {
	  'type': 'id'
	}], ['aria-expanded', {
	  'type': 'boolean',
	  'allowundefined': true
	}], ['aria-flowto', {
	  'type': 'idlist'
	}], ['aria-grabbed', {
	  'type': 'boolean',
	  'allowundefined': true
	}], ['aria-haspopup', {
	  'type': 'token',
	  'values': [false, true, 'menu', 'listbox', 'tree', 'grid', 'dialog']
	}], ['aria-hidden', {
	  'type': 'boolean',
	  'allowundefined': true
	}], ['aria-invalid', {
	  'type': 'token',
	  'values': ['grammar', false, 'spelling', true]
	}], ['aria-keyshortcuts', {
	  type: 'string'
	}], ['aria-label', {
	  'type': 'string'
	}], ['aria-labelledby', {
	  'type': 'idlist'
	}], ['aria-level', {
	  'type': 'integer'
	}], ['aria-live', {
	  'type': 'token',
	  'values': ['assertive', 'off', 'polite']
	}], ['aria-modal', {
	  type: 'boolean'
	}], ['aria-multiline', {
	  'type': 'boolean'
	}], ['aria-multiselectable', {
	  'type': 'boolean'
	}], ['aria-orientation', {
	  'type': 'token',
	  'values': ['vertical', 'undefined', 'horizontal']
	}], ['aria-owns', {
	  'type': 'idlist'
	}], ['aria-placeholder', {
	  type: 'string'
	}], ['aria-posinset', {
	  'type': 'integer'
	}], ['aria-pressed', {
	  'type': 'tristate'
	}], ['aria-readonly', {
	  'type': 'boolean'
	}], ['aria-relevant', {
	  'type': 'tokenlist',
	  'values': ['additions', 'all', 'removals', 'text']
	}], ['aria-required', {
	  'type': 'boolean'
	}], ['aria-roledescription', {
	  type: 'string'
	}], ['aria-rowcount', {
	  type: 'integer'
	}], ['aria-rowindex', {
	  type: 'integer'
	}], ['aria-rowspan', {
	  type: 'integer'
	}], ['aria-selected', {
	  'type': 'boolean',
	  'allowundefined': true
	}], ['aria-setsize', {
	  'type': 'integer'
	}], ['aria-sort', {
	  'type': 'token',
	  'values': ['ascending', 'descending', 'none', 'other']
	}], ['aria-valuemax', {
	  'type': 'number'
	}], ['aria-valuemin', {
	  'type': 'number'
	}], ['aria-valuenow', {
	  'type': 'number'
	}], ['aria-valuetext', {
	  'type': 'string'
	}]];
	var ariaPropsMap$1 = {
	  entries: function entries() {
	    return properties;
	  },
	  forEach: function forEach(fn) {
	    var thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
	    for (var _i = 0, _properties = properties; _i < _properties.length; _i++) {
	      var _properties$_i = _slicedToArray(_properties[_i], 2),
	        key = _properties$_i[0],
	        values = _properties$_i[1];
	      fn.call(thisArg, values, key, properties);
	    }
	  },
	  get: function get(key) {
	    var item = properties.filter(function (tuple) {
	      return tuple[0] === key ? true : false;
	    })[0];
	    return item && item[1];
	  },
	  has: function has(key) {
	    return !!ariaPropsMap$1.get(key);
	  },
	  keys: function keys() {
	    return properties.map(function (_ref) {
	      var _ref2 = _slicedToArray(_ref, 1),
	        key = _ref2[0];
	      return key;
	    });
	  },
	  values: function values() {
	    return properties.map(function (_ref3) {
	      var _ref4 = _slicedToArray(_ref3, 2),
	        values = _ref4[1];
	      return values;
	    });
	  }
	};
	ariaPropsMap.default = (0, _iterationDecorator.default)(ariaPropsMap$1, ariaPropsMap$1.entries());
	return ariaPropsMap;
}

var domMap = {};

var hasRequiredDomMap;

function requireDomMap () {
	if (hasRequiredDomMap) return domMap;
	hasRequiredDomMap = 1;

	Object.defineProperty(domMap, "__esModule", {
	  value: true
	});
	domMap.default = void 0;
	var _iterationDecorator = _interopRequireDefault(requireIterationDecorator$1());
	function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
	function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
	function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
	function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
	function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
	function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = true, o = false; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = true, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
	function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
	var dom = [['a', {
	  reserved: false
	}], ['abbr', {
	  reserved: false
	}], ['acronym', {
	  reserved: false
	}], ['address', {
	  reserved: false
	}], ['applet', {
	  reserved: false
	}], ['area', {
	  reserved: false
	}], ['article', {
	  reserved: false
	}], ['aside', {
	  reserved: false
	}], ['audio', {
	  reserved: false
	}], ['b', {
	  reserved: false
	}], ['base', {
	  reserved: true
	}], ['bdi', {
	  reserved: false
	}], ['bdo', {
	  reserved: false
	}], ['big', {
	  reserved: false
	}], ['blink', {
	  reserved: false
	}], ['blockquote', {
	  reserved: false
	}], ['body', {
	  reserved: false
	}], ['br', {
	  reserved: false
	}], ['button', {
	  reserved: false
	}], ['canvas', {
	  reserved: false
	}], ['caption', {
	  reserved: false
	}], ['center', {
	  reserved: false
	}], ['cite', {
	  reserved: false
	}], ['code', {
	  reserved: false
	}], ['col', {
	  reserved: true
	}], ['colgroup', {
	  reserved: true
	}], ['content', {
	  reserved: false
	}], ['data', {
	  reserved: false
	}], ['datalist', {
	  reserved: false
	}], ['dd', {
	  reserved: false
	}], ['del', {
	  reserved: false
	}], ['details', {
	  reserved: false
	}], ['dfn', {
	  reserved: false
	}], ['dialog', {
	  reserved: false
	}], ['dir', {
	  reserved: false
	}], ['div', {
	  reserved: false
	}], ['dl', {
	  reserved: false
	}], ['dt', {
	  reserved: false
	}], ['em', {
	  reserved: false
	}], ['embed', {
	  reserved: false
	}], ['fieldset', {
	  reserved: false
	}], ['figcaption', {
	  reserved: false
	}], ['figure', {
	  reserved: false
	}], ['font', {
	  reserved: false
	}], ['footer', {
	  reserved: false
	}], ['form', {
	  reserved: false
	}], ['frame', {
	  reserved: false
	}], ['frameset', {
	  reserved: false
	}], ['h1', {
	  reserved: false
	}], ['h2', {
	  reserved: false
	}], ['h3', {
	  reserved: false
	}], ['h4', {
	  reserved: false
	}], ['h5', {
	  reserved: false
	}], ['h6', {
	  reserved: false
	}], ['head', {
	  reserved: true
	}], ['header', {
	  reserved: false
	}], ['hgroup', {
	  reserved: false
	}], ['hr', {
	  reserved: false
	}], ['html', {
	  reserved: true
	}], ['i', {
	  reserved: false
	}], ['iframe', {
	  reserved: false
	}], ['img', {
	  reserved: false
	}], ['input', {
	  reserved: false
	}], ['ins', {
	  reserved: false
	}], ['kbd', {
	  reserved: false
	}], ['keygen', {
	  reserved: false
	}], ['label', {
	  reserved: false
	}], ['legend', {
	  reserved: false
	}], ['li', {
	  reserved: false
	}], ['link', {
	  reserved: true
	}], ['main', {
	  reserved: false
	}], ['map', {
	  reserved: false
	}], ['mark', {
	  reserved: false
	}], ['marquee', {
	  reserved: false
	}], ['menu', {
	  reserved: false
	}], ['menuitem', {
	  reserved: false
	}], ['meta', {
	  reserved: true
	}], ['meter', {
	  reserved: false
	}], ['nav', {
	  reserved: false
	}], ['noembed', {
	  reserved: true
	}], ['noscript', {
	  reserved: true
	}], ['object', {
	  reserved: false
	}], ['ol', {
	  reserved: false
	}], ['optgroup', {
	  reserved: false
	}], ['option', {
	  reserved: false
	}], ['output', {
	  reserved: false
	}], ['p', {
	  reserved: false
	}], ['param', {
	  reserved: true
	}], ['picture', {
	  reserved: true
	}], ['pre', {
	  reserved: false
	}], ['progress', {
	  reserved: false
	}], ['q', {
	  reserved: false
	}], ['rp', {
	  reserved: false
	}], ['rt', {
	  reserved: false
	}], ['rtc', {
	  reserved: false
	}], ['ruby', {
	  reserved: false
	}], ['s', {
	  reserved: false
	}], ['samp', {
	  reserved: false
	}], ['script', {
	  reserved: true
	}], ['section', {
	  reserved: false
	}], ['select', {
	  reserved: false
	}], ['small', {
	  reserved: false
	}], ['source', {
	  reserved: true
	}], ['spacer', {
	  reserved: false
	}], ['span', {
	  reserved: false
	}], ['strike', {
	  reserved: false
	}], ['strong', {
	  reserved: false
	}], ['style', {
	  reserved: true
	}], ['sub', {
	  reserved: false
	}], ['summary', {
	  reserved: false
	}], ['sup', {
	  reserved: false
	}], ['table', {
	  reserved: false
	}], ['tbody', {
	  reserved: false
	}], ['td', {
	  reserved: false
	}], ['textarea', {
	  reserved: false
	}], ['tfoot', {
	  reserved: false
	}], ['th', {
	  reserved: false
	}], ['thead', {
	  reserved: false
	}], ['time', {
	  reserved: false
	}], ['title', {
	  reserved: true
	}], ['tr', {
	  reserved: false
	}], ['track', {
	  reserved: true
	}], ['tt', {
	  reserved: false
	}], ['u', {
	  reserved: false
	}], ['ul', {
	  reserved: false
	}], ['var', {
	  reserved: false
	}], ['video', {
	  reserved: false
	}], ['wbr', {
	  reserved: false
	}], ['xmp', {
	  reserved: false
	}]];
	var domMap$1 = {
	  entries: function entries() {
	    return dom;
	  },
	  forEach: function forEach(fn) {
	    var thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
	    for (var _i = 0, _dom = dom; _i < _dom.length; _i++) {
	      var _dom$_i = _slicedToArray(_dom[_i], 2),
	        key = _dom$_i[0],
	        values = _dom$_i[1];
	      fn.call(thisArg, values, key, dom);
	    }
	  },
	  get: function get(key) {
	    var item = dom.filter(function (tuple) {
	      return tuple[0] === key ? true : false;
	    })[0];
	    return item && item[1];
	  },
	  has: function has(key) {
	    return !!domMap$1.get(key);
	  },
	  keys: function keys() {
	    return dom.map(function (_ref) {
	      var _ref2 = _slicedToArray(_ref, 1),
	        key = _ref2[0];
	      return key;
	    });
	  },
	  values: function values() {
	    return dom.map(function (_ref3) {
	      var _ref4 = _slicedToArray(_ref3, 2),
	        values = _ref4[1];
	      return values;
	    });
	  }
	};
	domMap.default = (0, _iterationDecorator.default)(domMap$1, domMap$1.entries());
	return domMap;
}

var rolesMap = {};

var ariaAbstractRoles = {};

var commandRole = {};

var hasRequiredCommandRole;

function requireCommandRole () {
	if (hasRequiredCommandRole) return commandRole;
	hasRequiredCommandRole = 1;

	Object.defineProperty(commandRole, "__esModule", {
	  value: true
	});
	commandRole.default = void 0;
	var commandRole$1 = {
	  abstract: true,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'widget']]
	};
	commandRole.default = commandRole$1;
	return commandRole;
}

var compositeRole = {};

var hasRequiredCompositeRole;

function requireCompositeRole () {
	if (hasRequiredCompositeRole) return compositeRole;
	hasRequiredCompositeRole = 1;

	Object.defineProperty(compositeRole, "__esModule", {
	  value: true
	});
	compositeRole.default = void 0;
	var compositeRole$1 = {
	  abstract: true,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-activedescendant': null,
	    'aria-disabled': null
	  },
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'widget']]
	};
	compositeRole.default = compositeRole$1;
	return compositeRole;
}

var inputRole = {};

var hasRequiredInputRole;

function requireInputRole () {
	if (hasRequiredInputRole) return inputRole;
	hasRequiredInputRole = 1;

	Object.defineProperty(inputRole, "__esModule", {
	  value: true
	});
	inputRole.default = void 0;
	var inputRole$1 = {
	  abstract: true,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'input'
	    },
	    module: 'XForms'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'widget']]
	};
	inputRole.default = inputRole$1;
	return inputRole;
}

var landmarkRole = {};

var hasRequiredLandmarkRole;

function requireLandmarkRole () {
	if (hasRequiredLandmarkRole) return landmarkRole;
	hasRequiredLandmarkRole = 1;

	Object.defineProperty(landmarkRole, "__esModule", {
	  value: true
	});
	landmarkRole.default = void 0;
	var landmarkRole$1 = {
	  abstract: true,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	landmarkRole.default = landmarkRole$1;
	return landmarkRole;
}

var rangeRole = {};

var hasRequiredRangeRole;

function requireRangeRole () {
	if (hasRequiredRangeRole) return rangeRole;
	hasRequiredRangeRole = 1;

	Object.defineProperty(rangeRole, "__esModule", {
	  value: true
	});
	rangeRole.default = void 0;
	var rangeRole$1 = {
	  abstract: true,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-valuemax': null,
	    'aria-valuemin': null,
	    'aria-valuenow': null
	  },
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure']]
	};
	rangeRole.default = rangeRole$1;
	return rangeRole;
}

var roletypeRole = {};

var hasRequiredRoletypeRole;

function requireRoletypeRole () {
	if (hasRequiredRoletypeRole) return roletypeRole;
	hasRequiredRoletypeRole = 1;

	Object.defineProperty(roletypeRole, "__esModule", {
	  value: true
	});
	roletypeRole.default = void 0;
	var roletypeRole$1 = {
	  abstract: true,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: [],
	  prohibitedProps: [],
	  props: {
	    'aria-atomic': null,
	    'aria-busy': null,
	    'aria-controls': null,
	    'aria-current': null,
	    'aria-describedby': null,
	    'aria-details': null,
	    'aria-dropeffect': null,
	    'aria-flowto': null,
	    'aria-grabbed': null,
	    'aria-hidden': null,
	    'aria-keyshortcuts': null,
	    'aria-label': null,
	    'aria-labelledby': null,
	    'aria-live': null,
	    'aria-owns': null,
	    'aria-relevant': null,
	    'aria-roledescription': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'role'
	    },
	    module: 'XHTML'
	  }, {
	    concept: {
	      name: 'type'
	    },
	    module: 'Dublin Core'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: []
	};
	roletypeRole.default = roletypeRole$1;
	return roletypeRole;
}

var sectionRole = {};

var hasRequiredSectionRole;

function requireSectionRole () {
	if (hasRequiredSectionRole) return sectionRole;
	hasRequiredSectionRole = 1;

	Object.defineProperty(sectionRole, "__esModule", {
	  value: true
	});
	sectionRole.default = void 0;
	var sectionRole$1 = {
	  abstract: true,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: [],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'frontmatter'
	    },
	    module: 'DTB'
	  }, {
	    concept: {
	      name: 'level'
	    },
	    module: 'DTB'
	  }, {
	    concept: {
	      name: 'level'
	    },
	    module: 'SMIL'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure']]
	};
	sectionRole.default = sectionRole$1;
	return sectionRole;
}

var sectionheadRole = {};

var hasRequiredSectionheadRole;

function requireSectionheadRole () {
	if (hasRequiredSectionheadRole) return sectionheadRole;
	hasRequiredSectionheadRole = 1;

	Object.defineProperty(sectionheadRole, "__esModule", {
	  value: true
	});
	sectionheadRole.default = void 0;
	var sectionheadRole$1 = {
	  abstract: true,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure']]
	};
	sectionheadRole.default = sectionheadRole$1;
	return sectionheadRole;
}

var selectRole = {};

var hasRequiredSelectRole;

function requireSelectRole () {
	if (hasRequiredSelectRole) return selectRole;
	hasRequiredSelectRole = 1;

	Object.defineProperty(selectRole, "__esModule", {
	  value: true
	});
	selectRole.default = void 0;
	var selectRole$1 = {
	  abstract: true,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-orientation': null
	  },
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'composite'], ['roletype', 'structure', 'section', 'group']]
	};
	selectRole.default = selectRole$1;
	return selectRole;
}

var structureRole = {};

var hasRequiredStructureRole;

function requireStructureRole () {
	if (hasRequiredStructureRole) return structureRole;
	hasRequiredStructureRole = 1;

	Object.defineProperty(structureRole, "__esModule", {
	  value: true
	});
	structureRole.default = void 0;
	var structureRole$1 = {
	  abstract: true,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: [],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype']]
	};
	structureRole.default = structureRole$1;
	return structureRole;
}

var widgetRole = {};

var hasRequiredWidgetRole;

function requireWidgetRole () {
	if (hasRequiredWidgetRole) return widgetRole;
	hasRequiredWidgetRole = 1;

	Object.defineProperty(widgetRole, "__esModule", {
	  value: true
	});
	widgetRole.default = void 0;
	var widgetRole$1 = {
	  abstract: true,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: [],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype']]
	};
	widgetRole.default = widgetRole$1;
	return widgetRole;
}

var windowRole = {};

var hasRequiredWindowRole$1;

function requireWindowRole$1 () {
	if (hasRequiredWindowRole$1) return windowRole;
	hasRequiredWindowRole$1 = 1;

	Object.defineProperty(windowRole, "__esModule", {
	  value: true
	});
	windowRole.default = void 0;
	var windowRole$1 = {
	  abstract: true,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-modal': null
	  },
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype']]
	};
	windowRole.default = windowRole$1;
	return windowRole;
}

var hasRequiredAriaAbstractRoles;

function requireAriaAbstractRoles () {
	if (hasRequiredAriaAbstractRoles) return ariaAbstractRoles;
	hasRequiredAriaAbstractRoles = 1;

	Object.defineProperty(ariaAbstractRoles, "__esModule", {
	  value: true
	});
	ariaAbstractRoles.default = void 0;
	var _commandRole = _interopRequireDefault(requireCommandRole());
	var _compositeRole = _interopRequireDefault(requireCompositeRole());
	var _inputRole = _interopRequireDefault(requireInputRole());
	var _landmarkRole = _interopRequireDefault(requireLandmarkRole());
	var _rangeRole = _interopRequireDefault(requireRangeRole());
	var _roletypeRole = _interopRequireDefault(requireRoletypeRole());
	var _sectionRole = _interopRequireDefault(requireSectionRole());
	var _sectionheadRole = _interopRequireDefault(requireSectionheadRole());
	var _selectRole = _interopRequireDefault(requireSelectRole());
	var _structureRole = _interopRequireDefault(requireStructureRole());
	var _widgetRole = _interopRequireDefault(requireWidgetRole());
	var _windowRole = _interopRequireDefault(requireWindowRole$1());
	function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
	var ariaAbstractRoles$1 = [['command', _commandRole.default], ['composite', _compositeRole.default], ['input', _inputRole.default], ['landmark', _landmarkRole.default], ['range', _rangeRole.default], ['roletype', _roletypeRole.default], ['section', _sectionRole.default], ['sectionhead', _sectionheadRole.default], ['select', _selectRole.default], ['structure', _structureRole.default], ['widget', _widgetRole.default], ['window', _windowRole.default]];
	ariaAbstractRoles.default = ariaAbstractRoles$1;
	return ariaAbstractRoles;
}

var ariaLiteralRoles = {};

var alertRole = {};

var hasRequiredAlertRole$1;

function requireAlertRole$1 () {
	if (hasRequiredAlertRole$1) return alertRole;
	hasRequiredAlertRole$1 = 1;

	Object.defineProperty(alertRole, "__esModule", {
	  value: true
	});
	alertRole.default = void 0;
	var alertRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-atomic': 'true',
	    'aria-live': 'assertive'
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'alert'
	    },
	    module: 'XForms'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	alertRole.default = alertRole$1;
	return alertRole;
}

var alertdialogRole = {};

var hasRequiredAlertdialogRole;

function requireAlertdialogRole () {
	if (hasRequiredAlertdialogRole) return alertdialogRole;
	hasRequiredAlertdialogRole = 1;

	Object.defineProperty(alertdialogRole, "__esModule", {
	  value: true
	});
	alertdialogRole.default = void 0;
	var alertdialogRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'alert'
	    },
	    module: 'XForms'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'alert'], ['roletype', 'window', 'dialog']]
	};
	alertdialogRole.default = alertdialogRole$1;
	return alertdialogRole;
}

var applicationRole = {};

var hasRequiredApplicationRole$1;

function requireApplicationRole$1 () {
	if (hasRequiredApplicationRole$1) return applicationRole;
	hasRequiredApplicationRole$1 = 1;

	Object.defineProperty(applicationRole, "__esModule", {
	  value: true
	});
	applicationRole.default = void 0;
	var applicationRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-activedescendant': null,
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'Device Independence Delivery Unit'
	    }
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure']]
	};
	applicationRole.default = applicationRole$1;
	return applicationRole;
}

var articleRole = {};

var hasRequiredArticleRole$1;

function requireArticleRole$1 () {
	if (hasRequiredArticleRole$1) return articleRole;
	hasRequiredArticleRole$1 = 1;

	Object.defineProperty(articleRole, "__esModule", {
	  value: true
	});
	articleRole.default = void 0;
	var articleRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-posinset': null,
	    'aria-setsize': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'article'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'document']]
	};
	articleRole.default = articleRole$1;
	return articleRole;
}

var bannerRole = {};

var hasRequiredBannerRole$1;

function requireBannerRole$1 () {
	if (hasRequiredBannerRole$1) return bannerRole;
	hasRequiredBannerRole$1 = 1;

	Object.defineProperty(bannerRole, "__esModule", {
	  value: true
	});
	bannerRole.default = void 0;
	var bannerRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      constraints: ['scoped to the body element'],
	      name: 'header'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	bannerRole.default = bannerRole$1;
	return bannerRole;
}

var blockquoteRole = {};

var hasRequiredBlockquoteRole$1;

function requireBlockquoteRole$1 () {
	if (hasRequiredBlockquoteRole$1) return blockquoteRole;
	hasRequiredBlockquoteRole$1 = 1;

	Object.defineProperty(blockquoteRole, "__esModule", {
	  value: true
	});
	blockquoteRole.default = void 0;
	var blockquoteRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'blockquote'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	blockquoteRole.default = blockquoteRole$1;
	return blockquoteRole;
}

var buttonRole = {};

var hasRequiredButtonRole$1;

function requireButtonRole$1 () {
	if (hasRequiredButtonRole$1) return buttonRole;
	hasRequiredButtonRole$1 = 1;

	Object.defineProperty(buttonRole, "__esModule", {
	  value: true
	});
	buttonRole.default = void 0;
	var buttonRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: true,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-pressed': null
	  },
	  relatedConcepts: [{
	    concept: {
	      attributes: [{
	        name: 'type',
	        value: 'button'
	      }],
	      name: 'input'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        name: 'type',
	        value: 'image'
	      }],
	      name: 'input'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        name: 'type',
	        value: 'reset'
	      }],
	      name: 'input'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        name: 'type',
	        value: 'submit'
	      }],
	      name: 'input'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'button'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'trigger'
	    },
	    module: 'XForms'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'command']]
	};
	buttonRole.default = buttonRole$1;
	return buttonRole;
}

var captionRole = {};

var hasRequiredCaptionRole$1;

function requireCaptionRole$1 () {
	if (hasRequiredCaptionRole$1) return captionRole;
	hasRequiredCaptionRole$1 = 1;

	Object.defineProperty(captionRole, "__esModule", {
	  value: true
	});
	captionRole.default = void 0;
	var captionRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['prohibited'],
	  prohibitedProps: ['aria-label', 'aria-labelledby'],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'caption'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: ['figure', 'grid', 'table'],
	  requiredContextRole: ['figure', 'grid', 'table'],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	captionRole.default = captionRole$1;
	return captionRole;
}

var cellRole = {};

var hasRequiredCellRole$1;

function requireCellRole$1 () {
	if (hasRequiredCellRole$1) return cellRole;
	hasRequiredCellRole$1 = 1;

	Object.defineProperty(cellRole, "__esModule", {
	  value: true
	});
	cellRole.default = void 0;
	var cellRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-colindex': null,
	    'aria-colspan': null,
	    'aria-rowindex': null,
	    'aria-rowspan': null
	  },
	  relatedConcepts: [{
	    concept: {
	      constraints: ['ancestor table element has table role'],
	      name: 'td'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: ['row'],
	  requiredContextRole: ['row'],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	cellRole.default = cellRole$1;
	return cellRole;
}

var checkboxRole = {};

var hasRequiredCheckboxRole;

function requireCheckboxRole () {
	if (hasRequiredCheckboxRole) return checkboxRole;
	hasRequiredCheckboxRole = 1;

	Object.defineProperty(checkboxRole, "__esModule", {
	  value: true
	});
	checkboxRole.default = void 0;
	var checkboxRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: true,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-checked': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-invalid': null,
	    'aria-readonly': null,
	    'aria-required': null
	  },
	  relatedConcepts: [{
	    concept: {
	      attributes: [{
	        name: 'type',
	        value: 'checkbox'
	      }],
	      name: 'input'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'option'
	    },
	    module: 'ARIA'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {
	    'aria-checked': null
	  },
	  superClass: [['roletype', 'widget', 'input']]
	};
	checkboxRole.default = checkboxRole$1;
	return checkboxRole;
}

var codeRole = {};

var hasRequiredCodeRole;

function requireCodeRole () {
	if (hasRequiredCodeRole) return codeRole;
	hasRequiredCodeRole = 1;

	Object.defineProperty(codeRole, "__esModule", {
	  value: true
	});
	codeRole.default = void 0;
	var codeRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['prohibited'],
	  prohibitedProps: ['aria-label', 'aria-labelledby'],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'code'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	codeRole.default = codeRole$1;
	return codeRole;
}

var columnheaderRole = {};

var hasRequiredColumnheaderRole;

function requireColumnheaderRole () {
	if (hasRequiredColumnheaderRole) return columnheaderRole;
	hasRequiredColumnheaderRole = 1;

	Object.defineProperty(columnheaderRole, "__esModule", {
	  value: true
	});
	columnheaderRole.default = void 0;
	var columnheaderRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-sort': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'th'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        name: 'scope',
	        value: 'col'
	      }],
	      name: 'th'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        name: 'scope',
	        value: 'colgroup'
	      }],
	      name: 'th'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: ['row'],
	  requiredContextRole: ['row'],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'cell'], ['roletype', 'structure', 'section', 'cell', 'gridcell'], ['roletype', 'widget', 'gridcell'], ['roletype', 'structure', 'sectionhead']]
	};
	columnheaderRole.default = columnheaderRole$1;
	return columnheaderRole;
}

var comboboxRole = {};

var hasRequiredComboboxRole;

function requireComboboxRole () {
	if (hasRequiredComboboxRole) return comboboxRole;
	hasRequiredComboboxRole = 1;

	Object.defineProperty(comboboxRole, "__esModule", {
	  value: true
	});
	comboboxRole.default = void 0;
	var comboboxRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-activedescendant': null,
	    'aria-autocomplete': null,
	    'aria-errormessage': null,
	    'aria-invalid': null,
	    'aria-readonly': null,
	    'aria-required': null,
	    'aria-expanded': 'false',
	    'aria-haspopup': 'listbox'
	  },
	  relatedConcepts: [{
	    concept: {
	      attributes: [{
	        constraints: ['set'],
	        name: 'list'
	      }, {
	        name: 'type',
	        value: 'email'
	      }],
	      name: 'input'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        constraints: ['set'],
	        name: 'list'
	      }, {
	        name: 'type',
	        value: 'search'
	      }],
	      name: 'input'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        constraints: ['set'],
	        name: 'list'
	      }, {
	        name: 'type',
	        value: 'tel'
	      }],
	      name: 'input'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        constraints: ['set'],
	        name: 'list'
	      }, {
	        name: 'type',
	        value: 'text'
	      }],
	      name: 'input'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        constraints: ['set'],
	        name: 'list'
	      }, {
	        name: 'type',
	        value: 'url'
	      }],
	      name: 'input'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        constraints: ['set'],
	        name: 'list'
	      }, {
	        name: 'type',
	        value: 'url'
	      }],
	      name: 'input'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        constraints: ['undefined'],
	        name: 'multiple'
	      }, {
	        constraints: ['undefined'],
	        name: 'size'
	      }],
	      constraints: ['the multiple attribute is not set and the size attribute does not have a value greater than 1'],
	      name: 'select'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'select'
	    },
	    module: 'XForms'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {
	    'aria-controls': null,
	    'aria-expanded': 'false'
	  },
	  superClass: [['roletype', 'widget', 'input']]
	};
	comboboxRole.default = comboboxRole$1;
	return comboboxRole;
}

var complementaryRole = {};

var hasRequiredComplementaryRole$1;

function requireComplementaryRole$1 () {
	if (hasRequiredComplementaryRole$1) return complementaryRole;
	hasRequiredComplementaryRole$1 = 1;

	Object.defineProperty(complementaryRole, "__esModule", {
	  value: true
	});
	complementaryRole.default = void 0;
	var complementaryRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      constraints: ['scoped to the body element', 'scoped to the main element'],
	      name: 'aside'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        constraints: ['set'],
	        name: 'aria-label'
	      }],
	      constraints: ['scoped to a sectioning content element', 'scoped to a sectioning root element other than body'],
	      name: 'aside'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        constraints: ['set'],
	        name: 'aria-labelledby'
	      }],
	      constraints: ['scoped to a sectioning content element', 'scoped to a sectioning root element other than body'],
	      name: 'aside'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	complementaryRole.default = complementaryRole$1;
	return complementaryRole;
}

var contentinfoRole = {};

var hasRequiredContentinfoRole;

function requireContentinfoRole () {
	if (hasRequiredContentinfoRole) return contentinfoRole;
	hasRequiredContentinfoRole = 1;

	Object.defineProperty(contentinfoRole, "__esModule", {
	  value: true
	});
	contentinfoRole.default = void 0;
	var contentinfoRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      constraints: ['scoped to the body element'],
	      name: 'footer'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	contentinfoRole.default = contentinfoRole$1;
	return contentinfoRole;
}

var definitionRole = {};

var hasRequiredDefinitionRole$1;

function requireDefinitionRole$1 () {
	if (hasRequiredDefinitionRole$1) return definitionRole;
	hasRequiredDefinitionRole$1 = 1;

	Object.defineProperty(definitionRole, "__esModule", {
	  value: true
	});
	definitionRole.default = void 0;
	var definitionRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'dd'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	definitionRole.default = definitionRole$1;
	return definitionRole;
}

var deletionRole = {};

var hasRequiredDeletionRole;

function requireDeletionRole () {
	if (hasRequiredDeletionRole) return deletionRole;
	hasRequiredDeletionRole = 1;

	Object.defineProperty(deletionRole, "__esModule", {
	  value: true
	});
	deletionRole.default = void 0;
	var deletionRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['prohibited'],
	  prohibitedProps: ['aria-label', 'aria-labelledby'],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'del'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	deletionRole.default = deletionRole$1;
	return deletionRole;
}

var dialogRole = {};

var hasRequiredDialogRole$1;

function requireDialogRole$1 () {
	if (hasRequiredDialogRole$1) return dialogRole;
	hasRequiredDialogRole$1 = 1;

	Object.defineProperty(dialogRole, "__esModule", {
	  value: true
	});
	dialogRole.default = void 0;
	var dialogRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'dialog'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'window']]
	};
	dialogRole.default = dialogRole$1;
	return dialogRole;
}

var directoryRole = {};

var hasRequiredDirectoryRole$1;

function requireDirectoryRole$1 () {
	if (hasRequiredDirectoryRole$1) return directoryRole;
	hasRequiredDirectoryRole$1 = 1;

	Object.defineProperty(directoryRole, "__esModule", {
	  value: true
	});
	directoryRole.default = void 0;
	var directoryRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    module: 'DAISY Guide'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'list']]
	};
	directoryRole.default = directoryRole$1;
	return directoryRole;
}

var documentRole = {};

var hasRequiredDocumentRole$1;

function requireDocumentRole$1 () {
	if (hasRequiredDocumentRole$1) return documentRole;
	hasRequiredDocumentRole$1 = 1;

	Object.defineProperty(documentRole, "__esModule", {
	  value: true
	});
	documentRole.default = void 0;
	var documentRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'Device Independence Delivery Unit'
	    }
	  }, {
	    concept: {
	      name: 'html'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure']]
	};
	documentRole.default = documentRole$1;
	return documentRole;
}

var emphasisRole = {};

var hasRequiredEmphasisRole;

function requireEmphasisRole () {
	if (hasRequiredEmphasisRole) return emphasisRole;
	hasRequiredEmphasisRole = 1;

	Object.defineProperty(emphasisRole, "__esModule", {
	  value: true
	});
	emphasisRole.default = void 0;
	var emphasisRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['prohibited'],
	  prohibitedProps: ['aria-label', 'aria-labelledby'],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'em'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	emphasisRole.default = emphasisRole$1;
	return emphasisRole;
}

var feedRole = {};

var hasRequiredFeedRole$1;

function requireFeedRole$1 () {
	if (hasRequiredFeedRole$1) return feedRole;
	hasRequiredFeedRole$1 = 1;

	Object.defineProperty(feedRole, "__esModule", {
	  value: true
	});
	feedRole.default = void 0;
	var feedRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [['article']],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'list']]
	};
	feedRole.default = feedRole$1;
	return feedRole;
}

var figureRole = {};

var hasRequiredFigureRole$1;

function requireFigureRole$1 () {
	if (hasRequiredFigureRole$1) return figureRole;
	hasRequiredFigureRole$1 = 1;

	Object.defineProperty(figureRole, "__esModule", {
	  value: true
	});
	figureRole.default = void 0;
	var figureRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'figure'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	figureRole.default = figureRole$1;
	return figureRole;
}

var formRole = {};

var hasRequiredFormRole$1;

function requireFormRole$1 () {
	if (hasRequiredFormRole$1) return formRole;
	hasRequiredFormRole$1 = 1;

	Object.defineProperty(formRole, "__esModule", {
	  value: true
	});
	formRole.default = void 0;
	var formRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      attributes: [{
	        constraints: ['set'],
	        name: 'aria-label'
	      }],
	      name: 'form'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        constraints: ['set'],
	        name: 'aria-labelledby'
	      }],
	      name: 'form'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        constraints: ['set'],
	        name: 'name'
	      }],
	      name: 'form'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	formRole.default = formRole$1;
	return formRole;
}

var genericRole = {};

var hasRequiredGenericRole;

function requireGenericRole () {
	if (hasRequiredGenericRole) return genericRole;
	hasRequiredGenericRole = 1;

	Object.defineProperty(genericRole, "__esModule", {
	  value: true
	});
	genericRole.default = void 0;
	var genericRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['prohibited'],
	  prohibitedProps: ['aria-label', 'aria-labelledby'],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'a'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'area'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'aside'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'b'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'bdo'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'body'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'data'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'div'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      constraints: ['scoped to the main element', 'scoped to a sectioning content element', 'scoped to a sectioning root element other than body'],
	      name: 'footer'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      constraints: ['scoped to the main element', 'scoped to a sectioning content element', 'scoped to a sectioning root element other than body'],
	      name: 'header'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'hgroup'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'i'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'pre'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'q'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'samp'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'section'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'small'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'span'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'u'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure']]
	};
	genericRole.default = genericRole$1;
	return genericRole;
}

var gridRole = {};

var hasRequiredGridRole$1;

function requireGridRole$1 () {
	if (hasRequiredGridRole$1) return gridRole;
	hasRequiredGridRole$1 = 1;

	Object.defineProperty(gridRole, "__esModule", {
	  value: true
	});
	gridRole.default = void 0;
	var gridRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-multiselectable': null,
	    'aria-readonly': null
	  },
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [['row'], ['row', 'rowgroup']],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'composite'], ['roletype', 'structure', 'section', 'table']]
	};
	gridRole.default = gridRole$1;
	return gridRole;
}

var gridcellRole = {};

var hasRequiredGridcellRole;

function requireGridcellRole () {
	if (hasRequiredGridcellRole) return gridcellRole;
	hasRequiredGridcellRole = 1;

	Object.defineProperty(gridcellRole, "__esModule", {
	  value: true
	});
	gridcellRole.default = void 0;
	var gridcellRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null,
	    'aria-readonly': null,
	    'aria-required': null,
	    'aria-selected': null
	  },
	  relatedConcepts: [{
	    concept: {
	      constraints: ['ancestor table element has grid role', 'ancestor table element has treegrid role'],
	      name: 'td'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: ['row'],
	  requiredContextRole: ['row'],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'cell'], ['roletype', 'widget']]
	};
	gridcellRole.default = gridcellRole$1;
	return gridcellRole;
}

var groupRole = {};

var hasRequiredGroupRole$1;

function requireGroupRole$1 () {
	if (hasRequiredGroupRole$1) return groupRole;
	hasRequiredGroupRole$1 = 1;

	Object.defineProperty(groupRole, "__esModule", {
	  value: true
	});
	groupRole.default = void 0;
	var groupRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-activedescendant': null,
	    'aria-disabled': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'details'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'fieldset'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'optgroup'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'address'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	groupRole.default = groupRole$1;
	return groupRole;
}

var headingRole = {};

var hasRequiredHeadingRole$1;

function requireHeadingRole$1 () {
	if (hasRequiredHeadingRole$1) return headingRole;
	hasRequiredHeadingRole$1 = 1;

	Object.defineProperty(headingRole, "__esModule", {
	  value: true
	});
	headingRole.default = void 0;
	var headingRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-level': '2'
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'h1'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'h2'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'h3'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'h4'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'h5'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'h6'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {
	    'aria-level': '2'
	  },
	  superClass: [['roletype', 'structure', 'sectionhead']]
	};
	headingRole.default = headingRole$1;
	return headingRole;
}

var imgRole = {};

var hasRequiredImgRole;

function requireImgRole () {
	if (hasRequiredImgRole) return imgRole;
	hasRequiredImgRole = 1;

	Object.defineProperty(imgRole, "__esModule", {
	  value: true
	});
	imgRole.default = void 0;
	var imgRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: true,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      attributes: [{
	        constraints: ['set'],
	        name: 'alt'
	      }],
	      name: 'img'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        constraints: ['undefined'],
	        name: 'alt'
	      }],
	      name: 'img'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'imggroup'
	    },
	    module: 'DTB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	imgRole.default = imgRole$1;
	return imgRole;
}

var insertionRole = {};

var hasRequiredInsertionRole;

function requireInsertionRole () {
	if (hasRequiredInsertionRole) return insertionRole;
	hasRequiredInsertionRole = 1;

	Object.defineProperty(insertionRole, "__esModule", {
	  value: true
	});
	insertionRole.default = void 0;
	var insertionRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['prohibited'],
	  prohibitedProps: ['aria-label', 'aria-labelledby'],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'ins'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	insertionRole.default = insertionRole$1;
	return insertionRole;
}

var linkRole = {};

var hasRequiredLinkRole$1;

function requireLinkRole$1 () {
	if (hasRequiredLinkRole$1) return linkRole;
	hasRequiredLinkRole$1 = 1;

	Object.defineProperty(linkRole, "__esModule", {
	  value: true
	});
	linkRole.default = void 0;
	var linkRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-expanded': null,
	    'aria-haspopup': null
	  },
	  relatedConcepts: [{
	    concept: {
	      attributes: [{
	        constraints: ['set'],
	        name: 'href'
	      }],
	      name: 'a'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        constraints: ['set'],
	        name: 'href'
	      }],
	      name: 'area'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'command']]
	};
	linkRole.default = linkRole$1;
	return linkRole;
}

var listRole = {};

var hasRequiredListRole$1;

function requireListRole$1 () {
	if (hasRequiredListRole$1) return listRole;
	hasRequiredListRole$1 = 1;

	Object.defineProperty(listRole, "__esModule", {
	  value: true
	});
	listRole.default = void 0;
	var listRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'menu'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'ol'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'ul'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [['listitem']],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	listRole.default = listRole$1;
	return listRole;
}

var listboxRole = {};

var hasRequiredListboxRole;

function requireListboxRole () {
	if (hasRequiredListboxRole) return listboxRole;
	hasRequiredListboxRole = 1;

	Object.defineProperty(listboxRole, "__esModule", {
	  value: true
	});
	listboxRole.default = void 0;
	var listboxRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-invalid': null,
	    'aria-multiselectable': null,
	    'aria-readonly': null,
	    'aria-required': null,
	    'aria-orientation': 'vertical'
	  },
	  relatedConcepts: [{
	    concept: {
	      attributes: [{
	        constraints: ['>1'],
	        name: 'size'
	      }],
	      constraints: ['the size attribute value is greater than 1'],
	      name: 'select'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        name: 'multiple'
	      }],
	      name: 'select'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'datalist'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'list'
	    },
	    module: 'ARIA'
	  }, {
	    concept: {
	      name: 'select'
	    },
	    module: 'XForms'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [['option', 'group'], ['option']],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'composite', 'select'], ['roletype', 'structure', 'section', 'group', 'select']]
	};
	listboxRole.default = listboxRole$1;
	return listboxRole;
}

var listitemRole = {};

var hasRequiredListitemRole;

function requireListitemRole () {
	if (hasRequiredListitemRole) return listitemRole;
	hasRequiredListitemRole = 1;

	Object.defineProperty(listitemRole, "__esModule", {
	  value: true
	});
	listitemRole.default = void 0;
	var listitemRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-level': null,
	    'aria-posinset': null,
	    'aria-setsize': null
	  },
	  relatedConcepts: [{
	    concept: {
	      constraints: ['direct descendant of ol', 'direct descendant of ul', 'direct descendant of menu'],
	      name: 'li'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'item'
	    },
	    module: 'XForms'
	  }],
	  requireContextRole: ['directory', 'list'],
	  requiredContextRole: ['directory', 'list'],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	listitemRole.default = listitemRole$1;
	return listitemRole;
}

var logRole = {};

var hasRequiredLogRole$1;

function requireLogRole$1 () {
	if (hasRequiredLogRole$1) return logRole;
	hasRequiredLogRole$1 = 1;

	Object.defineProperty(logRole, "__esModule", {
	  value: true
	});
	logRole.default = void 0;
	var logRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-live': 'polite'
	  },
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	logRole.default = logRole$1;
	return logRole;
}

var mainRole = {};

var hasRequiredMainRole$1;

function requireMainRole$1 () {
	if (hasRequiredMainRole$1) return mainRole;
	hasRequiredMainRole$1 = 1;

	Object.defineProperty(mainRole, "__esModule", {
	  value: true
	});
	mainRole.default = void 0;
	var mainRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'main'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	mainRole.default = mainRole$1;
	return mainRole;
}

var markRole = {};

var hasRequiredMarkRole$1;

function requireMarkRole$1 () {
	if (hasRequiredMarkRole$1) return markRole;
	hasRequiredMarkRole$1 = 1;

	Object.defineProperty(markRole, "__esModule", {
	  value: true
	});
	markRole.default = void 0;
	var markRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['prohibited'],
	  prohibitedProps: [],
	  props: {
	    'aria-braillelabel': null,
	    'aria-brailleroledescription': null,
	    'aria-description': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'mark'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	markRole.default = markRole$1;
	return markRole;
}

var marqueeRole = {};

var hasRequiredMarqueeRole$1;

function requireMarqueeRole$1 () {
	if (hasRequiredMarqueeRole$1) return marqueeRole;
	hasRequiredMarqueeRole$1 = 1;

	Object.defineProperty(marqueeRole, "__esModule", {
	  value: true
	});
	marqueeRole.default = void 0;
	var marqueeRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	marqueeRole.default = marqueeRole$1;
	return marqueeRole;
}

var mathRole = {};

var hasRequiredMathRole$1;

function requireMathRole$1 () {
	if (hasRequiredMathRole$1) return mathRole;
	hasRequiredMathRole$1 = 1;

	Object.defineProperty(mathRole, "__esModule", {
	  value: true
	});
	mathRole.default = void 0;
	var mathRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'math'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	mathRole.default = mathRole$1;
	return mathRole;
}

var menuRole = {};

var hasRequiredMenuRole$1;

function requireMenuRole$1 () {
	if (hasRequiredMenuRole$1) return menuRole;
	hasRequiredMenuRole$1 = 1;

	Object.defineProperty(menuRole, "__esModule", {
	  value: true
	});
	menuRole.default = void 0;
	var menuRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-orientation': 'vertical'
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'MENU'
	    },
	    module: 'JAPI'
	  }, {
	    concept: {
	      name: 'list'
	    },
	    module: 'ARIA'
	  }, {
	    concept: {
	      name: 'select'
	    },
	    module: 'XForms'
	  }, {
	    concept: {
	      name: 'sidebar'
	    },
	    module: 'DTB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [['menuitem', 'group'], ['menuitemradio', 'group'], ['menuitemcheckbox', 'group'], ['menuitem'], ['menuitemcheckbox'], ['menuitemradio']],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'composite', 'select'], ['roletype', 'structure', 'section', 'group', 'select']]
	};
	menuRole.default = menuRole$1;
	return menuRole;
}

var menubarRole = {};

var hasRequiredMenubarRole;

function requireMenubarRole () {
	if (hasRequiredMenubarRole) return menubarRole;
	hasRequiredMenubarRole = 1;

	Object.defineProperty(menubarRole, "__esModule", {
	  value: true
	});
	menubarRole.default = void 0;
	var menubarRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-orientation': 'horizontal'
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'toolbar'
	    },
	    module: 'ARIA'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [['menuitem', 'group'], ['menuitemradio', 'group'], ['menuitemcheckbox', 'group'], ['menuitem'], ['menuitemcheckbox'], ['menuitemradio']],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'composite', 'select', 'menu'], ['roletype', 'structure', 'section', 'group', 'select', 'menu']]
	};
	menubarRole.default = menubarRole$1;
	return menubarRole;
}

var menuitemRole = {};

var hasRequiredMenuitemRole;

function requireMenuitemRole () {
	if (hasRequiredMenuitemRole) return menuitemRole;
	hasRequiredMenuitemRole = 1;

	Object.defineProperty(menuitemRole, "__esModule", {
	  value: true
	});
	menuitemRole.default = void 0;
	var menuitemRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-posinset': null,
	    'aria-setsize': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'MENU_ITEM'
	    },
	    module: 'JAPI'
	  }, {
	    concept: {
	      name: 'listitem'
	    },
	    module: 'ARIA'
	  }, {
	    concept: {
	      name: 'option'
	    },
	    module: 'ARIA'
	  }],
	  requireContextRole: ['group', 'menu', 'menubar'],
	  requiredContextRole: ['group', 'menu', 'menubar'],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'command']]
	};
	menuitemRole.default = menuitemRole$1;
	return menuitemRole;
}

var menuitemcheckboxRole = {};

var hasRequiredMenuitemcheckboxRole;

function requireMenuitemcheckboxRole () {
	if (hasRequiredMenuitemcheckboxRole) return menuitemcheckboxRole;
	hasRequiredMenuitemcheckboxRole = 1;

	Object.defineProperty(menuitemcheckboxRole, "__esModule", {
	  value: true
	});
	menuitemcheckboxRole.default = void 0;
	var menuitemcheckboxRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: true,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'menuitem'
	    },
	    module: 'ARIA'
	  }],
	  requireContextRole: ['group', 'menu', 'menubar'],
	  requiredContextRole: ['group', 'menu', 'menubar'],
	  requiredOwnedElements: [],
	  requiredProps: {
	    'aria-checked': null
	  },
	  superClass: [['roletype', 'widget', 'input', 'checkbox'], ['roletype', 'widget', 'command', 'menuitem']]
	};
	menuitemcheckboxRole.default = menuitemcheckboxRole$1;
	return menuitemcheckboxRole;
}

var menuitemradioRole = {};

var hasRequiredMenuitemradioRole;

function requireMenuitemradioRole () {
	if (hasRequiredMenuitemradioRole) return menuitemradioRole;
	hasRequiredMenuitemradioRole = 1;

	Object.defineProperty(menuitemradioRole, "__esModule", {
	  value: true
	});
	menuitemradioRole.default = void 0;
	var menuitemradioRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: true,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'menuitem'
	    },
	    module: 'ARIA'
	  }],
	  requireContextRole: ['group', 'menu', 'menubar'],
	  requiredContextRole: ['group', 'menu', 'menubar'],
	  requiredOwnedElements: [],
	  requiredProps: {
	    'aria-checked': null
	  },
	  superClass: [['roletype', 'widget', 'input', 'checkbox', 'menuitemcheckbox'], ['roletype', 'widget', 'command', 'menuitem', 'menuitemcheckbox'], ['roletype', 'widget', 'input', 'radio']]
	};
	menuitemradioRole.default = menuitemradioRole$1;
	return menuitemradioRole;
}

var meterRole = {};

var hasRequiredMeterRole$1;

function requireMeterRole$1 () {
	if (hasRequiredMeterRole$1) return meterRole;
	hasRequiredMeterRole$1 = 1;

	Object.defineProperty(meterRole, "__esModule", {
	  value: true
	});
	meterRole.default = void 0;
	var meterRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: true,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-valuetext': null,
	    'aria-valuemax': '100',
	    'aria-valuemin': '0'
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'meter'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {
	    'aria-valuenow': null
	  },
	  superClass: [['roletype', 'structure', 'range']]
	};
	meterRole.default = meterRole$1;
	return meterRole;
}

var navigationRole = {};

var hasRequiredNavigationRole$1;

function requireNavigationRole$1 () {
	if (hasRequiredNavigationRole$1) return navigationRole;
	hasRequiredNavigationRole$1 = 1;

	Object.defineProperty(navigationRole, "__esModule", {
	  value: true
	});
	navigationRole.default = void 0;
	var navigationRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'nav'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	navigationRole.default = navigationRole$1;
	return navigationRole;
}

var noneRole = {};

var hasRequiredNoneRole$1;

function requireNoneRole$1 () {
	if (hasRequiredNoneRole$1) return noneRole;
	hasRequiredNoneRole$1 = 1;

	Object.defineProperty(noneRole, "__esModule", {
	  value: true
	});
	noneRole.default = void 0;
	var noneRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: [],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: []
	};
	noneRole.default = noneRole$1;
	return noneRole;
}

var noteRole = {};

var hasRequiredNoteRole$1;

function requireNoteRole$1 () {
	if (hasRequiredNoteRole$1) return noteRole;
	hasRequiredNoteRole$1 = 1;

	Object.defineProperty(noteRole, "__esModule", {
	  value: true
	});
	noteRole.default = void 0;
	var noteRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	noteRole.default = noteRole$1;
	return noteRole;
}

var optionRole = {};

var hasRequiredOptionRole;

function requireOptionRole () {
	if (hasRequiredOptionRole) return optionRole;
	hasRequiredOptionRole = 1;

	Object.defineProperty(optionRole, "__esModule", {
	  value: true
	});
	optionRole.default = void 0;
	var optionRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: true,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-checked': null,
	    'aria-posinset': null,
	    'aria-setsize': null,
	    'aria-selected': 'false'
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'item'
	    },
	    module: 'XForms'
	  }, {
	    concept: {
	      name: 'listitem'
	    },
	    module: 'ARIA'
	  }, {
	    concept: {
	      name: 'option'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {
	    'aria-selected': 'false'
	  },
	  superClass: [['roletype', 'widget', 'input']]
	};
	optionRole.default = optionRole$1;
	return optionRole;
}

var paragraphRole = {};

var hasRequiredParagraphRole$1;

function requireParagraphRole$1 () {
	if (hasRequiredParagraphRole$1) return paragraphRole;
	hasRequiredParagraphRole$1 = 1;

	Object.defineProperty(paragraphRole, "__esModule", {
	  value: true
	});
	paragraphRole.default = void 0;
	var paragraphRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['prohibited'],
	  prohibitedProps: ['aria-label', 'aria-labelledby'],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'p'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	paragraphRole.default = paragraphRole$1;
	return paragraphRole;
}

var presentationRole = {};

var hasRequiredPresentationRole;

function requirePresentationRole () {
	if (hasRequiredPresentationRole) return presentationRole;
	hasRequiredPresentationRole = 1;

	Object.defineProperty(presentationRole, "__esModule", {
	  value: true
	});
	presentationRole.default = void 0;
	var presentationRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['prohibited'],
	  prohibitedProps: ['aria-label', 'aria-labelledby'],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      attributes: [{
	        name: 'alt',
	        value: ''
	      }],
	      name: 'img'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure']]
	};
	presentationRole.default = presentationRole$1;
	return presentationRole;
}

var progressbarRole = {};

var hasRequiredProgressbarRole;

function requireProgressbarRole () {
	if (hasRequiredProgressbarRole) return progressbarRole;
	hasRequiredProgressbarRole = 1;

	Object.defineProperty(progressbarRole, "__esModule", {
	  value: true
	});
	progressbarRole.default = void 0;
	var progressbarRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: true,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-valuetext': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'progress'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'status'
	    },
	    module: 'ARIA'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'range'], ['roletype', 'widget']]
	};
	progressbarRole.default = progressbarRole$1;
	return progressbarRole;
}

var radioRole = {};

var hasRequiredRadioRole;

function requireRadioRole () {
	if (hasRequiredRadioRole) return radioRole;
	hasRequiredRadioRole = 1;

	Object.defineProperty(radioRole, "__esModule", {
	  value: true
	});
	radioRole.default = void 0;
	var radioRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: true,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-checked': null,
	    'aria-posinset': null,
	    'aria-setsize': null
	  },
	  relatedConcepts: [{
	    concept: {
	      attributes: [{
	        name: 'type',
	        value: 'radio'
	      }],
	      name: 'input'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {
	    'aria-checked': null
	  },
	  superClass: [['roletype', 'widget', 'input']]
	};
	radioRole.default = radioRole$1;
	return radioRole;
}

var radiogroupRole = {};

var hasRequiredRadiogroupRole;

function requireRadiogroupRole () {
	if (hasRequiredRadiogroupRole) return radiogroupRole;
	hasRequiredRadiogroupRole = 1;

	Object.defineProperty(radiogroupRole, "__esModule", {
	  value: true
	});
	radiogroupRole.default = void 0;
	var radiogroupRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-errormessage': null,
	    'aria-invalid': null,
	    'aria-readonly': null,
	    'aria-required': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'list'
	    },
	    module: 'ARIA'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [['radio']],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'composite', 'select'], ['roletype', 'structure', 'section', 'group', 'select']]
	};
	radiogroupRole.default = radiogroupRole$1;
	return radiogroupRole;
}

var regionRole = {};

var hasRequiredRegionRole$1;

function requireRegionRole$1 () {
	if (hasRequiredRegionRole$1) return regionRole;
	hasRequiredRegionRole$1 = 1;

	Object.defineProperty(regionRole, "__esModule", {
	  value: true
	});
	regionRole.default = void 0;
	var regionRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      attributes: [{
	        constraints: ['set'],
	        name: 'aria-label'
	      }],
	      name: 'section'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        constraints: ['set'],
	        name: 'aria-labelledby'
	      }],
	      name: 'section'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'Device Independence Glossart perceivable unit'
	    }
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	regionRole.default = regionRole$1;
	return regionRole;
}

var rowRole = {};

var hasRequiredRowRole$1;

function requireRowRole$1 () {
	if (hasRequiredRowRole$1) return rowRole;
	hasRequiredRowRole$1 = 1;

	Object.defineProperty(rowRole, "__esModule", {
	  value: true
	});
	rowRole.default = void 0;
	var rowRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-colindex': null,
	    'aria-expanded': null,
	    'aria-level': null,
	    'aria-posinset': null,
	    'aria-rowindex': null,
	    'aria-selected': null,
	    'aria-setsize': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'tr'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: ['grid', 'rowgroup', 'table', 'treegrid'],
	  requiredContextRole: ['grid', 'rowgroup', 'table', 'treegrid'],
	  requiredOwnedElements: [['cell'], ['columnheader'], ['gridcell'], ['rowheader']],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'group'], ['roletype', 'widget']]
	};
	rowRole.default = rowRole$1;
	return rowRole;
}

var rowgroupRole = {};

var hasRequiredRowgroupRole;

function requireRowgroupRole () {
	if (hasRequiredRowgroupRole) return rowgroupRole;
	hasRequiredRowgroupRole = 1;

	Object.defineProperty(rowgroupRole, "__esModule", {
	  value: true
	});
	rowgroupRole.default = void 0;
	var rowgroupRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'tbody'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'tfoot'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'thead'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: ['grid', 'table', 'treegrid'],
	  requiredContextRole: ['grid', 'table', 'treegrid'],
	  requiredOwnedElements: [['row']],
	  requiredProps: {},
	  superClass: [['roletype', 'structure']]
	};
	rowgroupRole.default = rowgroupRole$1;
	return rowgroupRole;
}

var rowheaderRole = {};

var hasRequiredRowheaderRole;

function requireRowheaderRole () {
	if (hasRequiredRowheaderRole) return rowheaderRole;
	hasRequiredRowheaderRole = 1;

	Object.defineProperty(rowheaderRole, "__esModule", {
	  value: true
	});
	rowheaderRole.default = void 0;
	var rowheaderRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-sort': null
	  },
	  relatedConcepts: [{
	    concept: {
	      attributes: [{
	        name: 'scope',
	        value: 'row'
	      }],
	      name: 'th'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        name: 'scope',
	        value: 'rowgroup'
	      }],
	      name: 'th'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: ['row', 'rowgroup'],
	  requiredContextRole: ['row', 'rowgroup'],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'cell'], ['roletype', 'structure', 'section', 'cell', 'gridcell'], ['roletype', 'widget', 'gridcell'], ['roletype', 'structure', 'sectionhead']]
	};
	rowheaderRole.default = rowheaderRole$1;
	return rowheaderRole;
}

var scrollbarRole = {};

var hasRequiredScrollbarRole;

function requireScrollbarRole () {
	if (hasRequiredScrollbarRole) return scrollbarRole;
	hasRequiredScrollbarRole = 1;

	Object.defineProperty(scrollbarRole, "__esModule", {
	  value: true
	});
	scrollbarRole.default = void 0;
	var scrollbarRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: true,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-valuetext': null,
	    'aria-orientation': 'vertical',
	    'aria-valuemax': '100',
	    'aria-valuemin': '0'
	  },
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {
	    'aria-controls': null,
	    'aria-valuenow': null
	  },
	  superClass: [['roletype', 'structure', 'range'], ['roletype', 'widget']]
	};
	scrollbarRole.default = scrollbarRole$1;
	return scrollbarRole;
}

var searchRole = {};

var hasRequiredSearchRole$1;

function requireSearchRole$1 () {
	if (hasRequiredSearchRole$1) return searchRole;
	hasRequiredSearchRole$1 = 1;

	Object.defineProperty(searchRole, "__esModule", {
	  value: true
	});
	searchRole.default = void 0;
	var searchRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	searchRole.default = searchRole$1;
	return searchRole;
}

var searchboxRole = {};

var hasRequiredSearchboxRole;

function requireSearchboxRole () {
	if (hasRequiredSearchboxRole) return searchboxRole;
	hasRequiredSearchboxRole = 1;

	Object.defineProperty(searchboxRole, "__esModule", {
	  value: true
	});
	searchboxRole.default = void 0;
	var searchboxRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      attributes: [{
	        constraints: ['undefined'],
	        name: 'list'
	      }, {
	        name: 'type',
	        value: 'search'
	      }],
	      constraints: ['the list attribute is not set'],
	      name: 'input'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'input', 'textbox']]
	};
	searchboxRole.default = searchboxRole$1;
	return searchboxRole;
}

var separatorRole = {};

var hasRequiredSeparatorRole;

function requireSeparatorRole () {
	if (hasRequiredSeparatorRole) return separatorRole;
	hasRequiredSeparatorRole = 1;

	Object.defineProperty(separatorRole, "__esModule", {
	  value: true
	});
	separatorRole.default = void 0;
	var separatorRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: true,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-orientation': 'horizontal',
	    'aria-valuemax': '100',
	    'aria-valuemin': '0',
	    'aria-valuenow': null,
	    'aria-valuetext': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'hr'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure']]
	};
	separatorRole.default = separatorRole$1;
	return separatorRole;
}

var sliderRole = {};

var hasRequiredSliderRole$1;

function requireSliderRole$1 () {
	if (hasRequiredSliderRole$1) return sliderRole;
	hasRequiredSliderRole$1 = 1;

	Object.defineProperty(sliderRole, "__esModule", {
	  value: true
	});
	sliderRole.default = void 0;
	var sliderRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: true,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-errormessage': null,
	    'aria-haspopup': null,
	    'aria-invalid': null,
	    'aria-readonly': null,
	    'aria-valuetext': null,
	    'aria-orientation': 'horizontal',
	    'aria-valuemax': '100',
	    'aria-valuemin': '0'
	  },
	  relatedConcepts: [{
	    concept: {
	      attributes: [{
	        name: 'type',
	        value: 'range'
	      }],
	      name: 'input'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {
	    'aria-valuenow': null
	  },
	  superClass: [['roletype', 'widget', 'input'], ['roletype', 'structure', 'range']]
	};
	sliderRole.default = sliderRole$1;
	return sliderRole;
}

var spinbuttonRole = {};

var hasRequiredSpinbuttonRole;

function requireSpinbuttonRole () {
	if (hasRequiredSpinbuttonRole) return spinbuttonRole;
	hasRequiredSpinbuttonRole = 1;

	Object.defineProperty(spinbuttonRole, "__esModule", {
	  value: true
	});
	spinbuttonRole.default = void 0;
	var spinbuttonRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-errormessage': null,
	    'aria-invalid': null,
	    'aria-readonly': null,
	    'aria-required': null,
	    'aria-valuetext': null,
	    'aria-valuenow': '0'
	  },
	  relatedConcepts: [{
	    concept: {
	      attributes: [{
	        name: 'type',
	        value: 'number'
	      }],
	      name: 'input'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'composite'], ['roletype', 'widget', 'input'], ['roletype', 'structure', 'range']]
	};
	spinbuttonRole.default = spinbuttonRole$1;
	return spinbuttonRole;
}

var statusRole = {};

var hasRequiredStatusRole$1;

function requireStatusRole$1 () {
	if (hasRequiredStatusRole$1) return statusRole;
	hasRequiredStatusRole$1 = 1;

	Object.defineProperty(statusRole, "__esModule", {
	  value: true
	});
	statusRole.default = void 0;
	var statusRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-atomic': 'true',
	    'aria-live': 'polite'
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'output'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	statusRole.default = statusRole$1;
	return statusRole;
}

var strongRole = {};

var hasRequiredStrongRole;

function requireStrongRole () {
	if (hasRequiredStrongRole) return strongRole;
	hasRequiredStrongRole = 1;

	Object.defineProperty(strongRole, "__esModule", {
	  value: true
	});
	strongRole.default = void 0;
	var strongRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['prohibited'],
	  prohibitedProps: ['aria-label', 'aria-labelledby'],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'strong'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	strongRole.default = strongRole$1;
	return strongRole;
}

var subscriptRole = {};

var hasRequiredSubscriptRole;

function requireSubscriptRole () {
	if (hasRequiredSubscriptRole) return subscriptRole;
	hasRequiredSubscriptRole = 1;

	Object.defineProperty(subscriptRole, "__esModule", {
	  value: true
	});
	subscriptRole.default = void 0;
	var subscriptRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['prohibited'],
	  prohibitedProps: ['aria-label', 'aria-labelledby'],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'sub'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	subscriptRole.default = subscriptRole$1;
	return subscriptRole;
}

var superscriptRole = {};

var hasRequiredSuperscriptRole;

function requireSuperscriptRole () {
	if (hasRequiredSuperscriptRole) return superscriptRole;
	hasRequiredSuperscriptRole = 1;

	Object.defineProperty(superscriptRole, "__esModule", {
	  value: true
	});
	superscriptRole.default = void 0;
	var superscriptRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['prohibited'],
	  prohibitedProps: ['aria-label', 'aria-labelledby'],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'sup'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	superscriptRole.default = superscriptRole$1;
	return superscriptRole;
}

var switchRole = {};

var hasRequiredSwitchRole$1;

function requireSwitchRole$1 () {
	if (hasRequiredSwitchRole$1) return switchRole;
	hasRequiredSwitchRole$1 = 1;

	Object.defineProperty(switchRole, "__esModule", {
	  value: true
	});
	switchRole.default = void 0;
	var switchRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: true,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'button'
	    },
	    module: 'ARIA'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {
	    'aria-checked': null
	  },
	  superClass: [['roletype', 'widget', 'input', 'checkbox']]
	};
	switchRole.default = switchRole$1;
	return switchRole;
}

var tabRole = {};

var hasRequiredTabRole$1;

function requireTabRole$1 () {
	if (hasRequiredTabRole$1) return tabRole;
	hasRequiredTabRole$1 = 1;

	Object.defineProperty(tabRole, "__esModule", {
	  value: true
	});
	tabRole.default = void 0;
	var tabRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: true,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-posinset': null,
	    'aria-setsize': null,
	    'aria-selected': 'false'
	  },
	  relatedConcepts: [],
	  requireContextRole: ['tablist'],
	  requiredContextRole: ['tablist'],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'sectionhead'], ['roletype', 'widget']]
	};
	tabRole.default = tabRole$1;
	return tabRole;
}

var tableRole = {};

var hasRequiredTableRole$1;

function requireTableRole$1 () {
	if (hasRequiredTableRole$1) return tableRole;
	hasRequiredTableRole$1 = 1;

	Object.defineProperty(tableRole, "__esModule", {
	  value: true
	});
	tableRole.default = void 0;
	var tableRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-colcount': null,
	    'aria-rowcount': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'table'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [['row'], ['row', 'rowgroup']],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	tableRole.default = tableRole$1;
	return tableRole;
}

var tablistRole = {};

var hasRequiredTablistRole;

function requireTablistRole () {
	if (hasRequiredTablistRole) return tablistRole;
	hasRequiredTablistRole = 1;

	Object.defineProperty(tablistRole, "__esModule", {
	  value: true
	});
	tablistRole.default = void 0;
	var tablistRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-level': null,
	    'aria-multiselectable': null,
	    'aria-orientation': 'horizontal'
	  },
	  relatedConcepts: [{
	    module: 'DAISY',
	    concept: {
	      name: 'guide'
	    }
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [['tab']],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'composite']]
	};
	tablistRole.default = tablistRole$1;
	return tablistRole;
}

var tabpanelRole = {};

var hasRequiredTabpanelRole;

function requireTabpanelRole () {
	if (hasRequiredTabpanelRole) return tabpanelRole;
	hasRequiredTabpanelRole = 1;

	Object.defineProperty(tabpanelRole, "__esModule", {
	  value: true
	});
	tabpanelRole.default = void 0;
	var tabpanelRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	tabpanelRole.default = tabpanelRole$1;
	return tabpanelRole;
}

var termRole = {};

var hasRequiredTermRole$1;

function requireTermRole$1 () {
	if (hasRequiredTermRole$1) return termRole;
	hasRequiredTermRole$1 = 1;

	Object.defineProperty(termRole, "__esModule", {
	  value: true
	});
	termRole.default = void 0;
	var termRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'dfn'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'dt'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	termRole.default = termRole$1;
	return termRole;
}

var textboxRole = {};

var hasRequiredTextboxRole;

function requireTextboxRole () {
	if (hasRequiredTextboxRole) return textboxRole;
	hasRequiredTextboxRole = 1;

	Object.defineProperty(textboxRole, "__esModule", {
	  value: true
	});
	textboxRole.default = void 0;
	var textboxRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-activedescendant': null,
	    'aria-autocomplete': null,
	    'aria-errormessage': null,
	    'aria-haspopup': null,
	    'aria-invalid': null,
	    'aria-multiline': null,
	    'aria-placeholder': null,
	    'aria-readonly': null,
	    'aria-required': null
	  },
	  relatedConcepts: [{
	    concept: {
	      attributes: [{
	        constraints: ['undefined'],
	        name: 'type'
	      }, {
	        constraints: ['undefined'],
	        name: 'list'
	      }],
	      constraints: ['the list attribute is not set'],
	      name: 'input'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        constraints: ['undefined'],
	        name: 'list'
	      }, {
	        name: 'type',
	        value: 'email'
	      }],
	      constraints: ['the list attribute is not set'],
	      name: 'input'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        constraints: ['undefined'],
	        name: 'list'
	      }, {
	        name: 'type',
	        value: 'tel'
	      }],
	      constraints: ['the list attribute is not set'],
	      name: 'input'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        constraints: ['undefined'],
	        name: 'list'
	      }, {
	        name: 'type',
	        value: 'text'
	      }],
	      constraints: ['the list attribute is not set'],
	      name: 'input'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        constraints: ['undefined'],
	        name: 'list'
	      }, {
	        name: 'type',
	        value: 'url'
	      }],
	      constraints: ['the list attribute is not set'],
	      name: 'input'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'input'
	    },
	    module: 'XForms'
	  }, {
	    concept: {
	      name: 'textarea'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'input']]
	};
	textboxRole.default = textboxRole$1;
	return textboxRole;
}

var timeRole = {};

var hasRequiredTimeRole$1;

function requireTimeRole$1 () {
	if (hasRequiredTimeRole$1) return timeRole;
	hasRequiredTimeRole$1 = 1;

	Object.defineProperty(timeRole, "__esModule", {
	  value: true
	});
	timeRole.default = void 0;
	var timeRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'time'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	timeRole.default = timeRole$1;
	return timeRole;
}

var timerRole = {};

var hasRequiredTimerRole$1;

function requireTimerRole$1 () {
	if (hasRequiredTimerRole$1) return timerRole;
	hasRequiredTimerRole$1 = 1;

	Object.defineProperty(timerRole, "__esModule", {
	  value: true
	});
	timerRole.default = void 0;
	var timerRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'status']]
	};
	timerRole.default = timerRole$1;
	return timerRole;
}

var toolbarRole = {};

var hasRequiredToolbarRole$1;

function requireToolbarRole$1 () {
	if (hasRequiredToolbarRole$1) return toolbarRole;
	hasRequiredToolbarRole$1 = 1;

	Object.defineProperty(toolbarRole, "__esModule", {
	  value: true
	});
	toolbarRole.default = void 0;
	var toolbarRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-orientation': 'horizontal'
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'menubar'
	    },
	    module: 'ARIA'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'group']]
	};
	toolbarRole.default = toolbarRole$1;
	return toolbarRole;
}

var tooltipRole = {};

var hasRequiredTooltipRole;

function requireTooltipRole () {
	if (hasRequiredTooltipRole) return tooltipRole;
	hasRequiredTooltipRole = 1;

	Object.defineProperty(tooltipRole, "__esModule", {
	  value: true
	});
	tooltipRole.default = void 0;
	var tooltipRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	tooltipRole.default = tooltipRole$1;
	return tooltipRole;
}

var treeRole = {};

var hasRequiredTreeRole$1;

function requireTreeRole$1 () {
	if (hasRequiredTreeRole$1) return treeRole;
	hasRequiredTreeRole$1 = 1;

	Object.defineProperty(treeRole, "__esModule", {
	  value: true
	});
	treeRole.default = void 0;
	var treeRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-errormessage': null,
	    'aria-invalid': null,
	    'aria-multiselectable': null,
	    'aria-required': null,
	    'aria-orientation': 'vertical'
	  },
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [['treeitem', 'group'], ['treeitem']],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'composite', 'select'], ['roletype', 'structure', 'section', 'group', 'select']]
	};
	treeRole.default = treeRole$1;
	return treeRole;
}

var treegridRole = {};

var hasRequiredTreegridRole;

function requireTreegridRole () {
	if (hasRequiredTreegridRole) return treegridRole;
	hasRequiredTreegridRole = 1;

	Object.defineProperty(treegridRole, "__esModule", {
	  value: true
	});
	treegridRole.default = void 0;
	var treegridRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [['row'], ['row', 'rowgroup']],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'composite', 'grid'], ['roletype', 'structure', 'section', 'table', 'grid'], ['roletype', 'widget', 'composite', 'select', 'tree'], ['roletype', 'structure', 'section', 'group', 'select', 'tree']]
	};
	treegridRole.default = treegridRole$1;
	return treegridRole;
}

var treeitemRole = {};

var hasRequiredTreeitemRole;

function requireTreeitemRole () {
	if (hasRequiredTreeitemRole) return treeitemRole;
	hasRequiredTreeitemRole = 1;

	Object.defineProperty(treeitemRole, "__esModule", {
	  value: true
	});
	treeitemRole.default = void 0;
	var treeitemRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-expanded': null,
	    'aria-haspopup': null
	  },
	  relatedConcepts: [],
	  requireContextRole: ['group', 'tree'],
	  requiredContextRole: ['group', 'tree'],
	  requiredOwnedElements: [],
	  requiredProps: {
	    'aria-selected': null
	  },
	  superClass: [['roletype', 'structure', 'section', 'listitem'], ['roletype', 'widget', 'input', 'option']]
	};
	treeitemRole.default = treeitemRole$1;
	return treeitemRole;
}

var hasRequiredAriaLiteralRoles;

function requireAriaLiteralRoles () {
	if (hasRequiredAriaLiteralRoles) return ariaLiteralRoles;
	hasRequiredAriaLiteralRoles = 1;

	Object.defineProperty(ariaLiteralRoles, "__esModule", {
	  value: true
	});
	ariaLiteralRoles.default = void 0;
	var _alertRole = _interopRequireDefault(requireAlertRole$1());
	var _alertdialogRole = _interopRequireDefault(requireAlertdialogRole());
	var _applicationRole = _interopRequireDefault(requireApplicationRole$1());
	var _articleRole = _interopRequireDefault(requireArticleRole$1());
	var _bannerRole = _interopRequireDefault(requireBannerRole$1());
	var _blockquoteRole = _interopRequireDefault(requireBlockquoteRole$1());
	var _buttonRole = _interopRequireDefault(requireButtonRole$1());
	var _captionRole = _interopRequireDefault(requireCaptionRole$1());
	var _cellRole = _interopRequireDefault(requireCellRole$1());
	var _checkboxRole = _interopRequireDefault(requireCheckboxRole());
	var _codeRole = _interopRequireDefault(requireCodeRole());
	var _columnheaderRole = _interopRequireDefault(requireColumnheaderRole());
	var _comboboxRole = _interopRequireDefault(requireComboboxRole());
	var _complementaryRole = _interopRequireDefault(requireComplementaryRole$1());
	var _contentinfoRole = _interopRequireDefault(requireContentinfoRole());
	var _definitionRole = _interopRequireDefault(requireDefinitionRole$1());
	var _deletionRole = _interopRequireDefault(requireDeletionRole());
	var _dialogRole = _interopRequireDefault(requireDialogRole$1());
	var _directoryRole = _interopRequireDefault(requireDirectoryRole$1());
	var _documentRole = _interopRequireDefault(requireDocumentRole$1());
	var _emphasisRole = _interopRequireDefault(requireEmphasisRole());
	var _feedRole = _interopRequireDefault(requireFeedRole$1());
	var _figureRole = _interopRequireDefault(requireFigureRole$1());
	var _formRole = _interopRequireDefault(requireFormRole$1());
	var _genericRole = _interopRequireDefault(requireGenericRole());
	var _gridRole = _interopRequireDefault(requireGridRole$1());
	var _gridcellRole = _interopRequireDefault(requireGridcellRole());
	var _groupRole = _interopRequireDefault(requireGroupRole$1());
	var _headingRole = _interopRequireDefault(requireHeadingRole$1());
	var _imgRole = _interopRequireDefault(requireImgRole());
	var _insertionRole = _interopRequireDefault(requireInsertionRole());
	var _linkRole = _interopRequireDefault(requireLinkRole$1());
	var _listRole = _interopRequireDefault(requireListRole$1());
	var _listboxRole = _interopRequireDefault(requireListboxRole());
	var _listitemRole = _interopRequireDefault(requireListitemRole());
	var _logRole = _interopRequireDefault(requireLogRole$1());
	var _mainRole = _interopRequireDefault(requireMainRole$1());
	var _markRole = _interopRequireDefault(requireMarkRole$1());
	var _marqueeRole = _interopRequireDefault(requireMarqueeRole$1());
	var _mathRole = _interopRequireDefault(requireMathRole$1());
	var _menuRole = _interopRequireDefault(requireMenuRole$1());
	var _menubarRole = _interopRequireDefault(requireMenubarRole());
	var _menuitemRole = _interopRequireDefault(requireMenuitemRole());
	var _menuitemcheckboxRole = _interopRequireDefault(requireMenuitemcheckboxRole());
	var _menuitemradioRole = _interopRequireDefault(requireMenuitemradioRole());
	var _meterRole = _interopRequireDefault(requireMeterRole$1());
	var _navigationRole = _interopRequireDefault(requireNavigationRole$1());
	var _noneRole = _interopRequireDefault(requireNoneRole$1());
	var _noteRole = _interopRequireDefault(requireNoteRole$1());
	var _optionRole = _interopRequireDefault(requireOptionRole());
	var _paragraphRole = _interopRequireDefault(requireParagraphRole$1());
	var _presentationRole = _interopRequireDefault(requirePresentationRole());
	var _progressbarRole = _interopRequireDefault(requireProgressbarRole());
	var _radioRole = _interopRequireDefault(requireRadioRole());
	var _radiogroupRole = _interopRequireDefault(requireRadiogroupRole());
	var _regionRole = _interopRequireDefault(requireRegionRole$1());
	var _rowRole = _interopRequireDefault(requireRowRole$1());
	var _rowgroupRole = _interopRequireDefault(requireRowgroupRole());
	var _rowheaderRole = _interopRequireDefault(requireRowheaderRole());
	var _scrollbarRole = _interopRequireDefault(requireScrollbarRole());
	var _searchRole = _interopRequireDefault(requireSearchRole$1());
	var _searchboxRole = _interopRequireDefault(requireSearchboxRole());
	var _separatorRole = _interopRequireDefault(requireSeparatorRole());
	var _sliderRole = _interopRequireDefault(requireSliderRole$1());
	var _spinbuttonRole = _interopRequireDefault(requireSpinbuttonRole());
	var _statusRole = _interopRequireDefault(requireStatusRole$1());
	var _strongRole = _interopRequireDefault(requireStrongRole());
	var _subscriptRole = _interopRequireDefault(requireSubscriptRole());
	var _superscriptRole = _interopRequireDefault(requireSuperscriptRole());
	var _switchRole = _interopRequireDefault(requireSwitchRole$1());
	var _tabRole = _interopRequireDefault(requireTabRole$1());
	var _tableRole = _interopRequireDefault(requireTableRole$1());
	var _tablistRole = _interopRequireDefault(requireTablistRole());
	var _tabpanelRole = _interopRequireDefault(requireTabpanelRole());
	var _termRole = _interopRequireDefault(requireTermRole$1());
	var _textboxRole = _interopRequireDefault(requireTextboxRole());
	var _timeRole = _interopRequireDefault(requireTimeRole$1());
	var _timerRole = _interopRequireDefault(requireTimerRole$1());
	var _toolbarRole = _interopRequireDefault(requireToolbarRole$1());
	var _tooltipRole = _interopRequireDefault(requireTooltipRole());
	var _treeRole = _interopRequireDefault(requireTreeRole$1());
	var _treegridRole = _interopRequireDefault(requireTreegridRole());
	var _treeitemRole = _interopRequireDefault(requireTreeitemRole());
	function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
	var ariaLiteralRoles$1 = [['alert', _alertRole.default], ['alertdialog', _alertdialogRole.default], ['application', _applicationRole.default], ['article', _articleRole.default], ['banner', _bannerRole.default], ['blockquote', _blockquoteRole.default], ['button', _buttonRole.default], ['caption', _captionRole.default], ['cell', _cellRole.default], ['checkbox', _checkboxRole.default], ['code', _codeRole.default], ['columnheader', _columnheaderRole.default], ['combobox', _comboboxRole.default], ['complementary', _complementaryRole.default], ['contentinfo', _contentinfoRole.default], ['definition', _definitionRole.default], ['deletion', _deletionRole.default], ['dialog', _dialogRole.default], ['directory', _directoryRole.default], ['document', _documentRole.default], ['emphasis', _emphasisRole.default], ['feed', _feedRole.default], ['figure', _figureRole.default], ['form', _formRole.default], ['generic', _genericRole.default], ['grid', _gridRole.default], ['gridcell', _gridcellRole.default], ['group', _groupRole.default], ['heading', _headingRole.default], ['img', _imgRole.default], ['insertion', _insertionRole.default], ['link', _linkRole.default], ['list', _listRole.default], ['listbox', _listboxRole.default], ['listitem', _listitemRole.default], ['log', _logRole.default], ['main', _mainRole.default], ['mark', _markRole.default], ['marquee', _marqueeRole.default], ['math', _mathRole.default], ['menu', _menuRole.default], ['menubar', _menubarRole.default], ['menuitem', _menuitemRole.default], ['menuitemcheckbox', _menuitemcheckboxRole.default], ['menuitemradio', _menuitemradioRole.default], ['meter', _meterRole.default], ['navigation', _navigationRole.default], ['none', _noneRole.default], ['note', _noteRole.default], ['option', _optionRole.default], ['paragraph', _paragraphRole.default], ['presentation', _presentationRole.default], ['progressbar', _progressbarRole.default], ['radio', _radioRole.default], ['radiogroup', _radiogroupRole.default], ['region', _regionRole.default], ['row', _rowRole.default], ['rowgroup', _rowgroupRole.default], ['rowheader', _rowheaderRole.default], ['scrollbar', _scrollbarRole.default], ['search', _searchRole.default], ['searchbox', _searchboxRole.default], ['separator', _separatorRole.default], ['slider', _sliderRole.default], ['spinbutton', _spinbuttonRole.default], ['status', _statusRole.default], ['strong', _strongRole.default], ['subscript', _subscriptRole.default], ['superscript', _superscriptRole.default], ['switch', _switchRole.default], ['tab', _tabRole.default], ['table', _tableRole.default], ['tablist', _tablistRole.default], ['tabpanel', _tabpanelRole.default], ['term', _termRole.default], ['textbox', _textboxRole.default], ['time', _timeRole.default], ['timer', _timerRole.default], ['toolbar', _toolbarRole.default], ['tooltip', _tooltipRole.default], ['tree', _treeRole.default], ['treegrid', _treegridRole.default], ['treeitem', _treeitemRole.default]];
	ariaLiteralRoles.default = ariaLiteralRoles$1;
	return ariaLiteralRoles;
}

var ariaDpubRoles = {};

var docAbstractRole = {};

var hasRequiredDocAbstractRole;

function requireDocAbstractRole () {
	if (hasRequiredDocAbstractRole) return docAbstractRole;
	hasRequiredDocAbstractRole = 1;

	Object.defineProperty(docAbstractRole, "__esModule", {
	  value: true
	});
	docAbstractRole.default = void 0;
	var docAbstractRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'abstract [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	docAbstractRole.default = docAbstractRole$1;
	return docAbstractRole;
}

var docAcknowledgmentsRole = {};

var hasRequiredDocAcknowledgmentsRole;

function requireDocAcknowledgmentsRole () {
	if (hasRequiredDocAcknowledgmentsRole) return docAcknowledgmentsRole;
	hasRequiredDocAcknowledgmentsRole = 1;

	Object.defineProperty(docAcknowledgmentsRole, "__esModule", {
	  value: true
	});
	docAcknowledgmentsRole.default = void 0;
	var docAcknowledgmentsRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'acknowledgments [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	docAcknowledgmentsRole.default = docAcknowledgmentsRole$1;
	return docAcknowledgmentsRole;
}

var docAfterwordRole = {};

var hasRequiredDocAfterwordRole;

function requireDocAfterwordRole () {
	if (hasRequiredDocAfterwordRole) return docAfterwordRole;
	hasRequiredDocAfterwordRole = 1;

	Object.defineProperty(docAfterwordRole, "__esModule", {
	  value: true
	});
	docAfterwordRole.default = void 0;
	var docAfterwordRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'afterword [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	docAfterwordRole.default = docAfterwordRole$1;
	return docAfterwordRole;
}

var docAppendixRole = {};

var hasRequiredDocAppendixRole;

function requireDocAppendixRole () {
	if (hasRequiredDocAppendixRole) return docAppendixRole;
	hasRequiredDocAppendixRole = 1;

	Object.defineProperty(docAppendixRole, "__esModule", {
	  value: true
	});
	docAppendixRole.default = void 0;
	var docAppendixRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'appendix [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	docAppendixRole.default = docAppendixRole$1;
	return docAppendixRole;
}

var docBacklinkRole = {};

var hasRequiredDocBacklinkRole;

function requireDocBacklinkRole () {
	if (hasRequiredDocBacklinkRole) return docBacklinkRole;
	hasRequiredDocBacklinkRole = 1;

	Object.defineProperty(docBacklinkRole, "__esModule", {
	  value: true
	});
	docBacklinkRole.default = void 0;
	var docBacklinkRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-errormessage': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'referrer [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'command', 'link']]
	};
	docBacklinkRole.default = docBacklinkRole$1;
	return docBacklinkRole;
}

var docBiblioentryRole = {};

var hasRequiredDocBiblioentryRole;

function requireDocBiblioentryRole () {
	if (hasRequiredDocBiblioentryRole) return docBiblioentryRole;
	hasRequiredDocBiblioentryRole = 1;

	Object.defineProperty(docBiblioentryRole, "__esModule", {
	  value: true
	});
	docBiblioentryRole.default = void 0;
	var docBiblioentryRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'EPUB biblioentry [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: ['doc-bibliography'],
	  requiredContextRole: ['doc-bibliography'],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'listitem']]
	};
	docBiblioentryRole.default = docBiblioentryRole$1;
	return docBiblioentryRole;
}

var docBibliographyRole = {};

var hasRequiredDocBibliographyRole;

function requireDocBibliographyRole () {
	if (hasRequiredDocBibliographyRole) return docBibliographyRole;
	hasRequiredDocBibliographyRole = 1;

	Object.defineProperty(docBibliographyRole, "__esModule", {
	  value: true
	});
	docBibliographyRole.default = void 0;
	var docBibliographyRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'bibliography [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [['doc-biblioentry']],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	docBibliographyRole.default = docBibliographyRole$1;
	return docBibliographyRole;
}

var docBibliorefRole = {};

var hasRequiredDocBibliorefRole;

function requireDocBibliorefRole () {
	if (hasRequiredDocBibliorefRole) return docBibliorefRole;
	hasRequiredDocBibliorefRole = 1;

	Object.defineProperty(docBibliorefRole, "__esModule", {
	  value: true
	});
	docBibliorefRole.default = void 0;
	var docBibliorefRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-errormessage': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'biblioref [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'command', 'link']]
	};
	docBibliorefRole.default = docBibliorefRole$1;
	return docBibliorefRole;
}

var docChapterRole = {};

var hasRequiredDocChapterRole;

function requireDocChapterRole () {
	if (hasRequiredDocChapterRole) return docChapterRole;
	hasRequiredDocChapterRole = 1;

	Object.defineProperty(docChapterRole, "__esModule", {
	  value: true
	});
	docChapterRole.default = void 0;
	var docChapterRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'chapter [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	docChapterRole.default = docChapterRole$1;
	return docChapterRole;
}

var docColophonRole = {};

var hasRequiredDocColophonRole;

function requireDocColophonRole () {
	if (hasRequiredDocColophonRole) return docColophonRole;
	hasRequiredDocColophonRole = 1;

	Object.defineProperty(docColophonRole, "__esModule", {
	  value: true
	});
	docColophonRole.default = void 0;
	var docColophonRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'colophon [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	docColophonRole.default = docColophonRole$1;
	return docColophonRole;
}

var docConclusionRole = {};

var hasRequiredDocConclusionRole;

function requireDocConclusionRole () {
	if (hasRequiredDocConclusionRole) return docConclusionRole;
	hasRequiredDocConclusionRole = 1;

	Object.defineProperty(docConclusionRole, "__esModule", {
	  value: true
	});
	docConclusionRole.default = void 0;
	var docConclusionRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'conclusion [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	docConclusionRole.default = docConclusionRole$1;
	return docConclusionRole;
}

var docCoverRole = {};

var hasRequiredDocCoverRole;

function requireDocCoverRole () {
	if (hasRequiredDocCoverRole) return docCoverRole;
	hasRequiredDocCoverRole = 1;

	Object.defineProperty(docCoverRole, "__esModule", {
	  value: true
	});
	docCoverRole.default = void 0;
	var docCoverRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'cover [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'img']]
	};
	docCoverRole.default = docCoverRole$1;
	return docCoverRole;
}

var docCreditRole = {};

var hasRequiredDocCreditRole;

function requireDocCreditRole () {
	if (hasRequiredDocCreditRole) return docCreditRole;
	hasRequiredDocCreditRole = 1;

	Object.defineProperty(docCreditRole, "__esModule", {
	  value: true
	});
	docCreditRole.default = void 0;
	var docCreditRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'credit [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	docCreditRole.default = docCreditRole$1;
	return docCreditRole;
}

var docCreditsRole = {};

var hasRequiredDocCreditsRole;

function requireDocCreditsRole () {
	if (hasRequiredDocCreditsRole) return docCreditsRole;
	hasRequiredDocCreditsRole = 1;

	Object.defineProperty(docCreditsRole, "__esModule", {
	  value: true
	});
	docCreditsRole.default = void 0;
	var docCreditsRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'credits [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	docCreditsRole.default = docCreditsRole$1;
	return docCreditsRole;
}

var docDedicationRole = {};

var hasRequiredDocDedicationRole;

function requireDocDedicationRole () {
	if (hasRequiredDocDedicationRole) return docDedicationRole;
	hasRequiredDocDedicationRole = 1;

	Object.defineProperty(docDedicationRole, "__esModule", {
	  value: true
	});
	docDedicationRole.default = void 0;
	var docDedicationRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'dedication [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	docDedicationRole.default = docDedicationRole$1;
	return docDedicationRole;
}

var docEndnoteRole = {};

var hasRequiredDocEndnoteRole;

function requireDocEndnoteRole () {
	if (hasRequiredDocEndnoteRole) return docEndnoteRole;
	hasRequiredDocEndnoteRole = 1;

	Object.defineProperty(docEndnoteRole, "__esModule", {
	  value: true
	});
	docEndnoteRole.default = void 0;
	var docEndnoteRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'rearnote [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: ['doc-endnotes'],
	  requiredContextRole: ['doc-endnotes'],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'listitem']]
	};
	docEndnoteRole.default = docEndnoteRole$1;
	return docEndnoteRole;
}

var docEndnotesRole = {};

var hasRequiredDocEndnotesRole;

function requireDocEndnotesRole () {
	if (hasRequiredDocEndnotesRole) return docEndnotesRole;
	hasRequiredDocEndnotesRole = 1;

	Object.defineProperty(docEndnotesRole, "__esModule", {
	  value: true
	});
	docEndnotesRole.default = void 0;
	var docEndnotesRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'rearnotes [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [['doc-endnote']],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	docEndnotesRole.default = docEndnotesRole$1;
	return docEndnotesRole;
}

var docEpigraphRole = {};

var hasRequiredDocEpigraphRole;

function requireDocEpigraphRole () {
	if (hasRequiredDocEpigraphRole) return docEpigraphRole;
	hasRequiredDocEpigraphRole = 1;

	Object.defineProperty(docEpigraphRole, "__esModule", {
	  value: true
	});
	docEpigraphRole.default = void 0;
	var docEpigraphRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'epigraph [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	docEpigraphRole.default = docEpigraphRole$1;
	return docEpigraphRole;
}

var docEpilogueRole = {};

var hasRequiredDocEpilogueRole;

function requireDocEpilogueRole () {
	if (hasRequiredDocEpilogueRole) return docEpilogueRole;
	hasRequiredDocEpilogueRole = 1;

	Object.defineProperty(docEpilogueRole, "__esModule", {
	  value: true
	});
	docEpilogueRole.default = void 0;
	var docEpilogueRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'epilogue [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	docEpilogueRole.default = docEpilogueRole$1;
	return docEpilogueRole;
}

var docErrataRole = {};

var hasRequiredDocErrataRole;

function requireDocErrataRole () {
	if (hasRequiredDocErrataRole) return docErrataRole;
	hasRequiredDocErrataRole = 1;

	Object.defineProperty(docErrataRole, "__esModule", {
	  value: true
	});
	docErrataRole.default = void 0;
	var docErrataRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'errata [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	docErrataRole.default = docErrataRole$1;
	return docErrataRole;
}

var docExampleRole = {};

var hasRequiredDocExampleRole;

function requireDocExampleRole () {
	if (hasRequiredDocExampleRole) return docExampleRole;
	hasRequiredDocExampleRole = 1;

	Object.defineProperty(docExampleRole, "__esModule", {
	  value: true
	});
	docExampleRole.default = void 0;
	var docExampleRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	docExampleRole.default = docExampleRole$1;
	return docExampleRole;
}

var docFootnoteRole = {};

var hasRequiredDocFootnoteRole;

function requireDocFootnoteRole () {
	if (hasRequiredDocFootnoteRole) return docFootnoteRole;
	hasRequiredDocFootnoteRole = 1;

	Object.defineProperty(docFootnoteRole, "__esModule", {
	  value: true
	});
	docFootnoteRole.default = void 0;
	var docFootnoteRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'footnote [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	docFootnoteRole.default = docFootnoteRole$1;
	return docFootnoteRole;
}

var docForewordRole = {};

var hasRequiredDocForewordRole;

function requireDocForewordRole () {
	if (hasRequiredDocForewordRole) return docForewordRole;
	hasRequiredDocForewordRole = 1;

	Object.defineProperty(docForewordRole, "__esModule", {
	  value: true
	});
	docForewordRole.default = void 0;
	var docForewordRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'foreword [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	docForewordRole.default = docForewordRole$1;
	return docForewordRole;
}

var docGlossaryRole = {};

var hasRequiredDocGlossaryRole;

function requireDocGlossaryRole () {
	if (hasRequiredDocGlossaryRole) return docGlossaryRole;
	hasRequiredDocGlossaryRole = 1;

	Object.defineProperty(docGlossaryRole, "__esModule", {
	  value: true
	});
	docGlossaryRole.default = void 0;
	var docGlossaryRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'glossary [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [['definition'], ['term']],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	docGlossaryRole.default = docGlossaryRole$1;
	return docGlossaryRole;
}

var docGlossrefRole = {};

var hasRequiredDocGlossrefRole;

function requireDocGlossrefRole () {
	if (hasRequiredDocGlossrefRole) return docGlossrefRole;
	hasRequiredDocGlossrefRole = 1;

	Object.defineProperty(docGlossrefRole, "__esModule", {
	  value: true
	});
	docGlossrefRole.default = void 0;
	var docGlossrefRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-errormessage': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'glossref [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'command', 'link']]
	};
	docGlossrefRole.default = docGlossrefRole$1;
	return docGlossrefRole;
}

var docIndexRole = {};

var hasRequiredDocIndexRole;

function requireDocIndexRole () {
	if (hasRequiredDocIndexRole) return docIndexRole;
	hasRequiredDocIndexRole = 1;

	Object.defineProperty(docIndexRole, "__esModule", {
	  value: true
	});
	docIndexRole.default = void 0;
	var docIndexRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'index [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark', 'navigation']]
	};
	docIndexRole.default = docIndexRole$1;
	return docIndexRole;
}

var docIntroductionRole = {};

var hasRequiredDocIntroductionRole;

function requireDocIntroductionRole () {
	if (hasRequiredDocIntroductionRole) return docIntroductionRole;
	hasRequiredDocIntroductionRole = 1;

	Object.defineProperty(docIntroductionRole, "__esModule", {
	  value: true
	});
	docIntroductionRole.default = void 0;
	var docIntroductionRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'introduction [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	docIntroductionRole.default = docIntroductionRole$1;
	return docIntroductionRole;
}

var docNoterefRole = {};

var hasRequiredDocNoterefRole;

function requireDocNoterefRole () {
	if (hasRequiredDocNoterefRole) return docNoterefRole;
	hasRequiredDocNoterefRole = 1;

	Object.defineProperty(docNoterefRole, "__esModule", {
	  value: true
	});
	docNoterefRole.default = void 0;
	var docNoterefRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-errormessage': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'noteref [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'command', 'link']]
	};
	docNoterefRole.default = docNoterefRole$1;
	return docNoterefRole;
}

var docNoticeRole = {};

var hasRequiredDocNoticeRole;

function requireDocNoticeRole () {
	if (hasRequiredDocNoticeRole) return docNoticeRole;
	hasRequiredDocNoticeRole = 1;

	Object.defineProperty(docNoticeRole, "__esModule", {
	  value: true
	});
	docNoticeRole.default = void 0;
	var docNoticeRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'notice [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'note']]
	};
	docNoticeRole.default = docNoticeRole$1;
	return docNoticeRole;
}

var docPagebreakRole = {};

var hasRequiredDocPagebreakRole;

function requireDocPagebreakRole () {
	if (hasRequiredDocPagebreakRole) return docPagebreakRole;
	hasRequiredDocPagebreakRole = 1;

	Object.defineProperty(docPagebreakRole, "__esModule", {
	  value: true
	});
	docPagebreakRole.default = void 0;
	var docPagebreakRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: true,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'pagebreak [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'separator']]
	};
	docPagebreakRole.default = docPagebreakRole$1;
	return docPagebreakRole;
}

var docPagefooterRole = {};

var hasRequiredDocPagefooterRole;

function requireDocPagefooterRole () {
	if (hasRequiredDocPagefooterRole) return docPagefooterRole;
	hasRequiredDocPagefooterRole = 1;

	Object.defineProperty(docPagefooterRole, "__esModule", {
	  value: true
	});
	docPagefooterRole.default = void 0;
	var docPagefooterRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['prohibited'],
	  prohibitedProps: [],
	  props: {
	    'aria-braillelabel': null,
	    'aria-brailleroledescription': null,
	    'aria-description': null,
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	docPagefooterRole.default = docPagefooterRole$1;
	return docPagefooterRole;
}

var docPageheaderRole = {};

var hasRequiredDocPageheaderRole;

function requireDocPageheaderRole () {
	if (hasRequiredDocPageheaderRole) return docPageheaderRole;
	hasRequiredDocPageheaderRole = 1;

	Object.defineProperty(docPageheaderRole, "__esModule", {
	  value: true
	});
	docPageheaderRole.default = void 0;
	var docPageheaderRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['prohibited'],
	  prohibitedProps: [],
	  props: {
	    'aria-braillelabel': null,
	    'aria-brailleroledescription': null,
	    'aria-description': null,
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	docPageheaderRole.default = docPageheaderRole$1;
	return docPageheaderRole;
}

var docPagelistRole = {};

var hasRequiredDocPagelistRole;

function requireDocPagelistRole () {
	if (hasRequiredDocPagelistRole) return docPagelistRole;
	hasRequiredDocPagelistRole = 1;

	Object.defineProperty(docPagelistRole, "__esModule", {
	  value: true
	});
	docPagelistRole.default = void 0;
	var docPagelistRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'page-list [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark', 'navigation']]
	};
	docPagelistRole.default = docPagelistRole$1;
	return docPagelistRole;
}

var docPartRole = {};

var hasRequiredDocPartRole;

function requireDocPartRole () {
	if (hasRequiredDocPartRole) return docPartRole;
	hasRequiredDocPartRole = 1;

	Object.defineProperty(docPartRole, "__esModule", {
	  value: true
	});
	docPartRole.default = void 0;
	var docPartRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'part [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	docPartRole.default = docPartRole$1;
	return docPartRole;
}

var docPrefaceRole = {};

var hasRequiredDocPrefaceRole;

function requireDocPrefaceRole () {
	if (hasRequiredDocPrefaceRole) return docPrefaceRole;
	hasRequiredDocPrefaceRole = 1;

	Object.defineProperty(docPrefaceRole, "__esModule", {
	  value: true
	});
	docPrefaceRole.default = void 0;
	var docPrefaceRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'preface [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	docPrefaceRole.default = docPrefaceRole$1;
	return docPrefaceRole;
}

var docPrologueRole = {};

var hasRequiredDocPrologueRole;

function requireDocPrologueRole () {
	if (hasRequiredDocPrologueRole) return docPrologueRole;
	hasRequiredDocPrologueRole = 1;

	Object.defineProperty(docPrologueRole, "__esModule", {
	  value: true
	});
	docPrologueRole.default = void 0;
	var docPrologueRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'prologue [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	docPrologueRole.default = docPrologueRole$1;
	return docPrologueRole;
}

var docPullquoteRole = {};

var hasRequiredDocPullquoteRole;

function requireDocPullquoteRole () {
	if (hasRequiredDocPullquoteRole) return docPullquoteRole;
	hasRequiredDocPullquoteRole = 1;

	Object.defineProperty(docPullquoteRole, "__esModule", {
	  value: true
	});
	docPullquoteRole.default = void 0;
	var docPullquoteRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'pullquote [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['none']]
	};
	docPullquoteRole.default = docPullquoteRole$1;
	return docPullquoteRole;
}

var docQnaRole = {};

var hasRequiredDocQnaRole;

function requireDocQnaRole () {
	if (hasRequiredDocQnaRole) return docQnaRole;
	hasRequiredDocQnaRole = 1;

	Object.defineProperty(docQnaRole, "__esModule", {
	  value: true
	});
	docQnaRole.default = void 0;
	var docQnaRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'qna [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	docQnaRole.default = docQnaRole$1;
	return docQnaRole;
}

var docSubtitleRole = {};

var hasRequiredDocSubtitleRole;

function requireDocSubtitleRole () {
	if (hasRequiredDocSubtitleRole) return docSubtitleRole;
	hasRequiredDocSubtitleRole = 1;

	Object.defineProperty(docSubtitleRole, "__esModule", {
	  value: true
	});
	docSubtitleRole.default = void 0;
	var docSubtitleRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'subtitle [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'sectionhead']]
	};
	docSubtitleRole.default = docSubtitleRole$1;
	return docSubtitleRole;
}

var docTipRole = {};

var hasRequiredDocTipRole;

function requireDocTipRole () {
	if (hasRequiredDocTipRole) return docTipRole;
	hasRequiredDocTipRole = 1;

	Object.defineProperty(docTipRole, "__esModule", {
	  value: true
	});
	docTipRole.default = void 0;
	var docTipRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'help [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'note']]
	};
	docTipRole.default = docTipRole$1;
	return docTipRole;
}

var docTocRole = {};

var hasRequiredDocTocRole;

function requireDocTocRole () {
	if (hasRequiredDocTocRole) return docTocRole;
	hasRequiredDocTocRole = 1;

	Object.defineProperty(docTocRole, "__esModule", {
	  value: true
	});
	docTocRole.default = void 0;
	var docTocRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'toc [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark', 'navigation']]
	};
	docTocRole.default = docTocRole$1;
	return docTocRole;
}

var hasRequiredAriaDpubRoles;

function requireAriaDpubRoles () {
	if (hasRequiredAriaDpubRoles) return ariaDpubRoles;
	hasRequiredAriaDpubRoles = 1;

	Object.defineProperty(ariaDpubRoles, "__esModule", {
	  value: true
	});
	ariaDpubRoles.default = void 0;
	var _docAbstractRole = _interopRequireDefault(requireDocAbstractRole());
	var _docAcknowledgmentsRole = _interopRequireDefault(requireDocAcknowledgmentsRole());
	var _docAfterwordRole = _interopRequireDefault(requireDocAfterwordRole());
	var _docAppendixRole = _interopRequireDefault(requireDocAppendixRole());
	var _docBacklinkRole = _interopRequireDefault(requireDocBacklinkRole());
	var _docBiblioentryRole = _interopRequireDefault(requireDocBiblioentryRole());
	var _docBibliographyRole = _interopRequireDefault(requireDocBibliographyRole());
	var _docBibliorefRole = _interopRequireDefault(requireDocBibliorefRole());
	var _docChapterRole = _interopRequireDefault(requireDocChapterRole());
	var _docColophonRole = _interopRequireDefault(requireDocColophonRole());
	var _docConclusionRole = _interopRequireDefault(requireDocConclusionRole());
	var _docCoverRole = _interopRequireDefault(requireDocCoverRole());
	var _docCreditRole = _interopRequireDefault(requireDocCreditRole());
	var _docCreditsRole = _interopRequireDefault(requireDocCreditsRole());
	var _docDedicationRole = _interopRequireDefault(requireDocDedicationRole());
	var _docEndnoteRole = _interopRequireDefault(requireDocEndnoteRole());
	var _docEndnotesRole = _interopRequireDefault(requireDocEndnotesRole());
	var _docEpigraphRole = _interopRequireDefault(requireDocEpigraphRole());
	var _docEpilogueRole = _interopRequireDefault(requireDocEpilogueRole());
	var _docErrataRole = _interopRequireDefault(requireDocErrataRole());
	var _docExampleRole = _interopRequireDefault(requireDocExampleRole());
	var _docFootnoteRole = _interopRequireDefault(requireDocFootnoteRole());
	var _docForewordRole = _interopRequireDefault(requireDocForewordRole());
	var _docGlossaryRole = _interopRequireDefault(requireDocGlossaryRole());
	var _docGlossrefRole = _interopRequireDefault(requireDocGlossrefRole());
	var _docIndexRole = _interopRequireDefault(requireDocIndexRole());
	var _docIntroductionRole = _interopRequireDefault(requireDocIntroductionRole());
	var _docNoterefRole = _interopRequireDefault(requireDocNoterefRole());
	var _docNoticeRole = _interopRequireDefault(requireDocNoticeRole());
	var _docPagebreakRole = _interopRequireDefault(requireDocPagebreakRole());
	var _docPagefooterRole = _interopRequireDefault(requireDocPagefooterRole());
	var _docPageheaderRole = _interopRequireDefault(requireDocPageheaderRole());
	var _docPagelistRole = _interopRequireDefault(requireDocPagelistRole());
	var _docPartRole = _interopRequireDefault(requireDocPartRole());
	var _docPrefaceRole = _interopRequireDefault(requireDocPrefaceRole());
	var _docPrologueRole = _interopRequireDefault(requireDocPrologueRole());
	var _docPullquoteRole = _interopRequireDefault(requireDocPullquoteRole());
	var _docQnaRole = _interopRequireDefault(requireDocQnaRole());
	var _docSubtitleRole = _interopRequireDefault(requireDocSubtitleRole());
	var _docTipRole = _interopRequireDefault(requireDocTipRole());
	var _docTocRole = _interopRequireDefault(requireDocTocRole());
	function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
	var ariaDpubRoles$1 = [['doc-abstract', _docAbstractRole.default], ['doc-acknowledgments', _docAcknowledgmentsRole.default], ['doc-afterword', _docAfterwordRole.default], ['doc-appendix', _docAppendixRole.default], ['doc-backlink', _docBacklinkRole.default], ['doc-biblioentry', _docBiblioentryRole.default], ['doc-bibliography', _docBibliographyRole.default], ['doc-biblioref', _docBibliorefRole.default], ['doc-chapter', _docChapterRole.default], ['doc-colophon', _docColophonRole.default], ['doc-conclusion', _docConclusionRole.default], ['doc-cover', _docCoverRole.default], ['doc-credit', _docCreditRole.default], ['doc-credits', _docCreditsRole.default], ['doc-dedication', _docDedicationRole.default], ['doc-endnote', _docEndnoteRole.default], ['doc-endnotes', _docEndnotesRole.default], ['doc-epigraph', _docEpigraphRole.default], ['doc-epilogue', _docEpilogueRole.default], ['doc-errata', _docErrataRole.default], ['doc-example', _docExampleRole.default], ['doc-footnote', _docFootnoteRole.default], ['doc-foreword', _docForewordRole.default], ['doc-glossary', _docGlossaryRole.default], ['doc-glossref', _docGlossrefRole.default], ['doc-index', _docIndexRole.default], ['doc-introduction', _docIntroductionRole.default], ['doc-noteref', _docNoterefRole.default], ['doc-notice', _docNoticeRole.default], ['doc-pagebreak', _docPagebreakRole.default], ['doc-pagefooter', _docPagefooterRole.default], ['doc-pageheader', _docPageheaderRole.default], ['doc-pagelist', _docPagelistRole.default], ['doc-part', _docPartRole.default], ['doc-preface', _docPrefaceRole.default], ['doc-prologue', _docPrologueRole.default], ['doc-pullquote', _docPullquoteRole.default], ['doc-qna', _docQnaRole.default], ['doc-subtitle', _docSubtitleRole.default], ['doc-tip', _docTipRole.default], ['doc-toc', _docTocRole.default]];
	ariaDpubRoles.default = ariaDpubRoles$1;
	return ariaDpubRoles;
}

var ariaGraphicsRoles = {};

var graphicsDocumentRole = {};

var hasRequiredGraphicsDocumentRole;

function requireGraphicsDocumentRole () {
	if (hasRequiredGraphicsDocumentRole) return graphicsDocumentRole;
	hasRequiredGraphicsDocumentRole = 1;

	Object.defineProperty(graphicsDocumentRole, "__esModule", {
	  value: true
	});
	graphicsDocumentRole.default = void 0;
	var graphicsDocumentRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    module: 'GRAPHICS',
	    concept: {
	      name: 'graphics-object'
	    }
	  }, {
	    module: 'ARIA',
	    concept: {
	      name: 'img'
	    }
	  }, {
	    module: 'ARIA',
	    concept: {
	      name: 'article'
	    }
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'document']]
	};
	graphicsDocumentRole.default = graphicsDocumentRole$1;
	return graphicsDocumentRole;
}

var graphicsObjectRole = {};

var hasRequiredGraphicsObjectRole;

function requireGraphicsObjectRole () {
	if (hasRequiredGraphicsObjectRole) return graphicsObjectRole;
	hasRequiredGraphicsObjectRole = 1;

	Object.defineProperty(graphicsObjectRole, "__esModule", {
	  value: true
	});
	graphicsObjectRole.default = void 0;
	var graphicsObjectRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    module: 'GRAPHICS',
	    concept: {
	      name: 'graphics-document'
	    }
	  }, {
	    module: 'ARIA',
	    concept: {
	      name: 'group'
	    }
	  }, {
	    module: 'ARIA',
	    concept: {
	      name: 'img'
	    }
	  }, {
	    module: 'GRAPHICS',
	    concept: {
	      name: 'graphics-symbol'
	    }
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'group']]
	};
	graphicsObjectRole.default = graphicsObjectRole$1;
	return graphicsObjectRole;
}

var graphicsSymbolRole = {};

var hasRequiredGraphicsSymbolRole;

function requireGraphicsSymbolRole () {
	if (hasRequiredGraphicsSymbolRole) return graphicsSymbolRole;
	hasRequiredGraphicsSymbolRole = 1;

	Object.defineProperty(graphicsSymbolRole, "__esModule", {
	  value: true
	});
	graphicsSymbolRole.default = void 0;
	var graphicsSymbolRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: true,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'img']]
	};
	graphicsSymbolRole.default = graphicsSymbolRole$1;
	return graphicsSymbolRole;
}

var hasRequiredAriaGraphicsRoles;

function requireAriaGraphicsRoles () {
	if (hasRequiredAriaGraphicsRoles) return ariaGraphicsRoles;
	hasRequiredAriaGraphicsRoles = 1;

	Object.defineProperty(ariaGraphicsRoles, "__esModule", {
	  value: true
	});
	ariaGraphicsRoles.default = void 0;
	var _graphicsDocumentRole = _interopRequireDefault(requireGraphicsDocumentRole());
	var _graphicsObjectRole = _interopRequireDefault(requireGraphicsObjectRole());
	var _graphicsSymbolRole = _interopRequireDefault(requireGraphicsSymbolRole());
	function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
	var ariaGraphicsRoles$1 = [['graphics-document', _graphicsDocumentRole.default], ['graphics-object', _graphicsObjectRole.default], ['graphics-symbol', _graphicsSymbolRole.default]];
	ariaGraphicsRoles.default = ariaGraphicsRoles$1;
	return ariaGraphicsRoles;
}

var hasRequiredRolesMap;

function requireRolesMap () {
	if (hasRequiredRolesMap) return rolesMap;
	hasRequiredRolesMap = 1;

	Object.defineProperty(rolesMap, "__esModule", {
	  value: true
	});
	rolesMap.default = void 0;
	var _ariaAbstractRoles = _interopRequireDefault(requireAriaAbstractRoles());
	var _ariaLiteralRoles = _interopRequireDefault(requireAriaLiteralRoles());
	var _ariaDpubRoles = _interopRequireDefault(requireAriaDpubRoles());
	var _ariaGraphicsRoles = _interopRequireDefault(requireAriaGraphicsRoles());
	var _iterationDecorator = _interopRequireDefault(requireIterationDecorator$1());
	function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
	function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: true } : { done: false, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = true, u = false; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = true, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
	function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
	function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
	function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
	function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
	function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = true, o = false; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = true, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
	function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
	var roles = [].concat(_ariaAbstractRoles.default, _ariaLiteralRoles.default, _ariaDpubRoles.default, _ariaGraphicsRoles.default);
	roles.forEach(function (_ref) {
	  var _ref2 = _slicedToArray(_ref, 2),
	    roleDefinition = _ref2[1];
	  // Conglomerate the properties
	  var _iterator = _createForOfIteratorHelper(roleDefinition.superClass),
	    _step;
	  try {
	    for (_iterator.s(); !(_step = _iterator.n()).done;) {
	      var superClassIter = _step.value;
	      var _iterator2 = _createForOfIteratorHelper(superClassIter),
	        _step2;
	      try {
	        var _loop = function _loop() {
	          var superClassName = _step2.value;
	          var superClassRoleTuple = roles.filter(function (_ref3) {
	            var _ref4 = _slicedToArray(_ref3, 1),
	              name = _ref4[0];
	            return name === superClassName;
	          })[0];
	          if (superClassRoleTuple) {
	            var superClassDefinition = superClassRoleTuple[1];
	            for (var _i = 0, _Object$keys = Object.keys(superClassDefinition.props); _i < _Object$keys.length; _i++) {
	              var prop = _Object$keys[_i];
	              if (
	              // $FlowIssue Accessing the hasOwnProperty on the Object prototype is fine.
	              !Object.prototype.hasOwnProperty.call(roleDefinition.props, prop)) {
	                // $FlowIgnore assigning without an index signature is fine
	                roleDefinition.props[prop] = superClassDefinition.props[prop];
	              }
	            }
	          }
	        };
	        for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
	          _loop();
	        }
	      } catch (err) {
	        _iterator2.e(err);
	      } finally {
	        _iterator2.f();
	      }
	    }
	  } catch (err) {
	    _iterator.e(err);
	  } finally {
	    _iterator.f();
	  }
	});
	var rolesMap$1 = {
	  entries: function entries() {
	    return roles;
	  },
	  forEach: function forEach(fn) {
	    var thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
	    var _iterator3 = _createForOfIteratorHelper(roles),
	      _step3;
	    try {
	      for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
	        var _step3$value = _slicedToArray(_step3.value, 2),
	          key = _step3$value[0],
	          values = _step3$value[1];
	        fn.call(thisArg, values, key, roles);
	      }
	    } catch (err) {
	      _iterator3.e(err);
	    } finally {
	      _iterator3.f();
	    }
	  },
	  get: function get(key) {
	    var item = roles.filter(function (tuple) {
	      return tuple[0] === key ? true : false;
	    })[0];
	    return item && item[1];
	  },
	  has: function has(key) {
	    return !!rolesMap$1.get(key);
	  },
	  keys: function keys() {
	    return roles.map(function (_ref5) {
	      var _ref6 = _slicedToArray(_ref5, 1),
	        key = _ref6[0];
	      return key;
	    });
	  },
	  values: function values() {
	    return roles.map(function (_ref7) {
	      var _ref8 = _slicedToArray(_ref7, 2),
	        values = _ref8[1];
	      return values;
	    });
	  }
	};
	rolesMap.default = (0, _iterationDecorator.default)(rolesMap$1, rolesMap$1.entries());
	return rolesMap;
}

var elementRoleMap = {};

var hasRequiredElementRoleMap;

function requireElementRoleMap () {
	if (hasRequiredElementRoleMap) return elementRoleMap;
	hasRequiredElementRoleMap = 1;

	Object.defineProperty(elementRoleMap, "__esModule", {
	  value: true
	});
	elementRoleMap.default = void 0;
	var _iterationDecorator = _interopRequireDefault(requireIterationDecorator$1());
	var _rolesMap = _interopRequireDefault(requireRolesMap());
	function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
	function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
	function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
	function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
	function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
	function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = true, o = false; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = true, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
	function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
	var elementRoles = [];
	var keys = _rolesMap.default.keys();
	for (var i = 0; i < keys.length; i++) {
	  var key = keys[i];
	  var role = _rolesMap.default.get(key);
	  if (role) {
	    var concepts = [].concat(role.baseConcepts, role.relatedConcepts);
	    var _loop = function _loop() {
	      var relation = concepts[k];
	      if (relation.module === 'HTML') {
	        var concept = relation.concept;
	        if (concept) {
	          var elementRoleRelation = elementRoles.filter(function (relation) {
	            return ariaRoleRelationConceptEquals(relation[0], concept);
	          })[0];
	          var roles;
	          if (elementRoleRelation) {
	            roles = elementRoleRelation[1];
	          } else {
	            roles = [];
	          }
	          var isUnique = true;
	          for (var _i = 0; _i < roles.length; _i++) {
	            if (roles[_i] === key) {
	              isUnique = false;
	              break;
	            }
	          }
	          if (isUnique) {
	            roles.push(key);
	          }
	          if (!elementRoleRelation) {
	            elementRoles.push([concept, roles]);
	          }
	        }
	      }
	    };
	    for (var k = 0; k < concepts.length; k++) {
	      _loop();
	    }
	  }
	}
	var elementRoleMap$1 = {
	  entries: function entries() {
	    return elementRoles;
	  },
	  forEach: function forEach(fn) {
	    var thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
	    for (var _i2 = 0, _elementRoles = elementRoles; _i2 < _elementRoles.length; _i2++) {
	      var _elementRoles$_i = _slicedToArray(_elementRoles[_i2], 2),
	        _key = _elementRoles$_i[0],
	        values = _elementRoles$_i[1];
	      fn.call(thisArg, values, _key, elementRoles);
	    }
	  },
	  get: function get(key) {
	    var item = elementRoles.filter(function (tuple) {
	      return key.name === tuple[0].name && ariaRoleRelationConceptAttributeEquals(key.attributes, tuple[0].attributes);
	    })[0];
	    return item && item[1];
	  },
	  has: function has(key) {
	    return !!elementRoleMap$1.get(key);
	  },
	  keys: function keys() {
	    return elementRoles.map(function (_ref) {
	      var _ref2 = _slicedToArray(_ref, 1),
	        key = _ref2[0];
	      return key;
	    });
	  },
	  values: function values() {
	    return elementRoles.map(function (_ref3) {
	      var _ref4 = _slicedToArray(_ref3, 2),
	        values = _ref4[1];
	      return values;
	    });
	  }
	};
	function ariaRoleRelationConceptEquals(a, b) {
	  return a.name === b.name && ariaRoleRelationConstraintsEquals(a.constraints, b.constraints) && ariaRoleRelationConceptAttributeEquals(a.attributes, b.attributes);
	}
	function ariaRoleRelationConstraintsEquals(a, b) {
	  if (a === undefined && b !== undefined) {
	    return false;
	  }
	  if (a !== undefined && b === undefined) {
	    return false;
	  }
	  if (a !== undefined && b !== undefined) {
	    if (a.length !== b.length) {
	      return false;
	    }
	    for (var _i3 = 0; _i3 < a.length; _i3++) {
	      if (a[_i3] !== b[_i3]) {
	        return false;
	      }
	    }
	  }
	  return true;
	}
	function ariaRoleRelationConceptAttributeEquals(a, b) {
	  if (a === undefined && b !== undefined) {
	    return false;
	  }
	  if (a !== undefined && b === undefined) {
	    return false;
	  }
	  if (a !== undefined && b !== undefined) {
	    if (a.length !== b.length) {
	      return false;
	    }
	    for (var _i4 = 0; _i4 < a.length; _i4++) {
	      if (a[_i4].name !== b[_i4].name || a[_i4].value !== b[_i4].value) {
	        return false;
	      }
	      if (a[_i4].constraints === undefined && b[_i4].constraints !== undefined) {
	        return false;
	      }
	      if (a[_i4].constraints !== undefined && b[_i4].constraints === undefined) {
	        return false;
	      }
	      if (a[_i4].constraints !== undefined && b[_i4].constraints !== undefined) {
	        if (a[_i4].constraints.length !== b[_i4].constraints.length) {
	          return false;
	        }
	        for (var j = 0; j < a[_i4].constraints.length; j++) {
	          if (a[_i4].constraints[j] !== b[_i4].constraints[j]) {
	            return false;
	          }
	        }
	      }
	    }
	  }
	  return true;
	}
	elementRoleMap.default = (0, _iterationDecorator.default)(elementRoleMap$1, elementRoleMap$1.entries());
	return elementRoleMap;
}

var roleElementMap = {};

var hasRequiredRoleElementMap;

function requireRoleElementMap () {
	if (hasRequiredRoleElementMap) return roleElementMap;
	hasRequiredRoleElementMap = 1;

	Object.defineProperty(roleElementMap, "__esModule", {
	  value: true
	});
	roleElementMap.default = void 0;
	var _iterationDecorator = _interopRequireDefault(requireIterationDecorator$1());
	var _rolesMap = _interopRequireDefault(requireRolesMap());
	function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
	function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
	function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
	function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
	function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
	function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = true, o = false; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = true, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
	function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
	var roleElement = [];
	var keys = _rolesMap.default.keys();
	for (var i = 0; i < keys.length; i++) {
	  var key = keys[i];
	  var role = _rolesMap.default.get(key);
	  var relationConcepts = [];
	  if (role) {
	    var concepts = [].concat(role.baseConcepts, role.relatedConcepts);
	    for (var k = 0; k < concepts.length; k++) {
	      var relation = concepts[k];
	      if (relation.module === 'HTML') {
	        var concept = relation.concept;
	        if (concept != null) {
	          relationConcepts.push(concept);
	        }
	      }
	    }
	    if (relationConcepts.length > 0) {
	      roleElement.push([key, relationConcepts]);
	    }
	  }
	}
	var roleElementMap$1 = {
	  entries: function entries() {
	    return roleElement;
	  },
	  forEach: function forEach(fn) {
	    var thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
	    for (var _i = 0, _roleElement = roleElement; _i < _roleElement.length; _i++) {
	      var _roleElement$_i = _slicedToArray(_roleElement[_i], 2),
	        _key = _roleElement$_i[0],
	        values = _roleElement$_i[1];
	      fn.call(thisArg, values, _key, roleElement);
	    }
	  },
	  get: function get(key) {
	    var item = roleElement.filter(function (tuple) {
	      return tuple[0] === key ? true : false;
	    })[0];
	    return item && item[1];
	  },
	  has: function has(key) {
	    return !!roleElementMap$1.get(key);
	  },
	  keys: function keys() {
	    return roleElement.map(function (_ref) {
	      var _ref2 = _slicedToArray(_ref, 1),
	        key = _ref2[0];
	      return key;
	    });
	  },
	  values: function values() {
	    return roleElement.map(function (_ref3) {
	      var _ref4 = _slicedToArray(_ref3, 2),
	        values = _ref4[1];
	      return values;
	    });
	  }
	};
	roleElementMap.default = (0, _iterationDecorator.default)(roleElementMap$1, roleElementMap$1.entries());
	return roleElementMap;
}

var hasRequiredLib$1;

function requireLib$1 () {
	if (hasRequiredLib$1) return lib$1;
	hasRequiredLib$1 = 1;

	Object.defineProperty(lib$1, "__esModule", {
	  value: true
	});
	lib$1.roles = lib$1.roleElements = lib$1.elementRoles = lib$1.dom = lib$1.aria = void 0;
	var _ariaPropsMap = _interopRequireDefault(requireAriaPropsMap());
	var _domMap = _interopRequireDefault(requireDomMap());
	var _rolesMap = _interopRequireDefault(requireRolesMap());
	var _elementRoleMap = _interopRequireDefault(requireElementRoleMap());
	var _roleElementMap = _interopRequireDefault(requireRoleElementMap());
	function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
	lib$1.aria = _ariaPropsMap.default;
	lib$1.dom = _domMap.default;
	lib$1.roles = _rolesMap.default;
	lib$1.elementRoles = _elementRoleMap.default;
	lib$1.roleElements = _roleElementMap.default;
	return lib$1;
}

var libExports$1 = requireLib$1();

var lib = {};

var AXObjectElementMap = {};

var iterationDecorator = {};

var iteratorProxy = {};

var hasRequiredIteratorProxy;

function requireIteratorProxy () {
	if (hasRequiredIteratorProxy) return iteratorProxy;
	hasRequiredIteratorProxy = 1;

	Object.defineProperty(iteratorProxy, "__esModule", {
	  value: true
	});
	iteratorProxy.default = void 0;
	// eslint-disable-next-line no-unused-vars
	function iteratorProxy$1() {
	  var values = this;
	  var index = 0;
	  var iter = {
	    '@@iterator': function iterator() {
	      return iter;
	    },
	    next: function next() {
	      if (index < values.length) {
	        var value = values[index];
	        index = index + 1;
	        return {
	          done: false,
	          value: value
	        };
	      } else {
	        return {
	          done: true
	        };
	      }
	    }
	  };
	  return iter;
	}
	var _default = iteratorProxy$1;
	iteratorProxy.default = _default;
	return iteratorProxy;
}

var hasRequiredIterationDecorator;

function requireIterationDecorator () {
	if (hasRequiredIterationDecorator) return iterationDecorator;
	hasRequiredIterationDecorator = 1;

	Object.defineProperty(iterationDecorator, "__esModule", {
	  value: true
	});
	iterationDecorator.default = iterationDecorator$1;
	var _iteratorProxy = _interopRequireDefault(requireIteratorProxy());
	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
	function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
	function iterationDecorator$1(collection, entries) {
	  if (typeof Symbol === 'function' && _typeof(Symbol.iterator) === 'symbol') {
	    Object.defineProperty(collection, Symbol.iterator, {
	      value: _iteratorProxy.default.bind(entries)
	    });
	  }
	  return collection;
	}
	return iterationDecorator;
}

var AXObjectsMap = {};

var AbbrRole = {};

var hasRequiredAbbrRole;

function requireAbbrRole () {
	if (hasRequiredAbbrRole) return AbbrRole;
	hasRequiredAbbrRole = 1;

	Object.defineProperty(AbbrRole, "__esModule", {
	  value: true
	});
	AbbrRole.default = void 0;
	var AbbrRole$1 = {
	  relatedConcepts: [{
	    module: 'HTML',
	    concept: {
	      name: 'abbr'
	    }
	  }],
	  type: 'structure'
	};
	var _default = AbbrRole$1;
	AbbrRole.default = _default;
	return AbbrRole;
}

var AlertDialogRole = {};

var hasRequiredAlertDialogRole;

function requireAlertDialogRole () {
	if (hasRequiredAlertDialogRole) return AlertDialogRole;
	hasRequiredAlertDialogRole = 1;

	Object.defineProperty(AlertDialogRole, "__esModule", {
	  value: true
	});
	AlertDialogRole.default = void 0;
	var AlertDialogRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'alertdialog'
	    }
	  }],
	  type: 'window'
	};
	var _default = AlertDialogRole$1;
	AlertDialogRole.default = _default;
	return AlertDialogRole;
}

var AlertRole = {};

var hasRequiredAlertRole;

function requireAlertRole () {
	if (hasRequiredAlertRole) return AlertRole;
	hasRequiredAlertRole = 1;

	Object.defineProperty(AlertRole, "__esModule", {
	  value: true
	});
	AlertRole.default = void 0;
	var AlertRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'alert'
	    }
	  }],
	  type: 'structure'
	};
	var _default = AlertRole$1;
	AlertRole.default = _default;
	return AlertRole;
}

var AnnotationRole = {};

var hasRequiredAnnotationRole;

function requireAnnotationRole () {
	if (hasRequiredAnnotationRole) return AnnotationRole;
	hasRequiredAnnotationRole = 1;

	Object.defineProperty(AnnotationRole, "__esModule", {
	  value: true
	});
	AnnotationRole.default = void 0;
	var AnnotationRole$1 = {
	  relatedConcepts: [],
	  type: 'structure'
	};
	var _default = AnnotationRole$1;
	AnnotationRole.default = _default;
	return AnnotationRole;
}

var ApplicationRole = {};

var hasRequiredApplicationRole;

function requireApplicationRole () {
	if (hasRequiredApplicationRole) return ApplicationRole;
	hasRequiredApplicationRole = 1;

	Object.defineProperty(ApplicationRole, "__esModule", {
	  value: true
	});
	ApplicationRole.default = void 0;
	var ApplicationRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'application'
	    }
	  }],
	  type: 'window'
	};
	var _default = ApplicationRole$1;
	ApplicationRole.default = _default;
	return ApplicationRole;
}

var ArticleRole = {};

var hasRequiredArticleRole;

function requireArticleRole () {
	if (hasRequiredArticleRole) return ArticleRole;
	hasRequiredArticleRole = 1;

	Object.defineProperty(ArticleRole, "__esModule", {
	  value: true
	});
	ArticleRole.default = void 0;
	var ArticleRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'article'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'article'
	    }
	  }],
	  type: 'structure'
	};
	var _default = ArticleRole$1;
	ArticleRole.default = _default;
	return ArticleRole;
}

var AudioRole = {};

var hasRequiredAudioRole;

function requireAudioRole () {
	if (hasRequiredAudioRole) return AudioRole;
	hasRequiredAudioRole = 1;

	Object.defineProperty(AudioRole, "__esModule", {
	  value: true
	});
	AudioRole.default = void 0;
	var AudioRole$1 = {
	  relatedConcepts: [{
	    module: 'HTML',
	    concept: {
	      name: 'audio'
	    }
	  }],
	  type: 'widget'
	};
	var _default = AudioRole$1;
	AudioRole.default = _default;
	return AudioRole;
}

var BannerRole = {};

var hasRequiredBannerRole;

function requireBannerRole () {
	if (hasRequiredBannerRole) return BannerRole;
	hasRequiredBannerRole = 1;

	Object.defineProperty(BannerRole, "__esModule", {
	  value: true
	});
	BannerRole.default = void 0;
	var BannerRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'banner'
	    }
	  }],
	  type: 'structure'
	};
	var _default = BannerRole$1;
	BannerRole.default = _default;
	return BannerRole;
}

var BlockquoteRole = {};

var hasRequiredBlockquoteRole;

function requireBlockquoteRole () {
	if (hasRequiredBlockquoteRole) return BlockquoteRole;
	hasRequiredBlockquoteRole = 1;

	Object.defineProperty(BlockquoteRole, "__esModule", {
	  value: true
	});
	BlockquoteRole.default = void 0;
	var BlockquoteRole$1 = {
	  relatedConcepts: [{
	    module: 'HTML',
	    concept: {
	      name: 'blockquote'
	    }
	  }],
	  type: 'structure'
	};
	var _default = BlockquoteRole$1;
	BlockquoteRole.default = _default;
	return BlockquoteRole;
}

var BusyIndicatorRole = {};

var hasRequiredBusyIndicatorRole;

function requireBusyIndicatorRole () {
	if (hasRequiredBusyIndicatorRole) return BusyIndicatorRole;
	hasRequiredBusyIndicatorRole = 1;

	Object.defineProperty(BusyIndicatorRole, "__esModule", {
	  value: true
	});
	BusyIndicatorRole.default = void 0;
	var BusyIndicatorRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      attributes: [{
	        name: 'aria-busy',
	        value: 'true'
	      }]
	    }
	  }],
	  type: 'widget'
	};
	var _default = BusyIndicatorRole$1;
	BusyIndicatorRole.default = _default;
	return BusyIndicatorRole;
}

var ButtonRole = {};

var hasRequiredButtonRole;

function requireButtonRole () {
	if (hasRequiredButtonRole) return ButtonRole;
	hasRequiredButtonRole = 1;

	Object.defineProperty(ButtonRole, "__esModule", {
	  value: true
	});
	ButtonRole.default = void 0;
	var ButtonRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'button'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'button'
	    }
	  }],
	  type: 'widget'
	};
	var _default = ButtonRole$1;
	ButtonRole.default = _default;
	return ButtonRole;
}

var CanvasRole = {};

var hasRequiredCanvasRole;

function requireCanvasRole () {
	if (hasRequiredCanvasRole) return CanvasRole;
	hasRequiredCanvasRole = 1;

	Object.defineProperty(CanvasRole, "__esModule", {
	  value: true
	});
	CanvasRole.default = void 0;
	var CanvasRole$1 = {
	  relatedConcepts: [{
	    module: 'HTML',
	    concept: {
	      name: 'canvas'
	    }
	  }],
	  type: 'widget'
	};
	var _default = CanvasRole$1;
	CanvasRole.default = _default;
	return CanvasRole;
}

var CaptionRole = {};

var hasRequiredCaptionRole;

function requireCaptionRole () {
	if (hasRequiredCaptionRole) return CaptionRole;
	hasRequiredCaptionRole = 1;

	Object.defineProperty(CaptionRole, "__esModule", {
	  value: true
	});
	CaptionRole.default = void 0;
	var CaptionRole$1 = {
	  relatedConcepts: [{
	    module: 'HTML',
	    concept: {
	      name: 'caption'
	    }
	  }],
	  type: 'structure'
	};
	var _default = CaptionRole$1;
	CaptionRole.default = _default;
	return CaptionRole;
}

var CellRole = {};

var hasRequiredCellRole;

function requireCellRole () {
	if (hasRequiredCellRole) return CellRole;
	hasRequiredCellRole = 1;

	Object.defineProperty(CellRole, "__esModule", {
	  value: true
	});
	CellRole.default = void 0;
	var CellRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'cell'
	    }
	  }, {
	    module: 'ARIA',
	    concept: {
	      name: 'gridcell'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'td'
	    }
	  }],
	  type: 'widget'
	};
	var _default = CellRole$1;
	CellRole.default = _default;
	return CellRole;
}

var CheckBoxRole = {};

var hasRequiredCheckBoxRole;

function requireCheckBoxRole () {
	if (hasRequiredCheckBoxRole) return CheckBoxRole;
	hasRequiredCheckBoxRole = 1;

	Object.defineProperty(CheckBoxRole, "__esModule", {
	  value: true
	});
	CheckBoxRole.default = void 0;
	var CheckBoxRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'checkbox'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'input',
	      attributes: [{
	        name: 'type',
	        value: 'checkbox'
	      }]
	    }
	  }],
	  type: 'widget'
	};
	var _default = CheckBoxRole$1;
	CheckBoxRole.default = _default;
	return CheckBoxRole;
}

var ColorWellRole = {};

var hasRequiredColorWellRole;

function requireColorWellRole () {
	if (hasRequiredColorWellRole) return ColorWellRole;
	hasRequiredColorWellRole = 1;

	Object.defineProperty(ColorWellRole, "__esModule", {
	  value: true
	});
	ColorWellRole.default = void 0;
	var ColorWellRole$1 = {
	  relatedConcepts: [{
	    module: 'HTML',
	    concept: {
	      name: 'input',
	      attributes: [{
	        name: 'type',
	        value: 'color'
	      }]
	    }
	  }],
	  type: 'widget'
	};
	var _default = ColorWellRole$1;
	ColorWellRole.default = _default;
	return ColorWellRole;
}

var ColumnHeaderRole = {};

var hasRequiredColumnHeaderRole;

function requireColumnHeaderRole () {
	if (hasRequiredColumnHeaderRole) return ColumnHeaderRole;
	hasRequiredColumnHeaderRole = 1;

	Object.defineProperty(ColumnHeaderRole, "__esModule", {
	  value: true
	});
	ColumnHeaderRole.default = void 0;
	var ColumnHeaderRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'columnheader'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'th'
	    }
	  }],
	  type: 'widget'
	};
	var _default = ColumnHeaderRole$1;
	ColumnHeaderRole.default = _default;
	return ColumnHeaderRole;
}

var ColumnRole = {};

var hasRequiredColumnRole;

function requireColumnRole () {
	if (hasRequiredColumnRole) return ColumnRole;
	hasRequiredColumnRole = 1;

	Object.defineProperty(ColumnRole, "__esModule", {
	  value: true
	});
	ColumnRole.default = void 0;
	var ColumnRole$1 = {
	  relatedConcepts: [],
	  type: 'structure'
	};
	var _default = ColumnRole$1;
	ColumnRole.default = _default;
	return ColumnRole;
}

var ComboBoxRole = {};

var hasRequiredComboBoxRole;

function requireComboBoxRole () {
	if (hasRequiredComboBoxRole) return ComboBoxRole;
	hasRequiredComboBoxRole = 1;

	Object.defineProperty(ComboBoxRole, "__esModule", {
	  value: true
	});
	ComboBoxRole.default = void 0;
	var ComboBoxRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'combobox'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'select'
	    }
	  }],
	  type: 'widget'
	};
	var _default = ComboBoxRole$1;
	ComboBoxRole.default = _default;
	return ComboBoxRole;
}

var ComplementaryRole = {};

var hasRequiredComplementaryRole;

function requireComplementaryRole () {
	if (hasRequiredComplementaryRole) return ComplementaryRole;
	hasRequiredComplementaryRole = 1;

	Object.defineProperty(ComplementaryRole, "__esModule", {
	  value: true
	});
	ComplementaryRole.default = void 0;
	var ComplementaryRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'complementary'
	    }
	  }],
	  type: 'structure'
	};
	var _default = ComplementaryRole$1;
	ComplementaryRole.default = _default;
	return ComplementaryRole;
}

var ContentInfoRole = {};

var hasRequiredContentInfoRole;

function requireContentInfoRole () {
	if (hasRequiredContentInfoRole) return ContentInfoRole;
	hasRequiredContentInfoRole = 1;

	Object.defineProperty(ContentInfoRole, "__esModule", {
	  value: true
	});
	ContentInfoRole.default = void 0;
	var ContentInfoRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'structureinfo'
	    }
	  }],
	  type: 'structure'
	};
	var _default = ContentInfoRole$1;
	ContentInfoRole.default = _default;
	return ContentInfoRole;
}

var DateRole = {};

var hasRequiredDateRole;

function requireDateRole () {
	if (hasRequiredDateRole) return DateRole;
	hasRequiredDateRole = 1;

	Object.defineProperty(DateRole, "__esModule", {
	  value: true
	});
	DateRole.default = void 0;
	var DateRole$1 = {
	  relatedConcepts: [{
	    module: 'HTML',
	    concept: {
	      name: 'input',
	      attributes: [{
	        name: 'type',
	        value: 'date'
	      }]
	    }
	  }],
	  type: 'widget'
	};
	var _default = DateRole$1;
	DateRole.default = _default;
	return DateRole;
}

var DateTimeRole = {};

var hasRequiredDateTimeRole;

function requireDateTimeRole () {
	if (hasRequiredDateTimeRole) return DateTimeRole;
	hasRequiredDateTimeRole = 1;

	Object.defineProperty(DateTimeRole, "__esModule", {
	  value: true
	});
	DateTimeRole.default = void 0;
	var DateTimeRole$1 = {
	  relatedConcepts: [{
	    module: 'HTML',
	    concept: {
	      name: 'input',
	      attributes: [{
	        name: 'type',
	        value: 'datetime'
	      }]
	    }
	  }],
	  type: 'widget'
	};
	var _default = DateTimeRole$1;
	DateTimeRole.default = _default;
	return DateTimeRole;
}

var DefinitionRole = {};

var hasRequiredDefinitionRole;

function requireDefinitionRole () {
	if (hasRequiredDefinitionRole) return DefinitionRole;
	hasRequiredDefinitionRole = 1;

	Object.defineProperty(DefinitionRole, "__esModule", {
	  value: true
	});
	DefinitionRole.default = void 0;
	var DefinitionRole$1 = {
	  relatedConcepts: [{
	    module: 'HTML',
	    concept: {
	      name: 'dfn'
	    }
	  }],
	  type: 'structure'
	};
	var _default = DefinitionRole$1;
	DefinitionRole.default = _default;
	return DefinitionRole;
}

var DescriptionListDetailRole = {};

var hasRequiredDescriptionListDetailRole;

function requireDescriptionListDetailRole () {
	if (hasRequiredDescriptionListDetailRole) return DescriptionListDetailRole;
	hasRequiredDescriptionListDetailRole = 1;

	Object.defineProperty(DescriptionListDetailRole, "__esModule", {
	  value: true
	});
	DescriptionListDetailRole.default = void 0;
	var DescriptionListDetailRole$1 = {
	  relatedConcepts: [{
	    module: 'HTML',
	    concept: {
	      name: 'dd'
	    }
	  }],
	  type: 'structure'
	};
	var _default = DescriptionListDetailRole$1;
	DescriptionListDetailRole.default = _default;
	return DescriptionListDetailRole;
}

var DescriptionListRole = {};

var hasRequiredDescriptionListRole;

function requireDescriptionListRole () {
	if (hasRequiredDescriptionListRole) return DescriptionListRole;
	hasRequiredDescriptionListRole = 1;

	Object.defineProperty(DescriptionListRole, "__esModule", {
	  value: true
	});
	DescriptionListRole.default = void 0;
	var DescriptionListRole$1 = {
	  relatedConcepts: [{
	    module: 'HTML',
	    concept: {
	      name: 'dl'
	    }
	  }],
	  type: 'structure'
	};
	var _default = DescriptionListRole$1;
	DescriptionListRole.default = _default;
	return DescriptionListRole;
}

var DescriptionListTermRole = {};

var hasRequiredDescriptionListTermRole;

function requireDescriptionListTermRole () {
	if (hasRequiredDescriptionListTermRole) return DescriptionListTermRole;
	hasRequiredDescriptionListTermRole = 1;

	Object.defineProperty(DescriptionListTermRole, "__esModule", {
	  value: true
	});
	DescriptionListTermRole.default = void 0;
	var DescriptionListTermRole$1 = {
	  relatedConcepts: [{
	    module: 'HTML',
	    concept: {
	      name: 'dt'
	    }
	  }],
	  type: 'structure'
	};
	var _default = DescriptionListTermRole$1;
	DescriptionListTermRole.default = _default;
	return DescriptionListTermRole;
}

var DetailsRole = {};

var hasRequiredDetailsRole;

function requireDetailsRole () {
	if (hasRequiredDetailsRole) return DetailsRole;
	hasRequiredDetailsRole = 1;

	Object.defineProperty(DetailsRole, "__esModule", {
	  value: true
	});
	DetailsRole.default = void 0;
	var DetailsRole$1 = {
	  relatedConcepts: [{
	    module: 'HTML',
	    concept: {
	      name: 'details'
	    }
	  }],
	  type: 'structure'
	};
	var _default = DetailsRole$1;
	DetailsRole.default = _default;
	return DetailsRole;
}

var DialogRole = {};

var hasRequiredDialogRole;

function requireDialogRole () {
	if (hasRequiredDialogRole) return DialogRole;
	hasRequiredDialogRole = 1;

	Object.defineProperty(DialogRole, "__esModule", {
	  value: true
	});
	DialogRole.default = void 0;
	var DialogRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'dialog'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'dialog'
	    }
	  }],
	  type: 'window'
	};
	var _default = DialogRole$1;
	DialogRole.default = _default;
	return DialogRole;
}

var DirectoryRole = {};

var hasRequiredDirectoryRole;

function requireDirectoryRole () {
	if (hasRequiredDirectoryRole) return DirectoryRole;
	hasRequiredDirectoryRole = 1;

	Object.defineProperty(DirectoryRole, "__esModule", {
	  value: true
	});
	DirectoryRole.default = void 0;
	var DirectoryRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'directory'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'dir'
	    }
	  }],
	  type: 'structure'
	};
	var _default = DirectoryRole$1;
	DirectoryRole.default = _default;
	return DirectoryRole;
}

var DisclosureTriangleRole = {};

var hasRequiredDisclosureTriangleRole;

function requireDisclosureTriangleRole () {
	if (hasRequiredDisclosureTriangleRole) return DisclosureTriangleRole;
	hasRequiredDisclosureTriangleRole = 1;

	Object.defineProperty(DisclosureTriangleRole, "__esModule", {
	  value: true
	});
	DisclosureTriangleRole.default = void 0;
	var DisclosureTriangleRole$1 = {
	  relatedConcepts: [{
	    module: 'HTML',
	    concept: {
	      constraints: ['scoped to a details element'],
	      name: 'summary'
	    }
	  }],
	  type: 'widget'
	};
	var _default = DisclosureTriangleRole$1;
	DisclosureTriangleRole.default = _default;
	return DisclosureTriangleRole;
}

var DivRole = {};

var hasRequiredDivRole;

function requireDivRole () {
	if (hasRequiredDivRole) return DivRole;
	hasRequiredDivRole = 1;

	Object.defineProperty(DivRole, "__esModule", {
	  value: true
	});
	DivRole.default = void 0;
	var DivRole$1 = {
	  relatedConcepts: [{
	    module: 'HTML',
	    concept: {
	      name: 'div'
	    }
	  }],
	  type: 'generic'
	};
	var _default = DivRole$1;
	DivRole.default = _default;
	return DivRole;
}

var DocumentRole = {};

var hasRequiredDocumentRole;

function requireDocumentRole () {
	if (hasRequiredDocumentRole) return DocumentRole;
	hasRequiredDocumentRole = 1;

	Object.defineProperty(DocumentRole, "__esModule", {
	  value: true
	});
	DocumentRole.default = void 0;
	var DocumentRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'document'
	    }
	  }],
	  type: 'structure'
	};
	var _default = DocumentRole$1;
	DocumentRole.default = _default;
	return DocumentRole;
}

var EmbeddedObjectRole = {};

var hasRequiredEmbeddedObjectRole;

function requireEmbeddedObjectRole () {
	if (hasRequiredEmbeddedObjectRole) return EmbeddedObjectRole;
	hasRequiredEmbeddedObjectRole = 1;

	Object.defineProperty(EmbeddedObjectRole, "__esModule", {
	  value: true
	});
	EmbeddedObjectRole.default = void 0;
	var EmbeddedObjectRole$1 = {
	  relatedConcepts: [{
	    module: 'HTML',
	    concept: {
	      name: 'embed'
	    }
	  }],
	  type: 'widget'
	};
	var _default = EmbeddedObjectRole$1;
	EmbeddedObjectRole.default = _default;
	return EmbeddedObjectRole;
}

var FeedRole = {};

var hasRequiredFeedRole;

function requireFeedRole () {
	if (hasRequiredFeedRole) return FeedRole;
	hasRequiredFeedRole = 1;

	Object.defineProperty(FeedRole, "__esModule", {
	  value: true
	});
	FeedRole.default = void 0;
	var FeedRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'feed'
	    }
	  }],
	  type: 'structure'
	};
	var _default = FeedRole$1;
	FeedRole.default = _default;
	return FeedRole;
}

var FigcaptionRole = {};

var hasRequiredFigcaptionRole;

function requireFigcaptionRole () {
	if (hasRequiredFigcaptionRole) return FigcaptionRole;
	hasRequiredFigcaptionRole = 1;

	Object.defineProperty(FigcaptionRole, "__esModule", {
	  value: true
	});
	FigcaptionRole.default = void 0;
	var FigcaptionRole$1 = {
	  relatedConcepts: [{
	    module: 'HTML',
	    concept: {
	      name: 'figcaption'
	    }
	  }],
	  type: 'structure'
	};
	var _default = FigcaptionRole$1;
	FigcaptionRole.default = _default;
	return FigcaptionRole;
}

var FigureRole = {};

var hasRequiredFigureRole;

function requireFigureRole () {
	if (hasRequiredFigureRole) return FigureRole;
	hasRequiredFigureRole = 1;

	Object.defineProperty(FigureRole, "__esModule", {
	  value: true
	});
	FigureRole.default = void 0;
	var FigureRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'figure'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'figure'
	    }
	  }],
	  type: 'structure'
	};
	var _default = FigureRole$1;
	FigureRole.default = _default;
	return FigureRole;
}

var FooterRole = {};

var hasRequiredFooterRole;

function requireFooterRole () {
	if (hasRequiredFooterRole) return FooterRole;
	hasRequiredFooterRole = 1;

	Object.defineProperty(FooterRole, "__esModule", {
	  value: true
	});
	FooterRole.default = void 0;
	var FooterRole$1 = {
	  relatedConcepts: [{
	    module: 'HTML',
	    concept: {
	      name: 'footer'
	    }
	  }],
	  type: 'structure'
	};
	var _default = FooterRole$1;
	FooterRole.default = _default;
	return FooterRole;
}

var FormRole = {};

var hasRequiredFormRole;

function requireFormRole () {
	if (hasRequiredFormRole) return FormRole;
	hasRequiredFormRole = 1;

	Object.defineProperty(FormRole, "__esModule", {
	  value: true
	});
	FormRole.default = void 0;
	var FormRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'form'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'form'
	    }
	  }],
	  type: 'structure'
	};
	var _default = FormRole$1;
	FormRole.default = _default;
	return FormRole;
}

var GridRole = {};

var hasRequiredGridRole;

function requireGridRole () {
	if (hasRequiredGridRole) return GridRole;
	hasRequiredGridRole = 1;

	Object.defineProperty(GridRole, "__esModule", {
	  value: true
	});
	GridRole.default = void 0;
	var GridRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'grid'
	    }
	  }],
	  type: 'widget'
	};
	var _default = GridRole$1;
	GridRole.default = _default;
	return GridRole;
}

var GroupRole = {};

var hasRequiredGroupRole;

function requireGroupRole () {
	if (hasRequiredGroupRole) return GroupRole;
	hasRequiredGroupRole = 1;

	Object.defineProperty(GroupRole, "__esModule", {
	  value: true
	});
	GroupRole.default = void 0;
	var GroupRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'group'
	    }
	  }],
	  type: 'structure'
	};
	var _default = GroupRole$1;
	GroupRole.default = _default;
	return GroupRole;
}

var HeadingRole = {};

var hasRequiredHeadingRole;

function requireHeadingRole () {
	if (hasRequiredHeadingRole) return HeadingRole;
	hasRequiredHeadingRole = 1;

	Object.defineProperty(HeadingRole, "__esModule", {
	  value: true
	});
	HeadingRole.default = void 0;
	var HeadingRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'heading'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'h1'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'h2'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'h3'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'h4'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'h5'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'h6'
	    }
	  }],
	  type: 'structure'
	};
	var _default = HeadingRole$1;
	HeadingRole.default = _default;
	return HeadingRole;
}

var IframePresentationalRole = {};

var hasRequiredIframePresentationalRole;

function requireIframePresentationalRole () {
	if (hasRequiredIframePresentationalRole) return IframePresentationalRole;
	hasRequiredIframePresentationalRole = 1;

	Object.defineProperty(IframePresentationalRole, "__esModule", {
	  value: true
	});
	IframePresentationalRole.default = void 0;
	var IframePresentationalRole$1 = {
	  relatedConcepts: [],
	  type: 'window'
	};
	var _default = IframePresentationalRole$1;
	IframePresentationalRole.default = _default;
	return IframePresentationalRole;
}

var IframeRole = {};

var hasRequiredIframeRole;

function requireIframeRole () {
	if (hasRequiredIframeRole) return IframeRole;
	hasRequiredIframeRole = 1;

	Object.defineProperty(IframeRole, "__esModule", {
	  value: true
	});
	IframeRole.default = void 0;
	var IframeRole$1 = {
	  relatedConcepts: [{
	    module: 'HTML',
	    concept: {
	      name: 'iframe'
	    }
	  }],
	  type: 'window'
	};
	var _default = IframeRole$1;
	IframeRole.default = _default;
	return IframeRole;
}

var IgnoredRole = {};

var hasRequiredIgnoredRole;

function requireIgnoredRole () {
	if (hasRequiredIgnoredRole) return IgnoredRole;
	hasRequiredIgnoredRole = 1;

	Object.defineProperty(IgnoredRole, "__esModule", {
	  value: true
	});
	IgnoredRole.default = void 0;
	var IgnoredRole$1 = {
	  relatedConcepts: [],
	  type: 'structure'
	};
	var _default = IgnoredRole$1;
	IgnoredRole.default = _default;
	return IgnoredRole;
}

var ImageMapLinkRole = {};

var hasRequiredImageMapLinkRole;

function requireImageMapLinkRole () {
	if (hasRequiredImageMapLinkRole) return ImageMapLinkRole;
	hasRequiredImageMapLinkRole = 1;

	Object.defineProperty(ImageMapLinkRole, "__esModule", {
	  value: true
	});
	ImageMapLinkRole.default = void 0;
	var ImageMapLinkRole$1 = {
	  relatedConcepts: [],
	  type: 'widget'
	};
	var _default = ImageMapLinkRole$1;
	ImageMapLinkRole.default = _default;
	return ImageMapLinkRole;
}

var ImageMapRole = {};

var hasRequiredImageMapRole;

function requireImageMapRole () {
	if (hasRequiredImageMapRole) return ImageMapRole;
	hasRequiredImageMapRole = 1;

	Object.defineProperty(ImageMapRole, "__esModule", {
	  value: true
	});
	ImageMapRole.default = void 0;
	var ImageMapRole$1 = {
	  relatedConcepts: [{
	    module: 'HTML',
	    concept: {
	      name: 'img',
	      attributes: [{
	        name: 'usemap'
	      }]
	    }
	  }],
	  type: 'structure'
	};
	var _default = ImageMapRole$1;
	ImageMapRole.default = _default;
	return ImageMapRole;
}

var ImageRole = {};

var hasRequiredImageRole;

function requireImageRole () {
	if (hasRequiredImageRole) return ImageRole;
	hasRequiredImageRole = 1;

	Object.defineProperty(ImageRole, "__esModule", {
	  value: true
	});
	ImageRole.default = void 0;
	var ImageRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'img'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'img'
	    }
	  }],
	  type: 'structure'
	};
	var _default = ImageRole$1;
	ImageRole.default = _default;
	return ImageRole;
}

var InlineTextBoxRole = {};

var hasRequiredInlineTextBoxRole;

function requireInlineTextBoxRole () {
	if (hasRequiredInlineTextBoxRole) return InlineTextBoxRole;
	hasRequiredInlineTextBoxRole = 1;

	Object.defineProperty(InlineTextBoxRole, "__esModule", {
	  value: true
	});
	InlineTextBoxRole.default = void 0;
	var InlineTextBoxRole$1 = {
	  relatedConcepts: [{
	    module: 'HTML',
	    concept: {
	      name: 'input'
	    }
	  }],
	  type: 'widget'
	};
	var _default = InlineTextBoxRole$1;
	InlineTextBoxRole.default = _default;
	return InlineTextBoxRole;
}

var InputTimeRole = {};

var hasRequiredInputTimeRole;

function requireInputTimeRole () {
	if (hasRequiredInputTimeRole) return InputTimeRole;
	hasRequiredInputTimeRole = 1;

	Object.defineProperty(InputTimeRole, "__esModule", {
	  value: true
	});
	InputTimeRole.default = void 0;
	var InputTimeRole$1 = {
	  relatedConcepts: [{
	    module: 'HTML',
	    concept: {
	      name: 'input',
	      attributes: [{
	        name: 'type',
	        value: 'time'
	      }]
	    }
	  }],
	  type: 'widget'
	};
	var _default = InputTimeRole$1;
	InputTimeRole.default = _default;
	return InputTimeRole;
}

var LabelRole = {};

var hasRequiredLabelRole;

function requireLabelRole () {
	if (hasRequiredLabelRole) return LabelRole;
	hasRequiredLabelRole = 1;

	Object.defineProperty(LabelRole, "__esModule", {
	  value: true
	});
	LabelRole.default = void 0;
	var LabelRole$1 = {
	  relatedConcepts: [{
	    module: 'HTML',
	    concept: {
	      name: 'label'
	    }
	  }],
	  type: 'structure'
	};
	var _default = LabelRole$1;
	LabelRole.default = _default;
	return LabelRole;
}

var LegendRole = {};

var hasRequiredLegendRole;

function requireLegendRole () {
	if (hasRequiredLegendRole) return LegendRole;
	hasRequiredLegendRole = 1;

	Object.defineProperty(LegendRole, "__esModule", {
	  value: true
	});
	LegendRole.default = void 0;
	var LegendRole$1 = {
	  relatedConcepts: [{
	    module: 'HTML',
	    concept: {
	      name: 'legend'
	    }
	  }],
	  type: 'structure'
	};
	var _default = LegendRole$1;
	LegendRole.default = _default;
	return LegendRole;
}

var LineBreakRole = {};

var hasRequiredLineBreakRole;

function requireLineBreakRole () {
	if (hasRequiredLineBreakRole) return LineBreakRole;
	hasRequiredLineBreakRole = 1;

	Object.defineProperty(LineBreakRole, "__esModule", {
	  value: true
	});
	LineBreakRole.default = void 0;
	var LineBreakRole$1 = {
	  relatedConcepts: [{
	    module: 'HTML',
	    concept: {
	      name: 'br'
	    }
	  }],
	  type: 'structure'
	};
	var _default = LineBreakRole$1;
	LineBreakRole.default = _default;
	return LineBreakRole;
}

var LinkRole = {};

var hasRequiredLinkRole;

function requireLinkRole () {
	if (hasRequiredLinkRole) return LinkRole;
	hasRequiredLinkRole = 1;

	Object.defineProperty(LinkRole, "__esModule", {
	  value: true
	});
	LinkRole.default = void 0;
	var LinkRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'link'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'a',
	      attributes: [{
	        name: 'href'
	      }]
	    }
	  }],
	  type: 'widget'
	};
	var _default = LinkRole$1;
	LinkRole.default = _default;
	return LinkRole;
}

var ListBoxOptionRole = {};

var hasRequiredListBoxOptionRole;

function requireListBoxOptionRole () {
	if (hasRequiredListBoxOptionRole) return ListBoxOptionRole;
	hasRequiredListBoxOptionRole = 1;

	Object.defineProperty(ListBoxOptionRole, "__esModule", {
	  value: true
	});
	ListBoxOptionRole.default = void 0;
	var ListBoxOptionRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'option'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'option'
	    }
	  }],
	  type: 'widget'
	};
	var _default = ListBoxOptionRole$1;
	ListBoxOptionRole.default = _default;
	return ListBoxOptionRole;
}

var ListBoxRole = {};

var hasRequiredListBoxRole;

function requireListBoxRole () {
	if (hasRequiredListBoxRole) return ListBoxRole;
	hasRequiredListBoxRole = 1;

	Object.defineProperty(ListBoxRole, "__esModule", {
	  value: true
	});
	ListBoxRole.default = void 0;
	var ListBoxRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'listbox'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'datalist'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'select'
	    }
	  }],
	  type: 'widget'
	};
	var _default = ListBoxRole$1;
	ListBoxRole.default = _default;
	return ListBoxRole;
}

var ListItemRole = {};

var hasRequiredListItemRole;

function requireListItemRole () {
	if (hasRequiredListItemRole) return ListItemRole;
	hasRequiredListItemRole = 1;

	Object.defineProperty(ListItemRole, "__esModule", {
	  value: true
	});
	ListItemRole.default = void 0;
	var ListItemRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'listitem'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'li'
	    }
	  }],
	  type: 'structure'
	};
	var _default = ListItemRole$1;
	ListItemRole.default = _default;
	return ListItemRole;
}

var ListMarkerRole = {};

var hasRequiredListMarkerRole;

function requireListMarkerRole () {
	if (hasRequiredListMarkerRole) return ListMarkerRole;
	hasRequiredListMarkerRole = 1;

	Object.defineProperty(ListMarkerRole, "__esModule", {
	  value: true
	});
	ListMarkerRole.default = void 0;
	var ListMarkerRole$1 = {
	  relatedConcepts: [],
	  type: 'structure'
	};
	var _default = ListMarkerRole$1;
	ListMarkerRole.default = _default;
	return ListMarkerRole;
}

var ListRole = {};

var hasRequiredListRole;

function requireListRole () {
	if (hasRequiredListRole) return ListRole;
	hasRequiredListRole = 1;

	Object.defineProperty(ListRole, "__esModule", {
	  value: true
	});
	ListRole.default = void 0;
	var ListRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'list'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'ul'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'ol'
	    }
	  }],
	  type: 'structure'
	};
	var _default = ListRole$1;
	ListRole.default = _default;
	return ListRole;
}

var LogRole = {};

var hasRequiredLogRole;

function requireLogRole () {
	if (hasRequiredLogRole) return LogRole;
	hasRequiredLogRole = 1;

	Object.defineProperty(LogRole, "__esModule", {
	  value: true
	});
	LogRole.default = void 0;
	var LogRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'log'
	    }
	  }],
	  type: 'structure'
	};
	var _default = LogRole$1;
	LogRole.default = _default;
	return LogRole;
}

var MainRole = {};

var hasRequiredMainRole;

function requireMainRole () {
	if (hasRequiredMainRole) return MainRole;
	hasRequiredMainRole = 1;

	Object.defineProperty(MainRole, "__esModule", {
	  value: true
	});
	MainRole.default = void 0;
	var MainRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'main'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'main'
	    }
	  }],
	  type: 'structure'
	};
	var _default = MainRole$1;
	MainRole.default = _default;
	return MainRole;
}

var MarkRole = {};

var hasRequiredMarkRole;

function requireMarkRole () {
	if (hasRequiredMarkRole) return MarkRole;
	hasRequiredMarkRole = 1;

	Object.defineProperty(MarkRole, "__esModule", {
	  value: true
	});
	MarkRole.default = void 0;
	var MarkRole$1 = {
	  relatedConcepts: [{
	    module: 'HTML',
	    concept: {
	      name: 'mark'
	    }
	  }],
	  type: 'structure'
	};
	var _default = MarkRole$1;
	MarkRole.default = _default;
	return MarkRole;
}

var MarqueeRole = {};

var hasRequiredMarqueeRole;

function requireMarqueeRole () {
	if (hasRequiredMarqueeRole) return MarqueeRole;
	hasRequiredMarqueeRole = 1;

	Object.defineProperty(MarqueeRole, "__esModule", {
	  value: true
	});
	MarqueeRole.default = void 0;
	var MarqueeRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'marquee'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'marquee'
	    }
	  }],
	  type: 'structure'
	};
	var _default = MarqueeRole$1;
	MarqueeRole.default = _default;
	return MarqueeRole;
}

var MathRole = {};

var hasRequiredMathRole;

function requireMathRole () {
	if (hasRequiredMathRole) return MathRole;
	hasRequiredMathRole = 1;

	Object.defineProperty(MathRole, "__esModule", {
	  value: true
	});
	MathRole.default = void 0;
	var MathRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'math'
	    }
	  }],
	  type: 'structure'
	};
	var _default = MathRole$1;
	MathRole.default = _default;
	return MathRole;
}

var MenuBarRole = {};

var hasRequiredMenuBarRole;

function requireMenuBarRole () {
	if (hasRequiredMenuBarRole) return MenuBarRole;
	hasRequiredMenuBarRole = 1;

	Object.defineProperty(MenuBarRole, "__esModule", {
	  value: true
	});
	MenuBarRole.default = void 0;
	var MenuBarRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'menubar'
	    }
	  }],
	  type: 'structure'
	};
	var _default = MenuBarRole$1;
	MenuBarRole.default = _default;
	return MenuBarRole;
}

var MenuButtonRole = {};

var hasRequiredMenuButtonRole;

function requireMenuButtonRole () {
	if (hasRequiredMenuButtonRole) return MenuButtonRole;
	hasRequiredMenuButtonRole = 1;

	Object.defineProperty(MenuButtonRole, "__esModule", {
	  value: true
	});
	MenuButtonRole.default = void 0;
	var MenuButtonRole$1 = {
	  relatedConcepts: [],
	  type: 'widget'
	};
	var _default = MenuButtonRole$1;
	MenuButtonRole.default = _default;
	return MenuButtonRole;
}

var MenuItemRole = {};

var hasRequiredMenuItemRole;

function requireMenuItemRole () {
	if (hasRequiredMenuItemRole) return MenuItemRole;
	hasRequiredMenuItemRole = 1;

	Object.defineProperty(MenuItemRole, "__esModule", {
	  value: true
	});
	MenuItemRole.default = void 0;
	var MenuItemRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'menuitem'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'menuitem'
	    }
	  }],
	  type: 'widget'
	};
	var _default = MenuItemRole$1;
	MenuItemRole.default = _default;
	return MenuItemRole;
}

var MenuItemCheckBoxRole = {};

var hasRequiredMenuItemCheckBoxRole;

function requireMenuItemCheckBoxRole () {
	if (hasRequiredMenuItemCheckBoxRole) return MenuItemCheckBoxRole;
	hasRequiredMenuItemCheckBoxRole = 1;

	Object.defineProperty(MenuItemCheckBoxRole, "__esModule", {
	  value: true
	});
	MenuItemCheckBoxRole.default = void 0;
	var MenuItemCheckBoxRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'menuitemcheckbox'
	    }
	  }],
	  type: 'widget'
	};
	var _default = MenuItemCheckBoxRole$1;
	MenuItemCheckBoxRole.default = _default;
	return MenuItemCheckBoxRole;
}

var MenuItemRadioRole = {};

var hasRequiredMenuItemRadioRole;

function requireMenuItemRadioRole () {
	if (hasRequiredMenuItemRadioRole) return MenuItemRadioRole;
	hasRequiredMenuItemRadioRole = 1;

	Object.defineProperty(MenuItemRadioRole, "__esModule", {
	  value: true
	});
	MenuItemRadioRole.default = void 0;
	var MenuItemRadioRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'menuitemradio'
	    }
	  }],
	  type: 'widget'
	};
	var _default = MenuItemRadioRole$1;
	MenuItemRadioRole.default = _default;
	return MenuItemRadioRole;
}

var MenuListOptionRole = {};

var hasRequiredMenuListOptionRole;

function requireMenuListOptionRole () {
	if (hasRequiredMenuListOptionRole) return MenuListOptionRole;
	hasRequiredMenuListOptionRole = 1;

	Object.defineProperty(MenuListOptionRole, "__esModule", {
	  value: true
	});
	MenuListOptionRole.default = void 0;
	var MenuListOptionRole$1 = {
	  relatedConcepts: [],
	  type: 'widget'
	};
	var _default = MenuListOptionRole$1;
	MenuListOptionRole.default = _default;
	return MenuListOptionRole;
}

var MenuListPopupRole = {};

var hasRequiredMenuListPopupRole;

function requireMenuListPopupRole () {
	if (hasRequiredMenuListPopupRole) return MenuListPopupRole;
	hasRequiredMenuListPopupRole = 1;

	Object.defineProperty(MenuListPopupRole, "__esModule", {
	  value: true
	});
	MenuListPopupRole.default = void 0;
	var MenuListPopupRole$1 = {
	  relatedConcepts: [],
	  type: 'widget'
	};
	var _default = MenuListPopupRole$1;
	MenuListPopupRole.default = _default;
	return MenuListPopupRole;
}

var MenuRole = {};

var hasRequiredMenuRole;

function requireMenuRole () {
	if (hasRequiredMenuRole) return MenuRole;
	hasRequiredMenuRole = 1;

	Object.defineProperty(MenuRole, "__esModule", {
	  value: true
	});
	MenuRole.default = void 0;
	var MenuRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'menu'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'menu'
	    }
	  }],
	  type: 'structure'
	};
	var _default = MenuRole$1;
	MenuRole.default = _default;
	return MenuRole;
}

var MeterRole = {};

var hasRequiredMeterRole;

function requireMeterRole () {
	if (hasRequiredMeterRole) return MeterRole;
	hasRequiredMeterRole = 1;

	Object.defineProperty(MeterRole, "__esModule", {
	  value: true
	});
	MeterRole.default = void 0;
	var MeterRole$1 = {
	  relatedConcepts: [{
	    module: 'HTML',
	    concept: {
	      name: 'meter'
	    }
	  }],
	  type: 'structure'
	};
	var _default = MeterRole$1;
	MeterRole.default = _default;
	return MeterRole;
}

var NavigationRole = {};

var hasRequiredNavigationRole;

function requireNavigationRole () {
	if (hasRequiredNavigationRole) return NavigationRole;
	hasRequiredNavigationRole = 1;

	Object.defineProperty(NavigationRole, "__esModule", {
	  value: true
	});
	NavigationRole.default = void 0;
	var NavigationRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'navigation'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'nav'
	    }
	  }],
	  type: 'structure'
	};
	var _default = NavigationRole$1;
	NavigationRole.default = _default;
	return NavigationRole;
}

var NoneRole = {};

var hasRequiredNoneRole;

function requireNoneRole () {
	if (hasRequiredNoneRole) return NoneRole;
	hasRequiredNoneRole = 1;

	Object.defineProperty(NoneRole, "__esModule", {
	  value: true
	});
	NoneRole.default = void 0;
	var NoneRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'none'
	    }
	  }],
	  type: 'structure'
	};
	var _default = NoneRole$1;
	NoneRole.default = _default;
	return NoneRole;
}

var NoteRole = {};

var hasRequiredNoteRole;

function requireNoteRole () {
	if (hasRequiredNoteRole) return NoteRole;
	hasRequiredNoteRole = 1;

	Object.defineProperty(NoteRole, "__esModule", {
	  value: true
	});
	NoteRole.default = void 0;
	var NoteRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'note'
	    }
	  }],
	  type: 'structure'
	};
	var _default = NoteRole$1;
	NoteRole.default = _default;
	return NoteRole;
}

var OutlineRole = {};

var hasRequiredOutlineRole;

function requireOutlineRole () {
	if (hasRequiredOutlineRole) return OutlineRole;
	hasRequiredOutlineRole = 1;

	Object.defineProperty(OutlineRole, "__esModule", {
	  value: true
	});
	OutlineRole.default = void 0;
	var OutlineRole$1 = {
	  relatedConcepts: [],
	  type: 'structure'
	};
	var _default = OutlineRole$1;
	OutlineRole.default = _default;
	return OutlineRole;
}

var ParagraphRole = {};

var hasRequiredParagraphRole;

function requireParagraphRole () {
	if (hasRequiredParagraphRole) return ParagraphRole;
	hasRequiredParagraphRole = 1;

	Object.defineProperty(ParagraphRole, "__esModule", {
	  value: true
	});
	ParagraphRole.default = void 0;
	var ParagraphRole$1 = {
	  relatedConcepts: [{
	    module: 'HTML',
	    concept: {
	      name: 'p'
	    }
	  }],
	  type: 'structure'
	};
	var _default = ParagraphRole$1;
	ParagraphRole.default = _default;
	return ParagraphRole;
}

var PopUpButtonRole = {};

var hasRequiredPopUpButtonRole;

function requirePopUpButtonRole () {
	if (hasRequiredPopUpButtonRole) return PopUpButtonRole;
	hasRequiredPopUpButtonRole = 1;

	Object.defineProperty(PopUpButtonRole, "__esModule", {
	  value: true
	});
	PopUpButtonRole.default = void 0;
	var PopUpButtonRole$1 = {
	  relatedConcepts: [],
	  type: 'widget'
	};
	var _default = PopUpButtonRole$1;
	PopUpButtonRole.default = _default;
	return PopUpButtonRole;
}

var PreRole = {};

var hasRequiredPreRole;

function requirePreRole () {
	if (hasRequiredPreRole) return PreRole;
	hasRequiredPreRole = 1;

	Object.defineProperty(PreRole, "__esModule", {
	  value: true
	});
	PreRole.default = void 0;
	var PreRole$1 = {
	  relatedConcepts: [{
	    module: 'HTML',
	    concept: {
	      name: 'pre'
	    }
	  }],
	  type: 'structure'
	};
	var _default = PreRole$1;
	PreRole.default = _default;
	return PreRole;
}

var PresentationalRole = {};

var hasRequiredPresentationalRole;

function requirePresentationalRole () {
	if (hasRequiredPresentationalRole) return PresentationalRole;
	hasRequiredPresentationalRole = 1;

	Object.defineProperty(PresentationalRole, "__esModule", {
	  value: true
	});
	PresentationalRole.default = void 0;
	var PresentationalRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'presentation'
	    }
	  }],
	  type: 'structure'
	};
	var _default = PresentationalRole$1;
	PresentationalRole.default = _default;
	return PresentationalRole;
}

var ProgressIndicatorRole = {};

var hasRequiredProgressIndicatorRole;

function requireProgressIndicatorRole () {
	if (hasRequiredProgressIndicatorRole) return ProgressIndicatorRole;
	hasRequiredProgressIndicatorRole = 1;

	Object.defineProperty(ProgressIndicatorRole, "__esModule", {
	  value: true
	});
	ProgressIndicatorRole.default = void 0;
	var ProgressIndicatorRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'progressbar'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'progress'
	    }
	  }],
	  type: 'structure'
	};
	var _default = ProgressIndicatorRole$1;
	ProgressIndicatorRole.default = _default;
	return ProgressIndicatorRole;
}

var RadioButtonRole = {};

var hasRequiredRadioButtonRole;

function requireRadioButtonRole () {
	if (hasRequiredRadioButtonRole) return RadioButtonRole;
	hasRequiredRadioButtonRole = 1;

	Object.defineProperty(RadioButtonRole, "__esModule", {
	  value: true
	});
	RadioButtonRole.default = void 0;
	var RadioButtonRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'radio'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'input',
	      attributes: [{
	        name: 'type',
	        value: 'radio'
	      }]
	    }
	  }],
	  type: 'widget'
	};
	var _default = RadioButtonRole$1;
	RadioButtonRole.default = _default;
	return RadioButtonRole;
}

var RadioGroupRole = {};

var hasRequiredRadioGroupRole;

function requireRadioGroupRole () {
	if (hasRequiredRadioGroupRole) return RadioGroupRole;
	hasRequiredRadioGroupRole = 1;

	Object.defineProperty(RadioGroupRole, "__esModule", {
	  value: true
	});
	RadioGroupRole.default = void 0;
	var RadioGroupRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'radiogroup'
	    }
	  }],
	  type: 'structure'
	};
	var _default = RadioGroupRole$1;
	RadioGroupRole.default = _default;
	return RadioGroupRole;
}

var RegionRole = {};

var hasRequiredRegionRole;

function requireRegionRole () {
	if (hasRequiredRegionRole) return RegionRole;
	hasRequiredRegionRole = 1;

	Object.defineProperty(RegionRole, "__esModule", {
	  value: true
	});
	RegionRole.default = void 0;
	var RegionRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'region'
	    }
	  }],
	  type: 'structure'
	};
	var _default = RegionRole$1;
	RegionRole.default = _default;
	return RegionRole;
}

var RootWebAreaRole = {};

var hasRequiredRootWebAreaRole;

function requireRootWebAreaRole () {
	if (hasRequiredRootWebAreaRole) return RootWebAreaRole;
	hasRequiredRootWebAreaRole = 1;

	Object.defineProperty(RootWebAreaRole, "__esModule", {
	  value: true
	});
	RootWebAreaRole.default = void 0;
	var RootWebAreaRole$1 = {
	  relatedConcepts: [],
	  type: 'structure'
	};
	var _default = RootWebAreaRole$1;
	RootWebAreaRole.default = _default;
	return RootWebAreaRole;
}

var RowHeaderRole = {};

var hasRequiredRowHeaderRole;

function requireRowHeaderRole () {
	if (hasRequiredRowHeaderRole) return RowHeaderRole;
	hasRequiredRowHeaderRole = 1;

	Object.defineProperty(RowHeaderRole, "__esModule", {
	  value: true
	});
	RowHeaderRole.default = void 0;
	var RowHeaderRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'rowheader'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'th',
	      attributes: [{
	        name: 'scope',
	        value: 'row'
	      }]
	    }
	  }],
	  type: 'widget'
	};
	var _default = RowHeaderRole$1;
	RowHeaderRole.default = _default;
	return RowHeaderRole;
}

var RowRole = {};

var hasRequiredRowRole;

function requireRowRole () {
	if (hasRequiredRowRole) return RowRole;
	hasRequiredRowRole = 1;

	Object.defineProperty(RowRole, "__esModule", {
	  value: true
	});
	RowRole.default = void 0;
	var RowRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'row'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'tr'
	    }
	  }],
	  type: 'structure'
	};
	var _default = RowRole$1;
	RowRole.default = _default;
	return RowRole;
}

var RubyRole = {};

var hasRequiredRubyRole;

function requireRubyRole () {
	if (hasRequiredRubyRole) return RubyRole;
	hasRequiredRubyRole = 1;

	Object.defineProperty(RubyRole, "__esModule", {
	  value: true
	});
	RubyRole.default = void 0;
	var RubyRole$1 = {
	  relatedConcepts: [{
	    module: 'HTML',
	    concept: {
	      name: 'ruby'
	    }
	  }],
	  type: 'structure'
	};
	var _default = RubyRole$1;
	RubyRole.default = _default;
	return RubyRole;
}

var RulerRole = {};

var hasRequiredRulerRole;

function requireRulerRole () {
	if (hasRequiredRulerRole) return RulerRole;
	hasRequiredRulerRole = 1;

	Object.defineProperty(RulerRole, "__esModule", {
	  value: true
	});
	RulerRole.default = void 0;
	var RulerRole$1 = {
	  relatedConcepts: [],
	  type: 'structure'
	};
	var _default = RulerRole$1;
	RulerRole.default = _default;
	return RulerRole;
}

var ScrollAreaRole = {};

var hasRequiredScrollAreaRole;

function requireScrollAreaRole () {
	if (hasRequiredScrollAreaRole) return ScrollAreaRole;
	hasRequiredScrollAreaRole = 1;

	Object.defineProperty(ScrollAreaRole, "__esModule", {
	  value: true
	});
	ScrollAreaRole.default = void 0;
	var ScrollAreaRole$1 = {
	  relatedConcepts: [],
	  type: 'structure'
	};
	var _default = ScrollAreaRole$1;
	ScrollAreaRole.default = _default;
	return ScrollAreaRole;
}

var ScrollBarRole = {};

var hasRequiredScrollBarRole;

function requireScrollBarRole () {
	if (hasRequiredScrollBarRole) return ScrollBarRole;
	hasRequiredScrollBarRole = 1;

	Object.defineProperty(ScrollBarRole, "__esModule", {
	  value: true
	});
	ScrollBarRole.default = void 0;
	var ScrollBarRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'scrollbar'
	    }
	  }],
	  type: 'widget'
	};
	var _default = ScrollBarRole$1;
	ScrollBarRole.default = _default;
	return ScrollBarRole;
}

var SeamlessWebAreaRole = {};

var hasRequiredSeamlessWebAreaRole;

function requireSeamlessWebAreaRole () {
	if (hasRequiredSeamlessWebAreaRole) return SeamlessWebAreaRole;
	hasRequiredSeamlessWebAreaRole = 1;

	Object.defineProperty(SeamlessWebAreaRole, "__esModule", {
	  value: true
	});
	SeamlessWebAreaRole.default = void 0;
	var SeamlessWebAreaRole$1 = {
	  relatedConcepts: [],
	  type: 'structure'
	};
	var _default = SeamlessWebAreaRole$1;
	SeamlessWebAreaRole.default = _default;
	return SeamlessWebAreaRole;
}

var SearchRole = {};

var hasRequiredSearchRole;

function requireSearchRole () {
	if (hasRequiredSearchRole) return SearchRole;
	hasRequiredSearchRole = 1;

	Object.defineProperty(SearchRole, "__esModule", {
	  value: true
	});
	SearchRole.default = void 0;
	var SearchRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'search'
	    }
	  }],
	  type: 'structure'
	};
	var _default = SearchRole$1;
	SearchRole.default = _default;
	return SearchRole;
}

var SearchBoxRole = {};

var hasRequiredSearchBoxRole;

function requireSearchBoxRole () {
	if (hasRequiredSearchBoxRole) return SearchBoxRole;
	hasRequiredSearchBoxRole = 1;

	Object.defineProperty(SearchBoxRole, "__esModule", {
	  value: true
	});
	SearchBoxRole.default = void 0;
	var SearchBoxRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'searchbox'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'input',
	      attributes: [{
	        name: 'type',
	        value: 'search'
	      }]
	    }
	  }],
	  type: 'widget'
	};
	var _default = SearchBoxRole$1;
	SearchBoxRole.default = _default;
	return SearchBoxRole;
}

var SliderRole = {};

var hasRequiredSliderRole;

function requireSliderRole () {
	if (hasRequiredSliderRole) return SliderRole;
	hasRequiredSliderRole = 1;

	Object.defineProperty(SliderRole, "__esModule", {
	  value: true
	});
	SliderRole.default = void 0;
	var SliderRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'slider'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'input',
	      attributes: [{
	        name: 'type',
	        value: 'range'
	      }]
	    }
	  }],
	  type: 'widget'
	};
	var _default = SliderRole$1;
	SliderRole.default = _default;
	return SliderRole;
}

var SliderThumbRole = {};

var hasRequiredSliderThumbRole;

function requireSliderThumbRole () {
	if (hasRequiredSliderThumbRole) return SliderThumbRole;
	hasRequiredSliderThumbRole = 1;

	Object.defineProperty(SliderThumbRole, "__esModule", {
	  value: true
	});
	SliderThumbRole.default = void 0;
	var SliderThumbRole$1 = {
	  relatedConcepts: [],
	  type: 'structure'
	};
	var _default = SliderThumbRole$1;
	SliderThumbRole.default = _default;
	return SliderThumbRole;
}

var SpinButtonRole = {};

var hasRequiredSpinButtonRole;

function requireSpinButtonRole () {
	if (hasRequiredSpinButtonRole) return SpinButtonRole;
	hasRequiredSpinButtonRole = 1;

	Object.defineProperty(SpinButtonRole, "__esModule", {
	  value: true
	});
	SpinButtonRole.default = void 0;
	var SpinButtonRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'spinbutton'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'input',
	      attributes: [{
	        name: 'type',
	        value: 'number'
	      }]
	    }
	  }],
	  type: 'widget'
	};
	var _default = SpinButtonRole$1;
	SpinButtonRole.default = _default;
	return SpinButtonRole;
}

var SpinButtonPartRole = {};

var hasRequiredSpinButtonPartRole;

function requireSpinButtonPartRole () {
	if (hasRequiredSpinButtonPartRole) return SpinButtonPartRole;
	hasRequiredSpinButtonPartRole = 1;

	Object.defineProperty(SpinButtonPartRole, "__esModule", {
	  value: true
	});
	SpinButtonPartRole.default = void 0;
	var SpinButtonPartRole$1 = {
	  relatedConcepts: [],
	  type: 'structure'
	};
	var _default = SpinButtonPartRole$1;
	SpinButtonPartRole.default = _default;
	return SpinButtonPartRole;
}

var SplitterRole = {};

var hasRequiredSplitterRole;

function requireSplitterRole () {
	if (hasRequiredSplitterRole) return SplitterRole;
	hasRequiredSplitterRole = 1;

	Object.defineProperty(SplitterRole, "__esModule", {
	  value: true
	});
	SplitterRole.default = void 0;
	var SplitterRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'separator'
	    }
	  }],
	  type: 'widget'
	};
	var _default = SplitterRole$1;
	SplitterRole.default = _default;
	return SplitterRole;
}

var StaticTextRole = {};

var hasRequiredStaticTextRole;

function requireStaticTextRole () {
	if (hasRequiredStaticTextRole) return StaticTextRole;
	hasRequiredStaticTextRole = 1;

	Object.defineProperty(StaticTextRole, "__esModule", {
	  value: true
	});
	StaticTextRole.default = void 0;
	var StaticTextRole$1 = {
	  relatedConcepts: [],
	  type: 'structure'
	};
	var _default = StaticTextRole$1;
	StaticTextRole.default = _default;
	return StaticTextRole;
}

var StatusRole = {};

var hasRequiredStatusRole;

function requireStatusRole () {
	if (hasRequiredStatusRole) return StatusRole;
	hasRequiredStatusRole = 1;

	Object.defineProperty(StatusRole, "__esModule", {
	  value: true
	});
	StatusRole.default = void 0;
	var StatusRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'status'
	    }
	  }],
	  type: 'structure'
	};
	var _default = StatusRole$1;
	StatusRole.default = _default;
	return StatusRole;
}

var SVGRootRole = {};

var hasRequiredSVGRootRole;

function requireSVGRootRole () {
	if (hasRequiredSVGRootRole) return SVGRootRole;
	hasRequiredSVGRootRole = 1;

	Object.defineProperty(SVGRootRole, "__esModule", {
	  value: true
	});
	SVGRootRole.default = void 0;
	var SVGRootRole$1 = {
	  relatedConcepts: [],
	  type: 'structure'
	};
	var _default = SVGRootRole$1;
	SVGRootRole.default = _default;
	return SVGRootRole;
}

var SwitchRole = {};

var hasRequiredSwitchRole;

function requireSwitchRole () {
	if (hasRequiredSwitchRole) return SwitchRole;
	hasRequiredSwitchRole = 1;

	Object.defineProperty(SwitchRole, "__esModule", {
	  value: true
	});
	SwitchRole.default = void 0;
	var SwitchRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'switch'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'input',
	      attributes: [{
	        name: 'type',
	        value: 'checkbox'
	      }]
	    }
	  }],
	  type: 'widget'
	};
	var _default = SwitchRole$1;
	SwitchRole.default = _default;
	return SwitchRole;
}

var TabGroupRole = {};

var hasRequiredTabGroupRole;

function requireTabGroupRole () {
	if (hasRequiredTabGroupRole) return TabGroupRole;
	hasRequiredTabGroupRole = 1;

	Object.defineProperty(TabGroupRole, "__esModule", {
	  value: true
	});
	TabGroupRole.default = void 0;
	var TabGroupRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'tablist'
	    }
	  }],
	  type: 'structure'
	};
	var _default = TabGroupRole$1;
	TabGroupRole.default = _default;
	return TabGroupRole;
}

var TabRole = {};

var hasRequiredTabRole;

function requireTabRole () {
	if (hasRequiredTabRole) return TabRole;
	hasRequiredTabRole = 1;

	Object.defineProperty(TabRole, "__esModule", {
	  value: true
	});
	TabRole.default = void 0;
	var TabRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'tab'
	    }
	  }],
	  type: 'widget'
	};
	var _default = TabRole$1;
	TabRole.default = _default;
	return TabRole;
}

var TableHeaderContainerRole = {};

var hasRequiredTableHeaderContainerRole;

function requireTableHeaderContainerRole () {
	if (hasRequiredTableHeaderContainerRole) return TableHeaderContainerRole;
	hasRequiredTableHeaderContainerRole = 1;

	Object.defineProperty(TableHeaderContainerRole, "__esModule", {
	  value: true
	});
	TableHeaderContainerRole.default = void 0;
	var TableHeaderContainerRole$1 = {
	  relatedConcepts: [],
	  type: 'structure'
	};
	var _default = TableHeaderContainerRole$1;
	TableHeaderContainerRole.default = _default;
	return TableHeaderContainerRole;
}

var TableRole = {};

var hasRequiredTableRole;

function requireTableRole () {
	if (hasRequiredTableRole) return TableRole;
	hasRequiredTableRole = 1;

	Object.defineProperty(TableRole, "__esModule", {
	  value: true
	});
	TableRole.default = void 0;
	var TableRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'table'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'table'
	    }
	  }],
	  type: 'structure'
	};
	var _default = TableRole$1;
	TableRole.default = _default;
	return TableRole;
}

var TabListRole = {};

var hasRequiredTabListRole;

function requireTabListRole () {
	if (hasRequiredTabListRole) return TabListRole;
	hasRequiredTabListRole = 1;

	Object.defineProperty(TabListRole, "__esModule", {
	  value: true
	});
	TabListRole.default = void 0;
	var TabListRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'tablist'
	    }
	  }],
	  type: 'structure'
	};
	var _default = TabListRole$1;
	TabListRole.default = _default;
	return TabListRole;
}

var TabPanelRole = {};

var hasRequiredTabPanelRole;

function requireTabPanelRole () {
	if (hasRequiredTabPanelRole) return TabPanelRole;
	hasRequiredTabPanelRole = 1;

	Object.defineProperty(TabPanelRole, "__esModule", {
	  value: true
	});
	TabPanelRole.default = void 0;
	var TabPanelRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'tabpanel'
	    }
	  }],
	  type: 'structure'
	};
	var _default = TabPanelRole$1;
	TabPanelRole.default = _default;
	return TabPanelRole;
}

var TermRole = {};

var hasRequiredTermRole;

function requireTermRole () {
	if (hasRequiredTermRole) return TermRole;
	hasRequiredTermRole = 1;

	Object.defineProperty(TermRole, "__esModule", {
	  value: true
	});
	TermRole.default = void 0;
	var TermRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'term'
	    }
	  }],
	  type: 'structure'
	};
	var _default = TermRole$1;
	TermRole.default = _default;
	return TermRole;
}

var TextAreaRole = {};

var hasRequiredTextAreaRole;

function requireTextAreaRole () {
	if (hasRequiredTextAreaRole) return TextAreaRole;
	hasRequiredTextAreaRole = 1;

	Object.defineProperty(TextAreaRole, "__esModule", {
	  value: true
	});
	TextAreaRole.default = void 0;
	var TextAreaRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      attributes: [{
	        name: 'aria-multiline',
	        value: 'true'
	      }],
	      name: 'textbox'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'textarea'
	    }
	  }],
	  type: 'widget'
	};
	var _default = TextAreaRole$1;
	TextAreaRole.default = _default;
	return TextAreaRole;
}

var TextFieldRole = {};

var hasRequiredTextFieldRole;

function requireTextFieldRole () {
	if (hasRequiredTextFieldRole) return TextFieldRole;
	hasRequiredTextFieldRole = 1;

	Object.defineProperty(TextFieldRole, "__esModule", {
	  value: true
	});
	TextFieldRole.default = void 0;
	var TextFieldRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'textbox'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'input'
	    }
	  }, {
	    module: 'HTML',
	    concept: {
	      name: 'input',
	      attributes: [{
	        name: 'type',
	        value: 'text'
	      }]
	    }
	  }],
	  type: 'widget'
	};
	var _default = TextFieldRole$1;
	TextFieldRole.default = _default;
	return TextFieldRole;
}

var TimeRole = {};

var hasRequiredTimeRole;

function requireTimeRole () {
	if (hasRequiredTimeRole) return TimeRole;
	hasRequiredTimeRole = 1;

	Object.defineProperty(TimeRole, "__esModule", {
	  value: true
	});
	TimeRole.default = void 0;
	var TimeRole$1 = {
	  relatedConcepts: [{
	    module: 'HTML',
	    concept: {
	      name: 'time'
	    }
	  }],
	  type: 'structure'
	};
	var _default = TimeRole$1;
	TimeRole.default = _default;
	return TimeRole;
}

var TimerRole = {};

var hasRequiredTimerRole;

function requireTimerRole () {
	if (hasRequiredTimerRole) return TimerRole;
	hasRequiredTimerRole = 1;

	Object.defineProperty(TimerRole, "__esModule", {
	  value: true
	});
	TimerRole.default = void 0;
	var TimerRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'timer'
	    }
	  }],
	  type: 'structure'
	};
	var _default = TimerRole$1;
	TimerRole.default = _default;
	return TimerRole;
}

var ToggleButtonRole = {};

var hasRequiredToggleButtonRole;

function requireToggleButtonRole () {
	if (hasRequiredToggleButtonRole) return ToggleButtonRole;
	hasRequiredToggleButtonRole = 1;

	Object.defineProperty(ToggleButtonRole, "__esModule", {
	  value: true
	});
	ToggleButtonRole.default = void 0;
	var ToggleButtonRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      attributes: [{
	        name: 'aria-pressed'
	      }]
	    }
	  }],
	  type: 'widget'
	};
	var _default = ToggleButtonRole$1;
	ToggleButtonRole.default = _default;
	return ToggleButtonRole;
}

var ToolbarRole = {};

var hasRequiredToolbarRole;

function requireToolbarRole () {
	if (hasRequiredToolbarRole) return ToolbarRole;
	hasRequiredToolbarRole = 1;

	Object.defineProperty(ToolbarRole, "__esModule", {
	  value: true
	});
	ToolbarRole.default = void 0;
	var ToolbarRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'toolbar'
	    }
	  }],
	  type: 'structure'
	};
	var _default = ToolbarRole$1;
	ToolbarRole.default = _default;
	return ToolbarRole;
}

var TreeRole = {};

var hasRequiredTreeRole;

function requireTreeRole () {
	if (hasRequiredTreeRole) return TreeRole;
	hasRequiredTreeRole = 1;

	Object.defineProperty(TreeRole, "__esModule", {
	  value: true
	});
	TreeRole.default = void 0;
	var TreeRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'tree'
	    }
	  }],
	  type: 'widget'
	};
	var _default = TreeRole$1;
	TreeRole.default = _default;
	return TreeRole;
}

var TreeGridRole = {};

var hasRequiredTreeGridRole;

function requireTreeGridRole () {
	if (hasRequiredTreeGridRole) return TreeGridRole;
	hasRequiredTreeGridRole = 1;

	Object.defineProperty(TreeGridRole, "__esModule", {
	  value: true
	});
	TreeGridRole.default = void 0;
	var TreeGridRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'treegrid'
	    }
	  }],
	  type: 'widget'
	};
	var _default = TreeGridRole$1;
	TreeGridRole.default = _default;
	return TreeGridRole;
}

var TreeItemRole = {};

var hasRequiredTreeItemRole;

function requireTreeItemRole () {
	if (hasRequiredTreeItemRole) return TreeItemRole;
	hasRequiredTreeItemRole = 1;

	Object.defineProperty(TreeItemRole, "__esModule", {
	  value: true
	});
	TreeItemRole.default = void 0;
	var TreeItemRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'treeitem'
	    }
	  }],
	  type: 'widget'
	};
	var _default = TreeItemRole$1;
	TreeItemRole.default = _default;
	return TreeItemRole;
}

var UserInterfaceTooltipRole = {};

var hasRequiredUserInterfaceTooltipRole;

function requireUserInterfaceTooltipRole () {
	if (hasRequiredUserInterfaceTooltipRole) return UserInterfaceTooltipRole;
	hasRequiredUserInterfaceTooltipRole = 1;

	Object.defineProperty(UserInterfaceTooltipRole, "__esModule", {
	  value: true
	});
	UserInterfaceTooltipRole.default = void 0;
	var UserInterfaceTooltipRole$1 = {
	  relatedConcepts: [{
	    module: 'ARIA',
	    concept: {
	      name: 'tooltip'
	    }
	  }],
	  type: 'structure'
	};
	var _default = UserInterfaceTooltipRole$1;
	UserInterfaceTooltipRole.default = _default;
	return UserInterfaceTooltipRole;
}

var VideoRole = {};

var hasRequiredVideoRole;

function requireVideoRole () {
	if (hasRequiredVideoRole) return VideoRole;
	hasRequiredVideoRole = 1;

	Object.defineProperty(VideoRole, "__esModule", {
	  value: true
	});
	VideoRole.default = void 0;
	var VideoRole$1 = {
	  relatedConcepts: [{
	    module: 'HTML',
	    concept: {
	      name: 'video'
	    }
	  }],
	  type: 'widget'
	};
	var _default = VideoRole$1;
	VideoRole.default = _default;
	return VideoRole;
}

var WebAreaRole = {};

var hasRequiredWebAreaRole;

function requireWebAreaRole () {
	if (hasRequiredWebAreaRole) return WebAreaRole;
	hasRequiredWebAreaRole = 1;

	Object.defineProperty(WebAreaRole, "__esModule", {
	  value: true
	});
	WebAreaRole.default = void 0;
	var WebAreaRole$1 = {
	  relatedConcepts: [],
	  type: 'structure'
	};
	var _default = WebAreaRole$1;
	WebAreaRole.default = _default;
	return WebAreaRole;
}

var WindowRole = {};

var hasRequiredWindowRole;

function requireWindowRole () {
	if (hasRequiredWindowRole) return WindowRole;
	hasRequiredWindowRole = 1;

	Object.defineProperty(WindowRole, "__esModule", {
	  value: true
	});
	WindowRole.default = void 0;
	var WindowRole$1 = {
	  relatedConcepts: [],
	  type: 'window'
	};
	var _default = WindowRole$1;
	WindowRole.default = _default;
	return WindowRole;
}

var hasRequiredAXObjectsMap;

function requireAXObjectsMap () {
	if (hasRequiredAXObjectsMap) return AXObjectsMap;
	hasRequiredAXObjectsMap = 1;

	Object.defineProperty(AXObjectsMap, "__esModule", {
	  value: true
	});
	AXObjectsMap.default = void 0;
	var _iterationDecorator = _interopRequireDefault(requireIterationDecorator());
	var _AbbrRole = _interopRequireDefault(requireAbbrRole());
	var _AlertDialogRole = _interopRequireDefault(requireAlertDialogRole());
	var _AlertRole = _interopRequireDefault(requireAlertRole());
	var _AnnotationRole = _interopRequireDefault(requireAnnotationRole());
	var _ApplicationRole = _interopRequireDefault(requireApplicationRole());
	var _ArticleRole = _interopRequireDefault(requireArticleRole());
	var _AudioRole = _interopRequireDefault(requireAudioRole());
	var _BannerRole = _interopRequireDefault(requireBannerRole());
	var _BlockquoteRole = _interopRequireDefault(requireBlockquoteRole());
	var _BusyIndicatorRole = _interopRequireDefault(requireBusyIndicatorRole());
	var _ButtonRole = _interopRequireDefault(requireButtonRole());
	var _CanvasRole = _interopRequireDefault(requireCanvasRole());
	var _CaptionRole = _interopRequireDefault(requireCaptionRole());
	var _CellRole = _interopRequireDefault(requireCellRole());
	var _CheckBoxRole = _interopRequireDefault(requireCheckBoxRole());
	var _ColorWellRole = _interopRequireDefault(requireColorWellRole());
	var _ColumnHeaderRole = _interopRequireDefault(requireColumnHeaderRole());
	var _ColumnRole = _interopRequireDefault(requireColumnRole());
	var _ComboBoxRole = _interopRequireDefault(requireComboBoxRole());
	var _ComplementaryRole = _interopRequireDefault(requireComplementaryRole());
	var _ContentInfoRole = _interopRequireDefault(requireContentInfoRole());
	var _DateRole = _interopRequireDefault(requireDateRole());
	var _DateTimeRole = _interopRequireDefault(requireDateTimeRole());
	var _DefinitionRole = _interopRequireDefault(requireDefinitionRole());
	var _DescriptionListDetailRole = _interopRequireDefault(requireDescriptionListDetailRole());
	var _DescriptionListRole = _interopRequireDefault(requireDescriptionListRole());
	var _DescriptionListTermRole = _interopRequireDefault(requireDescriptionListTermRole());
	var _DetailsRole = _interopRequireDefault(requireDetailsRole());
	var _DialogRole = _interopRequireDefault(requireDialogRole());
	var _DirectoryRole = _interopRequireDefault(requireDirectoryRole());
	var _DisclosureTriangleRole = _interopRequireDefault(requireDisclosureTriangleRole());
	var _DivRole = _interopRequireDefault(requireDivRole());
	var _DocumentRole = _interopRequireDefault(requireDocumentRole());
	var _EmbeddedObjectRole = _interopRequireDefault(requireEmbeddedObjectRole());
	var _FeedRole = _interopRequireDefault(requireFeedRole());
	var _FigcaptionRole = _interopRequireDefault(requireFigcaptionRole());
	var _FigureRole = _interopRequireDefault(requireFigureRole());
	var _FooterRole = _interopRequireDefault(requireFooterRole());
	var _FormRole = _interopRequireDefault(requireFormRole());
	var _GridRole = _interopRequireDefault(requireGridRole());
	var _GroupRole = _interopRequireDefault(requireGroupRole());
	var _HeadingRole = _interopRequireDefault(requireHeadingRole());
	var _IframePresentationalRole = _interopRequireDefault(requireIframePresentationalRole());
	var _IframeRole = _interopRequireDefault(requireIframeRole());
	var _IgnoredRole = _interopRequireDefault(requireIgnoredRole());
	var _ImageMapLinkRole = _interopRequireDefault(requireImageMapLinkRole());
	var _ImageMapRole = _interopRequireDefault(requireImageMapRole());
	var _ImageRole = _interopRequireDefault(requireImageRole());
	var _InlineTextBoxRole = _interopRequireDefault(requireInlineTextBoxRole());
	var _InputTimeRole = _interopRequireDefault(requireInputTimeRole());
	var _LabelRole = _interopRequireDefault(requireLabelRole());
	var _LegendRole = _interopRequireDefault(requireLegendRole());
	var _LineBreakRole = _interopRequireDefault(requireLineBreakRole());
	var _LinkRole = _interopRequireDefault(requireLinkRole());
	var _ListBoxOptionRole = _interopRequireDefault(requireListBoxOptionRole());
	var _ListBoxRole = _interopRequireDefault(requireListBoxRole());
	var _ListItemRole = _interopRequireDefault(requireListItemRole());
	var _ListMarkerRole = _interopRequireDefault(requireListMarkerRole());
	var _ListRole = _interopRequireDefault(requireListRole());
	var _LogRole = _interopRequireDefault(requireLogRole());
	var _MainRole = _interopRequireDefault(requireMainRole());
	var _MarkRole = _interopRequireDefault(requireMarkRole());
	var _MarqueeRole = _interopRequireDefault(requireMarqueeRole());
	var _MathRole = _interopRequireDefault(requireMathRole());
	var _MenuBarRole = _interopRequireDefault(requireMenuBarRole());
	var _MenuButtonRole = _interopRequireDefault(requireMenuButtonRole());
	var _MenuItemRole = _interopRequireDefault(requireMenuItemRole());
	var _MenuItemCheckBoxRole = _interopRequireDefault(requireMenuItemCheckBoxRole());
	var _MenuItemRadioRole = _interopRequireDefault(requireMenuItemRadioRole());
	var _MenuListOptionRole = _interopRequireDefault(requireMenuListOptionRole());
	var _MenuListPopupRole = _interopRequireDefault(requireMenuListPopupRole());
	var _MenuRole = _interopRequireDefault(requireMenuRole());
	var _MeterRole = _interopRequireDefault(requireMeterRole());
	var _NavigationRole = _interopRequireDefault(requireNavigationRole());
	var _NoneRole = _interopRequireDefault(requireNoneRole());
	var _NoteRole = _interopRequireDefault(requireNoteRole());
	var _OutlineRole = _interopRequireDefault(requireOutlineRole());
	var _ParagraphRole = _interopRequireDefault(requireParagraphRole());
	var _PopUpButtonRole = _interopRequireDefault(requirePopUpButtonRole());
	var _PreRole = _interopRequireDefault(requirePreRole());
	var _PresentationalRole = _interopRequireDefault(requirePresentationalRole());
	var _ProgressIndicatorRole = _interopRequireDefault(requireProgressIndicatorRole());
	var _RadioButtonRole = _interopRequireDefault(requireRadioButtonRole());
	var _RadioGroupRole = _interopRequireDefault(requireRadioGroupRole());
	var _RegionRole = _interopRequireDefault(requireRegionRole());
	var _RootWebAreaRole = _interopRequireDefault(requireRootWebAreaRole());
	var _RowHeaderRole = _interopRequireDefault(requireRowHeaderRole());
	var _RowRole = _interopRequireDefault(requireRowRole());
	var _RubyRole = _interopRequireDefault(requireRubyRole());
	var _RulerRole = _interopRequireDefault(requireRulerRole());
	var _ScrollAreaRole = _interopRequireDefault(requireScrollAreaRole());
	var _ScrollBarRole = _interopRequireDefault(requireScrollBarRole());
	var _SeamlessWebAreaRole = _interopRequireDefault(requireSeamlessWebAreaRole());
	var _SearchRole = _interopRequireDefault(requireSearchRole());
	var _SearchBoxRole = _interopRequireDefault(requireSearchBoxRole());
	var _SliderRole = _interopRequireDefault(requireSliderRole());
	var _SliderThumbRole = _interopRequireDefault(requireSliderThumbRole());
	var _SpinButtonRole = _interopRequireDefault(requireSpinButtonRole());
	var _SpinButtonPartRole = _interopRequireDefault(requireSpinButtonPartRole());
	var _SplitterRole = _interopRequireDefault(requireSplitterRole());
	var _StaticTextRole = _interopRequireDefault(requireStaticTextRole());
	var _StatusRole = _interopRequireDefault(requireStatusRole());
	var _SVGRootRole = _interopRequireDefault(requireSVGRootRole());
	var _SwitchRole = _interopRequireDefault(requireSwitchRole());
	var _TabGroupRole = _interopRequireDefault(requireTabGroupRole());
	var _TabRole = _interopRequireDefault(requireTabRole());
	var _TableHeaderContainerRole = _interopRequireDefault(requireTableHeaderContainerRole());
	var _TableRole = _interopRequireDefault(requireTableRole());
	var _TabListRole = _interopRequireDefault(requireTabListRole());
	var _TabPanelRole = _interopRequireDefault(requireTabPanelRole());
	var _TermRole = _interopRequireDefault(requireTermRole());
	var _TextAreaRole = _interopRequireDefault(requireTextAreaRole());
	var _TextFieldRole = _interopRequireDefault(requireTextFieldRole());
	var _TimeRole = _interopRequireDefault(requireTimeRole());
	var _TimerRole = _interopRequireDefault(requireTimerRole());
	var _ToggleButtonRole = _interopRequireDefault(requireToggleButtonRole());
	var _ToolbarRole = _interopRequireDefault(requireToolbarRole());
	var _TreeRole = _interopRequireDefault(requireTreeRole());
	var _TreeGridRole = _interopRequireDefault(requireTreeGridRole());
	var _TreeItemRole = _interopRequireDefault(requireTreeItemRole());
	var _UserInterfaceTooltipRole = _interopRequireDefault(requireUserInterfaceTooltipRole());
	var _VideoRole = _interopRequireDefault(requireVideoRole());
	var _WebAreaRole = _interopRequireDefault(requireWebAreaRole());
	var _WindowRole = _interopRequireDefault(requireWindowRole());
	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
	function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
	function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
	function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
	function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
	function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
	function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
	var AXObjects = [['AbbrRole', _AbbrRole.default], ['AlertDialogRole', _AlertDialogRole.default], ['AlertRole', _AlertRole.default], ['AnnotationRole', _AnnotationRole.default], ['ApplicationRole', _ApplicationRole.default], ['ArticleRole', _ArticleRole.default], ['AudioRole', _AudioRole.default], ['BannerRole', _BannerRole.default], ['BlockquoteRole', _BlockquoteRole.default], ['BusyIndicatorRole', _BusyIndicatorRole.default], ['ButtonRole', _ButtonRole.default], ['CanvasRole', _CanvasRole.default], ['CaptionRole', _CaptionRole.default], ['CellRole', _CellRole.default], ['CheckBoxRole', _CheckBoxRole.default], ['ColorWellRole', _ColorWellRole.default], ['ColumnHeaderRole', _ColumnHeaderRole.default], ['ColumnRole', _ColumnRole.default], ['ComboBoxRole', _ComboBoxRole.default], ['ComplementaryRole', _ComplementaryRole.default], ['ContentInfoRole', _ContentInfoRole.default], ['DateRole', _DateRole.default], ['DateTimeRole', _DateTimeRole.default], ['DefinitionRole', _DefinitionRole.default], ['DescriptionListDetailRole', _DescriptionListDetailRole.default], ['DescriptionListRole', _DescriptionListRole.default], ['DescriptionListTermRole', _DescriptionListTermRole.default], ['DetailsRole', _DetailsRole.default], ['DialogRole', _DialogRole.default], ['DirectoryRole', _DirectoryRole.default], ['DisclosureTriangleRole', _DisclosureTriangleRole.default], ['DivRole', _DivRole.default], ['DocumentRole', _DocumentRole.default], ['EmbeddedObjectRole', _EmbeddedObjectRole.default], ['FeedRole', _FeedRole.default], ['FigcaptionRole', _FigcaptionRole.default], ['FigureRole', _FigureRole.default], ['FooterRole', _FooterRole.default], ['FormRole', _FormRole.default], ['GridRole', _GridRole.default], ['GroupRole', _GroupRole.default], ['HeadingRole', _HeadingRole.default], ['IframePresentationalRole', _IframePresentationalRole.default], ['IframeRole', _IframeRole.default], ['IgnoredRole', _IgnoredRole.default], ['ImageMapLinkRole', _ImageMapLinkRole.default], ['ImageMapRole', _ImageMapRole.default], ['ImageRole', _ImageRole.default], ['InlineTextBoxRole', _InlineTextBoxRole.default], ['InputTimeRole', _InputTimeRole.default], ['LabelRole', _LabelRole.default], ['LegendRole', _LegendRole.default], ['LineBreakRole', _LineBreakRole.default], ['LinkRole', _LinkRole.default], ['ListBoxOptionRole', _ListBoxOptionRole.default], ['ListBoxRole', _ListBoxRole.default], ['ListItemRole', _ListItemRole.default], ['ListMarkerRole', _ListMarkerRole.default], ['ListRole', _ListRole.default], ['LogRole', _LogRole.default], ['MainRole', _MainRole.default], ['MarkRole', _MarkRole.default], ['MarqueeRole', _MarqueeRole.default], ['MathRole', _MathRole.default], ['MenuBarRole', _MenuBarRole.default], ['MenuButtonRole', _MenuButtonRole.default], ['MenuItemRole', _MenuItemRole.default], ['MenuItemCheckBoxRole', _MenuItemCheckBoxRole.default], ['MenuItemRadioRole', _MenuItemRadioRole.default], ['MenuListOptionRole', _MenuListOptionRole.default], ['MenuListPopupRole', _MenuListPopupRole.default], ['MenuRole', _MenuRole.default], ['MeterRole', _MeterRole.default], ['NavigationRole', _NavigationRole.default], ['NoneRole', _NoneRole.default], ['NoteRole', _NoteRole.default], ['OutlineRole', _OutlineRole.default], ['ParagraphRole', _ParagraphRole.default], ['PopUpButtonRole', _PopUpButtonRole.default], ['PreRole', _PreRole.default], ['PresentationalRole', _PresentationalRole.default], ['ProgressIndicatorRole', _ProgressIndicatorRole.default], ['RadioButtonRole', _RadioButtonRole.default], ['RadioGroupRole', _RadioGroupRole.default], ['RegionRole', _RegionRole.default], ['RootWebAreaRole', _RootWebAreaRole.default], ['RowHeaderRole', _RowHeaderRole.default], ['RowRole', _RowRole.default], ['RubyRole', _RubyRole.default], ['RulerRole', _RulerRole.default], ['ScrollAreaRole', _ScrollAreaRole.default], ['ScrollBarRole', _ScrollBarRole.default], ['SeamlessWebAreaRole', _SeamlessWebAreaRole.default], ['SearchRole', _SearchRole.default], ['SearchBoxRole', _SearchBoxRole.default], ['SliderRole', _SliderRole.default], ['SliderThumbRole', _SliderThumbRole.default], ['SpinButtonRole', _SpinButtonRole.default], ['SpinButtonPartRole', _SpinButtonPartRole.default], ['SplitterRole', _SplitterRole.default], ['StaticTextRole', _StaticTextRole.default], ['StatusRole', _StatusRole.default], ['SVGRootRole', _SVGRootRole.default], ['SwitchRole', _SwitchRole.default], ['TabGroupRole', _TabGroupRole.default], ['TabRole', _TabRole.default], ['TableHeaderContainerRole', _TableHeaderContainerRole.default], ['TableRole', _TableRole.default], ['TabListRole', _TabListRole.default], ['TabPanelRole', _TabPanelRole.default], ['TermRole', _TermRole.default], ['TextAreaRole', _TextAreaRole.default], ['TextFieldRole', _TextFieldRole.default], ['TimeRole', _TimeRole.default], ['TimerRole', _TimerRole.default], ['ToggleButtonRole', _ToggleButtonRole.default], ['ToolbarRole', _ToolbarRole.default], ['TreeRole', _TreeRole.default], ['TreeGridRole', _TreeGridRole.default], ['TreeItemRole', _TreeItemRole.default], ['UserInterfaceTooltipRole', _UserInterfaceTooltipRole.default], ['VideoRole', _VideoRole.default], ['WebAreaRole', _WebAreaRole.default], ['WindowRole', _WindowRole.default]];
	var AXObjectsMap$1 = {
	  entries: function entries() {
	    return AXObjects;
	  },
	  forEach: function forEach(fn) {
	    var thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
	    for (var _i = 0, _AXObjects = AXObjects; _i < _AXObjects.length; _i++) {
	      var _AXObjects$_i = _slicedToArray(_AXObjects[_i], 2),
	        key = _AXObjects$_i[0],
	        values = _AXObjects$_i[1];
	      fn.call(thisArg, values, key, AXObjects);
	    }
	  },
	  get: function get(key) {
	    var item = AXObjects.find(function (tuple) {
	      return tuple[0] === key ? true : false;
	    });
	    return item && item[1];
	  },
	  has: function has(key) {
	    return !!AXObjectsMap$1.get(key);
	  },
	  keys: function keys() {
	    return AXObjects.map(function (_ref) {
	      var _ref2 = _slicedToArray(_ref, 1),
	        key = _ref2[0];
	      return key;
	    });
	  },
	  values: function values() {
	    return AXObjects.map(function (_ref3) {
	      var _ref4 = _slicedToArray(_ref3, 2),
	        values = _ref4[1];
	      return values;
	    });
	  }
	};
	var _default = (0, _iterationDecorator.default)(AXObjectsMap$1, AXObjectsMap$1.entries());
	AXObjectsMap.default = _default;
	return AXObjectsMap;
}

var hasRequiredAXObjectElementMap;

function requireAXObjectElementMap () {
	if (hasRequiredAXObjectElementMap) return AXObjectElementMap;
	hasRequiredAXObjectElementMap = 1;

	Object.defineProperty(AXObjectElementMap, "__esModule", {
	  value: true
	});
	AXObjectElementMap.default = void 0;
	var _iterationDecorator = _interopRequireDefault(requireIterationDecorator());
	var _AXObjectsMap = _interopRequireDefault(requireAXObjectsMap());
	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
	function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
	function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
	function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
	function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
	function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike) { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e2) { throw _e2; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e3) { didErr = true; err = _e3; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
	function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
	function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
	var AXObjectElements = [];
	var _iterator = _createForOfIteratorHelper(_AXObjectsMap.default.entries()),
	  _step;
	try {
	  var _loop = function _loop() {
	    var _step$value = _slicedToArray(_step.value, 2),
	      name = _step$value[0],
	      def = _step$value[1];
	    var relatedConcepts = def.relatedConcepts;
	    if (Array.isArray(relatedConcepts)) {
	      relatedConcepts.forEach(function (relation) {
	        if (relation.module === 'HTML') {
	          var concept = relation.concept;
	          if (concept) {
	            var index = AXObjectElements.findIndex(function (_ref5) {
	              var _ref6 = _slicedToArray(_ref5, 1),
	                key = _ref6[0];
	              return key === name;
	            });
	            if (index === -1) {
	              AXObjectElements.push([name, []]);
	              index = AXObjectElements.length - 1;
	            }
	            AXObjectElements[index][1].push(concept);
	          }
	        }
	      });
	    }
	  };
	  for (_iterator.s(); !(_step = _iterator.n()).done;) {
	    _loop();
	  }
	} catch (err) {
	  _iterator.e(err);
	} finally {
	  _iterator.f();
	}
	var AXObjectElementMap$1 = {
	  entries: function entries() {
	    return AXObjectElements;
	  },
	  forEach: function forEach(fn) {
	    var thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
	    for (var _i = 0, _AXObjectElements = AXObjectElements; _i < _AXObjectElements.length; _i++) {
	      var _AXObjectElements$_i = _slicedToArray(_AXObjectElements[_i], 2),
	        key = _AXObjectElements$_i[0],
	        values = _AXObjectElements$_i[1];
	      fn.call(thisArg, values, key, AXObjectElements);
	    }
	  },
	  get: function get(key) {
	    var item = AXObjectElements.find(function (tuple) {
	      return tuple[0] === key ? true : false;
	    });
	    return item && item[1];
	  },
	  has: function has(key) {
	    return !!AXObjectElementMap$1.get(key);
	  },
	  keys: function keys() {
	    return AXObjectElements.map(function (_ref) {
	      var _ref2 = _slicedToArray(_ref, 1),
	        key = _ref2[0];
	      return key;
	    });
	  },
	  values: function values() {
	    return AXObjectElements.map(function (_ref3) {
	      var _ref4 = _slicedToArray(_ref3, 2),
	        values = _ref4[1];
	      return values;
	    });
	  }
	};
	var _default = (0, _iterationDecorator.default)(AXObjectElementMap$1, AXObjectElementMap$1.entries());
	AXObjectElementMap.default = _default;
	return AXObjectElementMap;
}

var AXObjectRoleMap = {};

var hasRequiredAXObjectRoleMap;

function requireAXObjectRoleMap () {
	if (hasRequiredAXObjectRoleMap) return AXObjectRoleMap;
	hasRequiredAXObjectRoleMap = 1;

	Object.defineProperty(AXObjectRoleMap, "__esModule", {
	  value: true
	});
	AXObjectRoleMap.default = void 0;
	var _iterationDecorator = _interopRequireDefault(requireIterationDecorator());
	var _AXObjectsMap = _interopRequireDefault(requireAXObjectsMap());
	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
	function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
	function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
	function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
	function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
	function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike) { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e2) { throw _e2; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e3) { didErr = true; err = _e3; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
	function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
	function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
	var AXObjectRoleElements = [];
	var _iterator = _createForOfIteratorHelper(_AXObjectsMap.default.entries()),
	  _step;
	try {
	  var _loop = function _loop() {
	    var _step$value = _slicedToArray(_step.value, 2),
	      name = _step$value[0],
	      def = _step$value[1];
	    var relatedConcepts = def.relatedConcepts;
	    if (Array.isArray(relatedConcepts)) {
	      relatedConcepts.forEach(function (relation) {
	        if (relation.module === 'ARIA') {
	          var concept = relation.concept;
	          if (concept) {
	            var index = AXObjectRoleElements.findIndex(function (_ref5) {
	              var _ref6 = _slicedToArray(_ref5, 1),
	                key = _ref6[0];
	              return key === name;
	            });
	            if (index === -1) {
	              AXObjectRoleElements.push([name, []]);
	              index = AXObjectRoleElements.length - 1;
	            }
	            AXObjectRoleElements[index][1].push(concept);
	          }
	        }
	      });
	    }
	  };
	  for (_iterator.s(); !(_step = _iterator.n()).done;) {
	    _loop();
	  }
	} catch (err) {
	  _iterator.e(err);
	} finally {
	  _iterator.f();
	}
	var AXObjectRoleMap$1 = {
	  entries: function entries() {
	    return AXObjectRoleElements;
	  },
	  forEach: function forEach(fn) {
	    var thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
	    for (var _i = 0, _AXObjectRoleElements = AXObjectRoleElements; _i < _AXObjectRoleElements.length; _i++) {
	      var _AXObjectRoleElements2 = _slicedToArray(_AXObjectRoleElements[_i], 2),
	        key = _AXObjectRoleElements2[0],
	        values = _AXObjectRoleElements2[1];
	      fn.call(thisArg, values, key, AXObjectRoleElements);
	    }
	  },
	  get: function get(key) {
	    var item = AXObjectRoleElements.find(function (tuple) {
	      return tuple[0] === key ? true : false;
	    });
	    return item && item[1];
	  },
	  has: function has(key) {
	    return !!AXObjectRoleMap$1.get(key);
	  },
	  keys: function keys() {
	    return AXObjectRoleElements.map(function (_ref) {
	      var _ref2 = _slicedToArray(_ref, 1),
	        key = _ref2[0];
	      return key;
	    });
	  },
	  values: function values() {
	    return AXObjectRoleElements.map(function (_ref3) {
	      var _ref4 = _slicedToArray(_ref3, 2),
	        values = _ref4[1];
	      return values;
	    });
	  }
	};
	var _default = (0, _iterationDecorator.default)(AXObjectRoleMap$1, AXObjectRoleMap$1.entries());
	AXObjectRoleMap.default = _default;
	return AXObjectRoleMap;
}

var elementAXObjectMap = {};

var hasRequiredElementAXObjectMap;

function requireElementAXObjectMap () {
	if (hasRequiredElementAXObjectMap) return elementAXObjectMap;
	hasRequiredElementAXObjectMap = 1;

	Object.defineProperty(elementAXObjectMap, "__esModule", {
	  value: true
	});
	elementAXObjectMap.default = void 0;
	var _AXObjectsMap = _interopRequireDefault(requireAXObjectsMap());
	var _iterationDecorator = _interopRequireDefault(requireIterationDecorator());
	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
	function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
	function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
	function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
	function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
	function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike) { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e2) { throw _e2; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e3) { didErr = true; err = _e3; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
	function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
	function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
	var elementAXObjects = [];
	var _iterator = _createForOfIteratorHelper(_AXObjectsMap.default.entries()),
	  _step;
	try {
	  var _loop = function _loop() {
	    var _step$value = _slicedToArray(_step.value, 2),
	      name = _step$value[0],
	      def = _step$value[1];
	    var relatedConcepts = def.relatedConcepts;
	    if (Array.isArray(relatedConcepts)) {
	      relatedConcepts.forEach(function (relation) {
	        if (relation.module === 'HTML') {
	          var concept = relation.concept;
	          if (concept != null) {
	            var conceptStr = JSON.stringify(concept);
	            var axObjects;
	            var index = 0;
	            for (; index < elementAXObjects.length; index++) {
	              var key = elementAXObjects[index][0];
	              if (JSON.stringify(key) === conceptStr) {
	                axObjects = elementAXObjects[index][1];
	                break;
	              }
	            }
	            if (!Array.isArray(axObjects)) {
	              axObjects = [];
	            }
	            var loc = axObjects.findIndex(function (item) {
	              return item === name;
	            });
	            if (loc === -1) {
	              axObjects.push(name);
	            }
	            if (index < elementAXObjects.length) {
	              elementAXObjects.splice(index, 1, [concept, axObjects]);
	            } else {
	              elementAXObjects.push([concept, axObjects]);
	            }
	          }
	        }
	      });
	    }
	  };
	  for (_iterator.s(); !(_step = _iterator.n()).done;) {
	    _loop();
	  }
	} catch (err) {
	  _iterator.e(err);
	} finally {
	  _iterator.f();
	}
	function deepAxObjectModelRelationshipConceptAttributeCheck(a, b) {
	  if (a === undefined && b !== undefined) {
	    return false;
	  }
	  if (a !== undefined && b === undefined) {
	    return false;
	  }
	  if (a !== undefined && b !== undefined) {
	    if (a.length != b.length) {
	      return false;
	    }

	    // dequal checks position equality
	    // https://github.com/lukeed/dequal/blob/5ecd990c4c055c4658c64b4bdfc170f219604eea/src/index.js#L17-L22
	    for (var i = 0; i < a.length; i++) {
	      if (b[i].name !== a[i].name || b[i].value !== a[i].value) {
	        return false;
	      }
	    }
	  }
	  return true;
	}
	var elementAXObjectMap$1 = {
	  entries: function entries() {
	    return elementAXObjects;
	  },
	  forEach: function forEach(fn) {
	    var thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
	    for (var _i = 0, _elementAXObjects = elementAXObjects; _i < _elementAXObjects.length; _i++) {
	      var _elementAXObjects$_i = _slicedToArray(_elementAXObjects[_i], 2),
	        key = _elementAXObjects$_i[0],
	        values = _elementAXObjects$_i[1];
	      fn.call(thisArg, values, key, elementAXObjects);
	    }
	  },
	  get: function get(key) {
	    var item = elementAXObjects.find(function (tuple) {
	      return key.name === tuple[0].name && deepAxObjectModelRelationshipConceptAttributeCheck(key.attributes, tuple[0].attributes);
	    });
	    return item && item[1];
	  },
	  has: function has(key) {
	    return !!elementAXObjectMap$1.get(key);
	  },
	  keys: function keys() {
	    return elementAXObjects.map(function (_ref) {
	      var _ref2 = _slicedToArray(_ref, 1),
	        key = _ref2[0];
	      return key;
	    });
	  },
	  values: function values() {
	    return elementAXObjects.map(function (_ref3) {
	      var _ref4 = _slicedToArray(_ref3, 2),
	        values = _ref4[1];
	      return values;
	    });
	  }
	};
	var _default = (0, _iterationDecorator.default)(elementAXObjectMap$1, elementAXObjectMap$1.entries());
	elementAXObjectMap.default = _default;
	return elementAXObjectMap;
}

var hasRequiredLib;

function requireLib () {
	if (hasRequiredLib) return lib;
	hasRequiredLib = 1;

	Object.defineProperty(lib, "__esModule", {
	  value: true
	});
	lib.elementAXObjects = lib.AXObjects = lib.AXObjectRoles = lib.AXObjectElements = void 0;
	var _AXObjectElementMap = _interopRequireDefault(requireAXObjectElementMap());
	var _AXObjectRoleMap = _interopRequireDefault(requireAXObjectRoleMap());
	var _AXObjectsMap = _interopRequireDefault(requireAXObjectsMap());
	var _elementAXObjectMap = _interopRequireDefault(requireElementAXObjectMap());
	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
	var AXObjectElements = _AXObjectElementMap.default;
	lib.AXObjectElements = AXObjectElements;
	var AXObjectRoles = _AXObjectRoleMap.default;
	lib.AXObjectRoles = AXObjectRoles;
	var AXObjects = _AXObjectsMap.default;
	lib.AXObjects = AXObjects;
	var elementAXObjects = _elementAXObjectMap.default;
	lib.elementAXObjects = elementAXObjects;
	return lib;
}

var libExports = requireLib();

/** @import { ARIARoleRelationConcept  } from 'aria-query' */

const aria_attributes =
	'activedescendant atomic autocomplete busy checked colcount colindex colspan controls current describedby description details disabled dropeffect errormessage expanded flowto grabbed haspopup hidden invalid keyshortcuts label labelledby level live modal multiline multiselectable orientation owns placeholder posinset pressed readonly relevant required roledescription rowcount rowindex rowspan selected setsize sort valuemax valuemin valuenow valuetext'.split(
		' '
	);

/** @type {Record<string, string[]>} */
const a11y_required_attributes = {
	a: ['href'],
	area: ['alt', 'aria-label', 'aria-labelledby'],
	// html-has-lang
	html: ['lang'],
	// iframe-has-title
	iframe: ['title'],
	img: ['alt'],
	object: ['title', 'aria-label', 'aria-labelledby']
};

const a11y_distracting_elements = ['blink', 'marquee'];

// this excludes `<a>` and `<button>` because they are handled separately
const a11y_required_content = [
	// heading-has-content
	'h1',
	'h2',
	'h3',
	'h4',
	'h5',
	'h6'
];

const a11y_labelable = [
	'button',
	'input',
	'keygen',
	'meter',
	'output',
	'progress',
	'select',
	'textarea'
];

const a11y_interactive_handlers = [
	// Keyboard events
	'keypress',
	'keydown',
	'keyup',
	// Click events
	'click',
	'contextmenu',
	'dblclick',
	'drag',
	'dragend',
	'dragenter',
	'dragexit',
	'dragleave',
	'dragover',
	'dragstart',
	'drop',
	'mousedown',
	'mouseenter',
	'mouseleave',
	'mousemove',
	'mouseout',
	'mouseover',
	'mouseup'
];

const a11y_recommended_interactive_handlers = [
	'click',
	'mousedown',
	'mouseup',
	'keypress',
	'keydown',
	'keyup'
];

const a11y_nested_implicit_semantics = new Map([
	['header', 'banner'],
	['footer', 'contentinfo']
]);

const a11y_implicit_semantics = new Map([
	['a', 'link'],
	['area', 'link'],
	['article', 'article'],
	['aside', 'complementary'],
	['body', 'document'],
	['button', 'button'],
	['datalist', 'listbox'],
	['dd', 'definition'],
	['dfn', 'term'],
	['dialog', 'dialog'],
	['details', 'group'],
	['dt', 'term'],
	['fieldset', 'group'],
	['figure', 'figure'],
	['form', 'form'],
	['h1', 'heading'],
	['h2', 'heading'],
	['h3', 'heading'],
	['h4', 'heading'],
	['h5', 'heading'],
	['h6', 'heading'],
	['hr', 'separator'],
	['img', 'img'],
	['li', 'listitem'],
	['link', 'link'],
	['main', 'main'],
	['menu', 'list'],
	['meter', 'progressbar'],
	['nav', 'navigation'],
	['ol', 'list'],
	['option', 'option'],
	['optgroup', 'group'],
	['output', 'status'],
	['progress', 'progressbar'],
	['section', 'region'],
	['summary', 'button'],
	['table', 'table'],
	['tbody', 'rowgroup'],
	['textarea', 'textbox'],
	['tfoot', 'rowgroup'],
	['thead', 'rowgroup'],
	['tr', 'row'],
	['ul', 'list']
]);

const menuitem_type_to_implicit_role = new Map([
	['command', 'menuitem'],
	['checkbox', 'menuitemcheckbox'],
	['radio', 'menuitemradio']
]);

const input_type_to_implicit_role = new Map([
	['button', 'button'],
	['image', 'button'],
	['reset', 'button'],
	['submit', 'button'],
	['checkbox', 'checkbox'],
	['radio', 'radio'],
	['range', 'slider'],
	['number', 'spinbutton'],
	['email', 'textbox'],
	['search', 'searchbox'],
	['tel', 'textbox'],
	['text', 'textbox'],
	['url', 'textbox']
]);

/**
 * Exceptions to the rule which follows common A11y conventions
 * TODO make this configurable by the user
 * @type {Record<string, string[]>}
 */
const a11y_non_interactive_element_to_interactive_role_exceptions = {
	ul: ['listbox', 'menu', 'menubar', 'radiogroup', 'tablist', 'tree', 'treegrid'],
	ol: ['listbox', 'menu', 'menubar', 'radiogroup', 'tablist', 'tree', 'treegrid'],
	li: ['menuitem', 'option', 'row', 'tab', 'treeitem'],
	table: ['grid'],
	td: ['gridcell'],
	fieldset: ['radiogroup', 'presentation']
};

const combobox_if_list = ['email', 'search', 'tel', 'text', 'url'];

// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute
const address_type_tokens = ['shipping', 'billing'];

const autofill_field_name_tokens = [
	'',
	'on',
	'off',
	'name',
	'honorific-prefix',
	'given-name',
	'additional-name',
	'family-name',
	'honorific-suffix',
	'nickname',
	'username',
	'new-password',
	'current-password',
	'one-time-code',
	'organization-title',
	'organization',
	'street-address',
	'address-line1',
	'address-line2',
	'address-line3',
	'address-level4',
	'address-level3',
	'address-level2',
	'address-level1',
	'country',
	'country-name',
	'postal-code',
	'cc-name',
	'cc-given-name',
	'cc-additional-name',
	'cc-family-name',
	'cc-number',
	'cc-exp',
	'cc-exp-month',
	'cc-exp-year',
	'cc-csc',
	'cc-type',
	'transaction-currency',
	'transaction-amount',
	'language',
	'bday',
	'bday-day',
	'bday-month',
	'bday-year',
	'sex',
	'url',
	'photo'
];

const contact_type_tokens = ['home', 'work', 'mobile', 'fax', 'pager'];

const autofill_contact_field_name_tokens = [
	'tel',
	'tel-country-code',
	'tel-national',
	'tel-area-code',
	'tel-local',
	'tel-local-prefix',
	'tel-local-suffix',
	'tel-extension',
	'email',
	'impp'
];

const ElementInteractivity = /** @type {const} */ ({
	Interactive: 'interactive',
	NonInteractive: 'non-interactive',
	Static: 'static'
});

const invisible_elements = ['meta', 'html', 'script', 'style'];

const aria_roles = libExports$1.roles.keys();

const abstract_roles = aria_roles.filter((role) => libExports$1.roles.get(role)?.abstract);

const non_abstract_roles = aria_roles.filter((name) => !abstract_roles.includes(name));

const non_interactive_roles = non_abstract_roles
	.filter((name) => {
		const role = libExports$1.roles.get(name);
		return (
			// 'toolbar' does not descend from widget, but it does support
			// aria-activedescendant, thus in practice we treat it as a widget.
			// focusable tabpanel elements are recommended if any panels in a set contain content where the first element in the panel is not focusable.
			// 'generic' is meant to have no semantic meaning.
			// 'cell' is treated as CellRole by the AXObject which is interactive, so we treat 'cell' it as interactive as well.
			!['toolbar', 'tabpanel', 'generic', 'cell'].includes(name) &&
			!role?.superClass.some((classes) => classes.includes('widget') || classes.includes('window'))
		);
	})
	.concat(
		// The `progressbar` is descended from `widget`, but in practice, its
		// value is always `readonly`, so we treat it as a non-interactive role.
		'progressbar'
	);

const interactive_roles = non_abstract_roles.filter(
	(name) =>
		!non_interactive_roles.includes(name) &&
		// 'generic' is meant to have no semantic meaning.
		name !== 'generic'
);

const presentation_roles = ['presentation', 'none'];

/** @type {ARIARoleRelationConcept[]} */
const non_interactive_element_role_schemas = [];

/** @type {ARIARoleRelationConcept[]} */
const interactive_element_role_schemas = [];

for (const [schema, roles] of libExports$1.elementRoles.entries()) {
	if ([...roles].every((role) => role !== 'generic' && non_interactive_roles.includes(role))) {
		non_interactive_element_role_schemas.push(schema);
	}

	if ([...roles].every((role) => interactive_roles.includes(role))) {
		interactive_element_role_schemas.push(schema);
	}
}

const interactive_ax_objects = [...libExports.AXObjects.keys()].filter(
	(name) => libExports.AXObjects.get(name).type === 'widget'
);

/** @type {ARIARoleRelationConcept[]} */
const interactive_element_ax_object_schemas = [];

/** @type {ARIARoleRelationConcept[]} */
const non_interactive_element_ax_object_schemas = [];

const non_interactive_ax_objects = [...libExports.AXObjects.keys()].filter((name) =>
	['windows', 'structure'].includes(libExports.AXObjects.get(name).type)
);

for (const [schema, ax_object] of libExports.elementAXObjects.entries()) {
	if ([...ax_object].every((role) => interactive_ax_objects.includes(role))) {
		interactive_element_ax_object_schemas.push(schema);
	}

	if ([...ax_object].every((role) => non_interactive_ax_objects.includes(role))) {
		non_interactive_element_ax_object_schemas.push(schema);
	}
}

/** @import { AST } from '#compiler' */
/** @import { Context } from '../../../types.js' */
/** @import { ARIARoleDefinitionKey, ARIARoleRelationConcept, ARIAProperty, ARIAPropertyDefinition, ARIARoleDefinition } from 'aria-query' */

/**
 * @param {AST.RegularElement | AST.SvelteElement} node
 * @param {Context} context
 */
function check_element(node, context) {
	/** @type {Map<string, AST.Attribute>} */
	const attribute_map = new Map();

	/** @type {Set<string>} */
	const handlers = new Set();

	/** @type {AST.Attribute[]} */
	const attributes = [];

	const is_dynamic_element = node.type === 'SvelteElement';

	let has_spread = false;
	let has_contenteditable_attr = false;
	let has_contenteditable_binding = false;

	for (const attribute of node.attributes) {
		switch (attribute.type) {
			case 'Attribute': {
				if (is_event_attribute(attribute)) {
					handlers.add(attribute.name.slice(2));
				} else {
					attributes.push(attribute);
					attribute_map.set(attribute.name, attribute);
					if (attribute.name === 'contenteditable') {
						has_contenteditable_attr = true;
					}
				}
				break;
			}
			case 'SpreadAttribute': {
				has_spread = true;
				break;
			}
			case 'BindDirective': {
				if (is_content_editable_binding(attribute.name)) {
					has_contenteditable_binding = true;
				}
				break;
			}
			case 'OnDirective': {
				handlers.add(attribute.name);
				break;
			}
		}
	}

	for (const attribute of node.attributes) {
		if (attribute.type !== 'Attribute') continue;

		const name = attribute.name.toLowerCase();
		// aria-props
		if (name.startsWith('aria-')) {
			if (invisible_elements.includes(node.name)) {
				// aria-unsupported-elements
				a11y_aria_attributes(attribute, node.name);
			}

			const type = name.slice(5);
			if (!aria_attributes.includes(type)) {
				const match = fuzzymatch(type, aria_attributes);
				a11y_unknown_aria_attribute(attribute, type, match);
			}

			if (name === 'aria-hidden' && regex_heading_tags.test(node.name)) {
				a11y_hidden(attribute, node.name);
			}

			// aria-proptypes
			let value = get_static_value(attribute);

			const schema = libExports$1.aria.get(/** @type {ARIAProperty} */ (name));
			if (schema !== undefined) {
				validate_aria_attribute_value(attribute, /** @type {ARIAProperty} */ (name), schema, value);
			}

			// aria-activedescendant-has-tabindex
			if (
				name === 'aria-activedescendant' &&
				!is_dynamic_element &&
				!is_interactive_element(node.name, attribute_map) &&
				!attribute_map.has('tabindex') &&
				!has_spread
			) {
				a11y_aria_activedescendant_has_tabindex(attribute);
			}
		}

		switch (name) {
			// aria-role
			case 'role': {
				if (invisible_elements.includes(node.name)) {
					// aria-unsupported-elements
					a11y_misplaced_role(attribute, node.name);
				}

				const value = get_static_value(attribute);
				if (typeof value !== 'string') {
					break;
				}
				for (const c_r of value.split(regex_whitespaces)) {
					const current_role = /** @type {ARIARoleDefinitionKey} current_role */ (c_r);

					if (current_role && is_abstract_role(current_role)) {
						a11y_no_abstract_role(attribute, current_role);
					} else if (current_role && !aria_roles.includes(current_role)) {
						const match = fuzzymatch(current_role, aria_roles);
						a11y_unknown_role(attribute, current_role, match);
					}

					// no-redundant-roles
					if (
						current_role === get_implicit_role(node.name, attribute_map) &&
						// <ul role="list"> is ok because CSS list-style:none removes the semantics and this is a way to bring them back
						!['ul', 'ol', 'li'].includes(node.name) &&
						// <a role="link" /> is ok because without href the a tag doesn't have a role of link
						!(node.name === 'a' && !attribute_map.has('href'))
					) {
						a11y_no_redundant_roles(attribute, current_role);
					}

					// Footers and headers are special cases, and should not have redundant roles unless they are the children of sections or articles.
					const is_parent_section_or_article = is_parent(context.path, ['section', 'article']);
					if (!is_parent_section_or_article) {
						const has_nested_redundant_role =
							current_role === a11y_nested_implicit_semantics.get(node.name);
						if (has_nested_redundant_role) {
							a11y_no_redundant_roles(attribute, current_role);
						}
					}

					// role-has-required-aria-props
					if (
						!is_dynamic_element &&
						!is_semantic_role_element(current_role, node.name, attribute_map)
					) {
						const role = libExports$1.roles.get(current_role);
						if (role) {
							const required_role_props = Object.keys(role.requiredProps);
							const has_missing_props =
								!has_spread &&
								required_role_props.some((prop) => !attributes.find((a) => a.name === prop));
							if (has_missing_props) {
								a11y_role_has_required_aria_props(
									attribute,
									current_role,
									list$1(
										required_role_props.map((v) => `"${v}"`),
										'and'
									)
								);
							}
						}
					}

					// interactive-supports-focus
					if (
						!has_spread &&
						!has_disabled_attribute(attribute_map) &&
						!is_hidden_from_screen_reader(node.name, attribute_map) &&
						!is_presentation_role(current_role) &&
						is_interactive_roles(current_role) &&
						is_static_element$1(node.name, attribute_map) &&
						!attribute_map.get('tabindex')
					) {
						const has_interactive_handlers = [...handlers].some((handler) =>
							a11y_interactive_handlers.includes(handler)
						);
						if (has_interactive_handlers) {
							a11y_interactive_supports_focus(node, current_role);
						}
					}

					// no-interactive-element-to-noninteractive-role
					if (
						!has_spread &&
						is_interactive_element(node.name, attribute_map) &&
						(is_non_interactive_roles(current_role) || is_presentation_role(current_role))
					) {
						a11y_no_interactive_element_to_noninteractive_role(node, node.name, current_role);
					}

					// no-noninteractive-element-to-interactive-role
					if (
						!has_spread &&
						is_non_interactive_element(node.name, attribute_map) &&
						is_interactive_roles(current_role) &&
						!a11y_non_interactive_element_to_interactive_role_exceptions[node.name]?.includes(
							current_role
						)
					) {
						a11y_no_noninteractive_element_to_interactive_role(node, node.name, current_role);
					}
				}
				break;
			}
			// no-access-key
			case 'accesskey': {
				a11y_accesskey(attribute);
				break;
			}
			// no-autofocus
			case 'autofocus': {
				if (node.name !== 'dialog' && !is_parent(context.path, ['dialog'])) {
					a11y_autofocus(attribute);
				}
				break;
			}
			// scope
			case 'scope': {
				if (!is_dynamic_element && node.name !== 'th') {
					a11y_misplaced_scope(attribute);
				}
				break;
			}
			// tabindex-no-positive
			case 'tabindex': {
				const value = get_static_value(attribute);
				// @ts-ignore todo is tabindex=true correct case?
				if (!isNaN(value) && +value > 0) {
					a11y_positive_tabindex(attribute);
				}
				break;
			}
		}
	}

	const role = attribute_map.get('role');
	const role_static_value = /** @type {ARIARoleDefinitionKey} */ (get_static_text_value(role));

	// click-events-have-key-events
	if (handlers.has('click')) {
		const is_non_presentation_role =
			role_static_value !== null && !is_presentation_role(role_static_value);
		if (
			!is_dynamic_element &&
			!is_hidden_from_screen_reader(node.name, attribute_map) &&
			(!role || is_non_presentation_role) &&
			!is_interactive_element(node.name, attribute_map) &&
			!has_spread
		) {
			const has_key_event =
				handlers.has('keydown') || handlers.has('keyup') || handlers.has('keypress');
			if (!has_key_event) {
				a11y_click_events_have_key_events(node);
			}
		}
	}

	const role_value = /** @type {ARIARoleDefinitionKey} */ (
		role ? role_static_value : get_implicit_role(node.name, attribute_map)
	);

	// no-noninteractive-tabindex
	if (
		!is_dynamic_element &&
		!is_interactive_element(node.name, attribute_map) &&
		!is_interactive_roles(role_static_value)
	) {
		const tab_index = attribute_map.get('tabindex');
		const tab_index_value = get_static_text_value(tab_index);
		if (tab_index && (tab_index_value === null || Number(tab_index_value) >= 0)) {
			a11y_no_noninteractive_tabindex(node);
		}
	}

	// role-supports-aria-props
	if (typeof role_value === 'string' && libExports$1.roles.has(role_value)) {
		const { props } = /** @type {ARIARoleDefinition} */ (libExports$1.roles.get(role_value));
		const invalid_aria_props = libExports$1.aria.keys().filter((attribute) => !(attribute in props));
		const is_implicit = role_value && role === undefined;
		for (const attr of attributes) {
			if (invalid_aria_props.includes(/** @type {ARIAProperty} */ (attr.name))) {
				if (is_implicit) {
					a11y_role_supports_aria_props_implicit(attr, attr.name, role_value, node.name);
				} else {
					a11y_role_supports_aria_props(attr, attr.name, role_value);
				}
			}
		}
	}

	// no-noninteractive-element-interactions
	if (
		!has_spread &&
		!has_contenteditable_attr &&
		!is_hidden_from_screen_reader(node.name, attribute_map) &&
		!is_presentation_role(role_static_value) &&
		((!is_interactive_element(node.name, attribute_map) &&
			is_non_interactive_roles(role_static_value)) ||
			(is_non_interactive_element(node.name, attribute_map) && !role))
	) {
		const has_interactive_handlers = [...handlers].some((handler) =>
			a11y_recommended_interactive_handlers.includes(handler)
		);
		if (has_interactive_handlers) {
			a11y_no_noninteractive_element_interactions(node, node.name);
		}
	}

	// no-static-element-interactions
	if (
		!has_spread &&
		(!role || role_static_value !== null) &&
		!is_hidden_from_screen_reader(node.name, attribute_map) &&
		!is_presentation_role(role_static_value) &&
		!is_interactive_element(node.name, attribute_map) &&
		!is_interactive_roles(role_static_value) &&
		!is_non_interactive_element(node.name, attribute_map) &&
		!is_non_interactive_roles(role_static_value) &&
		!is_abstract_role(role_static_value)
	) {
		const interactive_handlers = [...handlers].filter((handler) =>
			a11y_interactive_handlers.includes(handler)
		);
		if (interactive_handlers.length > 0) {
			a11y_no_static_element_interactions(node, node.name, list$1(interactive_handlers));
		}
	}

	if (!has_spread && handlers.has('mouseover') && !handlers.has('focus')) {
		a11y_mouse_events_have_key_events(node, 'mouseover', 'focus');
	}

	if (!has_spread && handlers.has('mouseout') && !handlers.has('blur')) {
		a11y_mouse_events_have_key_events(node, 'mouseout', 'blur');
	}

	// element-specific checks
	const is_labelled =
		attribute_map.has('aria-label') ||
		attribute_map.has('aria-labelledby') ||
		attribute_map.has('title');

	switch (node.name) {
		case 'a':
		case 'button': {
			const is_hidden =
				get_static_value(attribute_map.get('aria-hidden')) === 'true' ||
				get_static_value(attribute_map.get('inert')) !== null;

			if (!has_spread && !is_hidden && !is_labelled && !has_content$1(node)) {
				a11y_consider_explicit_label(node);
			}
			if (node.name === 'button') {
				break;
			}
			const href = attribute_map.get('href') || attribute_map.get('xlink:href');
			if (href) {
				const href_value = get_static_text_value(href);
				if (href_value !== null) {
					if (href_value === '' || href_value === '#' || regex_js_prefix.test(href_value)) {
						a11y_invalid_attribute(href, href_value, href.name);
					}
				}
			} else if (!has_spread) {
				const id_attribute = get_static_value(attribute_map.get('id'));
				const name_attribute = get_static_value(attribute_map.get('name'));
				const aria_disabled_attribute = get_static_value(attribute_map.get('aria-disabled'));
				if (!id_attribute && !name_attribute && aria_disabled_attribute !== 'true') {
					warn_missing_attribute(node, ['href']);
				}
			}
			break;
		}
		case 'input': {
			const type = attribute_map.get('type');
			const type_value = get_static_text_value(type);
			if (type_value === 'image' && !has_spread) {
				const required_attributes = ['alt', 'aria-label', 'aria-labelledby'];
				const has_attribute = required_attributes.some((name) => attribute_map.has(name));
				if (!has_attribute) {
					warn_missing_attribute(node, required_attributes, 'input type="image"');
				}
			}
			// autocomplete-valid
			const autocomplete = attribute_map.get('autocomplete');
			if (type && autocomplete) {
				const autocomplete_value = get_static_value(autocomplete);
				if (!is_valid_autocomplete(autocomplete_value)) {
					a11y_autocomplete_valid(
						autocomplete,
						/** @type {string} */ (autocomplete_value),
						type_value ?? '...'
					);
				}
			}
			break;
		}
		case 'img': {
			const alt_attribute = get_static_text_value(attribute_map.get('alt'));
			const aria_hidden = get_static_value(attribute_map.get('aria-hidden'));
			if (alt_attribute && !aria_hidden && !has_spread) {
				if (regex_redundant_img_alt.test(alt_attribute)) {
					a11y_img_redundant_alt(node);
				}
			}
			break;
		}
		case 'label': {
			/** @param {AST.TemplateNode} node */
			const has_input_child = (node) => {
				let has = false;
				walk$1(
					node,
					{},
					{
						_(node, { next }) {
							if (
								node.type === 'SvelteElement' ||
								node.type === 'SlotElement' ||
								node.type === 'Component' ||
								node.type === 'RenderTag' ||
								(node.type === 'RegularElement' &&
									(a11y_labelable.includes(node.name) || node.name === 'slot'))
							) {
								has = true;
							} else {
								next();
							}
						}
					}
				);
				return has;
			};
			if (!has_spread && !attribute_map.has('for') && !has_input_child(node)) {
				a11y_label_has_associated_control(node);
			}
			break;
		}
		case 'video': {
			const aria_hidden_attribute = attribute_map.get('aria-hidden');
			const aria_hidden_exist = aria_hidden_attribute && get_static_value(aria_hidden_attribute);
			if (attribute_map.has('muted') || aria_hidden_exist === 'true' || has_spread) {
				return;
			}
			let has_caption = false;
			const track = /** @type {AST.RegularElement | undefined} */ (
				node.fragment.nodes.find((i) => i.type === 'RegularElement' && i.name === 'track')
			);
			if (track) {
				has_caption = track.attributes.some(
					(a) =>
						a.type === 'SpreadAttribute' ||
						(a.type === 'Attribute' && a.name === 'kind' && get_static_value(a) === 'captions')
				);
			}
			if (!has_caption) {
				a11y_media_has_caption(node);
			}
			break;
		}
		case 'figcaption': {
			if (!is_parent(context.path, ['figure'])) {
				a11y_figcaption_parent(node);
			}
			break;
		}
		case 'figure': {
			const children = node.fragment.nodes.filter((node) => {
				if (node.type === 'Comment') return false;
				if (node.type === 'Text') return regex_not_whitespace.test(node.data);
				return true;
			});
			const index = children.findIndex(
				(child) => child.type === 'RegularElement' && child.name === 'figcaption'
			);
			if (index !== -1 && index !== 0 && index !== children.length - 1) {
				a11y_figcaption_index(children[index]);
			}
			break;
		}
	}

	if (!has_spread && node.name !== 'a') {
		const required_attributes = a11y_required_attributes[node.name];
		if (required_attributes) {
			const has_attribute = required_attributes.some((name) => attribute_map.has(name));
			if (!has_attribute) {
				warn_missing_attribute(node, required_attributes);
			}
		}
	}

	if (a11y_distracting_elements.includes(node.name)) {
		// no-distracting-elements
		a11y_distracting_elements$1(node, node.name);
	}

	// Check content
	if (
		!has_spread &&
		!is_labelled &&
		!has_contenteditable_binding &&
		a11y_required_content.includes(node.name) &&
		!has_content$1(node)
	) {
		a11y_missing_content(node, node.name);
	}
}

/**
 * @param {ARIARoleDefinitionKey} role
 */
function is_presentation_role(role) {
	return presentation_roles.includes(role);
}

/**
 * @param {string} tag_name
 * @param {Map<string, AST.Attribute>} attribute_map
 */
function is_hidden_from_screen_reader(tag_name, attribute_map) {
	if (tag_name === 'input') {
		const type = get_static_value(attribute_map.get('type'));
		if (type === 'hidden') {
			return true;
		}
	}

	const aria_hidden = attribute_map.get('aria-hidden');
	if (!aria_hidden) return false;
	const aria_hidden_value = get_static_value(aria_hidden);
	if (aria_hidden_value === null) return true;
	return aria_hidden_value === true || aria_hidden_value === 'true';
}

/**
 * @param {Map<string, AST.Attribute>} attribute_map
 */
function has_disabled_attribute(attribute_map) {
	const disabled_attr_value = get_static_value(attribute_map.get('disabled'));
	if (disabled_attr_value) {
		return true;
	}

	const aria_disabled_attr = attribute_map.get('aria-disabled');
	if (aria_disabled_attr) {
		const aria_disabled_attr_value = get_static_value(aria_disabled_attr);
		if (aria_disabled_attr_value === 'true') {
			return true;
		}
	}
	return false;
}

/**
 * @param {string} tag_name
 * @param {Map<string, AST.Attribute>} attribute_map
 * @returns {typeof ElementInteractivity[keyof typeof ElementInteractivity]}
 */
function element_interactivity(tag_name, attribute_map) {
	if (
		interactive_element_role_schemas.some((schema) => match_schema(schema, tag_name, attribute_map))
	) {
		return ElementInteractivity.Interactive;
	}
	if (
		tag_name !== 'header' &&
		non_interactive_element_role_schemas.some((schema) =>
			match_schema(schema, tag_name, attribute_map)
		)
	) {
		return ElementInteractivity.NonInteractive;
	}
	if (
		interactive_element_ax_object_schemas.some((schema) =>
			match_schema(schema, tag_name, attribute_map)
		)
	) {
		return ElementInteractivity.Interactive;
	}
	if (
		non_interactive_element_ax_object_schemas.some((schema) =>
			match_schema(schema, tag_name, attribute_map)
		)
	) {
		return ElementInteractivity.NonInteractive;
	}
	return ElementInteractivity.Static;
}

/**
 * @param {string} tag_name
 * @param {Map<string, AST.Attribute>} attribute_map
 * @returns {boolean}
 */
function is_interactive_element(tag_name, attribute_map) {
	return element_interactivity(tag_name, attribute_map) === ElementInteractivity.Interactive;
}

/**
 * @param {string} tag_name
 * @param {Map<string, AST.Attribute>} attribute_map
 * @returns {boolean}
 */
function is_non_interactive_element(tag_name, attribute_map) {
	return element_interactivity(tag_name, attribute_map) === ElementInteractivity.NonInteractive;
}

/**
 * @param {string} tag_name
 * @param {Map<string, AST.Attribute>} attribute_map
 * @returns {boolean}
 */
function is_static_element$1(tag_name, attribute_map) {
	return element_interactivity(tag_name, attribute_map) === ElementInteractivity.Static;
}

/**
 * @param {ARIARoleDefinitionKey} role
 * @param {string} tag_name
 * @param {Map<string, AST.Attribute>} attribute_map
 */
function is_semantic_role_element(role, tag_name, attribute_map) {
	for (const [schema, ax_object] of libExports.elementAXObjects.entries()) {
		if (
			schema.name === tag_name &&
			(!schema.attributes ||
				schema.attributes.every(
					/** @param {any} attr */
					(attr) =>
						attribute_map.has(attr.name) &&
						get_static_value(attribute_map.get(attr.name)) === attr.value
				))
		) {
			for (const name of ax_object) {
				const roles = libExports.AXObjectRoles.get(name);
				if (roles) {
					for (const { name } of roles) {
						if (name === role) {
							return true;
						}
					}
				}
			}
		}
	}
	return false;
}

/**
 * @param {null | true | string} autocomplete
 */
function is_valid_autocomplete(autocomplete) {
	if (autocomplete === true) {
		return false;
	} else if (!autocomplete) {
		return true; // dynamic value
	}
	const tokens = autocomplete.trim().toLowerCase().split(regex_whitespaces);
	if (typeof tokens[0] === 'string' && tokens[0].startsWith('section-')) {
		tokens.shift();
	}
	if (address_type_tokens.includes(tokens[0])) {
		tokens.shift();
	}
	if (autofill_field_name_tokens.includes(tokens[0])) {
		tokens.shift();
	} else {
		if (contact_type_tokens.includes(tokens[0])) {
			tokens.shift();
		}
		if (autofill_contact_field_name_tokens.includes(tokens[0])) {
			tokens.shift();
		} else {
			return false;
		}
	}
	if (tokens[0] === 'webauthn') {
		tokens.shift();
	}
	return tokens.length === 0;
}

/** @param {Map<string, AST.Attribute>} attribute_map */
function input_implicit_role(attribute_map) {
	const type_attribute = attribute_map.get('type');
	if (!type_attribute) return;
	const type = get_static_text_value(type_attribute);
	if (!type) return;
	const list_attribute_exists = attribute_map.has('list');
	if (list_attribute_exists && combobox_if_list.includes(type)) {
		return 'combobox';
	}
	return input_type_to_implicit_role.get(type);
}

/** @param {Map<string, AST.Attribute>} attribute_map */
function menuitem_implicit_role(attribute_map) {
	const type_attribute = attribute_map.get('type');
	if (!type_attribute) return;
	const type = get_static_text_value(type_attribute);
	if (!type) return;
	return menuitem_type_to_implicit_role.get(type);
}

/**
 * @param {string} name
 * @param {Map<string, AST.Attribute>} attribute_map
 */
function get_implicit_role(name, attribute_map) {
	if (name === 'menuitem') {
		return menuitem_implicit_role(attribute_map);
	} else if (name === 'input') {
		return input_implicit_role(attribute_map);
	} else {
		return a11y_implicit_semantics.get(name);
	}
}

/**
 * @param {ARIARoleDefinitionKey} role
 */
function is_non_interactive_roles(role) {
	return non_interactive_roles.includes(role);
}

/**
 * @param {ARIARoleDefinitionKey} role
 */
function is_interactive_roles(role) {
	return interactive_roles.includes(role);
}

/**
 * @param {ARIARoleDefinitionKey} role
 */
function is_abstract_role(role) {
	return abstract_roles.includes(role);
}

/**
 * @param {AST.Attribute | undefined} attribute
 */
function get_static_text_value(attribute) {
	const value = get_static_value(attribute);
	if (value === true) return null;
	return value;
}

/**
 * @param {AST.Attribute | undefined} attribute
 */
function get_static_value(attribute) {
	if (!attribute) return null;
	if (attribute.value === true) return true;
	if (is_text_attribute(attribute)) return attribute.value[0].data;
	return null;
}

/**
 * @param {AST.RegularElement | AST.SvelteElement} element
 */
function has_content$1(element) {
	for (const node of element.fragment.nodes) {
		if (node.type === 'Text') {
			if (node.data.trim() === '') {
				continue;
			}
		}

		if (node.type === 'RegularElement' || node.type === 'SvelteElement') {
			if (
				node.name === 'img' &&
				node.attributes.some((node) => node.type === 'Attribute' && node.name === 'alt')
			) {
				return true;
			}

			if (!has_content$1(node)) {
				continue;
			}
		}

		// assume everything else has content — this will result in false positives
		// (e.g. an empty `{#if ...}{/if}`) but that's probably fine
		return true;
	}
}

/**
 * @param {ARIARoleRelationConcept} schema
 * @param {string} tag_name
 * @param {Map<string, AST.Attribute>} attribute_map
 */
function match_schema(schema, tag_name, attribute_map) {
	if (schema.name !== tag_name) return false;
	if (!schema.attributes) return true;
	return schema.attributes.every((schema_attribute) => {
		const attribute = attribute_map.get(schema_attribute.name);
		if (!attribute) return false;
		if (schema_attribute.value && schema_attribute.value !== get_static_text_value(attribute)) {
			return false;
		}
		return true;
	});
}

/**
 * @param {AST.SvelteNode[]} path
 * @param {string[]} elements
 */
function is_parent(path, elements) {
	let i = path.length;
	while (i--) {
		const parent = path[i];
		if (parent.type === 'SvelteElement') return true; // unknown, play it safe, so we don't warn
		if (parent.type === 'RegularElement') {
			return elements.includes(parent.name);
		}
	}
	return false;
}

/**
 * @param {AST.Attribute} attribute
 * @param {ARIAProperty} name
 * @param {ARIAPropertyDefinition} schema
 * @param {string | true | null} value
 */
function validate_aria_attribute_value(attribute, name, schema, value) {
	const type = schema.type;

	if (value === null) return;
	if (value === true) value = '';

	switch (type) {
		case 'id':
		case 'string': {
			if (value === '') {
				a11y_incorrect_aria_attribute_type(attribute, name, 'non-empty string');
			}
			break;
		}
		case 'number': {
			if (value === '' || isNaN(+value)) {
				a11y_incorrect_aria_attribute_type(attribute, name, 'number');
			}
			break;
		}
		case 'boolean': {
			if (value !== 'true' && value !== 'false') {
				a11y_incorrect_aria_attribute_type_boolean(attribute, name);
			}
			break;
		}
		case 'idlist': {
			if (value === '') {
				a11y_incorrect_aria_attribute_type_idlist(attribute, name);
			}
			break;
		}
		case 'integer': {
			if (value === '' || !Number.isInteger(+value)) {
				a11y_incorrect_aria_attribute_type_integer(attribute, name);
			}
			break;
		}
		case 'token': {
			const values = (schema.values ?? []).map((value) => value.toString());
			if (!values.includes(value.toLowerCase())) {
				a11y_incorrect_aria_attribute_type_token(
					attribute,
					name,
					list$1(values.map((v) => `"${v}"`))
				);
			}
			break;
		}
		case 'tokenlist': {
			const values = (schema.values ?? []).map((value) => value.toString());
			if (
				value
					.toLowerCase()
					.split(regex_whitespaces)
					.some((value) => !values.includes(value))
			) {
				a11y_incorrect_aria_attribute_type_tokenlist(
					attribute,
					name,
					list$1(values.map((v) => `"${v}"`))
				);
			}
			break;
		}
		case 'tristate': {
			if (value !== 'true' && value !== 'false' && value !== 'mixed') {
				a11y_incorrect_aria_attribute_type_tristate(attribute, name);
			}
			break;
		}
	}
}

/**
 * @param {AST.RegularElement |AST.SvelteElement} node
 * @param {string[]} attributes
 * @param {string} name
 */
function warn_missing_attribute(node, attributes, name = node.name) {
	const article =
		regex_starts_with_vowel.test(attributes[0]) || attributes[0] === 'href' ? 'an' : 'a';
	const sequence =
		attributes.length > 1
			? attributes.slice(0, -1).join(', ') + ` or ${attributes[attributes.length - 1]}`
			: attributes[0];

	a11y_missing_attribute(node, name, article, sequence);
}

/** @import { AST } from '#compiler' */
/** @import { Context } from '../../types' */

const EVENT_MODIFIERS = [
	'preventDefault',
	'stopPropagation',
	'stopImmediatePropagation',
	'capture',
	'once',
	'passive',
	'nonpassive',
	'self',
	'trusted'
];

/**
 * @param {AST.RegularElement | AST.SvelteElement} node
 * @param {Context} context
 */
function validate_element(node, context) {
	let has_animate_directive = false;

	/** @type {AST.TransitionDirective | null} */
	let in_transition = null;

	/** @type {AST.TransitionDirective | null} */
	let out_transition = null;

	for (const attribute of node.attributes) {
		if (attribute.type === 'Attribute') {
			const is_expression = is_expression_attribute(attribute);

			if (context.state.analysis.runes) {
				validate_attribute(attribute, node);

				if (is_expression) {
					const expression = get_attribute_expression(attribute);
					if (expression.type === 'SequenceExpression') {
						let i = /** @type {number} */ (expression.start);
						while (--i > 0) {
							const char = context.state.analysis.source[i];
							if (char === '(') break; // parenthesized sequence expressions are ok
							if (char === '{') attribute_invalid_sequence_expression(expression);
						}
					}
				}
			}

			if (regex_illegal_attribute_character.test(attribute.name)) {
				attribute_invalid_name(attribute, attribute.name);
			}

			if (attribute.name.startsWith('on') && attribute.name.length > 2) {
				if (!is_expression) {
					attribute_invalid_event_handler(attribute);
				}

				const value = get_attribute_expression(attribute);
				if (
					value.type === 'Identifier' &&
					value.name === attribute.name &&
					!context.state.scope.get(value.name)
				) {
					attribute_global_event_reference(attribute, attribute.name);
				}
			}

			if (attribute.name === 'slot') {
				/** @type {AST.RegularElement | AST.SvelteElement | AST.Component | AST.SvelteComponent | AST.SvelteSelf | undefined} */
				validate_slot_attribute(context, attribute);
			}

			if (attribute.name === 'is') {
				attribute_avoid_is(attribute);
			}

			const correct_name = react_attributes.get(attribute.name);
			if (correct_name) {
				attribute_invalid_property_name(attribute, attribute.name, correct_name);
			}

			validate_attribute_name(attribute);
		} else if (attribute.type === 'AnimateDirective') {
			const parent = context.path.at(-2);
			if (parent?.type !== 'EachBlock') {
				animation_invalid_placement(attribute);
			} else if (!parent.key) {
				animation_missing_key(attribute);
			} else if (
				parent.body.nodes.filter(
					(n) =>
						n.type !== 'Comment' &&
						n.type !== 'ConstTag' &&
						(n.type !== 'Text' || n.data.trim() !== '')
				).length > 1
			) {
				animation_invalid_placement(attribute);
			}

			if (has_animate_directive) {
				animation_duplicate(attribute);
			} else {
				has_animate_directive = true;
			}
		} else if (attribute.type === 'TransitionDirective') {
			const existing = /** @type {AST.TransitionDirective | null} */ (
				(attribute.intro && in_transition) || (attribute.outro && out_transition)
			);

			if (existing) {
				const a = existing.intro ? (existing.outro ? 'transition' : 'in') : 'out';
				const b = attribute.intro ? (attribute.outro ? 'transition' : 'in') : 'out';

				if (a === b) {
					transition_duplicate(attribute, a);
				} else {
					transition_conflict(attribute, a, b);
				}
			}

			if (attribute.intro) in_transition = attribute;
			if (attribute.outro) out_transition = attribute;
		} else if (attribute.type === 'OnDirective') {
			let has_passive_modifier = false;
			let conflicting_passive_modifier = '';
			for (const modifier of attribute.modifiers) {
				if (!EVENT_MODIFIERS.includes(modifier)) {
					const list = `${EVENT_MODIFIERS.slice(0, -1).join(', ')} or ${EVENT_MODIFIERS.at(-1)}`;
					event_handler_invalid_modifier(attribute, list);
				}
				if (modifier === 'passive') {
					has_passive_modifier = true;
				} else if (modifier === 'nonpassive' || modifier === 'preventDefault') {
					conflicting_passive_modifier = modifier;
				}
				if (has_passive_modifier && conflicting_passive_modifier) {
					event_handler_invalid_modifier_combination(
						attribute,
						'passive',
						conflicting_passive_modifier
					);
				}
			}
		}
	}
}

const react_attributes = new Map([
	['className', 'class'],
	['htmlFor', 'for']
]);

/** @import { AST } from '#compiler' */
/** @import { Context } from '../types' */

/**
 * @param {AST.RegularElement} node
 * @param {Context} context
 */
function RegularElement$2(node, context) {
	validate_element(node, context);
	check_element(node, context);

	node.metadata.path = [...context.path];
	context.state.analysis.elements.push(node);

	// Special case: Move the children of <textarea> into a value attribute if they are dynamic
	if (node.name === 'textarea' && node.fragment.nodes.length > 0) {
		for (const attribute of node.attributes) {
			if (attribute.type === 'Attribute' && attribute.name === 'value') {
				textarea_invalid_content(node);
			}
		}

		if (node.fragment.nodes.length > 1 || node.fragment.nodes[0].type !== 'Text') {
			const first = node.fragment.nodes[0];
			if (first.type === 'Text') {
				// The leading newline character needs to be stripped because of a qirk:
				// It is ignored by browsers if the tag and its contents are set through
				// innerHTML, but we're now setting it through the value property at which
				// point it is _not_ ignored, so we need to strip it ourselves.
				// see https://html.spec.whatwg.org/multipage/syntax.html#element-restrictions
				// see https://html.spec.whatwg.org/multipage/grouping-content.html#the-pre-element
				first.data = first.data.replace(regex_starts_with_newline, '');
				first.raw = first.raw.replace(regex_starts_with_newline, '');
			}

			node.attributes.push(
				create_attribute(
					'value',
					/** @type {AST.Text} */ (node.fragment.nodes.at(0)).start,
					/** @type {AST.Text} */ (node.fragment.nodes.at(-1)).end,
					// @ts-ignore
					node.fragment.nodes
				)
			);

			node.fragment.nodes = [];
		}
	}

	// Special case: single expression tag child of option element -> add "fake" attribute
	// to ensure that value types are the same (else for example numbers would be strings)
	if (
		node.name === 'option' &&
		node.fragment.nodes?.length === 1 &&
		node.fragment.nodes[0].type === 'ExpressionTag' &&
		!node.attributes.some(
			(attribute) => attribute.type === 'Attribute' && attribute.name === 'value'
		)
	) {
		const child = node.fragment.nodes[0];
		node.metadata.synthetic_value_node = child;
	}

	const binding = context.state.scope.get(node.name);
	if (
		binding !== null &&
		binding.declaration_kind === 'import' &&
		binding.references.length === 0
	) {
		component_name_lowercase(node, node.name);
	}

	node.metadata.has_spread = node.attributes.some(
		(attribute) => attribute.type === 'SpreadAttribute'
	);

	const is_svg_element = () => {
		if (is_svg(node.name)) {
			return true;
		}

		if (node.name === 'a' || node.name === 'title') {
			let i = context.path.length;

			while (i--) {
				const ancestor = context.path[i];
				if (ancestor.type === 'RegularElement') {
					return ancestor.metadata.svg;
				}
			}
		}

		return false;
	};

	node.metadata.svg = is_svg_element();
	node.metadata.mathml = is_mathml(node.name);

	if (is_custom_element_node(node) && node.attributes.length > 0) {
		// we're setting all attributes on custom elements through properties
		mark_subtree_dynamic(context.path);
	}

	if (context.state.parent_element) {
		let past_parent = false;
		let only_warn = false;
		const ancestors = [context.state.parent_element];

		for (let i = context.path.length - 1; i >= 0; i--) {
			const ancestor = context.path[i];

			if (
				ancestor.type === 'IfBlock' ||
				ancestor.type === 'EachBlock' ||
				ancestor.type === 'AwaitBlock' ||
				ancestor.type === 'KeyBlock'
			) {
				// We're creating a separate template string inside blocks, which means client-side this would work
				only_warn = true;
			}

			if (!past_parent) {
				if (ancestor.type === 'RegularElement' && ancestor.name === context.state.parent_element) {
					const message = is_tag_valid_with_parent(node.name, context.state.parent_element);
					if (message) {
						if (only_warn) {
							node_invalid_placement_ssr(node, message);
						} else {
							node_invalid_placement(node, message);
						}
					}

					past_parent = true;
				}
			} else if (ancestor.type === 'RegularElement') {
				ancestors.push(ancestor.name);

				const message = is_tag_valid_with_ancestor(node.name, ancestors);
				if (message) {
					if (only_warn) {
						node_invalid_placement_ssr(node, message);
					} else {
						node_invalid_placement(node, message);
					}
				}
			} else if (
				ancestor.type === 'Component' ||
				ancestor.type === 'SvelteComponent' ||
				ancestor.type === 'SvelteElement' ||
				ancestor.type === 'SvelteSelf' ||
				ancestor.type === 'SnippetBlock'
			) {
				break;
			}
		}
	}

	// Strip off any namespace from the beginning of the node name.
	const node_name = node.name.replace(/[a-zA-Z-]*:/g, '');

	if (
		context.state.analysis.source[node.end - 2] === '/' &&
		!is_void(node_name) &&
		!is_svg(node_name) &&
		!is_mathml(node_name)
	) {
		element_invalid_self_closing_tag(node, node.name);
	}

	context.next({ ...context.state, parent_element: node.name });

	// Special case: <a> tags are valid in both the SVG and HTML namespace.
	// If there's no parent, look downwards to see if it's the parent of a SVG or HTML element.
	if (node.name === 'a' && !context.state.parent_element) {
		for (const child of node.fragment.nodes) {
			if (child.type === 'RegularElement') {
				if (child.metadata.svg && child.name !== 'svg') {
					node.metadata.svg = true;
					break;
				}
			}
		}
	}
}

/** @import { AST } from '#compiler' */
/** @import { Context } from '../types' */

/**
 * @param {AST.RenderTag} node
 * @param {Context} context
 */
function RenderTag$2(node, context) {
	validate_opening_tag(node, context.state, '@');

	node.metadata.path = [...context.path];

	const expression = unwrap_optional(node.expression);
	const callee = expression.callee;

	const binding = callee.type === 'Identifier' ? context.state.scope.get(callee.name) : null;

	node.metadata.dynamic = binding?.kind !== 'normal';

	/**
	 * If we can't unambiguously resolve this to a declaration, we
	 * must assume the worst and link the render tag to every snippet
	 */
	let resolved = callee.type === 'Identifier' && is_resolved_snippet(binding);

	if (binding?.initial?.type === 'SnippetBlock') {
		// if this render tag unambiguously references a local snippet, our job is easy
		node.metadata.snippets.add(binding.initial);
	}

	context.state.analysis.snippet_renderers.set(node, resolved);
	context.state.analysis.uses_render_tags = true;

	const raw_args = unwrap_optional(node.expression).arguments;
	for (const arg of raw_args) {
		if (arg.type === 'SpreadElement') {
			render_tag_invalid_spread_argument(arg);
		}
	}

	if (
		callee.type === 'MemberExpression' &&
		callee.property.type === 'Identifier' &&
		['bind', 'apply', 'call'].includes(callee.property.name)
	) {
		render_tag_invalid_call_expression(node);
	}

	mark_subtree_dynamic(context.path);

	context.visit(callee, { ...context.state, expression: node.metadata.expression });

	for (const arg of expression.arguments) {
		const metadata = new ExpressionMetadata();
		node.metadata.arguments.push(metadata);

		context.visit(arg, {
			...context.state,
			expression: metadata
		});
	}
}

/** @import { AST } from '#compiler' */
/** @import { Context } from '../types' */

/**
 * @param {AST.SlotElement} node
 * @param {Context} context
 */
function SlotElement$2(node, context) {
	if (context.state.analysis.runes && !context.state.analysis.custom_element) {
		slot_element_deprecated(node);
	}

	mark_subtree_dynamic(context.path);

	/** @type {string} */
	let name = 'default';

	for (const attribute of node.attributes) {
		if (attribute.type === 'Attribute') {
			if (attribute.name === 'name') {
				if (!is_text_attribute(attribute)) {
					slot_element_invalid_name(attribute);
				}

				name = attribute.value[0].data;
				if (name === 'default') {
					slot_element_invalid_name_default(attribute);
				}
			}
		} else if (attribute.type !== 'SpreadAttribute' && attribute.type !== 'LetDirective') {
			slot_element_invalid_attribute(attribute);
		}
	}

	context.state.analysis.slot_names.set(name, node);

	context.next();
}

/** @import { AST, Binding } from '#compiler' */
/** @import { Scope } from '../../scope' */
/** @import { Context } from '../types' */

/**
 * @param {AST.SnippetBlock} node
 * @param {Context} context
 */
function SnippetBlock$2(node, context) {
	context.state.analysis.snippets.add(node);

	validate_block_not_empty(node.body);

	if (context.state.analysis.runes) {
		validate_opening_tag(node, context.state, '#');
	}

	for (const arg of node.parameters) {
		if (arg.type === 'RestElement') {
			snippet_invalid_rest_parameter(arg);
		}
	}

	context.next({ ...context.state, parent_element: null });

	const can_hoist =
		context.path.length === 1 &&
		context.path[0].type === 'Fragment' &&
		can_hoist_snippet(context.state.scope, context.state.scopes);

	const name = node.expression.name;

	if (can_hoist) {
		const binding = /** @type {Binding} */ (context.state.scope.get(name));
		context.state.analysis.module.scope.declarations.set(name, binding);
	}

	node.metadata.can_hoist = can_hoist;

	const { path } = context;
	const parent = path.at(-2);
	if (!parent) return;

	if (
		parent.type === 'Component' &&
		parent.attributes.some(
			(attribute) =>
				(attribute.type === 'Attribute' || attribute.type === 'BindDirective') &&
				attribute.name === node.expression.name
		)
	) {
		snippet_shadowing_prop(node, node.expression.name);
	}

	if (node.expression.name !== 'children') return;

	if (
		parent.type === 'Component' ||
		parent.type === 'SvelteComponent' ||
		parent.type === 'SvelteSelf'
	) {
		if (
			parent.fragment.nodes.some(
				(node) =>
					node.type !== 'SnippetBlock' &&
					(node.type !== 'Text' || node.data.trim()) &&
					node.type !== 'Comment'
			)
		) {
			snippet_conflict(node);
		}
	}
}

/**
 * @param {Map<AST.SvelteNode, Scope>} scopes
 * @param {Scope} scope
 */
function can_hoist_snippet(scope, scopes, visited = new Set()) {
	for (const [reference] of scope.references) {
		const binding = scope.get(reference);
		if (!binding) continue;

		if (binding.blocker) {
			return false;
		}

		if (binding.scope.function_depth === 0) {
			continue;
		}

		// ignore bindings declared inside the snippet (e.g. the snippet's own parameters)
		if (binding.scope.function_depth >= scope.function_depth) {
			continue;
		}

		if (binding.initial?.type === 'SnippetBlock') {
			if (visited.has(binding)) continue;
			visited.add(binding);
			const snippet_scope = /** @type {Scope} */ (scopes.get(binding.initial));

			if (can_hoist_snippet(snippet_scope, scopes, visited)) {
				continue;
			}
		}

		return false;
	}

	return true;
}

/** @import { AST } from '#compiler' */
/** @import { Context } from '../types' */


/**
 * @param {AST.SpreadAttribute} node
 * @param {Context} context
 */
function SpreadAttribute$2(node, context) {
	mark_subtree_dynamic(context.path);
	context.next({ ...context.state, expression: node.metadata.expression });
}

/** @import { SpreadElement } from 'estree' */
/** @import { Context } from '../types' */

/**
 * @param {SpreadElement} node
 * @param {Context} context
 */
function SpreadElement(node, context) {
	if (context.state.expression) {
		// treat e.g. `[...x]` the same as `[...x.values()]`
		context.state.expression.has_call = true;
		context.state.expression.has_state = true;
	}

	context.next();
}

/** @import { AST } from '#compiler' */
/** @import { Context } from '../types' */

/**
 * @param {AST.StyleDirective} node
 * @param {Context} context
 */
function StyleDirective(node, context) {
	if (node.modifiers.length > 1 || (node.modifiers.length && node.modifiers[0] !== 'important')) {
		style_directive_invalid_modifier(node);
	}

	mark_subtree_dynamic(context.path);

	if (node.value === true) {
		// get the binding for node.name and change the binding to state
		let binding = context.state.scope.get(node.name);

		if (binding) {
			if (binding.kind !== 'normal') {
				node.metadata.expression.has_state = true;
			}
			if (binding.blocker) {
				node.metadata.expression.dependencies.add(binding);
			}
		}
	} else {
		context.next();

		for (const chunk of get_attribute_chunks(node.value)) {
			if (chunk.type !== 'ExpressionTag') continue;

			node.metadata.expression.merge(chunk.metadata.expression);
		}
	}
}

/** @import { AST } from '#compiler' */
/** @import { Context } from '../types' */

/**
 * @param {AST.SvelteBody} node
 * @param {Context} context
 */
function SvelteBody$1(node, context) {
	disallow_children(node);
	for (const attribute of node.attributes) {
		if (
			attribute.type === 'SpreadAttribute' ||
			(attribute.type === 'Attribute' && !is_event_attribute(attribute))
		) {
			svelte_body_illegal_attribute(attribute);
		}
	}
	context.next();
}

/** @import { AST } from '#compiler' */
/** @import { Context } from '../types' */

/**
 * @param {AST.SvelteComponent} node
 * @param {Context} context
 */
function SvelteComponent$2(node, context) {
	if (context.state.analysis.runes) {
		svelte_component_deprecated(node);
	}

	context.visit(node.expression, { ...context.state, expression: node.metadata.expression });

	visit_component(node, context);
}

/** @import { AST } from '#compiler' */
/** @import { Context } from '../types' */

/**
 * @param {AST.SvelteDocument} node
 * @param {Context} context
 */
function SvelteDocument$1(node, context) {
	disallow_children(node);

	for (const attribute of node.attributes) {
		if (
			attribute.type === 'SpreadAttribute' ||
			(attribute.type === 'Attribute' && !is_event_attribute(attribute))
		) {
			illegal_element_attribute(attribute, 'svelte:document');
		}
	}

	context.next();
}

/** @import { AST } from '#compiler' */
/** @import { Context } from '../types' */

/**
 * @param {AST.SvelteElement} node
 * @param {Context} context
 */
function SvelteElement$2(node, context) {
	validate_element(node, context);
	check_element(node, context);

	node.metadata.path = [...context.path];
	context.state.analysis.elements.push(node);

	const xmlns = /** @type {AST.Attribute & { value: [AST.Text] } | undefined} */ (
		node.attributes.find(
			(a) => a.type === 'Attribute' && a.name === 'xmlns' && is_text_attribute(a)
		)
	);

	if (xmlns) {
		node.metadata.svg = xmlns.value[0].data === NAMESPACE_SVG;
		node.metadata.mathml = xmlns.value[0].data === NAMESPACE_MATHML;
	} else {
		let i = context.path.length;
		while (i--) {
			const ancestor = context.path[i];

			if (
				ancestor.type === 'Component' ||
				ancestor.type === 'SvelteComponent' ||
				ancestor.type === 'SvelteFragment' ||
				ancestor.type === 'SnippetBlock' ||
				i === 0
			) {
				// Root element, or inside a slot or a snippet -> this resets the namespace, so assume the component namespace
				node.metadata.svg = context.state.options.namespace === 'svg';
				node.metadata.mathml = context.state.options.namespace === 'mathml';
				break;
			}

			if (ancestor.type === 'SvelteElement' || ancestor.type === 'RegularElement') {
				node.metadata.svg =
					ancestor.type === 'RegularElement' && ancestor.name === 'foreignObject'
						? false
						: ancestor.metadata.svg;

				node.metadata.mathml =
					ancestor.type === 'RegularElement' && ancestor.name === 'foreignObject'
						? false
						: ancestor.metadata.mathml;

				break;
			}
		}
	}

	mark_subtree_dynamic(context.path);

	context.visit(node.tag, {
		...context.state,
		expression: node.metadata.expression
	});

	for (const attribute of node.attributes) {
		context.visit(attribute);
	}

	context.visit(node.fragment, {
		...context.state,
		parent_element: null
	});
}

/** @import { AST } from '#compiler' */
/** @import { Context } from '../types' */

/**
 * @param {AST.SvelteFragment} node
 * @param {Context} context
 */
function SvelteFragment$2(node, context) {
	const parent = context.path.at(-2);
	if (parent?.type !== 'Component' && parent?.type !== 'SvelteComponent') {
		svelte_fragment_invalid_placement(node);
	}

	for (const attribute of node.attributes) {
		if (attribute.type === 'Attribute') {
			if (attribute.name === 'slot') {
				validate_slot_attribute(context, attribute);
			}
		} else if (attribute.type !== 'LetDirective') {
			svelte_fragment_invalid_attribute(attribute);
		}
	}

	context.next({ ...context.state, parent_element: null });
}

/** @import { AST } from '#compiler' */
/** @import { Context } from '../types' */

/**
 * @param {AST.SvelteHead} node
 * @param {Context} context
 */
function SvelteHead$2(node, context) {
	for (const attribute of node.attributes) {
		svelte_head_illegal_attribute(attribute);
	}

	mark_subtree_dynamic(context.path);

	context.next();
}

/** @import { AST } from '#compiler' */
/** @import { Context } from '../types' */

/**
 * @param {AST.SvelteSelf} node
 * @param {Context} context
 */
function SvelteSelf$2(node, context) {
	const valid = context.path.some(
		(node) =>
			node.type === 'IfBlock' ||
			node.type === 'EachBlock' ||
			node.type === 'Component' ||
			node.type === 'SnippetBlock'
	);

	if (!valid) {
		svelte_self_invalid_placement(node);
	}

	if (context.state.analysis.runes) {
		const name = filename === UNKNOWN_FILENAME ? 'Self' : context.state.analysis.name;
		const basename =
			filename === UNKNOWN_FILENAME
				? 'Self.svelte'
				: /** @type {string} */ (filename.split(/[/\\]/).pop());

		svelte_self_deprecated(node, name, basename);
	}

	visit_component(node, context);
}

/** @import { AST } from '#compiler' */
/** @import { Context } from '../types' */

/**
 * @param {AST.SvelteWindow} node
 * @param {Context} context
 */
function SvelteWindow$1(node, context) {
	disallow_children(node);

	for (const attribute of node.attributes) {
		if (
			attribute.type === 'SpreadAttribute' ||
			(attribute.type === 'Attribute' && !is_event_attribute(attribute))
		) {
			illegal_element_attribute(attribute, 'svelte:window');
		}
	}

	context.next();
}

/** @import { AST } from '#compiler' */
/** @import { Context } from '../types' */

const valid = ['onerror', 'failed', 'pending'];

/**
 * @param {AST.SvelteBoundary} node
 * @param {Context} context
 */
function SvelteBoundary$2(node, context) {
	for (const attribute of node.attributes) {
		if (attribute.type !== 'Attribute' || !valid.includes(attribute.name)) {
			svelte_boundary_invalid_attribute(attribute);
		}

		if (
			attribute.value === true ||
			(Array.isArray(attribute.value) &&
				(attribute.value.length !== 1 || attribute.value[0].type !== 'ExpressionTag'))
		) {
			svelte_boundary_invalid_attribute_value(attribute);
		}
	}

	context.next();
}

/** @import { TaggedTemplateExpression } from 'estree' */
/** @import { Context } from '../types' */

/**
 * @param {TaggedTemplateExpression} node
 * @param {Context} context
 */
function TaggedTemplateExpression(node, context) {
	if (context.state.expression && !is_pure(node.tag, context)) {
		context.state.expression.has_call = true;
		context.state.expression.has_state = true;
	}

	context.next();
}

/** @import { TemplateElement } from 'estree' */

/**
 * @param {TemplateElement} node
 */
function TemplateElement(node) {
	if (regex_bidirectional_control_characters.test(node.value.cooked ?? '')) {
		bidirectional_control_characters(node);
	}
}

/** @import { AST } from '#compiler' */
/** @import { Context } from '../types' */

/**
 * @param {AST.Text} node
 * @param {Context} context
 */
function Text(node, context) {
	const parent = /** @type {AST.SvelteNode} */ (context.path.at(-1));

	if (
		parent.type === 'Fragment' &&
		context.state.parent_element &&
		regex_not_whitespace.test(node.data)
	) {
		const message = is_tag_valid_with_parent('#text', context.state.parent_element);
		if (message) {
			node_invalid_placement(node, message);
		}
	}

	regex_bidirectional_control_characters.lastIndex = 0;
	for (const match of node.data.matchAll(regex_bidirectional_control_characters)) {
		let is_ignored = false;

		// if we have a svelte-ignore comment earlier in the text, bail
		// (otherwise we can only use svelte-ignore on parent elements/blocks)
		if (parent.type === 'Fragment') {
			for (const child of parent.nodes) {
				if (child === node) break;

				if (child.type === 'Comment') {
					is_ignored ||= extract_svelte_ignore(
						child.start + 4,
						child.data,
						context.state.analysis.runes
					).includes('bidirectional_control_characters');
				}
			}
		}

		if (!is_ignored) {
			let start = match.index + node.start;
			bidirectional_control_characters({ start, end: start + match[0].length });
		}
	}
}

/** @import { AST } from '#compiler' */
/** @import { Context } from '../types' */

/**
 * @param {AST.TitleElement} node
 * @param {Context} context
 */
function TitleElement$2(node, context) {
	for (const attribute of node.attributes) {
		title_illegal_attribute(attribute);
	}

	for (const child of node.fragment.nodes) {
		if (child.type !== 'Text' && child.type !== 'ExpressionTag') {
			title_invalid_content(child);
		}
	}

	context.next();
}

/** @import { AST } from '#compiler' */
/** @import { Context } from '../types' */

/**
 * @param {AST.TransitionDirective} node
 * @param {Context} context
 */
function TransitionDirective$1(node, context) {
	mark_subtree_dynamic(context.path);

	context.next({ ...context.state, expression: node.metadata.expression });

	if (node.metadata.expression.has_await) {
		illegal_await_expression(node);
	}
}

/** @import { UpdateExpression } from 'estree' */
/** @import { Context } from '../types' */

/**
 * @param {UpdateExpression} node
 * @param {Context} context
 */
function UpdateExpression$2(node, context) {
	validate_assignment(node, node.argument, context);

	if (context.state.reactive_statement) {
		const id = node.argument.type === 'MemberExpression' ? object$1(node.argument) : node.argument;
		if (id?.type === 'Identifier') {
			const binding = context.state.scope.get(id.name);

			if (binding) {
				context.state.reactive_statement.assignments.add(binding);
			}
		}
	}

	if (context.state.expression) {
		context.state.expression.has_assignment = true;
	}

	context.next();
}

/** @import { AST } from '#compiler' */
/** @import { Context } from '../types' */

/**
 * @param {AST.UseDirective} node
 * @param {Context} context
 */
function UseDirective$1(node, context) {
	mark_subtree_dynamic(context.path);

	context.next({ ...context.state, expression: node.metadata.expression });

	if (node.metadata.expression.has_await) {
		illegal_await_expression(node);
	}
}

/**
 * @template T
 * @param {any} actual
 * @param {T} expected
 * @returns {asserts actual is T}
 */
function equal(actual, expected) {
	if (actual !== expected) throw new Error('Assertion failed');
}

/** @import { Expression, Identifier, Literal, VariableDeclarator } from 'estree' */
/** @import { Binding } from '#compiler' */
/** @import { Context } from '../types' */

/**
 * @param {VariableDeclarator} node
 * @param {Context} context
 */
function VariableDeclarator(node, context) {
	ensure_no_module_import_conflict(node, context.state);

	if (context.state.analysis.runes) {
		const init = node.init;
		const rune = get_rune(init, context.state.scope);
		const { paths } = extract_paths(node.id, id('dummy'));

		for (const path of paths) {
			validate_identifier_name(context.state.scope.get(/** @type {Identifier} */ (path.node).name));
		}

		// TODO feels like this should happen during scope creation?
		if (
			rune === '$state' ||
			rune === '$state.raw' ||
			rune === '$derived' ||
			rune === '$derived.by' ||
			rune === '$props'
		) {
			for (const path of paths) {
				// @ts-ignore this fails in CI for some insane reason
				const binding = /** @type {Binding} */ (context.state.scope.get(path.node.name));
				binding.kind =
					rune === '$state'
						? 'state'
						: rune === '$state.raw'
							? 'raw_state'
							: rune === '$derived' || rune === '$derived.by'
								? 'derived'
								: path.is_rest
									? 'rest_prop'
									: 'prop';
				if (rune === '$props' && binding.kind === 'rest_prop' && node.id.type === 'ObjectPattern') {
					const { properties } = node.id;
					/** @type {string[]} */
					const exclude_props = [];
					for (const property of properties) {
						if (property.type === 'RestElement') {
							continue;
						}
						const key = /** @type {Identifier | Literal & { value: string | number }} */ (
							property.key
						);
						exclude_props.push(key.type === 'Identifier' ? key.name : key.value.toString());
					}
					(binding.metadata ??= {}).exclude_props = exclude_props;
				}
			}
		}

		if (rune === '$props') {
			if (node.id.type !== 'ObjectPattern' && node.id.type !== 'Identifier') {
				props_invalid_identifier(node);
			}

			if (
				context.state.analysis.custom_element &&
				context.state.options.customElementOptions?.props == null
			) {
				let warn_on;
				if (
					node.id.type === 'Identifier' ||
					(warn_on = node.id.properties.find((p) => p.type === 'RestElement')) != null
				) {
					custom_element_props_identifier(warn_on ?? node.id);
				}
			}

			context.state.analysis.needs_props = true;

			if (node.id.type === 'Identifier') {
				const binding = /** @type {Binding} */ (context.state.scope.get(node.id.name));
				binding.initial = null; // else would be $props()
				binding.kind = 'rest_prop';
			} else {
				equal(node.id.type, 'ObjectPattern');

				for (const property of node.id.properties) {
					if (property.type !== 'Property') continue;

					if (property.computed) {
						props_invalid_pattern(property);
					}

					if (property.key.type === 'Identifier' && property.key.name.startsWith('$$')) {
						props_illegal_name(property);
					}

					const value =
						property.value.type === 'AssignmentPattern' ? property.value.left : property.value;

					if (value.type !== 'Identifier') {
						props_invalid_pattern(property);
					}

					const alias =
						property.key.type === 'Identifier'
							? property.key.name
							: String(/** @type {Literal} */ (property.key).value);

					let initial = property.value.type === 'AssignmentPattern' ? property.value.right : null;

					const binding = /** @type {Binding} */ (context.state.scope.get(value.name));
					binding.prop_alias = alias;

					// rewire initial from $props() to the actual initial value, stripping $bindable() if necessary
					if (
						initial?.type === 'CallExpression' &&
						initial.callee.type === 'Identifier' &&
						initial.callee.name === '$bindable'
					) {
						binding.initial = /** @type {Expression | null} */ (initial.arguments[0] ?? null);
						binding.kind = 'bindable_prop';
					} else {
						binding.initial = initial;
					}
				}
			}
		}
	} else {
		if (node.init?.type === 'CallExpression') {
			const callee = node.init.callee;
			if (
				callee.type === 'Identifier' &&
				(callee.name === '$state' || callee.name === '$derived' || callee.name === '$props') &&
				context.state.scope.get(callee.name)?.kind !== 'store_sub'
			) {
				rune_invalid_usage(node.init, callee.name);
			}
		}
	}

	context.next();
}

/** @import * as ESTree from 'estree' */
/** @import { Binding, AST, ValidatedCompileOptions, ValidatedModuleCompileOptions } from '#compiler' */
/** @import { AnalysisState, Visitors } from './types' */
/** @import { Analysis, ComponentAnalysis, Js, ReactiveStatement, Template } from '../types' */

/**
 * @type {Visitors}
 */
const visitors$2 = {
	_(node, { state, next, path }) {
		const parent = path.at(-1);

		/** @type {string[]} */
		const ignores = [];

		if (parent?.type === 'Fragment' && node.type !== 'Comment' && node.type !== 'Text') {
			const idx = parent.nodes.indexOf(/** @type {any} */ (node));

			for (let i = idx - 1; i >= 0; i--) {
				const prev = parent.nodes[i];

				if (prev.type === 'Comment') {
					ignores.push(
						...extract_svelte_ignore(
							prev.start + 4 /* '<!--'.length */,
							prev.data,
							state.analysis.runes
						)
					);
				} else if (prev.type !== 'Text') {
					break;
				}
			}
		} else {
			const comments = /** @type {any} */ (node).leadingComments;

			if (comments) {
				for (const comment of comments) {
					ignores.push(
						...extract_svelte_ignore(
							comment.start + 2 /* '//'.length */,
							comment.value,
							state.analysis.runes
						)
					);
				}
			}
		}

		if (ignores.length > 0) {
			push_ignore(ignores);
		}

		ignore_map.set(node, structuredClone(ignore_stack));

		const scope = state.scopes.get(node);
		next(scope !== undefined && scope !== state.scope ? { ...state, scope } : state);

		if (ignores.length > 0) {
			pop_ignore();
		}
	},
	AnimateDirective: AnimateDirective$1,
	ArrowFunctionExpression: ArrowFunctionExpression$1,
	AssignmentExpression: AssignmentExpression$2,
	AttachTag: AttachTag$1,
	Attribute: Attribute$1,
	AwaitBlock: AwaitBlock$2,
	AwaitExpression: AwaitExpression$2,
	BindDirective: BindDirective$1,
	CallExpression: CallExpression$2,
	ClassBody: ClassBody$2,
	ClassDeclaration,
	ClassDirective,
	Component: Component$2,
	ConstTag: ConstTag$2,
	DebugTag: DebugTag$2,
	EachBlock: EachBlock$2,
	ExportDefaultDeclaration,
	ExportNamedDeclaration: ExportNamedDeclaration$1,
	ExportSpecifier,
	ExpressionStatement: ExpressionStatement$2,
	ExpressionTag,
	Fragment: Fragment$2,
	FunctionDeclaration: FunctionDeclaration$1,
	FunctionExpression: FunctionExpression$1,
	HtmlTag: HtmlTag$2,
	Identifier: Identifier$2,
	IfBlock: IfBlock$2,
	ImportDeclaration,
	KeyBlock: KeyBlock$2,
	LabeledStatement: LabeledStatement$2,
	LetDirective: LetDirective$1,
	Literal,
	MemberExpression: MemberExpression$2,
	NewExpression,
	OnDirective: OnDirective$1,
	PropertyDefinition: PropertyDefinition$1,
	RegularElement: RegularElement$2,
	RenderTag: RenderTag$2,
	SlotElement: SlotElement$2,
	SnippetBlock: SnippetBlock$2,
	SpreadAttribute: SpreadAttribute$2,
	SpreadElement,
	StyleDirective,
	SvelteBody: SvelteBody$1,
	SvelteComponent: SvelteComponent$2,
	SvelteDocument: SvelteDocument$1,
	SvelteElement: SvelteElement$2,
	SvelteFragment: SvelteFragment$2,
	SvelteHead: SvelteHead$2,
	SvelteSelf: SvelteSelf$2,
	SvelteWindow: SvelteWindow$1,
	SvelteBoundary: SvelteBoundary$2,
	TaggedTemplateExpression,
	TemplateElement,
	Text,
	TransitionDirective: TransitionDirective$1,
	TitleElement: TitleElement$2,
	UpdateExpression: UpdateExpression$2,
	UseDirective: UseDirective$1,
	VariableDeclarator
};

/**
 * @param {AST.Script | null} script
 * @param {ScopeRoot} root
 * @param {boolean} allow_reactive_declarations
 * @param {Scope | null} parent
 * @returns {Js}
 */
function js(script, root, allow_reactive_declarations, parent) {
	/** @type {ESTree.Program} */
	const ast = script?.content ?? {
		type: 'Program',
		sourceType: 'module',
		start: -1,
		end: -1,
		body: []
	};

	const { scope, scopes, has_await } = create_scopes(
		ast,
		root,
		allow_reactive_declarations,
		parent
	);

	return { ast, scope, scopes, has_await };
}

/**
 * @param {string} filename
 */
function get_component_name(filename) {
	const parts = filename.split(/[/\\]/);
	const basename = /** @type {string} */ (parts.pop());
	const last_dir = /** @type {string} */ (parts.at(-1));
	let name = basename.replace('.svelte', '');
	if (name === 'index' && last_dir && last_dir !== 'src') {
		name = last_dir;
	}
	return name[0].toUpperCase() + name.slice(1);
}

const RESERVED = ['$$props', '$$restProps', '$$slots'];

/**
 * @param {string} source
 * @param {ValidatedModuleCompileOptions} options
 * @returns {Analysis}
 */
function analyze_module(source, options) {
	/** @type {AST.JSComment[]} */
	const comments = [];

	set_source(source);
	const ast = parse$3(source, comments, false, false);

	const { scope, scopes, has_await } = create_scopes(ast, new ScopeRoot(), false, null);

	for (const [name, references] of scope.references) {
		if (name[0] !== '$' || RESERVED.includes(name)) continue;
		if (name === '$' || name[1] === '$') {
			global_reference_invalid(references[0].node, name);
		}

		const binding = scope.get(name.slice(1));

		if (binding !== null && !is_rune(name)) {
			store_invalid_subscription_module(references[0].node);
		}
	}

	/** @type {Analysis} */
	const analysis = {
		module: { ast, scope, scopes, has_await },
		name: options.filename,
		accessors: false,
		runes: true,
		immutable: true,
		tracing: false,
		async_deriveds: new Set(),
		comments,
		classes: new Map(),
		pickled_awaits: new Set()
	};

	adjust({
		dev: options.dev,
		rootDir: options.rootDir,
		runes: true
	});

	walk$1(
		/** @type {ESTree.Node} */ (ast),
		{
			scope,
			scopes,
			analysis: /** @type {ComponentAnalysis} */ (analysis),
			state_fields: new Map(),
			// TODO the following are not needed for modules, but we have to pass them in order to avoid type error,
			// and reducing the type would result in a lot of tedious type casts elsewhere - find a good solution one day
			ast_type: /** @type {any} */ (null),
			component_slots: /** @type {Set<string>} */ (new Set()),
			expression: null,
			function_depth: 0,
			has_props_rune: false,
			options: /** @type {ValidatedCompileOptions} */ (options),
			fragment: null,
			parent_element: null,
			reactive_statement: null,
			derived_function_depth: -1
		},
		visitors$2
	);

	return analysis;
}

/**
 * @param {AST.Root} root
 * @param {string} source
 * @param {ValidatedCompileOptions} options
 * @returns {ComponentAnalysis}
 */
function analyze_component(root, source, options) {
	const scope_root = new ScopeRoot();

	const module = js(root.module, scope_root, false, null);
	const instance = js(root.instance, scope_root, true, module.scope);

	const { scope, scopes, has_await } = create_scopes(
		root.fragment,
		scope_root,
		false,
		instance.scope
	);

	/** @type {Template} */
	const template = { ast: root.fragment, scope, scopes };

	let synthetic_stores_legacy_check = [];

	// create synthetic bindings for store subscriptions
	for (const [name, references] of module.scope.references) {
		if (name[0] !== '$' || RESERVED.includes(name)) continue;
		if (name === '$' || name[1] === '$') {
			global_reference_invalid(references[0].node, name);
		}

		const store_name = name.slice(1);
		const declaration = instance.scope.get(store_name);
		const init = /** @type {ESTree.Node | undefined} */ (declaration?.initial);

		// If we're not in legacy mode through the compiler option, assume the user
		// is referencing a rune and not a global store.
		if (
			options.runes === false ||
			!is_rune(name) ||
			(declaration !== null &&
				// const state = $state(0) is valid
				(get_rune(init, instance.scope) === null ||
					// rune-line names received as props are valid too (but we have to protect against $props as store)
					(store_name !== 'props' && get_rune(init, instance.scope) === '$props')) &&
				// allow `import { derived } from 'svelte/store'` in the same file as `const x = $derived(..)` because one is not a subscription to the other
				!(
					name === '$derived' &&
					declaration.initial?.type === 'ImportDeclaration' &&
					declaration.initial.source.value === 'svelte/store'
				))
		) {
			let is_nested_store_subscription_node = undefined;
			search: for (const reference of references) {
				for (let i = reference.path.length - 1; i >= 0; i--) {
					const scope =
						scopes.get(reference.path[i]) ||
						module.scopes.get(reference.path[i]) ||
						instance.scopes.get(reference.path[i]);
					if (scope) {
						const owner = scope?.owner(store_name);
						if (!!owner && owner !== module.scope && owner !== instance.scope) {
							is_nested_store_subscription_node = reference.node;
							break search;
						}
						break;
					}
				}
			}

			if (is_nested_store_subscription_node) {
				store_invalid_scoped_subscription(is_nested_store_subscription_node);
			}

			if (options.runes !== false) {
				if (declaration === null && /[a-z]/.test(store_name[0])) {
					global_reference_invalid(references[0].node, name);
				} else if (declaration !== null && is_rune(name)) {
					for (const { node, path } of references) {
						if (path.at(-1)?.type === 'CallExpression') {
							store_rune_conflict(node, store_name);
						}
					}
				}
			}

			if (module.ast) {
				for (const { node, path } of references) {
					// if the reference is inside module, error. this is a bit hacky but it works
					if (
						/** @type {number} */ (node.start) > /** @type {number} */ (module.ast.start) &&
						/** @type {number} */ (node.end) < /** @type {number} */ (module.ast.end) &&
						// const state = $state(0) is valid
						get_rune(/** @type {ESTree.Node} */ (path.at(-1)), module.scope) === null
					) {
						store_invalid_subscription(node);
					}
				}
			}

			// we push to the array because at this moment in time we can't be sure if we are in legacy
			// mode yet because we are still changing the module scope
			synthetic_stores_legacy_check.push(() => {
				// if we are creating a synthetic binding for a let declaration we should also declare
				// the declaration as state in case it's reassigned and we are not in runes mode (the function will
				// not be called if we are not in runes mode, that's why there's no !runes check here)
				if (
					declaration !== null &&
					declaration.kind === 'normal' &&
					declaration.declaration_kind === 'let' &&
					declaration.reassigned
				) {
					declaration.kind = 'state';
				}
			});

			const binding = instance.scope.declare(id(name), 'store_sub', 'synthetic');
			binding.references = references;
			instance.scope.references.set(name, references);
			module.scope.references.delete(name);
		}
	}

	const component_name = get_component_name(options.filename);

	const runes =
		options.runes ??
		(has_await || instance.has_await || Array.from(module.scope.references.keys()).some(is_rune));

	if (!runes) {
		for (let check of synthetic_stores_legacy_check) {
			check();
		}
	}

	if (runes && root.module) {
		const context = root.module.attributes.find((attribute) => attribute.name === 'context');
		if (context) {
			script_context_deprecated(context);
		}
	}

	const is_custom_element = !!options.customElementOptions || options.customElement;

	const name = module.scope.generate(options.name ?? component_name);

	adjust({
		component_name: name,
		dev: options.dev,
		rootDir: options.rootDir,
		runes
	});

	// TODO remove all the ?? stuff, we don't need it now that we're validating the config
	/** @type {ComponentAnalysis} */
	const analysis = {
		name,
		root: scope_root,
		module,
		instance,
		template,
		comments: root.comments,
		elements: [],
		runes,
		// if we are not in runes mode but we have no reserved references ($$props, $$restProps)
		// and no `export let` we might be in a wannabe runes component that is using runes in an external
		// module...we need to fallback to the runic behavior
		maybe_runes:
			!runes &&
			// if they explicitly disabled runes, use the legacy behavior
			options.runes !== false &&
			![...module.scope.references.keys()].some((name) =>
				['$$props', '$$restProps'].includes(name)
			) &&
			!instance.ast.body.some(
				(node) =>
					node.type === 'LabeledStatement' ||
					(node.type === 'ExportNamedDeclaration' &&
						((node.declaration &&
							node.declaration.type === 'VariableDeclaration' &&
							node.declaration.kind === 'let') ||
							node.specifiers.some(
								(specifier) =>
									specifier.local.type === 'Identifier' &&
									instance.scope.get(specifier.local.name)?.declaration_kind === 'let'
							)))
			),
		tracing: false,
		classes: new Map(),
		immutable: runes || options.immutable,
		exports: [],
		uses_props: false,
		props_id: null,
		uses_rest_props: false,
		uses_slots: false,
		uses_component_bindings: false,
		uses_render_tags: false,
		needs_context: false,
		needs_mutation_validation: false,
		needs_props: false,
		event_directive_node: null,
		uses_event_attributes: false,
		custom_element: is_custom_element,
		inject_styles: options.css === 'injected' || is_custom_element,
		accessors:
			is_custom_element ||
			(runes ? false : !!options.accessors) ||
			// because $set method needs accessors
			options.compatibility?.componentApi === 4,
		reactive_statements: new Map(),
		binding_groups: new Map(),
		slot_names: new Map(),
		css: {
			ast: root.css,
			hash: root.css
				? options.cssHash({
						css: root.css.content.styles,
						filename: filename,
						name: component_name,
						hash
					})
				: '',
			keyframes: [],
			has_global: false
		},
		source,
		snippet_renderers: new Map(),
		snippets: new Set(),
		async_deriveds: new Set(),
		pickled_awaits: new Set(),
		instance_body: {
			sync: [],
			async: [],
			declarations: [],
			hoisted: []
		}
	};

	if (!runes) {
		// every exported `let` or `var` declaration becomes a prop, everything else becomes an export
		for (const node of instance.ast.body) {
			if (node.type !== 'ExportNamedDeclaration') continue;

			analysis.needs_props = true;

			if (node.declaration) {
				if (
					node.declaration.type === 'FunctionDeclaration' ||
					node.declaration.type === 'ClassDeclaration'
				) {
					analysis.exports.push({
						name: /** @type {import('estree').Identifier} */ (node.declaration.id).name,
						alias: null
					});
				} else if (node.declaration.type === 'VariableDeclaration') {
					if (node.declaration.kind === 'const') {
						for (const declarator of node.declaration.declarations) {
							for (const node of extract_identifiers(declarator.id)) {
								analysis.exports.push({ name: node.name, alias: null });
							}
						}
					} else {
						for (const declarator of node.declaration.declarations) {
							for (const id of extract_identifiers(declarator.id)) {
								const binding = /** @type {Binding} */ (instance.scope.get(id.name));
								binding.kind = 'bindable_prop';
							}
						}
					}
				}
			} else {
				for (const specifier of node.specifiers) {
					if (specifier.local.type !== 'Identifier' || specifier.exported.type !== 'Identifier') {
						continue;
					}

					const binding = instance.scope.get(specifier.local.name);

					if (
						binding &&
						(binding.declaration_kind === 'var' || binding.declaration_kind === 'let')
					) {
						binding.kind = 'bindable_prop';

						if (specifier.exported.name !== specifier.local.name) {
							binding.prop_alias = specifier.exported.name;
						}
					} else {
						analysis.exports.push({ name: specifier.local.name, alias: specifier.exported.name });
					}
				}
			}
		}

		// if reassigned/mutated bindings are referenced in `$:` blocks
		// or the template, turn them into state
		for (const binding of instance.scope.declarations.values()) {
			if (binding.kind !== 'normal') continue;

			for (const { node, path } of binding.references) {
				if (node === binding.node) continue;

				if (binding.updated) {
					if (
						path[path.length - 1].type === 'StyleDirective' ||
						path.some((node) => node.type === 'Fragment') ||
						(path[1].type === 'LabeledStatement' && path[1].label.name === '$')
					) {
						binding.kind = 'state';
					}
				}
			}
		}

		// more legacy nonsense: if an `each` binding is reassigned/mutated,
		// treat the expression as being mutated as well
		walk$1(/** @type {AST.SvelteNode} */ (template.ast), null, {
			EachBlock(node) {
				const scope = /** @type {Scope} */ (template.scopes.get(node));

				for (const binding of scope.declarations.values()) {
					if (binding.updated) {
						const state = { scope: /** @type {Scope} */ (scope.parent), scopes: template.scopes };

						walk$1(node.expression, state, {
							// @ts-expect-error
							_: set_scope,
							Identifier(node, context) {
								const parent = /** @type {ESTree.Expression} */ (context.path.at(-1));

								if (is_reference(node, parent)) {
									const binding = context.state.scope.get(node.name);

									if (
										binding &&
										binding.kind === 'normal' &&
										binding.declaration_kind !== 'import'
									) {
										binding.kind = 'state';
										binding.mutated = true;
									}
								}
							}
						});

						break;
					}
				}
			}
		});
	}

	if (root.options) {
		for (const attribute of root.options.attributes) {
			if (attribute.name === 'accessors' && analysis.runes) {
				options_deprecated_accessors(attribute);
			}

			if (attribute.name === 'customElement' && !options.customElement) {
				options_missing_custom_element(attribute);
			}

			if (attribute.name === 'immutable' && analysis.runes) {
				options_deprecated_immutable(attribute);
			}
		}
	}

	calculate_blockers(instance, scopes, analysis);

	if (analysis.runes) {
		const props_refs = module.scope.references.get('$$props');
		if (props_refs) {
			legacy_props_invalid(props_refs[0].node);
		}

		const rest_props_refs = module.scope.references.get('$$restProps');
		if (rest_props_refs) {
			legacy_rest_props_invalid(rest_props_refs[0].node);
		}

		for (const { ast, scope, scopes } of [module, instance, template]) {
			/** @type {AnalysisState} */
			const state = {
				scope,
				scopes,
				analysis,
				options,
				ast_type: ast === instance.ast ? 'instance' : ast === template.ast ? 'template' : 'module',
				fragment: ast === template.ast ? ast : null,
				parent_element: null,
				has_props_rune: false,
				component_slots: new Set(),
				expression: null,
				state_fields: new Map(),
				function_depth: scope.function_depth,
				reactive_statement: null,
				derived_function_depth: -1
			};

			walk$1(/** @type {AST.SvelteNode} */ (ast), state, visitors$2);
		}

		// warn on any nonstate declarations that are a) reassigned and b) referenced in the template
		for (const scope of [module.scope, instance.scope]) {
			outer: for (const [name, binding] of scope.declarations) {
				if (binding.kind === 'normal' && binding.reassigned) {
					inner: for (const { path } of binding.references) {
						if (path[0].type !== 'Fragment') continue;
						for (let i = 1; i < path.length; i += 1) {
							const type = path[i].type;
							if (
								type === 'FunctionDeclaration' ||
								type === 'FunctionExpression' ||
								type === 'ArrowFunctionExpression'
							) {
								continue inner;
							}
							// bind:this doesn't need to be a state reference if it will never change
							if (
								type === 'BindDirective' &&
								/** @type {AST.BindDirective} */ (path[i]).name === 'this'
							) {
								for (let j = i - 1; j >= 0; j -= 1) {
									const type = path[j].type;
									if (
										type === 'IfBlock' ||
										type === 'EachBlock' ||
										type === 'AwaitBlock' ||
										type === 'KeyBlock'
									) {
										non_reactive_update(binding.node, name);
										continue outer;
									}
								}
								continue inner;
							}
						}

						non_reactive_update(binding.node, name);
						continue outer;
					}
				}
			}
		}
	} else {
		instance.scope.declare(id('$$props'), 'rest_prop', 'synthetic');
		instance.scope.declare(id('$$restProps'), 'rest_prop', 'synthetic');

		for (const { ast, scope, scopes } of [module, instance, template]) {
			/** @type {AnalysisState} */
			const state = {
				scope,
				scopes,
				analysis,
				options,
				fragment: ast === template.ast ? ast : null,
				parent_element: null,
				has_props_rune: false,
				ast_type: ast === instance.ast ? 'instance' : ast === template.ast ? 'template' : 'module',
				reactive_statement: null,
				component_slots: new Set(),
				expression: null,
				state_fields: new Map(),
				function_depth: scope.function_depth,
				derived_function_depth: -1
			};

			walk$1(/** @type {AST.SvelteNode} */ (ast), state, visitors$2);
		}

		for (const [name, binding] of instance.scope.declarations) {
			if (
				(binding.kind === 'prop' || binding.kind === 'bindable_prop') &&
				binding.node.name !== '$$props'
			) {
				const references = binding.references.filter(
					(r) => r.node !== binding.node && r.path.at(-1)?.type !== 'ExportSpecifier'
				);
				if (!references.length && !instance.scope.declarations.has(`$${name}`)) {
					export_let_unused(binding.node, name);
				}
			}
		}

		analysis.reactive_statements = order_reactive_statements(analysis.reactive_statements);
	}

	for (const node of analysis.module.ast.body) {
		if (node.type === 'ExportNamedDeclaration' && node.specifiers !== null && node.source == null) {
			for (const specifier of node.specifiers) {
				if (specifier.local.type !== 'Identifier') continue;
				const name = specifier.local.name;
				const binding = analysis.module.scope.get(name);
				if (!binding) {
					if ([...analysis.snippets].find((snippet) => snippet.expression.name === name)) {
						snippet_invalid_export(specifier);
					} else {
						export_undefined(specifier, name);
					}
				}
			}
		}
	}

	if (analysis.event_directive_node && analysis.uses_event_attributes) {
		mixed_event_handler_syntaxes(
			analysis.event_directive_node,
			analysis.event_directive_node.name
		);
	}

	for (const [node, resolved] of analysis.snippet_renderers) {
		if (!resolved) {
			node.metadata.snippets = analysis.snippets;
		}

		for (const snippet of node.metadata.snippets) {
			snippet.metadata.sites.add(node);
		}
	}

	if (
		analysis.uses_render_tags &&
		(analysis.uses_slots || (!analysis.custom_element && analysis.slot_names.size > 0))
	) {
		const pos = analysis.slot_names.values().next().value ?? analysis.source.indexOf('$$slot');
		slot_snippet_conflict(pos);
	}

	if (analysis.css.ast) {
		analyze_css(analysis.css.ast, analysis);

		// mark nodes as scoped/unused/empty etc
		for (const node of analysis.elements) {
			prune(analysis.css.ast, node);
		}

		const { comment } = analysis.css.ast.content;
		const should_ignore_unused =
			comment &&
			extract_svelte_ignore(comment.start, comment.data, analysis.runes).includes(
				'css_unused_selector'
			);

		if (!should_ignore_unused) {
			warn_unused(analysis.css.ast);
		}
	}

	for (const node of analysis.elements) {
		if (node.metadata.scoped && is_custom_element_node(node)) {
			mark_subtree_dynamic(node.metadata.path);
		}

		let has_class = false;
		let has_style = false;
		let has_spread = false;
		let has_class_directive = false;
		let has_style_directive = false;

		for (const attribute of node.attributes) {
			// The spread method appends the hash to the end of the class attribute on its own
			if (attribute.type === 'SpreadAttribute') {
				has_spread = true;
				break;
			} else if (attribute.type === 'Attribute') {
				has_class ||= attribute.name.toLowerCase() === 'class';
				has_style ||= attribute.name.toLowerCase() === 'style';
			} else if (attribute.type === 'ClassDirective') {
				has_class_directive = true;
			} else if (attribute.type === 'StyleDirective') {
				has_style_directive = true;
			}
		}

		// We need an empty class to generate the set_class() or class="" correctly
		if (!has_spread && !has_class && (node.metadata.scoped || has_class_directive)) {
			node.attributes.push(
				create_attribute('class', -1, -1, [
					{
						type: 'Text',
						data: '',
						raw: '',
						start: -1,
						end: -1
					}
				])
			);
		}

		// We need an empty style to generate the set_style() correctly
		if (!has_spread && !has_style && has_style_directive) {
			node.attributes.push(
				create_attribute('style', -1, -1, [
					{
						type: 'Text',
						data: '',
						raw: '',
						start: -1,
						end: -1
					}
				])
			);
		}
	}

	// TODO
	// analysis.stylesheet.warn_on_unused_selectors(analysis);

	return analysis;
}

/**
 * Analyzes the instance's top level statements to calculate which bindings need to wait on which
 * top level statements. This includes indirect blockers such as functions referencing async top level statements.
 *
 * @param {Js} instance
 * @param {Map<AST.SvelteNode, Scope>} scopes
 * @param {ComponentAnalysis} analysis
 * @returns {void}
 */
function calculate_blockers(instance, scopes, analysis) {
	/**
	 * @param {ESTree.Node} expression
	 * @param {Scope} scope
	 * @param {Set<Binding>} touched
	 * @param {Set<ESTree.Node>} seen
	 */
	const touch = (expression, scope, touched, seen = new Set()) => {
		if (seen.has(expression)) return;
		seen.add(expression);

		walk$1(
			expression,
			{ scope },
			{
				ImportDeclaration(node) {},
				Identifier(node, context) {
					const parent = /** @type {ESTree.Node} */ (context.path.at(-1));
					if (is_reference(node, parent)) {
						const binding = context.state.scope.get(node.name);
						if (binding) {
							touched.add(binding);

							for (const assignment of binding.assignments) {
								touch(assignment.value, assignment.scope, touched, seen);
							}
						}
					}
				}
			}
		);
	};

	/**
	 * @param {ESTree.Node} node
	 * @param {Set<ESTree.Node>} seen
	 * @param {Set<Binding>} reads
	 * @param {Set<Binding>} writes
	 */
	const trace_references = (node, reads, writes, seen = new Set()) => {
		if (seen.has(node)) return;
		seen.add(node);

		/**
		 * @param {ESTree.Pattern} node
		 * @param {Scope} scope
		 */
		function update(node, scope) {
			for (const pattern of unwrap_pattern(node)) {
				const node = object$1(pattern);
				if (!node) return;

				const binding = scope.get(node.name);
				if (!binding) return;

				writes.add(binding);
			}
		}

		walk$1(
			node,
			{ scope: instance.scope },
			{
				_(node, context) {
					const scope = scopes.get(node);
					if (scope) {
						context.next({ scope });
					} else {
						context.next();
					}
				},
				AssignmentExpression(node, context) {
					update(node.left, context.state.scope);
				},
				UpdateExpression(node, context) {
					update(
						/** @type {ESTree.Identifier | ESTree.MemberExpression} */ (node.argument),
						context.state.scope
					);
				},
				CallExpression(node, context) {
					// for now, assume everything touched by the callee ends up mutating the object
					// TODO optimise this better

					// special case — no need to peek inside effects as they only run once async work has completed
					const rune = get_rune(node, context.state.scope);
					if (rune === '$effect') return;

					/** @type {Set<Binding>} */
					const touched = new Set();
					touch(node, context.state.scope, touched);

					for (const b of touched) {
						writes.add(b);
					}
				},
				// don't look inside functions until they are called
				ArrowFunctionExpression(_, context) {},
				FunctionDeclaration(_, context) {},
				FunctionExpression(_, context) {},
				Identifier(node, context) {
					const parent = /** @type {ESTree.Node} */ (context.path.at(-1));
					if (is_reference(node, parent)) {
						const binding = context.state.scope.get(node.name);
						if (binding) {
							reads.add(binding);
						}
					}
				}
			}
		);
	};

	let awaited = false;

	// TODO this should probably be attached to the scope?
	const promises = id('$$promises');

	/**
	 * @param {ESTree.Identifier} id
	 * @param {NonNullable<Binding['blocker']>} blocker
	 */
	function push_declaration(id, blocker) {
		analysis.instance_body.declarations.push(id);

		const binding = /** @type {Binding} */ (instance.scope.get(id.name));
		binding.blocker = blocker;
	}

	/**
	 * Analysis of blockers for functions is deferred until we know which statements are async/blockers
	 * @type {Array<ESTree.FunctionDeclaration | ESTree.VariableDeclarator>}
	 */
	const functions = [];

	for (let node of instance.ast.body) {
		if (node.type === 'ImportDeclaration') {
			analysis.instance_body.hoisted.push(node);
			continue;
		}

		if (node.type === 'ExportDefaultDeclaration' || node.type === 'ExportAllDeclaration') {
			// these can't exist inside `<script>` but TypeScript doesn't know that
			continue;
		}

		if (node.type === 'ExportNamedDeclaration') {
			if (node.declaration) {
				node = node.declaration;
			} else {
				continue;
			}
		}

		const has_await = has_await_expression(node);
		awaited ||= has_await;

		if (node.type === 'FunctionDeclaration') {
			analysis.instance_body.sync.push(node);
			functions.push(node);
		} else if (node.type === 'VariableDeclaration') {
			for (const declarator of node.declarations) {
				if (
					declarator.init?.type === 'ArrowFunctionExpression' ||
					declarator.init?.type === 'FunctionExpression'
				) {
					// One declarator per declaration, makes things simpler. The ternary ensures more accurate source maps in the common case
					analysis.instance_body.sync.push(
						node.declarations.length === 1 ? node : declaration(node.kind, [declarator])
					);
					functions.push(declarator);
				} else if (!awaited) {
					// One declarator per declaration, makes things simpler. The ternary ensures more accurate source maps in the common case
					analysis.instance_body.sync.push(
						node.declarations.length === 1 ? node : declaration(node.kind, [declarator])
					);
				} else {
					/** @type {Set<Binding>} */
					const reads = new Set(); // TODO we're not actually using this yet

					/** @type {Set<Binding>} */
					const writes = new Set();

					trace_references(declarator, reads, writes);

					const blocker = /** @type {NonNullable<Binding['blocker']>} */ (
						member(promises, literal(analysis.instance_body.async.length), true)
					);

					for (const binding of writes) {
						binding.blocker = blocker;
					}

					for (const id of extract_identifiers(declarator.id)) {
						push_declaration(id, blocker);
					}

					// one declarator per declaration, makes things simpler
					analysis.instance_body.async.push({
						node: declarator,
						has_await
					});
				}
			}
		} else if (awaited) {
			/** @type {Set<Binding>} */
			const reads = new Set(); // TODO we're not actually using this yet

			/** @type {Set<Binding>} */
			const writes = new Set();

			trace_references(node, reads, writes);

			const blocker = /** @type {NonNullable<Binding['blocker']>} */ (
				member(promises, literal(analysis.instance_body.async.length), true)
			);

			for (const binding of writes) {
				binding.blocker = blocker;
			}

			if (node.type === 'ClassDeclaration') {
				push_declaration(node.id, blocker);
				analysis.instance_body.async.push({ node, has_await });
			} else {
				analysis.instance_body.async.push({ node, has_await });
			}
		} else {
			analysis.instance_body.sync.push(node);
		}
	}

	for (const fn of functions) {
		/** @type {Set<Binding>} */
		const reads_writes = new Set();
		const body =
			fn.type === 'VariableDeclarator'
				? /** @type {ESTree.FunctionExpression | ESTree.ArrowFunctionExpression} */ (fn.init).body
				: fn.body;

		trace_references(body, reads_writes, reads_writes);

		const max = [...reads_writes].reduce((max, binding) => {
			if (binding.blocker) {
				let property = /** @type {ESTree.SimpleLiteral & { value: number }} */ (
					binding.blocker.property
				);

				return Math.max(property.value, max);
			}

			return max;
		}, -1);

		if (max === -1) continue;

		const blocker = member(promises, literal(max), true);
		const binding = /** @type {Binding} */ (
			fn.type === 'FunctionDeclaration'
				? instance.scope.get(fn.id.name)
				: instance.scope.get(/** @type {ESTree.Identifier} */ (fn.id).name)
		);

		binding.blocker = /** @type {typeof binding['blocker']} */ (blocker);
	}
}

/**
 * @param {Map<import('estree').LabeledStatement, ReactiveStatement>} unsorted_reactive_declarations
 */
function order_reactive_statements(unsorted_reactive_declarations) {
	/** @typedef {[import('estree').LabeledStatement, ReactiveStatement]} Tuple */

	/** @type {Map<string, Array<Tuple>>} */
	const lookup = new Map();

	for (const [node, declaration] of unsorted_reactive_declarations) {
		for (const binding of declaration.assignments) {
			const statements = lookup.get(binding.node.name) ?? [];
			statements.push([node, declaration]);
			lookup.set(binding.node.name, statements);
		}
	}

	/** @type {Array<[string, string]>} */
	const edges = [];

	for (const [, { assignments, dependencies }] of unsorted_reactive_declarations) {
		for (const assignment of assignments) {
			for (const dependency of dependencies) {
				if (!assignments.has(dependency)) {
					edges.push([assignment.node.name, dependency.node.name]);
				}
			}
		}
	}

	const cycle = check_graph_for_cycles(edges);
	if (cycle?.length) {
		const declaration = /** @type {Tuple[]} */ (lookup.get(cycle[0]))[0];
		reactive_declaration_cycle(declaration[0], cycle.join(' → '));
	}

	// We use a map and take advantage of the fact that the spec says insertion order is preserved when iterating
	/** @type {Map<import('estree').LabeledStatement, ReactiveStatement>} */
	const reactive_declarations = new Map();

	/**
	 *
	 * @param {import('estree').LabeledStatement} node
	 * @param {ReactiveStatement} declaration
	 * @returns
	 */
	const add_declaration = (node, declaration) => {
		if ([...reactive_declarations.values()].includes(declaration)) return;

		for (const binding of declaration.dependencies) {
			if (declaration.assignments.has(binding)) continue;
			for (const [node, earlier] of lookup.get(binding.node.name) ?? []) {
				add_declaration(node, earlier);
			}
		}

		reactive_declarations.set(node, declaration);
	};

	for (const [node, declaration] of unsorted_reactive_declarations) {
		add_declaration(node, declaration);
	}

	return reactive_declarations;
}

// src/vlq.ts
var comma = ",".charCodeAt(0);
var semicolon = ";".charCodeAt(0);
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var intToChar = new Uint8Array(64);
var charToInt = new Uint8Array(128);
for (let i = 0; i < chars.length; i++) {
  const c = chars.charCodeAt(i);
  intToChar[i] = c;
  charToInt[c] = i;
}
function decodeInteger(reader, relative) {
  let value = 0;
  let shift = 0;
  let integer = 0;
  do {
    const c = reader.next();
    integer = charToInt[c];
    value |= (integer & 31) << shift;
    shift += 5;
  } while (integer & 32);
  const shouldNegate = value & 1;
  value >>>= 1;
  if (shouldNegate) {
    value = -2147483648 | -value;
  }
  return relative + value;
}
function encodeInteger(builder, num, relative) {
  let delta = num - relative;
  delta = delta < 0 ? -delta << 1 | 1 : delta << 1;
  do {
    let clamped = delta & 31;
    delta >>>= 5;
    if (delta > 0) clamped |= 32;
    builder.write(intToChar[clamped]);
  } while (delta > 0);
  return num;
}
function hasMoreVlq(reader, max) {
  if (reader.pos >= max) return false;
  return reader.peek() !== comma;
}

// src/strings.ts
var bufLength = 1024 * 16;
var td = typeof TextDecoder !== "undefined" ? /* @__PURE__ */ new TextDecoder() : typeof Buffer !== "undefined" ? {
  decode(buf) {
    const out = Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength);
    return out.toString();
  }
} : {
  decode(buf) {
    let out = "";
    for (let i = 0; i < buf.length; i++) {
      out += String.fromCharCode(buf[i]);
    }
    return out;
  }
};
var StringWriter = class {
  constructor() {
    this.pos = 0;
    this.out = "";
    this.buffer = new Uint8Array(bufLength);
  }
  write(v) {
    const { buffer } = this;
    buffer[this.pos++] = v;
    if (this.pos === bufLength) {
      this.out += td.decode(buffer);
      this.pos = 0;
    }
  }
  flush() {
    const { buffer, out, pos } = this;
    return pos > 0 ? out + td.decode(buffer.subarray(0, pos)) : out;
  }
};
var StringReader = class {
  constructor(buffer) {
    this.pos = 0;
    this.buffer = buffer;
  }
  next() {
    return this.buffer.charCodeAt(this.pos++);
  }
  peek() {
    return this.buffer.charCodeAt(this.pos);
  }
  indexOf(char) {
    const { buffer, pos } = this;
    const idx = buffer.indexOf(char, pos);
    return idx === -1 ? buffer.length : idx;
  }
};

// src/sourcemap-codec.ts
function decode(mappings) {
  const { length } = mappings;
  const reader = new StringReader(mappings);
  const decoded = [];
  let genColumn = 0;
  let sourcesIndex = 0;
  let sourceLine = 0;
  let sourceColumn = 0;
  let namesIndex = 0;
  do {
    const semi = reader.indexOf(";");
    const line = [];
    let sorted = true;
    let lastCol = 0;
    genColumn = 0;
    while (reader.pos < semi) {
      let seg;
      genColumn = decodeInteger(reader, genColumn);
      if (genColumn < lastCol) sorted = false;
      lastCol = genColumn;
      if (hasMoreVlq(reader, semi)) {
        sourcesIndex = decodeInteger(reader, sourcesIndex);
        sourceLine = decodeInteger(reader, sourceLine);
        sourceColumn = decodeInteger(reader, sourceColumn);
        if (hasMoreVlq(reader, semi)) {
          namesIndex = decodeInteger(reader, namesIndex);
          seg = [genColumn, sourcesIndex, sourceLine, sourceColumn, namesIndex];
        } else {
          seg = [genColumn, sourcesIndex, sourceLine, sourceColumn];
        }
      } else {
        seg = [genColumn];
      }
      line.push(seg);
      reader.pos++;
    }
    if (!sorted) sort(line);
    decoded.push(line);
    reader.pos = semi + 1;
  } while (reader.pos <= length);
  return decoded;
}
function sort(line) {
  line.sort(sortComparator$1);
}
function sortComparator$1(a, b) {
  return a[0] - b[0];
}
function encode(decoded) {
  const writer = new StringWriter();
  let sourcesIndex = 0;
  let sourceLine = 0;
  let sourceColumn = 0;
  let namesIndex = 0;
  for (let i = 0; i < decoded.length; i++) {
    const line = decoded[i];
    if (i > 0) writer.write(semicolon);
    if (line.length === 0) continue;
    let genColumn = 0;
    for (let j = 0; j < line.length; j++) {
      const segment = line[j];
      if (j > 0) writer.write(comma);
      genColumn = encodeInteger(writer, segment[0], genColumn);
      if (segment.length === 1) continue;
      sourcesIndex = encodeInteger(writer, segment[1], sourcesIndex);
      sourceLine = encodeInteger(writer, segment[2], sourceLine);
      sourceColumn = encodeInteger(writer, segment[3], sourceColumn);
      if (segment.length === 4) continue;
      namesIndex = encodeInteger(writer, segment[4], namesIndex);
    }
  }
  return writer.flush();
}

/** @import { TSESTree } from '@typescript-eslint/types' */
/** @import { BaseNode, Command, Visitors } from './types' */

const margin = 0;
const newline = 1;
const indent = 2;
const dedent = 3;
const space = 4;

class Context {
	#visitors;
	#commands;
	#has_newline = false;

	multiline = false;

	/**
	 *
	 * @param {Visitors} visitors
	 * @param {Command[]} commands
	 */
	constructor(visitors, commands = []) {
		this.#visitors = visitors;
		this.#commands = commands;
	}

	indent() {
		this.#commands.push(indent);
	}

	dedent() {
		this.#commands.push(dedent);
	}

	margin() {
		this.#commands.push(margin);
	}

	newline() {
		this.#has_newline = true;
		this.#commands.push(newline);
	}

	space() {
		this.#commands.push(space);
	}

	/**
	 * @param {Context} context
	 */
	append(context) {
		this.#commands.push(context.#commands);

		if (this.#has_newline) {
			this.multiline = true;
		}
	}

	/**
	 *
	 * @param {string} content
	 * @param {BaseNode} [node]
	 */
	write(content, node) {
		if (node?.loc) {
			this.location(node.loc.start.line, node.loc.start.column);
			this.#commands.push(content);
			this.location(node.loc.end.line, node.loc.end.column);
		} else {
			this.#commands.push(content);
		}

		if (this.#has_newline) {
			this.multiline = true;
		}
	}

	/**
	 *
	 * @param {number} line
	 * @param {number} column
	 */
	location(line, column) {
		this.#commands.push({ type: 'Location', line, column });
	}

	/**
	 * @param {{ type: string }} node
	 */
	visit(node) {
		const visitor = this.#visitors[node.type];

		if (!visitor) {
			let message = `Not implemented: ${node.type}`;

			if (node.type.includes('TS')) {
				message += ` (consider using 'esrap/languages/ts')`;
			}

			if (node.type.includes('JSX')) {
				message += ` (consider using 'esrap/languages/tsx')`;
			}

			throw new Error(message);
		}

		if (this.#visitors._) {
			// @ts-ignore
			this.#visitors._(node, this, (node) => visitor(node, this));
		} else {
			// @ts-ignore
			visitor(node, this);
		}
	}

	empty() {
		return !this.#commands.some(has_content);
	}

	measure() {
		return measure(this.#commands);
	}

	new() {
		return new Context(this.#visitors);
	}
}

/**
 *
 * @param {Command[]} commands
 * @param {number} [from]
 * @param {number} [to]
 */
function measure(commands, from = 0, to = commands.length) {
	let total = 0;

	for (let i = from; i < to; i += 1) {
		const command = commands[i];

		if (typeof command === 'string') {
			total += command.length;
		} else if (Array.isArray(command)) {
			total += measure(command);
		}
	}

	return total;
}

/**
 * @param {Command} command
 */
function has_content(command) {
	if (Array.isArray(command)) {
		return command.some(has_content);
	}

	if (typeof command === 'string') {
		return command.length > 0;
	}

	return false;
}

/** @import { BaseNode, Command, Visitors, PrintOptions } from './types' */

/** @type {(str: string) => string} str */
let btoa$2 = () => {
	throw new Error('Unsupported environment: `window.btoa` or `Buffer` should be supported.');
};

if (typeof window !== 'undefined' && typeof window.btoa === 'function') {
	btoa$2 = (str) => window.btoa(unescape(encodeURIComponent(str)));
} else if (typeof Buffer === 'function') {
	btoa$2 = (str) => Buffer.from(str, 'utf-8').toString('base64');
}

let SourceMap$2 = class SourceMap {
	version = 3;

	/** @type {string[]} */
	names = [];

	/**
	 * @param {[number, number, number, number][][]} mappings
	 * @param {PrintOptions} opts
	 */
	constructor(mappings, opts) {
		this.sources = [opts.sourceMapSource || null];
		this.sourcesContent = [opts.sourceMapContent || null];
		this.mappings = opts.sourceMapEncodeMappings === false ? mappings : encode(mappings);
	}

	/**
	 * Returns a JSON representation suitable for saving as a `*.map` file
	 */
	toString() {
		return JSON.stringify(this);
	}

	/**
	 * Returns a base64-encoded JSON representation suitable for inlining at the bottom of a file with `//# sourceMappingURL={...}`
	 */
	toUrl() {
		return 'data:application/json;charset=utf-8;base64,' + btoa$2(this.toString());
	}
};

/**
 * @template {BaseNode} [T=BaseNode]
 * @param {T} node
 * @param {Visitors<T>} visitors
 * @param {PrintOptions} opts
 * @returns {{ code: string, map: any }} // TODO
 */
function print(node, visitors, opts = {}) {
	/** @type {Command[]} */
	const commands = [];

	// @ts-expect-error some nonsense I don't understand
	const context = new Context(visitors, commands);

	context.visit(node);

	/** @typedef {[number, number, number, number]} Segment */

	let code = '';
	let current_column = 0;

	/** @type {Segment[][]} */
	let mappings = [];

	/** @type {Segment[]} */
	let current_line = [];

	/** @param {string} str */
	function append(str) {
		code += str;

		for (let i = 0; i < str.length; i += 1) {
			if (str[i] === '\n') {
				mappings.push(current_line);
				current_line = [];
				current_column = 0;
			} else {
				current_column += 1;
			}
		}
	}

	let current_newline = '\n';
	const indent_str = opts.indent ?? '\t';

	let needs_newline = false;
	let needs_margin = false;
	let needs_space = false;

	/** @param {Command} command */
	function run(command) {
		if (Array.isArray(command)) {
			for (let i = 0; i < command.length; i += 1) {
				run(command[i]);
			}
			return;
		}

		if (typeof command === 'number') {
			if (command === newline) {
				needs_newline = true;
			} else if (command === margin) {
				needs_margin = true;
			} else if (command === space) {
				needs_space = true;
			} else if (command === indent) {
				current_newline += indent_str;
			} else if (command === dedent) {
				current_newline = current_newline.slice(0, -indent_str.length);
			}

			return;
		}

		if (needs_newline) {
			append(needs_margin ? '\n' + current_newline : current_newline);
		} else if (needs_space) {
			append(' ');
		}

		needs_margin = needs_newline = needs_space = false;

		if (typeof command === 'string') {
			append(command);
			return;
		}

		if (command.type === 'Location') {
			current_line.push([
				current_column,
				0, // source index is always zero
				command.line - 1,
				command.column
			]);
		}
	}

	for (let i = 0; i < commands.length; i += 1) {
		run(commands[i]);
	}

	mappings.push(current_line);

	/** @type {SourceMap} */
	let map;

	return {
		code,
		// create sourcemap lazily in case we don't need it
		get map() {
			return (map ??= new SourceMap$2(mappings, opts));
		}
	};
}

/** @import { TSESTree } from '@typescript-eslint/types' */
/** @import { Visitors } from '../../types.js' */
/** @import { TSOptions, Comment } from '../types.js' */

/** @typedef {TSESTree.Node} Node */

/** @type {Record<TSESTree.Expression['type'] | 'Super' | 'RestElement', number>} */
const EXPRESSIONS_PRECEDENCE = {
	JSXFragment: 20,
	JSXElement: 20,
	ArrayPattern: 20,
	ObjectPattern: 20,
	ArrayExpression: 20,
	TaggedTemplateExpression: 20,
	ThisExpression: 20,
	Identifier: 20,
	TemplateLiteral: 20,
	Super: 20,
	SequenceExpression: 20,
	MemberExpression: 19,
	MetaProperty: 19,
	CallExpression: 19,
	ChainExpression: 19,
	ImportExpression: 19,
	NewExpression: 19,
	Literal: 18,
	TSSatisfiesExpression: 18,
	TSInstantiationExpression: 18,
	TSNonNullExpression: 18,
	TSTypeAssertion: 18,
	AwaitExpression: 17,
	ClassExpression: 17,
	FunctionExpression: 17,
	ObjectExpression: 17,
	TSAsExpression: 16,
	UpdateExpression: 16,
	UnaryExpression: 15,
	BinaryExpression: 14,
	LogicalExpression: 13,
	ConditionalExpression: 4,
	ArrowFunctionExpression: 3,
	AssignmentExpression: 3,
	YieldExpression: 2,
	RestElement: 1
};

const OPERATOR_PRECEDENCE = {
	'||': 2,
	'&&': 3,
	'??': 4,
	'|': 5,
	'^': 6,
	'&': 7,
	'==': 8,
	'!=': 8,
	'===': 8,
	'!==': 8,
	'<': 9,
	'>': 9,
	'<=': 9,
	'>=': 9,
	in: 9,
	instanceof: 9,
	'<<': 10,
	'>>': 10,
	'>>>': 10,
	'+': 11,
	'-': 11,
	'*': 12,
	'%': 12,
	'/': 12,
	'**': 13
};

/**
 * @param {Comment} comment
 * @param {Context} context
 */
function write_comment(comment, context) {
	if (comment.type === 'Line') {
		context.write(`//${comment.value}`);
	} else {
		context.write('/*');
		const lines = comment.value.split('\n');

		for (let i = 0; i < lines.length; i += 1) {
			if (i > 0) context.newline();
			context.write(lines[i]);
		}

		context.write('*/');
	}
}

/**
 * @param {TSOptions} [options]
 * @returns {Visitors<TSESTree.Node>}
 */
var ts = (options = {}) => {
	const quote_char = options.quotes === 'double' ? '"' : "'";

	const comments = options.comments ?? [];

	let comment_index = 0;

	/**
	 * Set `comment_index` to be the first comment after `start`.
	 * Most of the time this is already correct, but if nodes
	 * have been moved around we may need to search for it
	 * @param {TSESTree.Node} node
	 */
	function reset_comment_index(node) {
		if (!node.loc) {
			comment_index = comments.length;
			return;
		}

		let previous = comments[comment_index - 1];
		let comment = comments[comment_index];

		if (
			comment &&
			comment.loc &&
			!before(comment.loc.start, node.loc.start) &&
			(!previous || (previous.loc && before(previous.loc.start, node.loc.start)))
		) {
			return;
		}

		// TODO use a binary search here, account for synthetic nodes (without `loc`)
		comment_index = comments.findIndex(
			(comment) => comment.loc && node.loc && !before(comment.loc.start, node.loc.start)
		);
		if (comment_index === -1) comment_index = comments.length;
	}

	/**
	 * @param {Context} context
	 * @param {{ line: number, column: number } | null} prev
	 * @param {{ line: number, column: number } | null} next
	 */
	function flush_trailing_comments(context, prev, next) {
		while (comment_index < comments.length) {
			const comment = comments[comment_index];

			if (
				comment &&
				prev &&
				comment.loc.start.line === prev.line &&
				(next === null || before(comment.loc.end, next))
			) {
				context.write(' ');
				write_comment(comment, context);

				comment_index += 1;

				if (comment.type === 'Line') {
					context.newline();
				} else {
					continue;
				}
			}

			break;
		}
	}

	/**
	 * @param {Context} context
	 * @param {{ line: number, column: number } | null} from
	 * @param {{ line: number, column: number }} to
	 * @param {boolean} pad
	 */
	function flush_comments_until(context, from, to, pad) {
		let first = true;

		while (comment_index < comments.length) {
			const comment = comments[comment_index];

			if (comment && comment.loc && to && before(comment.loc.start, to)) {
				if (first && from !== null && comment.loc.start.line > from.line) {
					context.margin();
					context.newline();
				}

				first = false;

				write_comment(comment, context);

				if (comment.loc.end.line < to.line) {
					context.newline();
				} else if (pad) {
					context.write(' ');
				}

				comment_index += 1;
			} else {
				break;
			}
		}
	}

	/**
	 * @param {Context} context
	 * @param {TSESTree.Node[]} nodes
	 * @param {{ line: number, column: number }} until
	 * @param {boolean} pad
	 */
	function sequence(context, nodes, until, pad, separator = ',') {
		let multiline = false;
		let length = -1;

		/** @type {boolean[]} */
		const multiline_nodes = [];

		const children = nodes.map((child, i) => {
			const child_context = context.new();
			if (child) child_context.visit(child);

			multiline_nodes[i] = child_context.multiline;

			if (i < nodes.length - 1 || !child) {
				child_context.write(separator);
			}

			const next = i === nodes.length - 1 ? until : nodes[i + 1]?.loc?.start || null;
			flush_trailing_comments(child_context, child?.loc?.end || null, next);

			length += child_context.measure() + 1;
			multiline ||= child_context.multiline;

			return child_context;
		});

		multiline ||= length > 60;

		if (multiline) {
			context.indent();
			context.newline();
		} else if (pad && length > 0) {
			context.write(' ');
		}

		/** @type {Context | null} */
		let prev = null;

		for (let i = 0; i < nodes.length; i += 1) {
			const child = children[i];

			if (prev !== null) {
				if (multiline_nodes[i - 1] || multiline_nodes[i]) {
					context.margin();
				}

				if (nodes[i]) {
					if (multiline) {
						context.newline();
					} else {
						context.write(' ');
					}
				}
			}

			context.append(child);

			prev = child;
		}

		flush_comments_until(context, nodes[nodes.length - 1]?.loc?.end ?? null, until, false);

		if (multiline) {
			context.dedent();
			context.newline();
		} else if (pad && length > 0) {
			context.write(' ');
		}
	}

	/**
	 * Push a sequence of nodes onto separate lines, separating them with
	 * an extra newline where appropriate
	 * @param {Context} context
	 * @param {TSESTree.Node & { body: TSESTree.Node[] }} node
	 */
	function body(context, node) {
		reset_comment_index(node);

		/** @type {string | null} */
		let prev_type = null;
		let prev_multiline = false;

		for (let i = 0; i < node.body.length; i += 1) {
			const child = node.body[i];
			if (child.type === 'EmptyStatement') continue;

			const child_context = context.new();
			child_context.visit(child);

			if (prev_type !== null) {
				if (child_context.multiline || prev_multiline || child.type !== prev_type) {
					context.margin();
				}

				context.newline();
			}

			context.append(child_context);

			flush_trailing_comments(
				context,
				child.loc?.end || null,
				node.body[i + 1]?.loc?.end ?? node.loc?.end ?? null
			);

			prev_type = child.type;
			prev_multiline = child_context.multiline;
		}

		if (node.loc) {
			context.newline();
			flush_comments_until(
				context,
				node.body[node.body.length - 1]?.loc?.end ?? null,
				node.loc.end,
				false
			);
		}
	}

	const shared = {
		/**
		 * @param {TSESTree.ArrayExpression | TSESTree.ArrayPattern} node
		 * @param {Context} context
		 */
		'ArrayExpression|ArrayPattern': (node, context) => {
			context.write('[');
			sequence(
				context,
				/** @type {TSESTree.Node[]} */ (node.elements),
				node.loc?.end ?? null,
				false
			);
			context.write(']');
		},

		/**
		 * @param {TSESTree.BinaryExpression | TSESTree.LogicalExpression} node
		 * @param {Context} context
		 */
		'BinaryExpression|LogicalExpression': (node, context) => {
			// TODO
			// const is_in = node.operator === 'in';
			// if (is_in) {
			// 	// Avoids confusion in `for` loops initializers
			// 	chunks.write('(');
			// }
			if (needs_parens(node.left, node, false)) {
				context.write('(');
				context.visit(node.left);
				context.write(')');
			} else {
				context.visit(node.left);
			}

			context.write(` ${node.operator} `);

			if (needs_parens(node.right, node, true)) {
				context.write('(');
				context.visit(node.right);
				context.write(')');
			} else {
				context.visit(node.right);
			}
		},

		/**
		 * @param {TSESTree.BlockStatement | TSESTree.ClassBody} node
		 * @param {Context} context
		 */
		'BlockStatement|ClassBody': (node, context) => {
			if (node.loc) {
				const { line, column } = node.loc.start;
				context.location(line, column);
				context.write('{');
				context.location(line, column + 1);
			} else {
				context.write('{');
			}

			const child_context = context.new();
			body(child_context, node);

			if (!child_context.empty()) {
				context.indent();
				context.newline();
				context.append(child_context);
				context.dedent();
				context.newline();
			}

			if (node.loc) {
				const { line, column } = node.loc.end;

				context.location(line, column - 1);
				context.write('}');
				context.location(line, column);
			} else {
				context.write('}');
			}
		},

		/**
		 * @param {TSESTree.CallExpression | TSESTree.NewExpression} node
		 * @param {Context} context
		 */
		'CallExpression|NewExpression': (node, context) => {
			if (node.type === 'NewExpression') {
				context.write('new ');
			}

			const needs_parens =
				EXPRESSIONS_PRECEDENCE[node.callee.type] < EXPRESSIONS_PRECEDENCE.CallExpression ||
				(node.type === 'NewExpression' && has_call_expression(node.callee));

			if (needs_parens) {
				context.write('(');
				context.visit(node.callee);
				context.write(')');
			} else {
				context.visit(node.callee);
			}

			if (/** @type {TSESTree.CallExpression} */ (node).optional) {
				context.write('?.');
			}

			if (node.typeArguments) context.visit(node.typeArguments);

			const open = context.new();
			const join = context.new();

			context.write('(');
			context.append(open);

			// if the final argument is multiline, it doesn't need to force all the
			// other arguments to also be multiline
			const child_context = context.new();
			const final_context = context.new();

			context.append(child_context);
			context.append(final_context);

			for (let i = 0; i < node.arguments.length; i += 1) {
				const is_last = i === node.arguments.length - 1;
				const context = is_last ? final_context : child_context;
				const arg = node.arguments[i];

				// special case — if final argument has a comment above it,
				// we make the whole sequence multiline
				if (
					is_last &&
					arg.loc &&
					comments[comment_index] &&
					comments[comment_index].loc &&
					comments[comment_index].loc.start.line < arg.loc.start.line
				) {
					child_context.multiline = true;
				}

				context.visit(arg);

				if (!is_last) context.write(',');

				const next = is_last
					? (node.loc?.end ?? null)
					: (node.arguments[i + 1]?.loc?.start ?? null);

				flush_trailing_comments(context, arg.loc?.end ?? null, next);

				if (!is_last) context.append(join);
			}

			context.multiline ||= child_context.multiline || final_context.multiline;

			if (child_context.multiline) {
				open.indent();
				open.newline();
				join.newline();
				context.dedent();
				context.newline();
			} else {
				join.write(' ');
			}

			context.write(')');
		},

		/**
		 * @param {TSESTree.ClassDeclaration | TSESTree.ClassExpression} node
		 * @param {Context} context
		 */
		'ClassDeclaration|ClassExpression': (node, context) => {
			if (node.decorators) {
				for (const decorator of node.decorators) {
					context.visit(decorator);
				}
			}

			if (node.declare) {
				context.write('declare ');
			}

			if (node.abstract) context.write('abstract ');

			context.write('class ');

			if (node.id) {
				context.visit(node.id);
				context.write(' ');
			}

			if (node.superClass) {
				context.write('extends ');
				context.visit(node.superClass);
				context.write(' ');
			}

			if (node.implements && node.implements.length > 0) {
				context.write('implements');
				sequence(context, node.implements, node.body.loc?.start ?? null, true);
			}

			context.visit(node.body);
		},

		/**
		 * @param {TSESTree.ForInStatement | TSESTree.ForOfStatement} node
		 * @param {Context} context
		 */
		'ForInStatement|ForOfStatement': (node, context) => {
			context.write('for ');
			if (node.type === 'ForOfStatement' && node.await) context.write('await ');
			context.write('(');

			if (node.left.type === 'VariableDeclaration') {
				handle_var_declaration(node.left, context);
			} else {
				context.visit(node.left);
			}

			context.write(node.type === 'ForInStatement' ? ' in ' : ' of ');
			context.visit(node.right);
			context.write(') ');
			context.visit(node.body);
		},

		/**
		 * @param {TSESTree.FunctionDeclaration | TSESTree.FunctionExpression} node
		 * @param {Context} context
		 */
		'FunctionDeclaration|FunctionExpression': (node, context) => {
			if (node.async) context.write('async ');
			context.write(node.generator ? 'function* ' : 'function ');
			if (node.id) context.visit(node.id);

			if (node.typeParameters) {
				context.visit(node.typeParameters);
			}

			context.write('(');
			sequence(context, node.params, (node.returnType ?? node.body).loc?.start ?? null, false);
			context.write(')');

			if (node.returnType) context.visit(node.returnType);

			context.write(' ');

			context.visit(node.body);
		},

		/**
		 * @param {TSESTree.MethodDefinition | TSESTree.TSAbstractMethodDefinition} node
		 * @param {Context} context
		 */
		'MethodDefinition|TSAbstractMethodDefinition': (node, context) => {
			if (node.decorators) {
				for (const decorator of node.decorators) {
					context.visit(decorator);
				}
			}

			// @ts-expect-error `acorn-typescript` and `@typescript-eslint/types` have slightly different type definitions
			if (node.abstract || node.type === 'TSAbstractMethodDefinition') {
				context.write('abstract ');
			}

			if (node.static) {
				context.write('static ');
			}

			if (node.kind === 'get' || node.kind === 'set') {
				// Getter or setter
				context.write(node.kind + ' ');
			}

			if (node.value.async) {
				context.write('async ');
			}

			if (node.value.generator) {
				context.write('*');
			}

			if (node.computed) context.write('[');
			context.visit(node.key);
			if (node.computed) context.write(']');

			context.write('(');
			sequence(
				context,
				node.value.params,
				(node.value.returnType ?? node.value.body)?.loc?.start ?? node.loc?.end ?? null,
				false
			);
			context.write(')');

			if (node.value.returnType) context.visit(node.value.returnType);

			context.write(' ');

			if (node.value.body) context.visit(node.value.body);
		},

		/**
		 * @param {TSESTree.PropertyDefinition | TSESTree.TSAbstractPropertyDefinition | TSESTree.AccessorProperty | TSESTree.TSAbstractAccessorProperty} node
		 * @param {Context} context
		 */
		'PropertyDefinition|TSAbstractPropertyDefinition|AccessorProperty|TSAbstractAccessorProperty': (
			node,
			context
		) => {
			if (node.decorators) {
				for (const decorator of node.decorators) {
					context.visit(decorator);
				}
			}

			if (node.accessibility) {
				context.write(node.accessibility + ' ');
			}

			if (
				// @ts-expect-error `acorn-typescript` and `@typescript-eslint/types` have slightly different type definitions
				node.abstract ||
				node.type === 'TSAbstractPropertyDefinition' ||
				node.type === 'TSAbstractAccessorProperty'
			) {
				context.write('abstract ');
			}

			if (node.static) {
				context.write('static ');
			}

			if (
				// @ts-expect-error `acorn-typescript` and `@typescript-eslint/types` have slightly different type definitions
				node.accessor ||
				node.type === 'AccessorProperty' ||
				node.type === 'TSAbstractAccessorProperty'
			) {
				context.write('accessor ');
			}

			if (node.computed) {
				context.write('[');
				context.visit(node.key);
				context.write(']');
			} else {
				context.visit(node.key);
			}

			if (node.typeAnnotation) {
				if (node.type === 'AccessorProperty' || node.type === 'TSAbstractAccessorProperty') {
					context.visit(node.typeAnnotation);
				} else {
					context.write(': ');
					context.visit(node.typeAnnotation.typeAnnotation);
				}
			}

			if (node.value) {
				context.write(' = ');
				context.visit(node.value);
			}

			context.write(';');

			flush_trailing_comments(
				context,
				(node.value ?? node.typeAnnotation ?? node.key).loc?.end ?? null,
				null
			);
		},

		/**
		 * @param {TSESTree.RestElement | TSESTree.SpreadElement} node
		 * @param {Context} context
		 */
		'RestElement|SpreadElement': (node, context) => {
			context.write('...');
			context.visit(node.argument);

			// @ts-expect-error `acorn-typescript` and `@typescript-eslint/types` have slightly different type definitions
			if (node.typeAnnotation) context.visit(node.typeAnnotation);
		},

		/**
		 * @param {TSESTree.TSConstructSignatureDeclaration | TSESTree.TSCallSignatureDeclaration} node
		 * @param {Context} context
		 */
		'TSConstructSignatureDeclaration|TSCallSignatureDeclaration': (node, context) => {
			if (node.type === 'TSConstructSignatureDeclaration') context.write('new');

			if (node.typeParameters) {
				context.visit(node.typeParameters);
			}

			context.write('(');

			sequence(
				context,
				// @ts-expect-error `acorn-typescript` and `@typescript-eslint/types` have slightly different type definitions
				node.parameters ?? node.params,
				// @ts-expect-error `acorn-typescript` and `@typescript-eslint/types` have slightly different type definitions
				(node.typeAnnotation ?? node.returnType)?.loc?.start ?? null,
				false
			);
			context.write(')');

			// @ts-expect-error `acorn-typescript` and `@typescript-eslint/types` have slightly different type definitions
			if (node.typeAnnotation || node.returnType) {
				// @ts-expect-error `acorn-typescript` and `@typescript-eslint/types` have slightly different type definitions
				context.visit(node.typeAnnotation ?? node.returnType);
			}
		},

		/**
		 * @param {TSESTree.TSFunctionType | TSESTree.TSConstructorType} node
		 * @param {Context} context
		 */
		'TSFunctionType|TSConstructorType': (node, context) => {
			if (node.type === 'TSConstructorType') context.write('new ');
			if (node.typeParameters) context.visit(node.typeParameters);

			context.write('(');

			sequence(
				context,
				// @ts-expect-error `acorn-typescript` and `@typescript-eslint/types` have slightly different type definitions
				node.parameters ?? node.params,
				// @ts-expect-error `acorn-typescript` and `@typescript-eslint/types` have slightly different type definitions
				node.typeAnnotation?.typeAnnotation?.loc?.start ??
					node.returnType?.typeAnnotation?.loc?.start ??
					null,
				false
			);

			context.write(') => ');

			// @ts-expect-error `acorn-typescript` and `@typescript-eslint/types` have slightly different type definitions
			context.visit(node.typeAnnotation?.typeAnnotation ?? node.returnType?.typeAnnotation);
		}
	};

	return {
		_(node, context, visit) {
			if (node.loc) {
				flush_comments_until(context, null, node.loc.start, true);
			}

			visit(node);
		},

		AccessorProperty:
			shared[
				'PropertyDefinition|TSAbstractPropertyDefinition|AccessorProperty|TSAbstractAccessorProperty'
			],

		ArrayExpression: shared['ArrayExpression|ArrayPattern'],

		ArrayPattern: shared['ArrayExpression|ArrayPattern'],

		ArrowFunctionExpression: (node, context) => {
			if (node.async) context.write('async ');

			context.write('(');
			sequence(context, node.params, node.body.loc?.start ?? null, false);
			context.write(') => ');

			if (
				node.body.type === 'ObjectExpression' ||
				(node.body.type === 'AssignmentExpression' && node.body.left.type === 'ObjectPattern') ||
				(node.body.type === 'LogicalExpression' && node.body.left.type === 'ObjectExpression') ||
				(node.body.type === 'ConditionalExpression' && node.body.test.type === 'ObjectExpression')
			) {
				context.write('(');
				context.visit(node.body);
				context.write(')');
			} else {
				context.visit(node.body);
			}
		},

		AssignmentExpression(node, context) {
			context.visit(node.left);
			context.write(` ${node.operator} `);
			context.visit(node.right);
		},

		AssignmentPattern(node, context) {
			context.visit(node.left);
			context.write(' = ');
			context.visit(node.right);
		},

		AwaitExpression(node, context) {
			if (node.argument) {
				const precedence = EXPRESSIONS_PRECEDENCE[node.argument.type];

				if (precedence && precedence < EXPRESSIONS_PRECEDENCE.AwaitExpression) {
					context.write('await (');
					context.visit(node.argument);
					context.write(')');
				} else {
					context.write('await ');
					context.visit(node.argument);
				}
			} else {
				context.write('await');
			}
		},

		BinaryExpression: shared['BinaryExpression|LogicalExpression'],

		BlockStatement: shared['BlockStatement|ClassBody'],

		BreakStatement(node, context) {
			if (node.label) {
				context.write('break ');
				context.visit(node.label);
				context.write(';');
			} else {
				context.write('break;');
			}
		},

		CallExpression: shared['CallExpression|NewExpression'],

		ChainExpression(node, context) {
			context.visit(node.expression);
		},

		ClassBody: shared['BlockStatement|ClassBody'],

		ClassDeclaration: shared['ClassDeclaration|ClassExpression'],

		ClassExpression: shared['ClassDeclaration|ClassExpression'],

		ConditionalExpression(node, context) {
			if (EXPRESSIONS_PRECEDENCE[node.test.type] > EXPRESSIONS_PRECEDENCE.ConditionalExpression) {
				context.visit(node.test);
			} else {
				context.write('(');
				context.visit(node.test);
				context.write(')');
			}

			const consequent = context.new();
			const alternate = context.new();

			// TODO flush comments here, rather than in visitors

			consequent.visit(node.consequent);
			alternate.visit(node.alternate);

			if (
				consequent.multiline ||
				alternate.multiline ||
				consequent.measure() + alternate.measure() > 50
			) {
				context.indent();
				context.newline();
				context.write('? ');
				context.append(consequent);
				context.newline();
				context.write(': ');
				context.append(alternate);
				context.dedent();
			} else {
				context.write(' ? ');
				context.append(consequent);
				context.write(' : ');
				context.append(alternate);
			}
		},

		ContinueStatement(node, context) {
			if (node.label) {
				context.write('continue ');
				context.visit(node.label);
				context.write(';');
			} else {
				context.write('continue;');
			}
		},

		DebuggerStatement(node, context) {
			context.write('debugger', node);
			context.write(';');
		},

		Decorator(node, context) {
			context.write('@');
			context.visit(node.expression);
			context.newline();
		},

		DoWhileStatement(node, context) {
			context.write('do ');
			context.visit(node.body);
			context.write(' while (');
			context.visit(node.test);
			context.write(');');
		},

		EmptyStatement(node, context) {
			context.write(';');
		},

		ExportAllDeclaration(node, context) {
			context.write(node.exportKind === 'type' ? 'export type * ' : 'export * ');

			if (node.exported) {
				context.write('as ');
				context.visit(node.exported);
			}

			context.write(' from ');
			context.visit(node.source);
			context.write(';');
		},

		ExportDefaultDeclaration(node, context) {
			context.write('export default ');

			context.visit(node.declaration);

			if (node.declaration.type !== 'FunctionDeclaration') {
				context.write(';');
			}
		},

		ExportNamedDeclaration(node, context) {
			context.write('export ');

			if (node.declaration) {
				context.visit(node.declaration);
				return;
			}

			if (node.exportKind === 'type') {
				context.write('type ');
			}

			context.write('{');
			sequence(context, node.specifiers, node.source?.loc?.start ?? node.loc?.end ?? null, true);
			context.write('}');

			if (node.source) {
				context.write(' from ');
				context.visit(node.source);
			}

			context.write(';');
		},

		ExportSpecifier(node, context) {
			if (node.exportKind === 'type') {
				context.write('type ');
			}

			context.visit(node.local);

			if (
				node.local.type === 'Identifier' &&
				node.exported.type === 'Identifier' &&
				node.local.name !== node.exported.name
			) {
				context.write(' as ');
				context.visit(node.exported);
			}
		},

		ExpressionStatement(node, context) {
			if (
				node.expression.type === 'ObjectExpression' ||
				(node.expression.type === 'AssignmentExpression' &&
					node.expression.left.type === 'ObjectPattern') ||
				node.expression.type === 'FunctionExpression'
			) {
				// is an AssignmentExpression to an ObjectPattern
				context.write('(');
				context.visit(node.expression);
				context.write(');');
				return;
			}

			context.visit(node.expression);
			context.write(';');
		},

		ForStatement: (node, context) => {
			context.write('for (');

			if (node.init) {
				if (node.init.type === 'VariableDeclaration') {
					handle_var_declaration(node.init, context);
				} else {
					context.visit(node.init);
				}
			}

			context.write('; ');
			if (node.test) context.visit(node.test);
			context.write('; ');
			if (node.update) context.visit(node.update);

			context.write(') ');
			context.visit(node.body);
		},

		ForInStatement: shared['ForInStatement|ForOfStatement'],

		ForOfStatement: shared['ForInStatement|ForOfStatement'],

		FunctionDeclaration: shared['FunctionDeclaration|FunctionExpression'],

		FunctionExpression: shared['FunctionDeclaration|FunctionExpression'],

		Identifier(node, context) {
			let name = node.name;
			context.write(name, node);

			if (node.typeAnnotation) context.visit(node.typeAnnotation);
		},

		IfStatement(node, context) {
			context.write('if (');
			context.visit(node.test);
			context.write(') ');
			context.visit(node.consequent);

			if (node.alternate) {
				context.space();
				context.write('else ');
				context.visit(node.alternate);
			}
		},

		ImportDeclaration(node, context) {
			if (node.specifiers.length === 0) {
				context.write('import ');
				context.visit(node.source);
				context.write(';');
				return;
			}

			/** @type {TSESTree.ImportNamespaceSpecifier | null} */
			let namespace_specifier = null;

			/** @type {TSESTree.ImportDefaultSpecifier | null} */
			let default_specifier = null;

			/** @type {TSESTree.ImportSpecifier[]} */
			const named_specifiers = [];

			for (const s of node.specifiers) {
				if (s.type === 'ImportNamespaceSpecifier') {
					namespace_specifier = s;
				} else if (s.type === 'ImportDefaultSpecifier') {
					default_specifier = s;
				} else {
					named_specifiers.push(s);
				}
			}

			context.write('import ');
			if (node.importKind == 'type') context.write('type ');

			if (default_specifier) {
				context.write(default_specifier.local.name, default_specifier);
				if (namespace_specifier || named_specifiers.length > 0) context.write(', ');
			}

			if (namespace_specifier) {
				context.write('* as ' + namespace_specifier.local.name, namespace_specifier);
			}

			if (named_specifiers.length > 0) {
				context.write('{');
				sequence(context, named_specifiers, node.source.loc?.start ?? null, true);
				context.write('}');
			}

			context.write(' from ');
			context.visit(node.source);
			if (node.attributes && node.attributes.length > 0) {
				context.write(' with { ');
				for (let index = 0; index < node.attributes.length; index++) {
					const { key, value } = node.attributes[index];
					context.visit(key);
					context.write(': ');
					context.visit(value);
					if (index + 1 !== node.attributes.length) {
						context.write(', ');
					}
				}
				context.write(' }');
			}
			context.write(';');
		},

		ImportExpression(node, context) {
			context.write('import(');
			context.visit(node.source);
			//@ts-expect-error for some reason the types haven't been updated
			if (node.arguments) {
				//@ts-expect-error
				for (let index = 0; index < node.arguments.length; index++) {
					context.write(', ');
					//@ts-expect-error
					context.visit(node.arguments[index]);
				}
			}
			if (node.options) {
				context.write(', ');
				context.visit(node.options);
			}
			context.write(')');
		},

		ImportSpecifier(node, context) {
			if (
				node.local.type === 'Identifier' &&
				node.imported.type === 'Identifier' &&
				node.local.name !== node.imported.name
			) {
				context.visit(node.imported);
				context.write(' as ');
			}

			if (node.importKind == 'type') context.write('type ');
			context.visit(node.local);
		},

		LabeledStatement(node, context) {
			context.visit(node.label);
			context.write(': ');
			context.visit(node.body);
		},

		Literal(node, context) {
			// TODO do we need to handle weird unicode characters somehow?
			// str.replace(/\\u(\d{4})/g, (m, n) => String.fromCharCode(+n))

			const value =
				node.raw ||
				(typeof node.value === 'string' ? quote(node.value, quote_char) : String(node.value));

			context.write(value, node);
		},

		LogicalExpression: shared['BinaryExpression|LogicalExpression'],

		MemberExpression(node, context) {
			if (EXPRESSIONS_PRECEDENCE[node.object.type] < EXPRESSIONS_PRECEDENCE.MemberExpression) {
				context.write('(');
				context.visit(node.object);
				context.write(')');
			} else {
				context.visit(node.object);
			}

			if (node.computed) {
				if (node.optional) {
					context.write('?.');
				}
				context.write('[');
				context.visit(node.property);
				context.write(']');
			} else {
				context.write(node.optional ? '?.' : '.');
				context.visit(node.property);
			}
		},

		MetaProperty(node, context) {
			context.visit(node.meta);
			context.write('.');
			context.visit(node.property);
		},

		MethodDefinition: shared['MethodDefinition|TSAbstractMethodDefinition'],

		NewExpression: shared['CallExpression|NewExpression'],

		ObjectExpression(node, context) {
			context.write('{');
			sequence(context, node.properties, node.loc?.end ?? null, true);
			context.write('}');
		},

		ObjectPattern(node, context) {
			context.write('{');
			sequence(context, node.properties, node.loc?.end ?? null, true);
			context.write('}');

			if (node.typeAnnotation) context.visit(node.typeAnnotation);
		},

		// @ts-expect-error this isn't a real node type, but Acorn produces it
		ParenthesizedExpression(node, context) {
			context.write('(');
			context.visit(node.expression);
			context.write(')');
		},

		PrivateIdentifier(node, context) {
			context.write('#');
			context.write(node.name, node);
		},

		Program(node, context) {
			body(context, node);
		},

		Property(node, context) {
			const value = node.value.type === 'AssignmentPattern' ? node.value.left : node.value;

			const shorthand =
				!node.computed &&
				node.kind === 'init' &&
				node.key.type === 'Identifier' &&
				value.type === 'Identifier' &&
				node.key.name === value.name;

			if (shorthand) {
				context.visit(node.value);
				return;
			}

			// shorthand methods
			if (node.value.type === 'FunctionExpression') {
				if (node.kind !== 'init') context.write(node.kind + ' ');
				if (node.value.async) context.write('async ');
				if (node.value.generator) context.write('*');
				if (node.computed) context.write('[');
				context.visit(node.key);
				if (node.computed) context.write(']');
				context.write('(');
				sequence(
					context,
					node.value.params,
					(node.value.returnType ?? node.value.body).loc?.start ?? null,
					false
				);
				context.write(')');

				if (node.value.returnType) context.visit(node.value.returnType);

				context.write(' ');
				context.visit(node.value.body);
			} else {
				if (node.computed) context.write('[');
				if (node.kind === 'get' || node.kind === 'set') context.write(node.kind + ' ');
				context.visit(node.key);
				context.write(node.computed ? ']: ' : ': ');
				context.visit(node.value);
			}
		},

		PropertyDefinition:
			shared[
				'PropertyDefinition|TSAbstractPropertyDefinition|AccessorProperty|TSAbstractAccessorProperty'
			],

		RestElement: shared['RestElement|SpreadElement'],

		ReturnStatement(node, context) {
			if (node.argument) {
				const contains_comment =
					comments[comment_index] &&
					comments[comment_index].loc &&
					node.argument.loc &&
					before(comments[comment_index].loc.start, node.argument.loc.start);

				context.write(contains_comment ? 'return (' : 'return ');
				context.visit(node.argument);
				context.write(contains_comment ? ');' : ';');
			} else {
				context.write('return;');
			}
		},

		SequenceExpression(node, context) {
			context.write('(');
			sequence(context, node.expressions, node.loc?.end ?? null, false);
			context.write(')');
		},

		SpreadElement: shared['RestElement|SpreadElement'],

		StaticBlock(node, context) {
			context.write('static {');
			context.indent();
			context.newline();

			body(context, node);

			context.dedent();
			context.newline();
			context.write('}');
		},

		Super(node, context) {
			context.write('super', node);
		},

		SwitchStatement(node, context) {
			context.write('switch (');
			context.visit(node.discriminant);
			context.write(') {');
			context.indent();

			let first = true;

			for (const block of node.cases) {
				if (!first) {
					context.margin();
				}

				first = false;

				if (block.test) {
					context.newline();
					context.write('case ');
					context.visit(block.test);
					context.write(':');
				} else {
					context.newline();
					context.write('default:');
				}

				context.indent();

				for (const statement of block.consequent) {
					context.newline();
					context.visit(statement);
				}

				context.dedent();
			}

			context.dedent();
			context.newline();
			context.write('}');
		},

		TaggedTemplateExpression(node, context) {
			context.visit(node.tag);
			context.visit(node.quasi);
		},

		TemplateLiteral(node, context) {
			context.write('`');

			const { quasis, expressions } = node;

			for (let i = 0; i < expressions.length; i++) {
				const raw = quasis[i].value.raw;

				context.write(raw + '${');
				context.visit(expressions[i]);
				context.write('}');

				if (/\n/.test(raw)) context.multiline = true;
			}

			const raw = quasis[quasis.length - 1].value.raw;

			context.write(raw + '`');
			if (/\n/.test(raw)) context.multiline = true;
		},

		ThisExpression(node, context) {
			context.write('this', node);
		},

		ThrowStatement(node, context) {
			context.write('throw ');
			if (node.argument) context.visit(node.argument);
			context.write(';');
		},

		TryStatement(node, context) {
			context.write('try ');
			context.visit(node.block);

			if (node.handler) {
				if (node.handler.param) {
					context.write(' catch(');
					context.visit(node.handler.param);
					context.write(') ');
				} else {
					context.write(' catch ');
				}

				context.visit(node.handler.body);
			}

			if (node.finalizer) {
				context.write(' finally ');
				context.visit(node.finalizer);
			}
		},

		UnaryExpression(node, context) {
			context.write(node.operator);

			if (node.operator.length > 1) {
				context.write(' ');
			}

			if (EXPRESSIONS_PRECEDENCE[node.argument.type] < EXPRESSIONS_PRECEDENCE.UnaryExpression) {
				context.write('(');
				context.visit(node.argument);
				context.write(')');
			} else {
				context.visit(node.argument);
			}
		},

		UpdateExpression(node, context) {
			if (node.prefix) {
				context.write(node.operator);
				context.visit(node.argument);
			} else {
				context.visit(node.argument);
				context.write(node.operator);
			}
		},

		VariableDeclaration(node, context) {
			handle_var_declaration(node, context);
			context.write(';');
		},

		VariableDeclarator(node, context) {
			context.visit(node.id);

			if (node.init) {
				context.write(' = ');
				context.visit(node.init);
			}
		},

		WhileStatement(node, context) {
			context.write('while (');
			context.visit(node.test);
			context.write(') ');
			context.visit(node.body);
		},

		WithStatement(node, context) {
			context.write('with (');
			context.visit(node.object);
			context.write(') ');
			context.visit(node.body);
		},

		YieldExpression(node, context) {
			if (node.argument) {
				context.write(node.delegate ? `yield* ` : `yield `);
				context.visit(node.argument);
			} else {
				context.write(node.delegate ? `yield*` : `yield`);
			}
		},

		TSAbstractMethodDefinition: shared['MethodDefinition|TSAbstractMethodDefinition'],

		TSAbstractAccessorProperty:
			shared[
				'PropertyDefinition|TSAbstractPropertyDefinition|AccessorProperty|TSAbstractAccessorProperty'
			],

		TSAbstractPropertyDefinition:
			shared[
				'PropertyDefinition|TSAbstractPropertyDefinition|AccessorProperty|TSAbstractAccessorProperty'
			],

		TSDeclareFunction(node, context) {
			context.write('declare ');

			if (node.async) {
				context.write('async ');
			}

			context.write('function');

			if (node.generator) {
				context.write('*');
			}

			if (node.id) {
				context.write(' ');
				context.visit(node.id);
			}

			if (node.typeParameters) {
				context.visit(node.typeParameters);
			}

			context.write('(');
			sequence(context, node.params, node.returnType?.loc?.start ?? node.loc?.end ?? null, false);
			context.write(')');

			if (node.returnType) {
				context.visit(node.returnType);
			}

			context.write(';');
		},

		TSNumberKeyword(node, context) {
			context.write('number', node);
		},

		TSStringKeyword(node, context) {
			context.write('string', node);
		},

		TSBooleanKeyword(node, context) {
			context.write('boolean', node);
		},

		TSAnyKeyword(node, context) {
			context.write('any', node);
		},

		TSVoidKeyword(node, context) {
			context.write('void', node);
		},

		TSUnknownKeyword(node, context) {
			context.write('unknown', node);
		},

		TSNeverKeyword(node, context) {
			context.write('never', node);
		},

		TSSymbolKeyword(node, context) {
			context.write('symbol', node);
		},

		TSNullKeyword(node, context) {
			context.write('null', node);
		},

		TSUndefinedKeyword(node, context) {
			context.write('undefined', node);
		},

		TSObjectKeyword(node, context) {
			context.write('object', node);
		},

		TSBigIntKeyword(node, context) {
			context.write('bigint', node);
		},

		TSIntrinsicKeyword(node, context) {
			context.write('intrinsic', node);
		},

		TSArrayType(node, context) {
			context.visit(node.elementType);
			context.write('[]');
		},

		TSTypeAnnotation(node, context) {
			context.write(': ');
			context.visit(node.typeAnnotation);
		},

		TSTypeLiteral(node, context) {
			context.write('{ ');
			sequence(context, node.members, node.loc?.end ?? null, false, ';');
			context.write(' }');
		},

		TSPropertySignature(node, context) {
			context.visit(node.key);
			if (node.optional) context.write('?');
			if (node.typeAnnotation) context.visit(node.typeAnnotation);
		},

		TSTypeReference(node, context) {
			context.visit(node.typeName);

			if (node.typeArguments) {
				context.visit(node.typeArguments);
			}
		},

		TSTypeOperator(node, context) {
			context.write(node.operator + ' ');
			if (node.typeAnnotation) {
				context.visit(node.typeAnnotation);
			}
		},

		TSTemplateLiteralType(node, context) {
			context.write('`');
			const { quasis, types } = node;
			for (let i = 0; i < types.length; i++) {
				const raw = quasis[i].value.raw;

				context.write(raw + '${');
				context.visit(types[i]);
				context.write('}');

				if (/\n/.test(raw)) context.multiline = true;
			}
			context.write('`');
		},

		TSParameterProperty(node, context) {
			if (node.accessibility) {
				context.write(node.accessibility + ' ');
			}

			if (node.readonly) {
				context.write('readonly ');
			}

			context.visit(node.parameter);
		},

		TSExportAssignment(node, context) {
			context.write('export = ');
			context.visit(node.expression);
			context.write(';');
		},

		TSNamespaceExportDeclaration(node, context) {
			context.write('export as namespace ');
			context.visit(node.id);
			context.write(';');
		},

		//@ts-expect-error I don't know why, but this is relied upon in the tests, but doesn't exist in the TSESTree types
		TSExpressionWithTypeArguments(node, context) {
			context.visit(node.expression);
		},

		TSTypeAssertion(node, context) {
			context.write('<');
			context.visit(node.typeAnnotation);
			context.write('>');
			if (EXPRESSIONS_PRECEDENCE[node.expression.type] < EXPRESSIONS_PRECEDENCE.TSTypeAssertion) {
				context.write('(');
				context.visit(node.expression);
				context.write(')');
			} else {
				context.visit(node.expression);
			}
		},

		TSTypeParameterInstantiation(node, context) {
			context.write('<');
			for (let i = 0; i < node.params.length; i++) {
				context.visit(node.params[i]);
				if (i != node.params.length - 1) context.write(', ');
			}
			context.write('>');
		},

		TSTypeParameterDeclaration(node, context) {
			context.write('<');
			for (let i = 0; i < node.params.length; i++) {
				context.visit(node.params[i]);
				if (i != node.params.length - 1) context.write(', ');
			}
			context.write('>');
		},

		TSTypeParameter(node, context) {
			if (node.name && node.name.type) context.visit(node.name);
			// @ts-expect-error type mismatch TSESTree and acorn-typescript?
			else context.write(node.name, node);

			if (node.constraint) {
				context.write(' extends ');
				context.visit(node.constraint);
			}
		},

		TSTypePredicate(node, context) {
			if (node.parameterName) {
				context.visit(node.parameterName);
			} else if (node.typeAnnotation) {
				context.visit(node.typeAnnotation);
			}

			if (node.asserts) {
				context.write(' asserts ');
			} else {
				context.write(' is ');
			}

			if (node.typeAnnotation) {
				context.visit(node.typeAnnotation.typeAnnotation);
			}
		},

		TSTypeQuery(node, context) {
			context.write('typeof ');
			context.visit(node.exprName);
		},

		TSClassImplements(node, context) {
			if (node.expression) {
				context.visit(node.expression);
			}
		},

		TSEnumMember(node, context) {
			context.visit(node.id);
			if (node.initializer) {
				context.write(' = ');
				context.visit(node.initializer);
			}
		},

		TSFunctionType: shared['TSFunctionType|TSConstructorType'],

		TSIndexSignature(node, context) {
			context.write('[');

			// @ts-expect-error `acorn-typescript` and `@typescript-eslint/types` have slightly different type definitions
			sequence(context, node.parameters, node.typeAnnotation?.loc?.start ?? null, false);
			context.write(']');

			// @ts-expect-error `acorn-typescript` and `@typescript-eslint/types` have slightly different type definitions
			context.visit(node.typeAnnotation);
		},

		TSMappedType(node, context) {
			context.write('{[');

			if (node.typeParameter) {
				context.visit(node.typeParameter);
			} else {
				context.visit(node.key);
				context.write(' in ');
				context.visit(node.constraint);
			}

			context.write(']');
			if (node.typeAnnotation) {
				context.write(': ');
				context.visit(node.typeAnnotation);
			}
			context.write('}');
		},

		TSMethodSignature(node, context) {
			context.visit(node.key);

			context.write('(');

			sequence(
				context,
				// @ts-expect-error `acorn-typescript` and `@typescript-eslint/types` have slightly different type definitions
				node.parameters ?? node.params,
				// @ts-expect-error `acorn-typescript` and `@typescript-eslint/types` have slightly different type definitions
				(node.typeAnnotation ?? node.returnType)?.loc?.start ?? null,
				false
			);
			context.write(')');

			// @ts-expect-error `acorn-typescript` and `@typescript-eslint/types` have slightly different type definitions
			if (node.typeAnnotation || node.returnType) {
				// @ts-expect-error `acorn-typescript` and `@typescript-eslint/types` have slightly different type definitions
				context.visit(node.typeAnnotation ?? node.returnType);
			}
		},

		TSTupleType(node, context) {
			context.write('[');
			sequence(context, node.elementTypes, node.loc?.end ?? null, false);
			context.write(']');
		},

		TSNamedTupleMember(node, context) {
			context.visit(node.label);
			context.write(': ');
			context.visit(node.elementType);
		},

		TSUnionType(node, context) {
			sequence(context, node.types, node.loc?.end ?? null, false, ' |');
		},

		TSIntersectionType(node, context) {
			sequence(context, node.types, node.loc?.end ?? null, false, ' &');
		},

		TSInferType(node, context) {
			context.write('infer ');
			context.visit(node.typeParameter);
		},

		TSLiteralType(node, context) {
			context.visit(node.literal);
		},

		TSCallSignatureDeclaration:
			shared['TSConstructSignatureDeclaration|TSCallSignatureDeclaration'],

		TSConditionalType(node, context) {
			context.visit(node.checkType);
			context.write(' extends ');
			context.visit(node.extendsType);
			context.write(' ? ');
			context.visit(node.trueType);
			context.write(' : ');
			context.visit(node.falseType);
		},

		TSConstructSignatureDeclaration:
			shared['TSConstructSignatureDeclaration|TSCallSignatureDeclaration'],

		TSConstructorType: shared['TSFunctionType|TSConstructorType'],

		TSExternalModuleReference(node, context) {
			context.write('require(');
			context.visit(node.expression);
			context.write(');');
		},

		TSIndexedAccessType(node, context) {
			context.visit(node.objectType);
			context.write('[');
			context.visit(node.indexType);
			context.write(']');
		},

		TSImportEqualsDeclaration(node, context) {
			context.write('import ');
			context.visit(node.id);
			context.write(' = ');
			context.visit(node.moduleReference);
		},

		TSImportType(node, context) {
			context.write('import(');
			context.visit(node.argument);
			context.write(')');

			if (node.qualifier) {
				context.write('.');
				context.visit(node.qualifier);
			}
		},

		TSOptionalType(node, context) {
			context.visit(node.typeAnnotation);
			context.write('?');
		},

		TSRestType(node, context) {
			context.write('...');
			context.visit(node.typeAnnotation);
		},

		TSThisType(node, context) {
			context.write('this', node);
		},

		TSAsExpression(node, context) {
			if (node.expression) {
				const needs_parens =
					EXPRESSIONS_PRECEDENCE[node.expression.type] < EXPRESSIONS_PRECEDENCE.TSAsExpression;

				if (needs_parens) {
					context.write('(');
					context.visit(node.expression);
					context.write(')');
				} else {
					context.visit(node.expression);
				}
			}
			context.write(' as ');
			context.visit(node.typeAnnotation);
		},

		TSEnumDeclaration(node, context) {
			context.write('enum ');
			context.visit(node.id);
			context.write(' {');
			context.indent();
			context.newline();
			sequence(context, node.members ?? node.body.members, node.loc?.end ?? null, false);
			context.dedent();
			context.newline();
			context.write('}');
		},

		TSModuleBlock(node, context) {
			context.write(' {');
			context.indent();
			context.newline();
			body(context, node);
			context.dedent();
			context.newline();
			context.write('}');
		},

		TSModuleDeclaration(node, context) {
			if (node.declare) context.write('declare ');
			else context.write('namespace ');

			context.visit(node.id);

			if (!node.body) return;
			context.visit(node.body);
		},

		TSNonNullExpression(node, context) {
			context.visit(node.expression);
			context.write('!');
		},

		TSInterfaceBody(node, context) {
			sequence(context, node.body, node.loc?.end ?? null, true, ';');
		},

		TSInterfaceDeclaration(node, context) {
			context.write('interface ');
			context.visit(node.id);
			if (node.typeParameters) context.visit(node.typeParameters);
			if (node.extends && node.extends.length > 0) {
				context.write(' extends ');
				sequence(context, node.extends, node.body.loc?.start ?? null, false);
			}
			context.write(' {');
			context.visit(node.body);
			context.write('}');
		},

		TSInstantiationExpression(node, context) {
			context.visit(node.expression);
			context.visit(node.typeArguments);
		},

		TSInterfaceHeritage(node, context) {
			if (node.expression) {
				context.visit(node.expression);
			}
		},

		//@ts-expect-error I don't know why, but this is relied upon in the tests, but doesn't exist in the TSESTree types
		TSParenthesizedType(node, context) {
			context.write('(');
			context.visit(node.typeAnnotation);
			context.write(')');
		},

		TSSatisfiesExpression(node, context) {
			if (node.expression) {
				const needs_parens =
					EXPRESSIONS_PRECEDENCE[node.expression.type] <
					EXPRESSIONS_PRECEDENCE.TSSatisfiesExpression;

				if (needs_parens) {
					context.write('(');
					context.visit(node.expression);
					context.write(')');
				} else {
					context.visit(node.expression);
				}
			}
			context.write(' satisfies ');
			context.visit(node.typeAnnotation);
		},

		TSTypeAliasDeclaration(node, context) {
			context.write('type ');
			context.visit(node.id);
			if (node.typeParameters) context.visit(node.typeParameters);
			context.write(' = ');
			context.visit(node.typeAnnotation);
			context.write(';');
		},

		TSQualifiedName(node, context) {
			context.visit(node.left);
			context.write('.');
			context.visit(node.right);
		}
	};
};

/** @satisfies {Visitors} */

/**
 *
 * @param {TSESTree.Expression | TSESTree.PrivateIdentifier} node
 * @param {TSESTree.BinaryExpression | TSESTree.LogicalExpression} parent
 * @param {boolean} is_right
 * @returns
 */
function needs_parens(node, parent, is_right) {
	if (node.type === 'PrivateIdentifier') return false;

	// special case where logical expressions and coalesce expressions cannot be mixed,
	// either of them need to be wrapped with parentheses
	if (
		node.type === 'LogicalExpression' &&
		parent.type === 'LogicalExpression' &&
		((parent.operator === '??' && node.operator !== '??') ||
			(parent.operator !== '??' && node.operator === '??'))
	) {
		return true;
	}

	const precedence = EXPRESSIONS_PRECEDENCE[node.type];
	const parent_precedence = EXPRESSIONS_PRECEDENCE[parent.type];

	if (precedence !== parent_precedence) {
		// Different node types
		return (
			(!is_right && precedence === 15 && parent_precedence === 14 && parent.operator === '**') ||
			precedence < parent_precedence
		);
	}

	if (precedence !== 13 && precedence !== 14) {
		// Not a `LogicalExpression` or `BinaryExpression`
		return false;
	}

	if (
		/** @type {TSESTree.BinaryExpression} */ (node).operator === '**' &&
		parent.operator === '**'
	) {
		// Exponentiation operator has right-to-left associativity
		return !is_right;
	}

	if (is_right) {
		// Parenthesis are used if both operators have the same precedence
		return (
			OPERATOR_PRECEDENCE[/** @type {TSESTree.BinaryExpression} */ (node).operator] <=
			OPERATOR_PRECEDENCE[parent.operator]
		);
	}

	return (
		OPERATOR_PRECEDENCE[/** @type {TSESTree.BinaryExpression} */ (node).operator] <
		OPERATOR_PRECEDENCE[parent.operator]
	);
}

/** @param {TSESTree.Node} node */
function has_call_expression(node) {
	while (node) {
		if (node.type === 'CallExpression') {
			return true;
		} else if (node.type === 'MemberExpression') {
			node = node.object;
		} else {
			return false;
		}
	}
}

/**
 * @param {TSESTree.VariableDeclaration} node
 * @param {Context} context
 */
function handle_var_declaration(node, context) {
	const open = context.new();
	const join = context.new();
	const child_context = context.new();

	context.append(child_context);

	if (node.declare) {
		child_context.write('declare ');
	}

	child_context.write(`${node.kind} `);
	child_context.append(open);

	let first = true;

	for (const d of node.declarations) {
		if (!first) child_context.append(join);
		first = false;

		child_context.visit(d);
	}

	const length = child_context.measure() + 2 * (node.declarations.length - 1);

	const multiline = child_context.multiline || (node.declarations.length > 1 && length > 50);

	if (multiline) {
		context.multiline = true;

		if (node.declarations.length > 1) open.indent();
		join.write(',');
		join.newline();
		if (node.declarations.length > 1) context.dedent();
	} else {
		join.write(', ');
	}
}

/**
 * @param {string} string
 * @param {string} char
 */
function quote(string, char) {
	let out = char;

	for (const c of string) {
		if (c === '\\') {
			out += '\\\\';
		} else if (c === char) {
			out += '\\' + c;
		} else if (c === '\n') {
			out += '\\n';
		} else if (c === '\r') {
			out += '\\r';
		} else {
			out += c;
		}
	}

	return out + char;
}

/**
 *
 * @param {{ line: number, column: number }} a
 * @param {{ line: number, column: number }} b
 */
function before(a, b) {
	if (a.line < b.line) return true;
	if (a.line > b.line) return false;
	return a.column < b.column;
}

class BitSet {
	constructor(arg) {
		this.bits = arg instanceof BitSet ? arg.bits.slice() : [];
	}

	add(n) {
		this.bits[n >> 5] |= 1 << (n & 31);
	}

	has(n) {
		return !!(this.bits[n >> 5] & (1 << (n & 31)));
	}
}

class Chunk {
	constructor(start, end, content) {
		this.start = start;
		this.end = end;
		this.original = content;

		this.intro = '';
		this.outro = '';

		this.content = content;
		this.storeName = false;
		this.edited = false;

		{
			this.previous = null;
			this.next = null;
		}
	}

	appendLeft(content) {
		this.outro += content;
	}

	appendRight(content) {
		this.intro = this.intro + content;
	}

	clone() {
		const chunk = new Chunk(this.start, this.end, this.original);

		chunk.intro = this.intro;
		chunk.outro = this.outro;
		chunk.content = this.content;
		chunk.storeName = this.storeName;
		chunk.edited = this.edited;

		return chunk;
	}

	contains(index) {
		return this.start < index && index < this.end;
	}

	eachNext(fn) {
		let chunk = this;
		while (chunk) {
			fn(chunk);
			chunk = chunk.next;
		}
	}

	eachPrevious(fn) {
		let chunk = this;
		while (chunk) {
			fn(chunk);
			chunk = chunk.previous;
		}
	}

	edit(content, storeName, contentOnly) {
		this.content = content;
		if (!contentOnly) {
			this.intro = '';
			this.outro = '';
		}
		this.storeName = storeName;

		this.edited = true;

		return this;
	}

	prependLeft(content) {
		this.outro = content + this.outro;
	}

	prependRight(content) {
		this.intro = content + this.intro;
	}

	reset() {
		this.intro = '';
		this.outro = '';
		if (this.edited) {
			this.content = this.original;
			this.storeName = false;
			this.edited = false;
		}
	}

	split(index) {
		const sliceIndex = index - this.start;

		const originalBefore = this.original.slice(0, sliceIndex);
		const originalAfter = this.original.slice(sliceIndex);

		this.original = originalBefore;

		const newChunk = new Chunk(index, this.end, originalAfter);
		newChunk.outro = this.outro;
		this.outro = '';

		this.end = index;

		if (this.edited) {
			// after split we should save the edit content record into the correct chunk
			// to make sure sourcemap correct
			// For example:
			// '  test'.trim()
			//     split   -> '  ' + 'test'
			//   ✔️ edit    -> '' + 'test'
			//   ✖️ edit    -> 'test' + ''
			// TODO is this block necessary?...
			newChunk.edit('', false);
			this.content = '';
		} else {
			this.content = originalBefore;
		}

		newChunk.next = this.next;
		if (newChunk.next) newChunk.next.previous = newChunk;
		newChunk.previous = this;
		this.next = newChunk;

		return newChunk;
	}

	toString() {
		return this.intro + this.content + this.outro;
	}

	trimEnd(rx) {
		this.outro = this.outro.replace(rx, '');
		if (this.outro.length) return true;

		const trimmed = this.content.replace(rx, '');

		if (trimmed.length) {
			if (trimmed !== this.content) {
				this.split(this.start + trimmed.length).edit('', undefined, true);
				if (this.edited) {
					// save the change, if it has been edited
					this.edit(trimmed, this.storeName, true);
				}
			}
			return true;
		} else {
			this.edit('', undefined, true);

			this.intro = this.intro.replace(rx, '');
			if (this.intro.length) return true;
		}
	}

	trimStart(rx) {
		this.intro = this.intro.replace(rx, '');
		if (this.intro.length) return true;

		const trimmed = this.content.replace(rx, '');

		if (trimmed.length) {
			if (trimmed !== this.content) {
				const newChunk = this.split(this.end - trimmed.length);
				if (this.edited) {
					// save the change, if it has been edited
					newChunk.edit(trimmed, this.storeName, true);
				}
				this.edit('', undefined, true);
			}
			return true;
		} else {
			this.edit('', undefined, true);

			this.outro = this.outro.replace(rx, '');
			if (this.outro.length) return true;
		}
	}
}

function getBtoa() {
	if (typeof globalThis !== 'undefined' && typeof globalThis.btoa === 'function') {
		return (str) => globalThis.btoa(unescape(encodeURIComponent(str)));
	} else if (typeof Buffer === 'function') {
		return (str) => Buffer.from(str, 'utf-8').toString('base64');
	} else {
		return () => {
			throw new Error('Unsupported environment: `window.btoa` or `Buffer` should be supported.');
		};
	}
}

const btoa$1 = /*#__PURE__*/ getBtoa();

let SourceMap$1 = class SourceMap {
	constructor(properties) {
		this.version = 3;
		this.file = properties.file;
		this.sources = properties.sources;
		this.sourcesContent = properties.sourcesContent;
		this.names = properties.names;
		this.mappings = encode(properties.mappings);
		if (typeof properties.x_google_ignoreList !== 'undefined') {
			this.x_google_ignoreList = properties.x_google_ignoreList;
		}
		if (typeof properties.debugId !== 'undefined') {
			this.debugId = properties.debugId;
		}
	}

	toString() {
		return JSON.stringify(this);
	}

	toUrl() {
		return 'data:application/json;charset=utf-8;base64,' + btoa$1(this.toString());
	}
};

function guessIndent(code) {
	const lines = code.split('\n');

	const tabbed = lines.filter((line) => /^\t+/.test(line));
	const spaced = lines.filter((line) => /^ {2,}/.test(line));

	if (tabbed.length === 0 && spaced.length === 0) {
		return null;
	}

	// More lines tabbed than spaced? Assume tabs, and
	// default to tabs in the case of a tie (or nothing
	// to go on)
	if (tabbed.length >= spaced.length) {
		return '\t';
	}

	// Otherwise, we need to guess the multiple
	const min = spaced.reduce((previous, current) => {
		const numSpaces = /^ +/.exec(current)[0].length;
		return Math.min(numSpaces, previous);
	}, Infinity);

	return new Array(min + 1).join(' ');
}

function getRelativePath(from, to) {
	const fromParts = from.split(/[/\\]/);
	const toParts = to.split(/[/\\]/);

	fromParts.pop(); // get dirname

	while (fromParts[0] === toParts[0]) {
		fromParts.shift();
		toParts.shift();
	}

	if (fromParts.length) {
		let i = fromParts.length;
		while (i--) fromParts[i] = '..';
	}

	return fromParts.concat(toParts).join('/');
}

const toString = Object.prototype.toString;

function isObject(thing) {
	return toString.call(thing) === '[object Object]';
}

function getLocator(source) {
	const originalLines = source.split('\n');
	const lineOffsets = [];

	for (let i = 0, pos = 0; i < originalLines.length; i++) {
		lineOffsets.push(pos);
		pos += originalLines[i].length + 1;
	}

	return function locate(index) {
		let i = 0;
		let j = lineOffsets.length;
		while (i < j) {
			const m = (i + j) >> 1;
			if (index < lineOffsets[m]) {
				j = m;
			} else {
				i = m + 1;
			}
		}
		const line = i - 1;
		const column = index - lineOffsets[line];
		return { line, column };
	};
}

const wordRegex = /\w/;

class Mappings {
	constructor(hires) {
		this.hires = hires;
		this.generatedCodeLine = 0;
		this.generatedCodeColumn = 0;
		this.raw = [];
		this.rawSegments = this.raw[this.generatedCodeLine] = [];
		this.pending = null;
	}

	addEdit(sourceIndex, content, loc, nameIndex) {
		if (content.length) {
			const contentLengthMinusOne = content.length - 1;
			let contentLineEnd = content.indexOf('\n', 0);
			let previousContentLineEnd = -1;
			// Loop through each line in the content and add a segment, but stop if the last line is empty,
			// else code afterwards would fill one line too many
			while (contentLineEnd >= 0 && contentLengthMinusOne > contentLineEnd) {
				const segment = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column];
				if (nameIndex >= 0) {
					segment.push(nameIndex);
				}
				this.rawSegments.push(segment);

				this.generatedCodeLine += 1;
				this.raw[this.generatedCodeLine] = this.rawSegments = [];
				this.generatedCodeColumn = 0;

				previousContentLineEnd = contentLineEnd;
				contentLineEnd = content.indexOf('\n', contentLineEnd + 1);
			}

			const segment = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column];
			if (nameIndex >= 0) {
				segment.push(nameIndex);
			}
			this.rawSegments.push(segment);

			this.advance(content.slice(previousContentLineEnd + 1));
		} else if (this.pending) {
			this.rawSegments.push(this.pending);
			this.advance(content);
		}

		this.pending = null;
	}

	addUneditedChunk(sourceIndex, chunk, original, loc, sourcemapLocations) {
		let originalCharIndex = chunk.start;
		let first = true;
		// when iterating each char, check if it's in a word boundary
		let charInHiresBoundary = false;

		while (originalCharIndex < chunk.end) {
			if (original[originalCharIndex] === '\n') {
				loc.line += 1;
				loc.column = 0;
				this.generatedCodeLine += 1;
				this.raw[this.generatedCodeLine] = this.rawSegments = [];
				this.generatedCodeColumn = 0;
				first = true;
				charInHiresBoundary = false;
			} else {
				if (this.hires || first || sourcemapLocations.has(originalCharIndex)) {
					const segment = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column];

					if (this.hires === 'boundary') {
						// in hires "boundary", group segments per word boundary than per char
						if (wordRegex.test(original[originalCharIndex])) {
							// for first char in the boundary found, start the boundary by pushing a segment
							if (!charInHiresBoundary) {
								this.rawSegments.push(segment);
								charInHiresBoundary = true;
							}
						} else {
							// for non-word char, end the boundary by pushing a segment
							this.rawSegments.push(segment);
							charInHiresBoundary = false;
						}
					} else {
						this.rawSegments.push(segment);
					}
				}

				loc.column += 1;
				this.generatedCodeColumn += 1;
				first = false;
			}

			originalCharIndex += 1;
		}

		this.pending = null;
	}

	advance(str) {
		if (!str) return;

		const lines = str.split('\n');

		if (lines.length > 1) {
			for (let i = 0; i < lines.length - 1; i++) {
				this.generatedCodeLine++;
				this.raw[this.generatedCodeLine] = this.rawSegments = [];
			}
			this.generatedCodeColumn = 0;
		}

		this.generatedCodeColumn += lines[lines.length - 1].length;
	}
}

const n = '\n';

const warned$1 = {
	insertLeft: false,
	insertRight: false,
	storeName: false,
};

class MagicString {
	constructor(string, options = {}) {
		const chunk = new Chunk(0, string.length, string);

		Object.defineProperties(this, {
			original: { writable: true, value: string },
			outro: { writable: true, value: '' },
			intro: { writable: true, value: '' },
			firstChunk: { writable: true, value: chunk },
			lastChunk: { writable: true, value: chunk },
			lastSearchedChunk: { writable: true, value: chunk },
			byStart: { writable: true, value: {} },
			byEnd: { writable: true, value: {} },
			filename: { writable: true, value: options.filename },
			indentExclusionRanges: { writable: true, value: options.indentExclusionRanges },
			sourcemapLocations: { writable: true, value: new BitSet() },
			storedNames: { writable: true, value: {} },
			indentStr: { writable: true, value: undefined },
			ignoreList: { writable: true, value: options.ignoreList },
			offset: { writable: true, value: options.offset || 0 },
		});

		this.byStart[0] = chunk;
		this.byEnd[string.length] = chunk;
	}

	addSourcemapLocation(char) {
		this.sourcemapLocations.add(char);
	}

	append(content) {
		if (typeof content !== 'string') throw new TypeError('outro content must be a string');

		this.outro += content;
		return this;
	}

	appendLeft(index, content) {
		index = index + this.offset;

		if (typeof content !== 'string') throw new TypeError('inserted content must be a string');

		this._split(index);

		const chunk = this.byEnd[index];

		if (chunk) {
			chunk.appendLeft(content);
		} else {
			this.intro += content;
		}
		return this;
	}

	appendRight(index, content) {
		index = index + this.offset;

		if (typeof content !== 'string') throw new TypeError('inserted content must be a string');

		this._split(index);

		const chunk = this.byStart[index];

		if (chunk) {
			chunk.appendRight(content);
		} else {
			this.outro += content;
		}
		return this;
	}

	clone() {
		const cloned = new MagicString(this.original, { filename: this.filename, offset: this.offset });

		let originalChunk = this.firstChunk;
		let clonedChunk = (cloned.firstChunk = cloned.lastSearchedChunk = originalChunk.clone());

		while (originalChunk) {
			cloned.byStart[clonedChunk.start] = clonedChunk;
			cloned.byEnd[clonedChunk.end] = clonedChunk;

			const nextOriginalChunk = originalChunk.next;
			const nextClonedChunk = nextOriginalChunk && nextOriginalChunk.clone();

			if (nextClonedChunk) {
				clonedChunk.next = nextClonedChunk;
				nextClonedChunk.previous = clonedChunk;

				clonedChunk = nextClonedChunk;
			}

			originalChunk = nextOriginalChunk;
		}

		cloned.lastChunk = clonedChunk;

		if (this.indentExclusionRanges) {
			cloned.indentExclusionRanges = this.indentExclusionRanges.slice();
		}

		cloned.sourcemapLocations = new BitSet(this.sourcemapLocations);

		cloned.intro = this.intro;
		cloned.outro = this.outro;

		return cloned;
	}

	generateDecodedMap(options) {
		options = options || {};

		const sourceIndex = 0;
		const names = Object.keys(this.storedNames);
		const mappings = new Mappings(options.hires);

		const locate = getLocator(this.original);

		if (this.intro) {
			mappings.advance(this.intro);
		}

		this.firstChunk.eachNext((chunk) => {
			const loc = locate(chunk.start);

			if (chunk.intro.length) mappings.advance(chunk.intro);

			if (chunk.edited) {
				mappings.addEdit(
					sourceIndex,
					chunk.content,
					loc,
					chunk.storeName ? names.indexOf(chunk.original) : -1,
				);
			} else {
				mappings.addUneditedChunk(sourceIndex, chunk, this.original, loc, this.sourcemapLocations);
			}

			if (chunk.outro.length) mappings.advance(chunk.outro);
		});

		if (this.outro) {
			mappings.advance(this.outro);
		}

		return {
			file: options.file ? options.file.split(/[/\\]/).pop() : undefined,
			sources: [
				options.source ? getRelativePath(options.file || '', options.source) : options.file || '',
			],
			sourcesContent: options.includeContent ? [this.original] : undefined,
			names,
			mappings: mappings.raw,
			x_google_ignoreList: this.ignoreList ? [sourceIndex] : undefined,
		};
	}

	generateMap(options) {
		return new SourceMap$1(this.generateDecodedMap(options));
	}

	_ensureindentStr() {
		if (this.indentStr === undefined) {
			this.indentStr = guessIndent(this.original);
		}
	}

	_getRawIndentString() {
		this._ensureindentStr();
		return this.indentStr;
	}

	getIndentString() {
		this._ensureindentStr();
		return this.indentStr === null ? '\t' : this.indentStr;
	}

	indent(indentStr, options) {
		const pattern = /^[^\r\n]/gm;

		if (isObject(indentStr)) {
			options = indentStr;
			indentStr = undefined;
		}

		if (indentStr === undefined) {
			this._ensureindentStr();
			indentStr = this.indentStr || '\t';
		}

		if (indentStr === '') return this; // noop

		options = options || {};

		// Process exclusion ranges
		const isExcluded = {};

		if (options.exclude) {
			const exclusions =
				typeof options.exclude[0] === 'number' ? [options.exclude] : options.exclude;
			exclusions.forEach((exclusion) => {
				for (let i = exclusion[0]; i < exclusion[1]; i += 1) {
					isExcluded[i] = true;
				}
			});
		}

		let shouldIndentNextCharacter = options.indentStart !== false;
		const replacer = (match) => {
			if (shouldIndentNextCharacter) return `${indentStr}${match}`;
			shouldIndentNextCharacter = true;
			return match;
		};

		this.intro = this.intro.replace(pattern, replacer);

		let charIndex = 0;
		let chunk = this.firstChunk;

		while (chunk) {
			const end = chunk.end;

			if (chunk.edited) {
				if (!isExcluded[charIndex]) {
					chunk.content = chunk.content.replace(pattern, replacer);

					if (chunk.content.length) {
						shouldIndentNextCharacter = chunk.content[chunk.content.length - 1] === '\n';
					}
				}
			} else {
				charIndex = chunk.start;

				while (charIndex < end) {
					if (!isExcluded[charIndex]) {
						const char = this.original[charIndex];

						if (char === '\n') {
							shouldIndentNextCharacter = true;
						} else if (char !== '\r' && shouldIndentNextCharacter) {
							shouldIndentNextCharacter = false;

							if (charIndex === chunk.start) {
								chunk.prependRight(indentStr);
							} else {
								this._splitChunk(chunk, charIndex);
								chunk = chunk.next;
								chunk.prependRight(indentStr);
							}
						}
					}

					charIndex += 1;
				}
			}

			charIndex = chunk.end;
			chunk = chunk.next;
		}

		this.outro = this.outro.replace(pattern, replacer);

		return this;
	}

	insert() {
		throw new Error(
			'magicString.insert(...) is deprecated. Use prependRight(...) or appendLeft(...)',
		);
	}

	insertLeft(index, content) {
		if (!warned$1.insertLeft) {
			console.warn(
				'magicString.insertLeft(...) is deprecated. Use magicString.appendLeft(...) instead',
			);
			warned$1.insertLeft = true;
		}

		return this.appendLeft(index, content);
	}

	insertRight(index, content) {
		if (!warned$1.insertRight) {
			console.warn(
				'magicString.insertRight(...) is deprecated. Use magicString.prependRight(...) instead',
			);
			warned$1.insertRight = true;
		}

		return this.prependRight(index, content);
	}

	move(start, end, index) {
		start = start + this.offset;
		end = end + this.offset;
		index = index + this.offset;

		if (index >= start && index <= end) throw new Error('Cannot move a selection inside itself');

		this._split(start);
		this._split(end);
		this._split(index);

		const first = this.byStart[start];
		const last = this.byEnd[end];

		const oldLeft = first.previous;
		const oldRight = last.next;

		const newRight = this.byStart[index];
		if (!newRight && last === this.lastChunk) return this;
		const newLeft = newRight ? newRight.previous : this.lastChunk;

		if (oldLeft) oldLeft.next = oldRight;
		if (oldRight) oldRight.previous = oldLeft;

		if (newLeft) newLeft.next = first;
		if (newRight) newRight.previous = last;

		if (!first.previous) this.firstChunk = last.next;
		if (!last.next) {
			this.lastChunk = first.previous;
			this.lastChunk.next = null;
		}

		first.previous = newLeft;
		last.next = newRight || null;

		if (!newLeft) this.firstChunk = first;
		if (!newRight) this.lastChunk = last;
		return this;
	}

	overwrite(start, end, content, options) {
		options = options || {};
		return this.update(start, end, content, { ...options, overwrite: !options.contentOnly });
	}

	update(start, end, content, options) {
		start = start + this.offset;
		end = end + this.offset;

		if (typeof content !== 'string') throw new TypeError('replacement content must be a string');

		if (this.original.length !== 0) {
			while (start < 0) start += this.original.length;
			while (end < 0) end += this.original.length;
		}

		if (end > this.original.length) throw new Error('end is out of bounds');
		if (start === end)
			throw new Error(
				'Cannot overwrite a zero-length range – use appendLeft or prependRight instead',
			);

		this._split(start);
		this._split(end);

		if (options === true) {
			if (!warned$1.storeName) {
				console.warn(
					'The final argument to magicString.overwrite(...) should be an options object. See https://github.com/rich-harris/magic-string',
				);
				warned$1.storeName = true;
			}

			options = { storeName: true };
		}
		const storeName = options !== undefined ? options.storeName : false;
		const overwrite = options !== undefined ? options.overwrite : false;

		if (storeName) {
			const original = this.original.slice(start, end);
			Object.defineProperty(this.storedNames, original, {
				writable: true,
				value: true,
				enumerable: true,
			});
		}

		const first = this.byStart[start];
		const last = this.byEnd[end];

		if (first) {
			let chunk = first;
			while (chunk !== last) {
				if (chunk.next !== this.byStart[chunk.end]) {
					throw new Error('Cannot overwrite across a split point');
				}
				chunk = chunk.next;
				chunk.edit('', false);
			}

			first.edit(content, storeName, !overwrite);
		} else {
			// must be inserting at the end
			const newChunk = new Chunk(start, end, '').edit(content, storeName);

			// TODO last chunk in the array may not be the last chunk, if it's moved...
			last.next = newChunk;
			newChunk.previous = last;
		}
		return this;
	}

	prepend(content) {
		if (typeof content !== 'string') throw new TypeError('outro content must be a string');

		this.intro = content + this.intro;
		return this;
	}

	prependLeft(index, content) {
		index = index + this.offset;

		if (typeof content !== 'string') throw new TypeError('inserted content must be a string');

		this._split(index);

		const chunk = this.byEnd[index];

		if (chunk) {
			chunk.prependLeft(content);
		} else {
			this.intro = content + this.intro;
		}
		return this;
	}

	prependRight(index, content) {
		index = index + this.offset;

		if (typeof content !== 'string') throw new TypeError('inserted content must be a string');

		this._split(index);

		const chunk = this.byStart[index];

		if (chunk) {
			chunk.prependRight(content);
		} else {
			this.outro = content + this.outro;
		}
		return this;
	}

	remove(start, end) {
		start = start + this.offset;
		end = end + this.offset;

		if (this.original.length !== 0) {
			while (start < 0) start += this.original.length;
			while (end < 0) end += this.original.length;
		}

		if (start === end) return this;

		if (start < 0 || end > this.original.length) throw new Error('Character is out of bounds');
		if (start > end) throw new Error('end must be greater than start');

		this._split(start);
		this._split(end);

		let chunk = this.byStart[start];

		while (chunk) {
			chunk.intro = '';
			chunk.outro = '';
			chunk.edit('');

			chunk = end > chunk.end ? this.byStart[chunk.end] : null;
		}
		return this;
	}

	reset(start, end) {
		start = start + this.offset;
		end = end + this.offset;

		if (this.original.length !== 0) {
			while (start < 0) start += this.original.length;
			while (end < 0) end += this.original.length;
		}

		if (start === end) return this;

		if (start < 0 || end > this.original.length) throw new Error('Character is out of bounds');
		if (start > end) throw new Error('end must be greater than start');

		this._split(start);
		this._split(end);

		let chunk = this.byStart[start];

		while (chunk) {
			chunk.reset();

			chunk = end > chunk.end ? this.byStart[chunk.end] : null;
		}
		return this;
	}

	lastChar() {
		if (this.outro.length) return this.outro[this.outro.length - 1];
		let chunk = this.lastChunk;
		do {
			if (chunk.outro.length) return chunk.outro[chunk.outro.length - 1];
			if (chunk.content.length) return chunk.content[chunk.content.length - 1];
			if (chunk.intro.length) return chunk.intro[chunk.intro.length - 1];
		} while ((chunk = chunk.previous));
		if (this.intro.length) return this.intro[this.intro.length - 1];
		return '';
	}

	lastLine() {
		let lineIndex = this.outro.lastIndexOf(n);
		if (lineIndex !== -1) return this.outro.substr(lineIndex + 1);
		let lineStr = this.outro;
		let chunk = this.lastChunk;
		do {
			if (chunk.outro.length > 0) {
				lineIndex = chunk.outro.lastIndexOf(n);
				if (lineIndex !== -1) return chunk.outro.substr(lineIndex + 1) + lineStr;
				lineStr = chunk.outro + lineStr;
			}

			if (chunk.content.length > 0) {
				lineIndex = chunk.content.lastIndexOf(n);
				if (lineIndex !== -1) return chunk.content.substr(lineIndex + 1) + lineStr;
				lineStr = chunk.content + lineStr;
			}

			if (chunk.intro.length > 0) {
				lineIndex = chunk.intro.lastIndexOf(n);
				if (lineIndex !== -1) return chunk.intro.substr(lineIndex + 1) + lineStr;
				lineStr = chunk.intro + lineStr;
			}
		} while ((chunk = chunk.previous));
		lineIndex = this.intro.lastIndexOf(n);
		if (lineIndex !== -1) return this.intro.substr(lineIndex + 1) + lineStr;
		return this.intro + lineStr;
	}

	slice(start = 0, end = this.original.length - this.offset) {
		start = start + this.offset;
		end = end + this.offset;

		if (this.original.length !== 0) {
			while (start < 0) start += this.original.length;
			while (end < 0) end += this.original.length;
		}

		let result = '';

		// find start chunk
		let chunk = this.firstChunk;
		while (chunk && (chunk.start > start || chunk.end <= start)) {
			// found end chunk before start
			if (chunk.start < end && chunk.end >= end) {
				return result;
			}

			chunk = chunk.next;
		}

		if (chunk && chunk.edited && chunk.start !== start)
			throw new Error(`Cannot use replaced character ${start} as slice start anchor.`);

		const startChunk = chunk;
		while (chunk) {
			if (chunk.intro && (startChunk !== chunk || chunk.start === start)) {
				result += chunk.intro;
			}

			const containsEnd = chunk.start < end && chunk.end >= end;
			if (containsEnd && chunk.edited && chunk.end !== end)
				throw new Error(`Cannot use replaced character ${end} as slice end anchor.`);

			const sliceStart = startChunk === chunk ? start - chunk.start : 0;
			const sliceEnd = containsEnd ? chunk.content.length + end - chunk.end : chunk.content.length;

			result += chunk.content.slice(sliceStart, sliceEnd);

			if (chunk.outro && (!containsEnd || chunk.end === end)) {
				result += chunk.outro;
			}

			if (containsEnd) {
				break;
			}

			chunk = chunk.next;
		}

		return result;
	}

	// TODO deprecate this? not really very useful
	snip(start, end) {
		const clone = this.clone();
		clone.remove(0, start);
		clone.remove(end, clone.original.length);

		return clone;
	}

	_split(index) {
		if (this.byStart[index] || this.byEnd[index]) return;

		let chunk = this.lastSearchedChunk;
		let previousChunk = chunk;
		const searchForward = index > chunk.end;

		while (chunk) {
			if (chunk.contains(index)) return this._splitChunk(chunk, index);

			chunk = searchForward ? this.byStart[chunk.end] : this.byEnd[chunk.start];

			// Prevent infinite loop (e.g. via empty chunks, where start === end)
			if (chunk === previousChunk) return;

			previousChunk = chunk;
		}
	}

	_splitChunk(chunk, index) {
		if (chunk.edited && chunk.content.length) {
			// zero-length edited chunks are a special case (overlapping replacements)
			const loc = getLocator(this.original)(index);
			throw new Error(
				`Cannot split a chunk that has already been edited (${loc.line}:${loc.column} – "${chunk.original}")`,
			);
		}

		const newChunk = chunk.split(index);

		this.byEnd[index] = chunk;
		this.byStart[index] = newChunk;
		this.byEnd[newChunk.end] = newChunk;

		if (chunk === this.lastChunk) this.lastChunk = newChunk;

		this.lastSearchedChunk = chunk;
		return true;
	}

	toString() {
		let str = this.intro;

		let chunk = this.firstChunk;
		while (chunk) {
			str += chunk.toString();
			chunk = chunk.next;
		}

		return str + this.outro;
	}

	isEmpty() {
		let chunk = this.firstChunk;
		do {
			if (
				(chunk.intro.length && chunk.intro.trim()) ||
				(chunk.content.length && chunk.content.trim()) ||
				(chunk.outro.length && chunk.outro.trim())
			)
				return false;
		} while ((chunk = chunk.next));
		return true;
	}

	length() {
		let chunk = this.firstChunk;
		let length = 0;
		do {
			length += chunk.intro.length + chunk.content.length + chunk.outro.length;
		} while ((chunk = chunk.next));
		return length;
	}

	trimLines() {
		return this.trim('[\\r\\n]');
	}

	trim(charType) {
		return this.trimStart(charType).trimEnd(charType);
	}

	trimEndAborted(charType) {
		const rx = new RegExp((charType || '\\s') + '+$');

		this.outro = this.outro.replace(rx, '');
		if (this.outro.length) return true;

		let chunk = this.lastChunk;

		do {
			const end = chunk.end;
			const aborted = chunk.trimEnd(rx);

			// if chunk was trimmed, we have a new lastChunk
			if (chunk.end !== end) {
				if (this.lastChunk === chunk) {
					this.lastChunk = chunk.next;
				}

				this.byEnd[chunk.end] = chunk;
				this.byStart[chunk.next.start] = chunk.next;
				this.byEnd[chunk.next.end] = chunk.next;
			}

			if (aborted) return true;
			chunk = chunk.previous;
		} while (chunk);

		return false;
	}

	trimEnd(charType) {
		this.trimEndAborted(charType);
		return this;
	}
	trimStartAborted(charType) {
		const rx = new RegExp('^' + (charType || '\\s') + '+');

		this.intro = this.intro.replace(rx, '');
		if (this.intro.length) return true;

		let chunk = this.firstChunk;

		do {
			const end = chunk.end;
			const aborted = chunk.trimStart(rx);

			if (chunk.end !== end) {
				// special case...
				if (chunk === this.lastChunk) this.lastChunk = chunk.next;

				this.byEnd[chunk.end] = chunk;
				this.byStart[chunk.next.start] = chunk.next;
				this.byEnd[chunk.next.end] = chunk.next;
			}

			if (aborted) return true;
			chunk = chunk.next;
		} while (chunk);

		return false;
	}

	trimStart(charType) {
		this.trimStartAborted(charType);
		return this;
	}

	hasChanged() {
		return this.original !== this.toString();
	}

	_replaceRegexp(searchValue, replacement) {
		function getReplacement(match, str) {
			if (typeof replacement === 'string') {
				return replacement.replace(/\$(\$|&|\d+)/g, (_, i) => {
					// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#specifying_a_string_as_a_parameter
					if (i === '$') return '$';
					if (i === '&') return match[0];
					const num = +i;
					if (num < match.length) return match[+i];
					return `$${i}`;
				});
			} else {
				return replacement(...match, match.index, str, match.groups);
			}
		}
		function matchAll(re, str) {
			let match;
			const matches = [];
			while ((match = re.exec(str))) {
				matches.push(match);
			}
			return matches;
		}
		if (searchValue.global) {
			const matches = matchAll(searchValue, this.original);
			matches.forEach((match) => {
				if (match.index != null) {
					const replacement = getReplacement(match, this.original);
					if (replacement !== match[0]) {
						this.overwrite(match.index, match.index + match[0].length, replacement);
					}
				}
			});
		} else {
			const match = this.original.match(searchValue);
			if (match && match.index != null) {
				const replacement = getReplacement(match, this.original);
				if (replacement !== match[0]) {
					this.overwrite(match.index, match.index + match[0].length, replacement);
				}
			}
		}
		return this;
	}

	_replaceString(string, replacement) {
		const { original } = this;
		const index = original.indexOf(string);

		if (index !== -1) {
			if (typeof replacement === 'function') {
				replacement = replacement(string, index, original);
			}
			if (string !== replacement) {
				this.overwrite(index, index + string.length, replacement);
			}
		}

		return this;
	}

	replace(searchValue, replacement) {
		if (typeof searchValue === 'string') {
			return this._replaceString(searchValue, replacement);
		}

		return this._replaceRegexp(searchValue, replacement);
	}

	_replaceAllString(string, replacement) {
		const { original } = this;
		const stringLength = string.length;
		for (
			let index = original.indexOf(string);
			index !== -1;
			index = original.indexOf(string, index + stringLength)
		) {
			const previous = original.slice(index, index + stringLength);
			let _replacement = replacement;
			if (typeof replacement === 'function') {
				_replacement = replacement(previous, index, original);
			}
			if (previous !== _replacement) this.overwrite(index, index + stringLength, _replacement);
		}

		return this;
	}

	replaceAll(searchValue, replacement) {
		if (typeof searchValue === 'string') {
			return this._replaceAllString(searchValue, replacement);
		}

		if (!searchValue.global) {
			throw new TypeError(
				'MagicString.prototype.replaceAll called with a non-global RegExp argument',
			);
		}

		return this._replaceRegexp(searchValue, replacement);
	}
}

var resolveUri_umd$1 = {exports: {}};

var resolveUri_umd = resolveUri_umd$1.exports;

var hasRequiredResolveUri_umd;

function requireResolveUri_umd () {
	if (hasRequiredResolveUri_umd) return resolveUri_umd$1.exports;
	hasRequiredResolveUri_umd = 1;
	(function (module, exports$1) {
		(function (global, factory) {
		    module.exports = factory() ;
		})(resolveUri_umd, (function () {
		    // Matches the scheme of a URL, eg "http://"
		    const schemeRegex = /^[\w+.-]+:\/\//;
		    /**
		     * Matches the parts of a URL:
		     * 1. Scheme, including ":", guaranteed.
		     * 2. User/password, including "@", optional.
		     * 3. Host, guaranteed.
		     * 4. Port, including ":", optional.
		     * 5. Path, including "/", optional.
		     * 6. Query, including "?", optional.
		     * 7. Hash, including "#", optional.
		     */
		    const urlRegex = /^([\w+.-]+:)\/\/([^@/#?]*@)?([^:/#?]*)(:\d+)?(\/[^#?]*)?(\?[^#]*)?(#.*)?/;
		    /**
		     * File URLs are weird. They dont' need the regular `//` in the scheme, they may or may not start
		     * with a leading `/`, they can have a domain (but only if they don't start with a Windows drive).
		     *
		     * 1. Host, optional.
		     * 2. Path, which may include "/", guaranteed.
		     * 3. Query, including "?", optional.
		     * 4. Hash, including "#", optional.
		     */
		    const fileRegex = /^file:(?:\/\/((?![a-z]:)[^/#?]*)?)?(\/?[^#?]*)(\?[^#]*)?(#.*)?/i;
		    function isAbsoluteUrl(input) {
		        return schemeRegex.test(input);
		    }
		    function isSchemeRelativeUrl(input) {
		        return input.startsWith('//');
		    }
		    function isAbsolutePath(input) {
		        return input.startsWith('/');
		    }
		    function isFileUrl(input) {
		        return input.startsWith('file:');
		    }
		    function isRelative(input) {
		        return /^[.?#]/.test(input);
		    }
		    function parseAbsoluteUrl(input) {
		        const match = urlRegex.exec(input);
		        return makeUrl(match[1], match[2] || '', match[3], match[4] || '', match[5] || '/', match[6] || '', match[7] || '');
		    }
		    function parseFileUrl(input) {
		        const match = fileRegex.exec(input);
		        const path = match[2];
		        return makeUrl('file:', '', match[1] || '', '', isAbsolutePath(path) ? path : '/' + path, match[3] || '', match[4] || '');
		    }
		    function makeUrl(scheme, user, host, port, path, query, hash) {
		        return {
		            scheme,
		            user,
		            host,
		            port,
		            path,
		            query,
		            hash,
		            type: 7 /* Absolute */,
		        };
		    }
		    function parseUrl(input) {
		        if (isSchemeRelativeUrl(input)) {
		            const url = parseAbsoluteUrl('http:' + input);
		            url.scheme = '';
		            url.type = 6 /* SchemeRelative */;
		            return url;
		        }
		        if (isAbsolutePath(input)) {
		            const url = parseAbsoluteUrl('http://foo.com' + input);
		            url.scheme = '';
		            url.host = '';
		            url.type = 5 /* AbsolutePath */;
		            return url;
		        }
		        if (isFileUrl(input))
		            return parseFileUrl(input);
		        if (isAbsoluteUrl(input))
		            return parseAbsoluteUrl(input);
		        const url = parseAbsoluteUrl('http://foo.com/' + input);
		        url.scheme = '';
		        url.host = '';
		        url.type = input
		            ? input.startsWith('?')
		                ? 3 /* Query */
		                : input.startsWith('#')
		                    ? 2 /* Hash */
		                    : 4 /* RelativePath */
		            : 1 /* Empty */;
		        return url;
		    }
		    function stripPathFilename(path) {
		        // If a path ends with a parent directory "..", then it's a relative path with excess parent
		        // paths. It's not a file, so we can't strip it.
		        if (path.endsWith('/..'))
		            return path;
		        const index = path.lastIndexOf('/');
		        return path.slice(0, index + 1);
		    }
		    function mergePaths(url, base) {
		        normalizePath(base, base.type);
		        // If the path is just a "/", then it was an empty path to begin with (remember, we're a relative
		        // path).
		        if (url.path === '/') {
		            url.path = base.path;
		        }
		        else {
		            // Resolution happens relative to the base path's directory, not the file.
		            url.path = stripPathFilename(base.path) + url.path;
		        }
		    }
		    /**
		     * The path can have empty directories "//", unneeded parents "foo/..", or current directory
		     * "foo/.". We need to normalize to a standard representation.
		     */
		    function normalizePath(url, type) {
		        const rel = type <= 4 /* RelativePath */;
		        const pieces = url.path.split('/');
		        // We need to preserve the first piece always, so that we output a leading slash. The item at
		        // pieces[0] is an empty string.
		        let pointer = 1;
		        // Positive is the number of real directories we've output, used for popping a parent directory.
		        // Eg, "foo/bar/.." will have a positive 2, and we can decrement to be left with just "foo".
		        let positive = 0;
		        // We need to keep a trailing slash if we encounter an empty directory (eg, splitting "foo/" will
		        // generate `["foo", ""]` pieces). And, if we pop a parent directory. But once we encounter a
		        // real directory, we won't need to append, unless the other conditions happen again.
		        let addTrailingSlash = false;
		        for (let i = 1; i < pieces.length; i++) {
		            const piece = pieces[i];
		            // An empty directory, could be a trailing slash, or just a double "//" in the path.
		            if (!piece) {
		                addTrailingSlash = true;
		                continue;
		            }
		            // If we encounter a real directory, then we don't need to append anymore.
		            addTrailingSlash = false;
		            // A current directory, which we can always drop.
		            if (piece === '.')
		                continue;
		            // A parent directory, we need to see if there are any real directories we can pop. Else, we
		            // have an excess of parents, and we'll need to keep the "..".
		            if (piece === '..') {
		                if (positive) {
		                    addTrailingSlash = true;
		                    positive--;
		                    pointer--;
		                }
		                else if (rel) {
		                    // If we're in a relativePath, then we need to keep the excess parents. Else, in an absolute
		                    // URL, protocol relative URL, or an absolute path, we don't need to keep excess.
		                    pieces[pointer++] = piece;
		                }
		                continue;
		            }
		            // We've encountered a real directory. Move it to the next insertion pointer, which accounts for
		            // any popped or dropped directories.
		            pieces[pointer++] = piece;
		            positive++;
		        }
		        let path = '';
		        for (let i = 1; i < pointer; i++) {
		            path += '/' + pieces[i];
		        }
		        if (!path || (addTrailingSlash && !path.endsWith('/..'))) {
		            path += '/';
		        }
		        url.path = path;
		    }
		    /**
		     * Attempts to resolve `input` URL/path relative to `base`.
		     */
		    function resolve(input, base) {
		        if (!input && !base)
		            return '';
		        const url = parseUrl(input);
		        let inputType = url.type;
		        if (base && inputType !== 7 /* Absolute */) {
		            const baseUrl = parseUrl(base);
		            const baseType = baseUrl.type;
		            switch (inputType) {
		                case 1 /* Empty */:
		                    url.hash = baseUrl.hash;
		                // fall through
		                case 2 /* Hash */:
		                    url.query = baseUrl.query;
		                // fall through
		                case 3 /* Query */:
		                case 4 /* RelativePath */:
		                    mergePaths(url, baseUrl);
		                // fall through
		                case 5 /* AbsolutePath */:
		                    // The host, user, and port are joined, you can't copy one without the others.
		                    url.user = baseUrl.user;
		                    url.host = baseUrl.host;
		                    url.port = baseUrl.port;
		                // fall through
		                case 6 /* SchemeRelative */:
		                    // The input doesn't have a schema at least, so we need to copy at least that over.
		                    url.scheme = baseUrl.scheme;
		            }
		            if (baseType > inputType)
		                inputType = baseType;
		        }
		        normalizePath(url, inputType);
		        const queryHash = url.query + url.hash;
		        switch (inputType) {
		            // This is impossible, because of the empty checks at the start of the function.
		            // case UrlType.Empty:
		            case 2 /* Hash */:
		            case 3 /* Query */:
		                return queryHash;
		            case 4 /* RelativePath */: {
		                // The first char is always a "/", and we need it to be relative.
		                const path = url.path.slice(1);
		                if (!path)
		                    return queryHash || '.';
		                if (isRelative(base || input) && !isRelative(path)) {
		                    // If base started with a leading ".", or there is no base and input started with a ".",
		                    // then we need to ensure that the relative path starts with a ".". We don't know if
		                    // relative starts with a "..", though, so check before prepending.
		                    return './' + path + queryHash;
		                }
		                return path + queryHash;
		            }
		            case 5 /* AbsolutePath */:
		                return url.path + queryHash;
		            default:
		                return url.scheme + '//' + url.user + url.host + url.port + url.path + queryHash;
		        }
		    }

		    return resolve;

		}));
		
	} (resolveUri_umd$1));
	return resolveUri_umd$1.exports;
}

var resolveUri_umdExports = requireResolveUri_umd();
var resolveUri = /*@__PURE__*/getDefaultExportFromCjs(resolveUri_umdExports);

// src/trace-mapping.ts

// src/strip-filename.ts
function stripFilename(path) {
  if (!path) return "";
  const index = path.lastIndexOf("/");
  return path.slice(0, index + 1);
}

// src/resolve.ts
function resolver(mapUrl, sourceRoot) {
  const from = stripFilename(mapUrl);
  const prefix = sourceRoot ? sourceRoot + "/" : "";
  return (source) => resolveUri(prefix + (source || ""), from);
}

// src/sourcemap-segment.ts
var COLUMN$1 = 0;

// src/sort.ts
function maybeSort(mappings, owned) {
  const unsortedIndex = nextUnsortedSegmentLine(mappings, 0);
  if (unsortedIndex === mappings.length) return mappings;
  if (!owned) mappings = mappings.slice();
  for (let i = unsortedIndex; i < mappings.length; i = nextUnsortedSegmentLine(mappings, i + 1)) {
    mappings[i] = sortSegments(mappings[i], owned);
  }
  return mappings;
}
function nextUnsortedSegmentLine(mappings, start) {
  for (let i = start; i < mappings.length; i++) {
    if (!isSorted(mappings[i])) return i;
  }
  return mappings.length;
}
function isSorted(line) {
  for (let j = 1; j < line.length; j++) {
    if (line[j][COLUMN$1] < line[j - 1][COLUMN$1]) {
      return false;
    }
  }
  return true;
}
function sortSegments(line, owned) {
  if (!owned) line = line.slice();
  return line.sort(sortComparator);
}
function sortComparator(a, b) {
  return a[COLUMN$1] - b[COLUMN$1];
}

// src/binary-search.ts
var found = false;
function binarySearch(haystack, needle, low, high) {
  while (low <= high) {
    const mid = low + (high - low >> 1);
    const cmp = haystack[mid][COLUMN$1] - needle;
    if (cmp === 0) {
      found = true;
      return mid;
    }
    if (cmp < 0) {
      low = mid + 1;
    } else {
      high = mid - 1;
    }
  }
  found = false;
  return low - 1;
}
function lowerBound(haystack, needle, index) {
  for (let i = index - 1; i >= 0; index = i--) {
    if (haystack[i][COLUMN$1] !== needle) break;
  }
  return index;
}
function memoizedState() {
  return {
    lastKey: -1,
    lastNeedle: -1,
    lastIndex: -1
  };
}
function memoizedBinarySearch(haystack, needle, state, key) {
  const { lastKey, lastNeedle, lastIndex } = state;
  let low = 0;
  let high = haystack.length - 1;
  if (key === lastKey) {
    if (needle === lastNeedle) {
      found = lastIndex !== -1 && haystack[lastIndex][COLUMN$1] === needle;
      return lastIndex;
    }
    if (needle >= lastNeedle) {
      low = lastIndex === -1 ? 0 : lastIndex;
    } else {
      high = lastIndex;
    }
  }
  state.lastKey = key;
  state.lastNeedle = needle;
  return state.lastIndex = binarySearch(haystack, needle, low, high);
}

// src/types.ts
function parse$1(map) {
  return typeof map === "string" ? JSON.parse(map) : map;
}
var TraceMap = class {
  constructor(map, mapUrl) {
    const isString = typeof map === "string";
    if (!isString && map._decodedMemo) return map;
    const parsed = parse$1(map);
    const { version, file, names, sourceRoot, sources, sourcesContent } = parsed;
    this.version = version;
    this.file = file;
    this.names = names || [];
    this.sourceRoot = sourceRoot;
    this.sources = sources;
    this.sourcesContent = sourcesContent;
    this.ignoreList = parsed.ignoreList || parsed.x_google_ignoreList || void 0;
    const resolve = resolver(mapUrl, sourceRoot);
    this.resolvedSources = sources.map(resolve);
    const { mappings } = parsed;
    if (typeof mappings === "string") {
      this._encoded = mappings;
      this._decoded = void 0;
    } else if (Array.isArray(mappings)) {
      this._encoded = void 0;
      this._decoded = maybeSort(mappings, isString);
    } else if (parsed.sections) {
      throw new Error(`TraceMap passed sectioned source map, please use FlattenMap export instead`);
    } else {
      throw new Error(`invalid source map: ${JSON.stringify(parsed)}`);
    }
    this._decodedMemo = memoizedState();
    this._bySources = void 0;
    this._bySourceMemos = void 0;
  }
};
function cast$1(map) {
  return map;
}
function decodedMappings(map) {
  var _a;
  return (_a = cast$1(map))._decoded || (_a._decoded = decode(cast$1(map)._encoded));
}
function traceSegment(map, line, column) {
  const decoded = decodedMappings(map);
  if (line >= decoded.length) return null;
  const segments = decoded[line];
  const index = traceSegmentInternal(
    segments,
    cast$1(map)._decodedMemo,
    line,
    column);
  return index === -1 ? null : segments[index];
}
function traceSegmentInternal(segments, memo, line, column, bias) {
  let index = memoizedBinarySearch(segments, column, memo, line);
  if (found) {
    index = (lowerBound)(segments, column, index);
  }
  if (index === -1 || index === segments.length) return -1;
  return index;
}

// src/set-array.ts
var SetArray = class {
  constructor() {
    this._indexes = { __proto__: null };
    this.array = [];
  }
};
function cast(set) {
  return set;
}
function get(setarr, key) {
  return cast(setarr)._indexes[key];
}
function put(setarr, key) {
  const index = get(setarr, key);
  if (index !== void 0) return index;
  const { array, _indexes: indexes } = cast(setarr);
  const length = array.push(key);
  return indexes[key] = length - 1;
}
function remove(setarr, key) {
  const index = get(setarr, key);
  if (index === void 0) return;
  const { array, _indexes: indexes } = cast(setarr);
  for (let i = index + 1; i < array.length; i++) {
    const k = array[i];
    array[i - 1] = k;
    indexes[k]--;
  }
  indexes[key] = void 0;
  array.pop();
}

// src/sourcemap-segment.ts
var COLUMN = 0;
var SOURCES_INDEX = 1;
var SOURCE_LINE = 2;
var SOURCE_COLUMN = 3;
var NAMES_INDEX = 4;

// src/gen-mapping.ts
var NO_NAME = -1;
var GenMapping = class {
  constructor({ file, sourceRoot } = {}) {
    this._names = new SetArray();
    this._sources = new SetArray();
    this._sourcesContent = [];
    this._mappings = [];
    this.file = file;
    this.sourceRoot = sourceRoot;
    this._ignoreList = new SetArray();
  }
};
function cast2(map) {
  return map;
}
var maybeAddSegment = (map, genLine, genColumn, source, sourceLine, sourceColumn, name, content) => {
  return addSegmentInternal(
    true,
    map,
    genLine,
    genColumn,
    source,
    sourceLine,
    sourceColumn,
    name);
};
function setSourceContent(map, source, content) {
  const {
    _sources: sources,
    _sourcesContent: sourcesContent
    // _originalScopes: originalScopes,
  } = cast2(map);
  const index = put(sources, source);
  sourcesContent[index] = content;
}
function setIgnore(map, source, ignore = true) {
  const {
    _sources: sources,
    _sourcesContent: sourcesContent,
    _ignoreList: ignoreList
    // _originalScopes: originalScopes,
  } = cast2(map);
  const index = put(sources, source);
  if (index === sourcesContent.length) sourcesContent[index] = null;
  if (ignore) put(ignoreList, index);
  else remove(ignoreList, index);
}
function toDecodedMap(map) {
  const {
    _mappings: mappings,
    _sources: sources,
    _sourcesContent: sourcesContent,
    _names: names,
    _ignoreList: ignoreList
    // _originalScopes: originalScopes,
    // _generatedRanges: generatedRanges,
  } = cast2(map);
  removeEmptyFinalLines(mappings);
  return {
    version: 3,
    file: map.file || void 0,
    names: names.array,
    sourceRoot: map.sourceRoot || void 0,
    sources: sources.array,
    sourcesContent,
    mappings,
    // originalScopes,
    // generatedRanges,
    ignoreList: ignoreList.array
  };
}
function toEncodedMap(map) {
  const decoded = toDecodedMap(map);
  return Object.assign({}, decoded, {
    // originalScopes: decoded.originalScopes.map((os) => encodeOriginalScopes(os)),
    // generatedRanges: encodeGeneratedRanges(decoded.generatedRanges as GeneratedRange[]),
    mappings: encode(decoded.mappings)
  });
}
function addSegmentInternal(skipable, map, genLine, genColumn, source, sourceLine, sourceColumn, name, content) {
  const {
    _mappings: mappings,
    _sources: sources,
    _sourcesContent: sourcesContent,
    _names: names
    // _originalScopes: originalScopes,
  } = cast2(map);
  const line = getIndex(mappings, genLine);
  const index = getColumnIndex(line, genColumn);
  if (!source) {
    if (skipSourceless(line, index)) return;
    return insert(line, index, [genColumn]);
  }
  const sourcesIndex = put(sources, source);
  const namesIndex = name ? put(names, name) : NO_NAME;
  if (sourcesIndex === sourcesContent.length) sourcesContent[sourcesIndex] = null;
  if (skipSource(line, index, sourcesIndex, sourceLine, sourceColumn, namesIndex)) {
    return;
  }
  return insert(
    line,
    index,
    name ? [genColumn, sourcesIndex, sourceLine, sourceColumn, namesIndex] : [genColumn, sourcesIndex, sourceLine, sourceColumn]
  );
}
function getIndex(arr, index) {
  for (let i = arr.length; i <= index; i++) {
    arr[i] = [];
  }
  return arr[index];
}
function getColumnIndex(line, genColumn) {
  let index = line.length;
  for (let i = index - 1; i >= 0; index = i--) {
    const current = line[i];
    if (genColumn >= current[COLUMN]) break;
  }
  return index;
}
function insert(array, index, value) {
  for (let i = array.length; i > index; i--) {
    array[i] = array[i - 1];
  }
  array[index] = value;
}
function removeEmptyFinalLines(mappings) {
  const { length } = mappings;
  let len = length;
  for (let i = len - 1; i >= 0; len = i, i--) {
    if (mappings[i].length > 0) break;
  }
  if (len < length) mappings.length = len;
}
function skipSourceless(line, index) {
  if (index === 0) return true;
  const prev = line[index - 1];
  return prev.length === 1;
}
function skipSource(line, index, sourcesIndex, sourceLine, sourceColumn, namesIndex) {
  if (index === 0) return false;
  const prev = line[index - 1];
  if (prev.length === 1) return false;
  return sourcesIndex === prev[SOURCES_INDEX] && sourceLine === prev[SOURCE_LINE] && sourceColumn === prev[SOURCE_COLUMN] && namesIndex === (prev.length === 5 ? prev[NAMES_INDEX] : NO_NAME);
}

// src/build-source-map-tree.ts
var SOURCELESS_MAPPING = /* @__PURE__ */ SegmentObject("", -1, -1, "", null, false);
var EMPTY_SOURCES = [];
function SegmentObject(source, line, column, name, content, ignore) {
  return { source, line, column, name, content, ignore };
}
function Source(map, sources, source, content, ignore) {
  return {
    map,
    sources,
    source,
    content,
    ignore
  };
}
function MapSource(map, sources) {
  return Source(map, sources, "", null, false);
}
function OriginalSource(source, content, ignore) {
  return Source(null, EMPTY_SOURCES, source, content, ignore);
}
function traceMappings(tree) {
  const gen = new GenMapping({ file: tree.map.file });
  const { sources: rootSources, map } = tree;
  const rootNames = map.names;
  const rootMappings = decodedMappings(map);
  for (let i = 0; i < rootMappings.length; i++) {
    const segments = rootMappings[i];
    for (let j = 0; j < segments.length; j++) {
      const segment = segments[j];
      const genCol = segment[0];
      let traced = SOURCELESS_MAPPING;
      if (segment.length !== 1) {
        const source2 = rootSources[segment[1]];
        traced = originalPositionFor(
          source2,
          segment[2],
          segment[3],
          segment.length === 5 ? rootNames[segment[4]] : ""
        );
        if (traced == null) continue;
      }
      const { column, line, name, content, source, ignore } = traced;
      maybeAddSegment(gen, i, genCol, source, line, column, name);
      if (source && content != null) setSourceContent(gen, source, content);
      if (ignore) setIgnore(gen, source, true);
    }
  }
  return gen;
}
function originalPositionFor(source, line, column, name) {
  if (!source.map) {
    return SegmentObject(source.source, line, column, name, source.content, source.ignore);
  }
  const segment = traceSegment(source.map, line, column);
  if (segment == null) return null;
  if (segment.length === 1) return SOURCELESS_MAPPING;
  return originalPositionFor(
    source.sources[segment[1]],
    segment[2],
    segment[3],
    segment.length === 5 ? source.map.names[segment[4]] : name
  );
}

// src/build-source-map-tree.ts
function asArray(value) {
  if (Array.isArray(value)) return value;
  return [value];
}
function buildSourceMapTree(input, loader) {
  const maps = asArray(input).map((m) => new TraceMap(m, ""));
  const map = maps.pop();
  for (let i = 0; i < maps.length; i++) {
    if (maps[i].sources.length > 1) {
      throw new Error(
        `Transformation map ${i} must have exactly one source file.
Did you specify these with the most recent transformation maps first?`
      );
    }
  }
  let tree = build(map, loader, "", 0);
  for (let i = maps.length - 1; i >= 0; i--) {
    tree = MapSource(maps[i], [tree]);
  }
  return tree;
}
function build(map, loader, importer, importerDepth) {
  const { resolvedSources, sourcesContent, ignoreList } = map;
  const depth = importerDepth + 1;
  const children = resolvedSources.map((sourceFile, i) => {
    const ctx = {
      importer,
      depth,
      source: sourceFile || "",
      content: void 0,
      ignore: void 0
    };
    const sourceMap = loader(ctx.source, ctx);
    const { source} = ctx;
    if (sourceMap) return build(new TraceMap(sourceMap, source), loader, source, depth);
    const sourceContent = sourcesContent ? sourcesContent[i] : null;
    const ignored = ignoreList ? ignoreList.includes(i) : false;
    return OriginalSource(source, sourceContent, ignored);
  });
  return MapSource(map, children);
}
var SourceMap = class {
  constructor(map, options) {
    const out = options.decodedMappings ? toDecodedMap(map) : toEncodedMap(map);
    this.version = out.version;
    this.file = out.file;
    this.mappings = out.mappings;
    this.names = out.names;
    this.ignoreList = out.ignoreList;
    this.sourceRoot = out.sourceRoot;
    this.sources = out.sources;
    if (!options.excludeContent) {
      this.sourcesContent = out.sourcesContent;
    }
  }
  toString() {
    return JSON.stringify(this);
  }
};

// src/remapping.ts
function remapping(input, loader, options) {
  const opts = { excludeContent: true, decodedMappings: false };
  const tree = buildSourceMapTree(input, loader);
  return new SourceMap(traceMappings(tree), opts);
}

/**
 * Pushes all `items` into `array` using `push`, therefore mutating the array.
 * We do this for memory and perf reasons, and because `array.push(...items)` would
 * run into a "max call stack size exceeded" error with too many items (~65k).
 * @template T
 * @param {T[]} array
 * @param {T[]} items
 */
function push_array(array, items) {
	for (let i = 0; i < items.length; i++) {
		array.push(items[i]);
	}
}

/** @import { ValidatedCompileOptions } from '#compiler' */
/** @import { Processed } from '../preprocess/public.js' */
/** @import { SourceMap } from 'magic-string' */
/** @import { Source } from '../preprocess/private.js' */
/** @import { DecodedSourceMap, SourceMapSegment, RawSourceMap } from '@jridgewell/remapping' */

/**
 * @param {string} s
 */
function last_line_length(s) {
	return s.length - s.lastIndexOf('\n') - 1;
}
// mutate map in-place

/**
 * @param {DecodedSourceMap} map
 * @param {{ line: number; column: number; }} offset
 * @param {number} source_index
 */
function sourcemap_add_offset(map, offset, source_index) {
	if (map.mappings.length == 0) return;
	for (let line = 0; line < map.mappings.length; line++) {
		const segment_list = map.mappings[line];
		for (let segment = 0; segment < segment_list.length; segment++) {
			const seg = segment_list[segment];
			// shift only segments that belong to component source file
			if (seg[1] === source_index) {
				// also ensures that seg.length >= 4
				// shift column if it points at the first line
				if (seg[2] === 0) {
					/** @type {any} */ (seg[3]) += offset.column;
				}
				// shift line
				/** @type {any} */ (seg[2]) += offset.line;
			}
		}
	}
}

/**
 * @template T
 * @param {T[]} this_table
 * @param {T[]} other_table
 * @returns {[T[], number[], boolean, boolean]}
 */
function merge_tables(this_table, other_table) {
	const new_table = this_table.slice();
	const idx_map = [];
	other_table = other_table || [];
	let val_changed = false;
	for (const [other_idx, other_val] of other_table.entries()) {
		const this_idx = this_table.indexOf(other_val);
		if (this_idx >= 0) {
			idx_map[other_idx] = this_idx;
		} else {
			const new_idx = new_table.length;
			new_table[new_idx] = other_val;
			idx_map[other_idx] = new_idx;
			val_changed = true;
		}
	}
	let idx_changed = val_changed;
	if (val_changed) {
		if (idx_map.find((val, idx) => val != idx) === undefined) {
			// idx_map is identity map [0, 1, 2, 3, 4, ....]
			idx_changed = false;
		}
	}
	return [new_table, idx_map, val_changed, idx_changed];
}
const regex_line_token = /([^\w\s]|\s+)/g;
/** */
class MappedCode {
	/**
	 * @type {string}
	 */
	string = /** @type {any} */ (undefined);

	/**
	 * @type {DecodedSourceMap}
	 */
	map = /** @type {any} */ (undefined);

	/**
	 * @param {string} string
	 * @param {DecodedSourceMap | null} map
	 */
	constructor(string = '', map = null) {
		this.string = string;
		if (map) {
			this.map = map;
		} else {
			this.map = {
				version: 3,
				mappings: [],
				sources: [],
				names: []
			};
		}
	}
	/**
	 * concat in-place (mutable), return this (chainable)
	 * will also mutate the `other` object
	 * @param {MappedCode} other
	 * @returns {MappedCode}
	 */
	concat(other) {
		// noop: if one is empty, return the other
		if (other.string == '') return this;
		if (this.string == '') {
			this.string = other.string;
			this.map = other.map;
			return this;
		}
		// compute last line length before mutating
		const column_offset = last_line_length(this.string);
		this.string += other.string;
		const m1 = this.map;
		const m2 = other.map;
		if (m2.mappings.length == 0) return this;
		// combine sources and names
		const [sources, new_source_idx, sources_changed, sources_idx_changed] = merge_tables(
			m1.sources,
			m2.sources
		);
		const [names, new_name_idx, names_changed, names_idx_changed] = merge_tables(
			m1.names,
			m2.names
		);
		if (sources_changed) m1.sources = sources;
		if (names_changed) m1.names = names;
		// unswitched loops are faster
		if (sources_idx_changed && names_idx_changed) {
			for (let line = 0; line < m2.mappings.length; line++) {
				const segment_list = m2.mappings[line];
				for (let segment = 0; segment < segment_list.length; segment++) {
					const seg = segment_list[segment];
					// @ts-ignore
					if (seg[1] >= 0) seg[1] = new_source_idx[seg[1]];
					// @ts-ignore
					if (seg[4] >= 0) seg[4] = new_name_idx[seg[4]];
				}
			}
		} else if (sources_idx_changed) {
			for (let line = 0; line < m2.mappings.length; line++) {
				const segment_list = m2.mappings[line];
				for (let segment = 0; segment < segment_list.length; segment++) {
					const seg = segment_list[segment];
					// @ts-ignore
					if (seg[1] >= 0) seg[1] = new_source_idx[seg[1]];
				}
			}
		} else if (names_idx_changed) {
			for (let line = 0; line < m2.mappings.length; line++) {
				const segment_list = m2.mappings[line];
				for (let segment = 0; segment < segment_list.length; segment++) {
					const seg = segment_list[segment];
					// @ts-ignore
					if (seg[4] >= 0) seg[4] = new_name_idx[seg[4]];
				}
			}
		}
		// combine the mappings
		// combine
		// 1. last line of first map
		// 2. first line of second map
		// columns of 2 must be shifted
		if (m2.mappings.length > 0 && column_offset > 0) {
			const first_line = m2.mappings[0];
			for (let i = 0; i < first_line.length; i++) {
				first_line[i][0] += column_offset;
			}
		}
		// combine last line + first line
		push_array(
			m1.mappings[m1.mappings.length - 1],
			/** @type {SourceMapSegment[]} */ (m2.mappings.shift())
		);
		// append other lines
		push_array(m1.mappings, m2.mappings);
		return this;
	}

	/**
	 * @static
	 * @param {string} string
	 * @param {DecodedSourceMap} [map]
	 * @returns {MappedCode}
	 */
	static from_processed(string, map) {
		const line_count = string.split('\n').length;
		if (map) {
			// ensure that count of source map mappings lines
			// is equal to count of generated code lines
			// (some tools may produce less)
			const missing_lines = line_count - map.mappings.length;
			for (let i = 0; i < missing_lines; i++) {
				map.mappings.push([]);
			}
			return new MappedCode(string, map);
		}
		if (string == '') return new MappedCode();
		map = { version: 3, names: [], sources: [], mappings: [] };
		// add empty SourceMapSegment[] for every line
		for (let i = 0; i < line_count; i++) map.mappings.push([]);
		return new MappedCode(string, map);
	}

	/**
	 * @static
	 * @param {Source} opts
	 * @returns {MappedCode}
	 */
	static from_source({ source, file_basename, get_location }) {
		/**
		 * @type {{ line: number; column: number; }}
		 */
		let offset = get_location(0);
		if (!offset) offset = { line: 0, column: 0 };

		/**
		 * @type {DecodedSourceMap}
		 */
		const map = { version: 3, names: [], sources: [file_basename], mappings: [] };
		if (source == '') return new MappedCode(source, map);
		// we create a high resolution identity map here,
		// we know that it will eventually be merged with svelte's map,
		// at which stage the resolution will decrease.
		const line_list = source.split('\n');
		for (let line = 0; line < line_list.length; line++) {
			map.mappings.push([]);
			const token_list = line_list[line].split(regex_line_token);
			for (let token = 0, column = 0; token < token_list.length; token++) {
				if (token_list[token] == '') continue;
				map.mappings[line].push([column, 0, offset.line + line, column]);
				column += token_list[token].length;
			}
		}
		// shift columns in first line
		const segment_list = map.mappings[0];
		for (let segment = 0; segment < segment_list.length; segment++) {
			// @ts-ignore
			segment_list[segment][3] += offset.column;
		}
		return new MappedCode(source, map);
	}
}

// browser vs node.js
const b64enc =
	typeof window !== 'undefined' && typeof btoa === 'function'
		? /** @param {string} str */ (str) => btoa(unescape(encodeURIComponent(str)))
		: /** @param {string} str */ (str) => Buffer.from(str).toString('base64');
const b64dec =
	typeof window !== 'undefined' && typeof atob === 'function'
		? atob
		: /** @param {any} a */ (a) => Buffer.from(a, 'base64').toString();

/**
 * @param {string} filename Basename of the input file
 * @param {Array<DecodedSourceMap | RawSourceMap>} sourcemap_list
 */
function combine_sourcemaps(filename, sourcemap_list) {
	if (sourcemap_list.length == 0) return null;
	let map_idx = 1;
	const map =
		sourcemap_list.slice(0, -1).find((m) => m.sources.length !== 1) === undefined
			? remapping(
					// use array interface
					// only the oldest sourcemap can have multiple sources
					sourcemap_list,
					() => null)
			: remapping(
					// use loader interface
					sourcemap_list[0], // last map
					(sourcefile) => {
						// TODO the equality check assumes that the preprocessor map has the input file as a relative path in sources,
						// e.g. when the input file is `src/foo/bar.svelte`, then sources is expected to contain just `bar.svelte`.
						// Therefore filename also needs to be the basename of the path. This feels brittle, investigate how we can
						// harden this (without breaking other tooling that assumes this behavior).
						if (sourcefile === filename && sourcemap_list[map_idx]) {
							return sourcemap_list[map_idx++]; // idx 1, 2, ...
							// bundle file = branch node
						} else {
							return null; // source file = leaf node
						}
					});
	if (!map.file) delete map.file; // skip optional field `file`
	// When source maps are combined and the leading map is empty, sources is not set.
	// Add the filename to the empty array in this case.
	// Further improvements to remapping may help address this as well https://github.com/ampproject/remapping/issues/116
	if (!map.sources.length) map.sources = [filename];
	return map;
}

/**
 * @param {string} filename
 * @param {SourceMap} svelte_map
 * @param {string | DecodedSourceMap | RawSourceMap} preprocessor_map_input
 * @returns {SourceMap}
 */
function apply_preprocessor_sourcemap(filename, svelte_map, preprocessor_map_input) {
	if (!svelte_map || !preprocessor_map_input) return svelte_map;
	const preprocessor_map =
		typeof preprocessor_map_input === 'string'
			? JSON.parse(preprocessor_map_input)
			: preprocessor_map_input;
	const result_map = combine_sourcemaps(filename, [svelte_map, preprocessor_map]);
	// Svelte expects a SourceMap which includes toUrl and toString. Instead of wrapping our output in a class,
	// we just tack on the extra properties.
	Object.defineProperties(result_map, {
		toString: {
			enumerable: false,
			value: function toString() {
				return JSON.stringify(this);
			}
		},
		toUrl: {
			enumerable: false,
			value: function toUrl() {
				return 'data:application/json;charset=utf-8;base64,' + b64enc(this.toString());
			}
		}
	});
	return /** @type {any} */ (result_map);
}
const regex_data_uri = /data:(?:application|text)\/json;(?:charset[:=]\S+?;)?base64,(\S*)/;
// parse attached sourcemap in processed.code

/**
 * @param {Processed} processed
 * @param {'script' | 'style'} tag_name
 * @returns {void}
 */
function parse_attached_sourcemap(processed, tag_name) {
	const r_in = '[#@]\\s*sourceMappingURL\\s*=\\s*(\\S*)';
	const regex =
		tag_name == 'script'
			? new RegExp('(?://' + r_in + ')|(?:/\\*' + r_in + '\\s*\\*/)$')
			: new RegExp('/\\*' + r_in + '\\s*\\*/$');

	/**
	 * @param {any} message
	 */
	function log_warning(message) {
		// code_start: help to find preprocessor
		const code_start =
			processed.code.length < 100 ? processed.code : processed.code.slice(0, 100) + ' [...]';
		// eslint-disable-next-line no-console
		console.warn(`warning: ${message}. processed.code = ${JSON.stringify(code_start)}`);
	}
	processed.code = processed.code.replace(regex, (_, match1, match2) => {
		const map_url = tag_name == 'script' ? match1 || match2 : match1;
		const map_data = (map_url.match(regex_data_uri) || [])[1];
		if (map_data) {
			// sourceMappingURL is data URL
			if (processed.map) {
				log_warning(
					'Not implemented. ' +
						'Found sourcemap in both processed.code and processed.map. ' +
						'Please update your preprocessor to return only one sourcemap.'
				);
				// ignore attached sourcemap
				return '';
			}
			processed.map = b64dec(map_data); // use attached sourcemap
			return ''; // remove from processed.code
		}
		// sourceMappingURL is path or URL
		if (!processed.map) {
			log_warning(
				`Found sourcemap path ${JSON.stringify(
					map_url
				)} in processed.code, but no sourcemap data. ` +
					'Please update your preprocessor to return sourcemap data directly.'
			);
		}
		// ignore sourcemap path
		return ''; // remove from processed.code
	});
}

/**
 * @param {{ code: string, map: SourceMap}} result
 * @param {ValidatedCompileOptions} options
 * @param {string} source_name
 */
function merge_with_preprocessor_map(result, options, source_name) {
	if (options.sourcemap) {
		const file_basename = get_basename(options.filename);
		// The preprocessor map is expected to contain `sources: [basename_of_filename]`, but our own
		// map may contain a different file name. Patch our map beforehand to align sources so merging
		// with the preprocessor map works correctly.
		result.map.sources = [file_basename];
		Object.assign(
			result.map,
			apply_preprocessor_sourcemap(
				file_basename,
				result.map,
				/** @type {any} */ (options.sourcemap)
			)
		);
		// After applying the preprocessor map, we need to do the inverse and make the sources
		// relative to the input file again in case the output code is in a different directory.
		if (file_basename !== source_name) {
			result.map.sources = result.map.sources.map(
				/** @param {string} source */ (source) => get_relative_path(source_name, source)
			);
		}
	}
}

/**
 * @param {string} from
 * @param {string} to
 */
function get_relative_path(from, to) {
	// Don't use node's utils here to ensure the compiler is usable in a browser environment
	const from_parts = from.split(/[/\\]/);
	const to_parts = to.split(/[/\\]/);
	from_parts.pop(); // get dirname
	while (from_parts[0] === to_parts[0]) {
		from_parts.shift();
		to_parts.shift();
	}
	if (from_parts.length) {
		let i = from_parts.length;
		while (i--) from_parts[i] = '..';
	}
	return from_parts.concat(to_parts).join('/');
}

/**
 * Like node's `basename`, but doesn't use it to ensure the compiler is usable in a browser environment
 * @param {string} filename
 */
function get_basename(filename) {
	return /** @type {string} */ (filename.split(/[/\\]/).pop());
}

/**
 * @param {string} filename
 * @param {string | undefined} output_filename
 * @param {string} fallback
 */
function get_source_name(filename, output_filename, fallback) {
	return output_filename ? get_relative_path(output_filename, filename) : get_basename(filename);
}

/** @import { Visitors } from 'zimmerframe' */
/** @import { AST, ValidatedCompileOptions } from '#compiler' */
/** @import { ComponentAnalysis } from '../../types.js' */

/**
 * @typedef {{
 *   code: MagicString;
 *   hash: string;
 *   minify: boolean;
 *   selector: string;
 *   keyframes: string[];
 *   specificity: {
 *     bumped: boolean
 *   }
 * }} State
 */

/**
 *
 * @param {string} source
 * @param {ComponentAnalysis} analysis
 * @param {ValidatedCompileOptions} options
 */
function render_stylesheet(source, analysis, options) {
	const code = new MagicString(source);

	/** @type {State} */
	const state = {
		code,
		hash: analysis.css.hash,
		minify: analysis.inject_styles && !options.dev,
		selector: `.${analysis.css.hash}`,
		keyframes: analysis.css.keyframes,
		specificity: {
			bumped: false
		}
	};

	const ast = /** @type {AST.CSS.StyleSheet} */ (analysis.css.ast);

	walk$1(/** @type {AST.CSS.Node} */ (ast), state, visitors$1);

	code.remove(0, ast.content.start);
	code.remove(/** @type {number} */ (ast.content.end), source.length);
	if (state.minify) {
		remove_preceding_whitespace(ast.content.end, state);
	}

	const css = {
		code: code.toString(),
		map: code.generateMap({
			// include source content; makes it easier/more robust looking up the source map code
			includeContent: true,
			// generateMap takes care of calculating source relative to file
			source: options.filename,
			file: options.cssOutputFilename || options.filename
		}),
		hasGlobal: analysis.css.has_global
	};

	merge_with_preprocessor_map(css, options, css.map.sources[0]);

	if (dev && options.css === 'injected' && css.code) {
		css.code += `\n/*# sourceMappingURL=${css.map.toUrl()} */`;
	}

	return css;
}

/** @type {Visitors<AST.CSS.Node, State>} */
const visitors$1 = {
	_: (node, context) => {
		context.state.code.addSourcemapLocation(node.start);
		context.state.code.addSourcemapLocation(node.end);
		context.next();
	},
	Atrule(node, { state, next, path }) {
		if (is_keyframes_node(node)) {
			let start = node.start + node.name.length + 1;
			while (state.code.original[start] === ' ') start += 1;
			let end = start;
			while (state.code.original[end] !== '{' && state.code.original[end] !== ' ') end += 1;

			if (node.prelude.startsWith('-global-')) {
				state.code.remove(start, start + 8);
			} else if (!is_in_global_block(path)) {
				state.code.prependRight(start, `${state.hash}-`);
			}

			return; // don't transform anything within
		}

		next();
	},
	Declaration(node, { state }) {
		const property = node.property && remove_css_prefix(node.property.toLowerCase());
		if (property === 'animation' || property === 'animation-name') {
			let index = node.start + node.property.length + 1;
			let name = '';

			while (index < state.code.original.length) {
				const character = state.code.original[index];

				if (regex_css_name_boundary.test(character)) {
					if (state.keyframes.includes(name)) {
						state.code.prependRight(index - name.length, `${state.hash}-`);
					}

					if (character === ';' || character === '}') {
						break;
					}

					name = '';
				} else {
					name += character;
				}

				index++;
			}
		} else if (state.minify) {
			remove_preceding_whitespace(node.start, state);

			// Don't minify whitespace in custom properties, since some browsers (Chromium < 99)
			// treat --foo: ; and --foo:; differently
			if (!node.property.startsWith('--')) {
				let start = node.start + node.property.length + 1;
				let end = start;
				while (/\s/.test(state.code.original[end])) end++;
				if (end > start) state.code.remove(start, end);
			}
		}
	},
	Rule(node, { state, next, visit, path }) {
		if (state.minify) {
			remove_preceding_whitespace(node.start, state);
			remove_preceding_whitespace(node.block.end - 1, state);
		}

		// keep empty rules in dev, because it's convenient to
		// see them in devtools
		if (!dev && is_empty(node, is_in_global_block(path))) {
			if (state.minify) {
				state.code.remove(node.start, node.end);
			} else {
				state.code.prependRight(node.start, '/* (empty) ');
				state.code.appendLeft(node.end, '*/');
				escape_comment_close(node, state.code);
			}

			return;
		}

		if (!is_used(node) && !is_in_global_block(path)) {
			if (state.minify) {
				state.code.remove(node.start, node.end);
			} else {
				state.code.prependRight(node.start, '/* (unused) ');
				state.code.appendLeft(node.end, '*/');
				escape_comment_close(node, state.code);
			}

			return;
		}

		if (node.metadata.is_global_block) {
			const selector = node.prelude.children[0];

			if (
				node.prelude.children.length === 1 &&
				selector.children.length === 1 &&
				selector.children[0].selectors.length === 1
			) {
				// `:global {...}`
				if (state.minify) {
					state.code.remove(node.start, node.block.start + 1);
					state.code.remove(node.block.end - 1, node.end);
				} else {
					state.code.prependRight(node.start, '/* ');
					state.code.appendLeft(node.block.start + 1, '*/');

					state.code.prependRight(node.block.end - 1, '/*');
					state.code.appendLeft(node.block.end, '*/');
				}

				// don't recurse into selectors but visit the body
				visit(node.block);
				return;
			}
		}

		next();
	},
	SelectorList(node, { state, next, path }) {
		const parent = path.at(-1);

		// Only add comments if we're not inside a complex selector that itself is unused or a global block
		if (
			(!is_in_global_block(path) ||
				(node.children.length > 1 && parent?.type === 'Rule' && parent.metadata.is_global_block)) &&
			!path.find((n) => n.type === 'ComplexSelector' && !n.metadata.used)
		) {
			const children = node.children;
			let pruning = false;
			let prune_start = children[0].start;
			let last = prune_start;
			let has_previous_used = false;

			for (let i = 0; i < children.length; i += 1) {
				const selector = children[i];

				if (selector.metadata.used === pruning) {
					if (pruning) {
						let i = selector.start;
						while (state.code.original[i] !== ',') i--;

						if (state.minify) {
							state.code.remove(prune_start, has_previous_used ? i : i + 1);
						} else {
							state.code.appendRight(has_previous_used ? i : i + 1, '*/');
						}
					} else {
						if (i === 0) {
							if (state.minify) {
								prune_start = selector.start;
							} else {
								state.code.prependRight(selector.start, '/* (unused) ');
							}
						} else {
							if (state.minify) {
								prune_start = last;
							} else {
								state.code.overwrite(last, selector.start, ` /* (unused) `);
							}
						}
					}

					pruning = !pruning;
				}

				if (!pruning && selector.metadata.used) {
					has_previous_used = true;
				}

				last = selector.end;
			}

			if (pruning) {
				if (state.minify) {
					state.code.remove(prune_start, last);
				} else {
					state.code.appendLeft(last, '*/');
				}
			}
		}

		// if we're in a `:is(...)` or whatever, keep existing specificity bump state
		let specificity = state.specificity;

		// if this selector list belongs to a rule, require a specificity bump for the
		// first scoped selector but only if we're at the top level
		if (parent?.type === 'Rule') {
			specificity = { bumped: false };

			/** @type {AST.CSS.Rule | null} */
			let rule = parent.metadata.parent_rule;

			while (rule) {
				if (rule.metadata.has_local_selectors) {
					specificity = { bumped: true };
					break;
				}
				rule = rule.metadata.parent_rule;
			}
		}

		next({ ...state, specificity });
	},
	ComplexSelector(node, context) {
		const before_bumped = context.state.specificity.bumped;

		for (const relative_selector of node.children) {
			if (relative_selector.metadata.is_global) {
				const global = /** @type {AST.CSS.PseudoClassSelector} */ (relative_selector.selectors[0]);
				remove_global_pseudo_class(global, relative_selector.combinator, context.state);

				const parent_rule = node.metadata.rule?.metadata.parent_rule;
				if (parent_rule && global.args === null) {
					if (relative_selector.combinator === null) {
						// div { :global.x { ... } } becomes div { &.x { ... } }
						context.state.code.prependRight(global.start, '&');
					}

					// In case of multiple :global selectors in a selector list we gotta delete the comma, too, but only if
					// the next selector is used; if it's unused then the comma deletion happens as part of removal of that next selector
					if (
						parent_rule.prelude.children.length > 1 &&
						node.children.length === node.children.findIndex((s) => s === relative_selector) - 1
					) {
						const next_selector = parent_rule.prelude.children.find((s) => s.start > global.end);
						if (next_selector && next_selector.metadata.used) {
							context.state.code.update(global.end, next_selector.start, '');
						}
					}
				}
				continue;
			} else {
				// for any :global() or :global at the middle of compound selector
				for (const selector of relative_selector.selectors) {
					if (selector.type === 'PseudoClassSelector' && selector.name === 'global') {
						remove_global_pseudo_class(selector, null, context.state);
					}
				}
			}

			if (relative_selector.metadata.scoped) {
				if (relative_selector.selectors.length === 1) {
					// skip standalone :is/:where/& selectors
					const selector = relative_selector.selectors[0];
					if (
						selector.type === 'PseudoClassSelector' &&
						(selector.name === 'is' || selector.name === 'where')
					) {
						continue;
					}
				}

				if (relative_selector.selectors.some((s) => s.type === 'NestingSelector')) {
					continue;
				}

				// for the first occurrence, we use a classname selector, so that every
				// encapsulated selector gets a +0-1-0 specificity bump. thereafter,
				// we use a `:where` selector, which does not affect specificity
				let modifier = context.state.selector;
				if (context.state.specificity.bumped) modifier = `:where(${modifier})`;

				context.state.specificity.bumped = true;

				let i = relative_selector.selectors.length;
				while (i--) {
					const selector = relative_selector.selectors[i];

					if (
						selector.type === 'PseudoElementSelector' ||
						selector.type === 'PseudoClassSelector'
					) {
						if (selector.name !== 'root' && selector.name !== 'host') {
							if (i === 0) context.state.code.prependRight(selector.start, modifier);
						}
						continue;
					}

					if (selector.type === 'TypeSelector' && selector.name === '*') {
						context.state.code.update(selector.start, selector.end, modifier);
					} else {
						context.state.code.appendLeft(selector.end, modifier);
					}

					break;
				}
			}
		}

		context.next();

		context.state.specificity.bumped = before_bumped;
	},
	PseudoClassSelector(node, context) {
		if (node.name === 'is' || node.name === 'where' || node.name === 'has' || node.name === 'not') {
			context.next();
		}
	}
};

/**
 * @param {Array<AST.CSS.Node>} path
 */
function is_in_global_block(path) {
	return path.some((node) => node.type === 'Rule' && node.metadata.is_global_block);
}

/**
 * @param {AST.CSS.PseudoClassSelector} selector
 * @param {AST.CSS.Combinator | null} combinator
 * @param {State} state
 */
function remove_global_pseudo_class(selector, combinator, state) {
	if (selector.args === null) {
		let start = selector.start;
		if (combinator?.name === ' ') {
			// div :global.x becomes div.x
			while (/\s/.test(state.code.original[start - 1])) start--;
		}

		// update(...), not remove(...) because there could be a closing unused comment at the end
		state.code.update(start, selector.start + ':global'.length, '');
	} else {
		state.code
			.remove(selector.start, selector.start + ':global('.length)
			.remove(selector.end - 1, selector.end);
	}
}

/**
 * Walk backwards until we find a non-whitespace character
 * @param {number} end
 * @param {State} state
 */
function remove_preceding_whitespace(end, state) {
	let start = end;
	while (/\s/.test(state.code.original[start - 1])) start--;
	if (start < end) state.code.remove(start, end);
}

/**
 *  @param {AST.CSS.Rule} rule
 * @param {boolean} is_in_global_block
 */
function is_empty(rule, is_in_global_block) {
	if (rule.metadata.is_global_block) {
		return rule.block.children.length === 0;
	}

	for (const child of rule.block.children) {
		if (child.type === 'Declaration') {
			return false;
		}

		if (child.type === 'Rule') {
			if ((is_used(child) || is_in_global_block) && !is_empty(child, is_in_global_block)) {
				return false;
			}
		}

		if (child.type === 'Atrule') {
			if (child.block === null || child.block.children.length > 0) return false;
		}
	}

	return true;
}

/** @param {AST.CSS.Rule} rule */
function is_used(rule) {
	return rule.prelude.children.some((selector) => selector.metadata.used);
}

/**
 *
 * @param {AST.CSS.Rule} node
 * @param {MagicString} code
 */
function escape_comment_close(node, code) {
	let escaped = false;
	let in_comment = false;

	for (let i = node.start; i < node.end; i++) {
		if (escaped) {
			escaped = false;
		} else {
			const char = code.original[i];
			if (in_comment) {
				if (char === '*' && code.original[i + 1] === '/') {
					code.prependRight(++i, '\\');
					in_comment = false;
				}
			} else if (char === '\\') {
				escaped = true;
			} else if (char === '/' && code.original[++i] === '*') {
				in_comment = true;
			}
		}
	}
}

/** @import { Identifier } from 'estree' */
/** @import { ComponentContext, Context } from '../../types' */

/**
 * Turns `foo` into `$.get(foo)`
 * @param {Identifier} node
 */
function get_value(node) {
	return call('$.get', node);
}

/**
 *
 * @param {Context | ComponentContext} context
 */
function add_state_transformers(context) {
	for (const [name, binding] of context.state.scope.declarations) {
		if (
			is_state_source(binding, context.state.analysis) ||
			binding.kind === 'derived' ||
			binding.kind === 'legacy_reactive'
		) {
			context.state.transform[name] = {
				read: binding.declaration_kind === 'var' ? (node) => call('$.safe_get', node) : get_value,
				assign: (node, value, proxy = false) => {
					let call$1 = call('$.set', node, value, proxy && true_instance);

					if (context.state.scope.get(`$${node.name}`)?.kind === 'store_sub') {
						call$1 = call('$.store_unsub', call$1, literal(`$${node.name}`), id('$$stores'));
					}

					return call$1;
				},
				mutate: (node, mutation) => {
					if (context.state.analysis.runes) {
						return mutation;
					}

					return call('$.mutate', node, mutation);
				},
				update: (node) => {
					return call(
						node.prefix ? '$.update_pre' : '$.update',
						node.argument,
						node.operator === '--' && literal(-1)
					);
				}
			};
		}
	}
}

/** @import { AssignmentExpression, AssignmentOperator, Expression, Node, Pattern, Statement } from 'estree' */
/** @import { Context as ClientContext } from '../client/types.js' */
/** @import { Context as ServerContext } from '../server/types.js' */

/**
 * @template {ClientContext | ServerContext} Context
 * @param {AssignmentExpression} node
 * @param {Context} context
 * @param {(operator: AssignmentOperator, left: Pattern, right: Expression, context: Context) => Expression | null} build_assignment
 * @returns
 */
function visit_assignment_expression(node, context, build_assignment) {
	if (
		node.left.type === 'ArrayPattern' ||
		node.left.type === 'ObjectPattern' ||
		node.left.type === 'RestElement'
	) {
		const value = /** @type {Expression} */ (context.visit(node.right));
		const should_cache = value.type !== 'Identifier';
		const rhs = should_cache ? id('$$value') : value;

		let changed = false;

		const { inserts, paths } = extract_paths(node.left, rhs);

		for (const { id } of inserts) {
			id.name = context.state.scope.generate('$$array');
		}

		const assignments = paths.map((path) => {
			const value = path.expression;

			let assignment$1 = build_assignment('=', path.node, value, context);
			if (assignment$1 !== null) changed = true;

			return (
				assignment$1 ??
				assignment(
					'=',
					/** @type {Pattern} */ (context.visit(path.node)),
					/** @type {Expression} */ (context.visit(value))
				)
			);
		});

		if (!changed) {
			// No change to output -> nothing to transform -> we can keep the original assignment
			return null;
		}

		const is_standalone = /** @type {Node} */ (context.path.at(-1)).type.endsWith('Statement');

		if (inserts.length > 0 || should_cache) {
			/** @type {Statement[]} */
			const statements = [
				...inserts.map(({ id, value }) => var_builder(id, value)),
				...assignments.map(stmt)
			];

			if (!is_standalone) {
				// this is part of an expression, we need the sequence to end with the value
				statements.push(return_builder(rhs));
			}

			const async =
				is_expression_async(value) ||
				assignments.some((assignment) => is_expression_async(assignment));

			const iife = arrow([rhs], block(statements), async);
			const call$1 = call(iife, value);

			return async ? await_builder(call$1) : call$1;
		}

		const sequence$1 = sequence(assignments);

		if (!is_standalone) {
			// this is part of an expression, we need the sequence to end with the value
			sequence$1.expressions.push(rhs);
		}

		return sequence$1;
	}

	if (node.left.type !== 'Identifier' && node.left.type !== 'MemberExpression') {
		throw new Error(`Unexpected assignment type ${node.left.type}`);
	}

	return build_assignment(node.operator, node.left, node.right, context);
}

/** @import { AssignmentExpression, AssignmentOperator, Expression, Pattern } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { Context, ServerTransformState } from '../types.js' */

/**
 * @param {AssignmentExpression} node
 * @param {Context} context
 */
function AssignmentExpression$1(node, context) {
	return visit_assignment_expression(node, context, build_assignment$1) ?? context.next();
}

/**
 * Only returns an expression if this is not a `$store` assignment, as others can be kept as-is
 * @param {AssignmentOperator} operator
 * @param {Pattern} left
 * @param {Expression} right
 * @param {import('zimmerframe').Context<AST.SvelteNode, ServerTransformState>} context
 * @returns {Expression | null}
 */
function build_assignment$1(operator, left, right, context) {
	if (
		context.state.analysis.runes &&
		left.type === 'MemberExpression' &&
		left.object.type === 'ThisExpression' &&
		!left.computed
	) {
		const name = get_name(left.property);
		const field = name && context.state.state_fields.get(name);

		// special case — state declaration in class constructor
		if (field && field.node.type === 'AssignmentExpression' && left === field.node.left) {
			const rune = get_rune(right, context.state.scope);

			if (rune) {
				const key =
					left.property.type === 'PrivateIdentifier' || rune === '$state' || rune === '$state.raw'
						? left.property
						: field.key;

				return assignment(
					operator,
					member(this_instance, key, key.type === 'Literal'),
					/** @type {Expression} */ (context.visit(right))
				);
			}
		} else if (
			field &&
			(field.type === '$derived' || field.type === '$derived.by') &&
			left.property.type === 'PrivateIdentifier'
		) {
			let value = /** @type {Expression} */ (
				context.visit(build_assignment_value(operator, left, right))
			);
			return call(member(this_instance, name), value);
		}
	}

	let object = left;

	while (object.type === 'MemberExpression') {
		// @ts-expect-error
		object = object.object;
	}

	if (object.type !== 'Identifier' || !is_store_name(object.name)) {
		return null;
	}

	const name = object.name.slice(1);

	if (!context.state.scope.get(name)) {
		return null;
	}

	if (object === left) {
		let value = /** @type {Expression} */ (
			context.visit(build_assignment_value(operator, left, right))
		);

		return call('$.store_set', id(name), value);
	}

	return call(
		'$.store_mutate',
		assignment('??=', id('$$store_subs'), object$2([])),
		literal(object.name),
		id(name),
		assignment(
			operator,
			/** @type {Pattern} */ (context.visit(left)),
			/** @type {Expression} */ (context.visit(right))
		)
	);
}

/**
 * @param {string} name
 */
function is_store_name(name) {
	return name[0] === '$' && /[A-Za-z_]/.test(name[1]);
}

/** @import { Expression, Identifier, Node, Statement, BlockStatement, ArrayExpression } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext, ServerTransformState } from '../../types.js' */


/** Opens an if/each block, so that we can remove nodes in the case of a mismatch */
const block_open = literal(BLOCK_OPEN);

/** Opens an if/each block, so that we can remove nodes in the case of a mismatch */
const block_open_else = literal(BLOCK_OPEN_ELSE);

/** Closes an if/each block, so that we can remove nodes in the case of a mismatch. Also serves as an anchor for these blocks */
const block_close = literal(BLOCK_CLOSE);

/** Empty comment to keep text nodes separate, or provide an anchor node for blocks */
const empty_comment = literal(EMPTY_COMMENT);

/**
 * Processes an array of template nodes, joining sibling text/expression nodes and
 * recursing into child nodes.
 * @param {Array<AST.SvelteNode>} nodes
 * @param {ComponentContext} context
 */
function process_children$1(nodes, { visit, state }) {
	/** @type {Array<AST.Text | AST.Comment | AST.ExpressionTag>} */
	let sequence = [];

	function flush() {
		if (sequence.length === 0) {
			return;
		}

		let quasi$1 = quasi('', false);
		const quasis = [quasi$1];

		/** @type {Expression[]} */
		const expressions = [];

		for (let i = 0; i < sequence.length; i++) {
			const node = sequence[i];

			if (node.type === 'Text' || node.type === 'Comment') {
				quasi$1.value.cooked +=
					node.type === 'Comment' ? `<!--${node.data}-->` : escape_html(node.data);
			} else {
				const evaluated = state.scope.evaluate(node.expression);

				if (evaluated.is_known) {
					quasi$1.value.cooked += escape_html((evaluated.value ?? '') + '');
				} else {
					expressions.push(call('$.escape', /** @type {Expression} */ (visit(node.expression))));

					quasi$1 = quasi('', i + 1 === sequence.length);
					quasis.push(quasi$1);
				}
			}
		}

		for (const quasi of quasis) {
			quasi.value.raw = sanitize_template_string(/** @type {string} */ (quasi.value.cooked));
		}

		state.template.push(template$1(quasis, expressions));
		sequence = [];
	}

	for (const node of nodes) {
		if (node.type === 'ExpressionTag' && node.metadata.expression.is_async()) {
			flush();

			const expression = /** @type {Expression} */ (visit(node.expression));
			state.template.push(create_push(call('$.escape', expression), node.metadata.expression));
		} else if (node.type === 'Text' || node.type === 'Comment' || node.type === 'ExpressionTag') {
			sequence.push(node);
		} else {
			flush();
			visit(node, { ...state });
		}
	}

	flush();
}

/**
 * @param {Node} node
 * @returns {node is Statement}
 */
function is_statement(node) {
	return node.type.endsWith('Statement') || node.type.endsWith('Declaration');
}

/**
 * @param {Array<Statement | Expression>} template
 * @returns {Statement[]}
 */
function build_template(template) {
	/** @type {string[]} */
	let strings = [];

	/** @type {Expression[]} */
	let expressions = [];

	/** @type {Statement[]} */
	const statements = [];

	const flush = () => {
		statements.push(
			stmt(
				call(
					id('$$renderer.push'),
					template$1(
						strings.map((cooked, i) => quasi(cooked, i === strings.length - 1)),
						expressions
					)
				)
			)
		);

		strings = [];
		expressions = [];
	};

	for (let i = 0; i < template.length; i++) {
		const node = template[i];

		if (is_statement(node)) {
			if (strings.length !== 0) {
				flush();
			}

			statements.push(node);
		} else {
			if (strings.length === 0) {
				strings.push('');
			}

			if (node.type === 'Literal') {
				strings[strings.length - 1] += node.value;
			} else if (node.type === 'TemplateLiteral') {
				strings[strings.length - 1] += node.quasis[0].value.cooked;
				strings.push(...node.quasis.slice(1).map((q) => /** @type {string} */ (q.value.cooked)));
				expressions.push(...node.expressions);
			} else {
				expressions.push(node);
				strings.push('');
			}
		}
	}

	if (strings.length !== 0) {
		flush();
	}

	return statements;
}

/**
 *
 * @param {AST.Attribute['value']} value
 * @param {ComponentContext} context
 * @param {(expression: Expression, metadata: ExpressionMetadata) => Expression} transform
 * @param {boolean} trim_whitespace
 * @param {boolean} is_component
 * @returns {Expression}
 */
function build_attribute_value$1(
	value,
	context,
	transform,
	trim_whitespace = false,
	is_component = false
) {
	if (value === true) {
		return true_instance;
	}

	if (!Array.isArray(value) || value.length === 1) {
		const chunk = Array.isArray(value) ? value[0] : value;

		if (chunk.type === 'Text') {
			const data = trim_whitespace
				? chunk.data.replace(regex_whitespaces_strict, ' ').trim()
				: chunk.data;

			return literal(is_component ? data : escape_html(data, true));
		}

		return transform(
			/** @type {Expression} */ (context.visit(chunk.expression)),
			chunk.metadata.expression
		);
	}

	let quasi$1 = quasi('', false);
	const quasis = [quasi$1];

	/** @type {Expression[]} */
	const expressions = [];

	for (let i = 0; i < value.length; i++) {
		const node = value[i];

		if (node.type === 'Text') {
			quasi$1.value.raw += trim_whitespace
				? node.data.replace(regex_whitespaces_strict, ' ')
				: node.data;
		} else {
			expressions.push(
				call(
					'$.stringify',
					transform(
						/** @type {Expression} */ (context.visit(node.expression)),
						node.metadata.expression
					)
				)
			);

			quasi$1 = quasi('', i + 1 === value.length);
			quasis.push(quasi$1);
		}
	}

	return template$1(quasis, expressions);
}

/**
 * @param {Identifier} node
 * @param {ServerTransformState} state
 * @returns {Expression}
 */
function build_getter(node, state) {
	const binding = state.scope.get(node.name);

	if (binding === null || node === binding.node) {
		// No associated binding or the declaration itself which shouldn't be transformed
		return node;
	}

	if (binding.kind === 'store_sub') {
		const store_id = id(node.name.slice(1));
		return call(
			'$.store_get',
			assignment('??=', id('$$store_subs'), object$2([])),
			literal(node.name),
			build_getter(store_id, state)
		);
	}

	return node;
}

/**
 * Creates a `$$renderer.child(...)` expression statement
 * @param {BlockStatement | Expression} body
 * @param {boolean} async
 * @returns {Statement}
 */
function create_child_block(body, async) {
	return stmt(call('$$renderer.child', arrow([id('$$renderer')], body, async)));
}

/**
 * Creates a `$$renderer.async(...)` expression statement
 * @param {BlockStatement | Expression} body
 * @param {ArrayExpression} blockers
 * @param {boolean} has_await
 * @param {boolean} needs_hydration_markers
 */
function create_async_block(
	body,
	blockers = array([]),
	has_await = true,
	needs_hydration_markers = true
) {
	return stmt(
		call(
			needs_hydration_markers ? '$$renderer.async_block' : '$$renderer.async',
			blockers,
			arrow([id('$$renderer')], body, has_await)
		)
	);
}

/**
 * @param {Expression} expression
 * @param {ExpressionMetadata} metadata
 * @param {boolean} needs_hydration_markers
 * @returns {Expression | Statement}
 */
function create_push(expression, metadata, needs_hydration_markers = false) {
	if (metadata.is_async()) {
		let statement = stmt(call('$$renderer.push', thunk(expression, metadata.has_await)));

		const blockers = metadata.blockers();

		if (blockers.elements.length > 0) {
			statement = create_async_block(
				block([statement]),
				blockers,
				false,
				needs_hydration_markers
			);
		}

		return statement;
	}

	return expression;
}

/**
 * @param {BlockStatement | Expression} body
 * @param {Identifier | false} component_fn_id
 * @returns {Statement}
 */
function call_component_renderer(body, component_fn_id) {
	return stmt(
		call('$$renderer.component', arrow([id('$$renderer')], body, false), component_fn_id)
	);
}

/**
 * A utility for optimising promises in templates. Without it code like
 * `<Component foo={await fetch()} bar={await other()} />` would be transformed
 * into two blocking promises, with it it's using `Promise.all` to await them.
 * It also keeps track of blocking promises, i.e. those that need to be resolved before continuing.
 */
class PromiseOptimiser {
	/** @type {Expression[]} */
	expressions = [];

	has_await = false;

	/** @type {Set<Expression>} */
	#blockers = new Set();

	/**
	 * @param {Expression} expression
	 * @param {ExpressionMetadata} metadata
	 */
	transform = (expression, metadata) => {
		this.check_blockers(metadata);

		if (metadata.has_await) {
			this.has_await = true;

			const length = this.expressions.push(expression);
			return id(`$$${length - 1}`);
		}

		return expression;
	};

	/**
	 * @param {ExpressionMetadata} metadata
	 */
	check_blockers(metadata) {
		for (const binding of metadata.dependencies) {
			if (binding.blocker) {
				this.#blockers.add(binding.blocker);
			}
		}
	}

	apply() {
		if (this.expressions.length === 0) {
			return empty;
		}

		if (this.expressions.length === 1) {
			return const_builder('$$0', this.expressions[0]);
		}

		const promises = array(
			this.expressions.map((expression) => {
				return expression.type === 'AwaitExpression' && !has_await_expression(expression.argument)
					? expression.argument
					: call(thunk(expression, true));
			})
		);

		return const_builder(
			array_pattern(this.expressions.map((_, i) => id(`$$${i}`))),
			await_builder(call('Promise.all', promises))
		);
	}

	blockers() {
		return array([...this.#blockers]);
	}

	is_async() {
		return this.expressions.length > 0 || this.#blockers.size > 0;
	}
}

/** @import { BlockStatement, Expression, Pattern, Statement } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types.js' */

/**
 * @param {AST.AwaitBlock} node
 * @param {ComponentContext} context
 */
function AwaitBlock$1(node, context) {
	/** @type {Statement} */
	let statement = stmt(
		call(
			'$.await',
			id('$$renderer'),
			/** @type {Expression} */ (context.visit(node.expression)),
			thunk(
				node.pending ? /** @type {BlockStatement} */ (context.visit(node.pending)) : block([])
			),
			arrow(
				node.value ? [/** @type {Pattern} */ (context.visit(node.value))] : [],
				node.then ? /** @type {BlockStatement} */ (context.visit(node.then)) : block([])
			)
		)
	);

	if (node.metadata.expression.is_async()) {
		statement = create_async_block(
			block([statement]),
			node.metadata.expression.blockers(),
			node.metadata.expression.has_await
		);
	}

	context.state.template.push(statement, block_close);
}

/** @import { AwaitExpression, Expression } from 'estree' */
/** @import { Context } from '../types' */

/**
 * @param {AwaitExpression} node
 * @param {Context} context
 */
function AwaitExpression$1(node, context) {
	const argument = /** @type {Expression} */ (context.visit(node.argument));

	if (context.state.analysis.pickled_awaits.has(node)) {
		return save(argument);
	}

	// we also need to restore context after block expressions
	let i = context.path.length;
	while (i--) {
		const parent = context.path[i];

		if (
			parent.type === 'ArrowFunctionExpression' ||
			parent.type === 'FunctionExpression' ||
			parent.type === 'FunctionDeclaration'
		) {
			break;
		}

		// @ts-ignore
		if (parent.metadata) {
			if (parent.type !== 'ExpressionTag' && parent.type !== 'Fragment') {
				return save(argument);
			}

			break;
		}
	}

	return argument === node.argument ? node : { ...node, argument };
}

/** @import { TransformState } from './types.js' */
/** @import { AST, Binding, Namespace, ValidatedCompileOptions } from '#compiler' */
/** @import { Node, Expression, CallExpression, MemberExpression } from 'estree' */

/**
 * Match Svelte 4 behaviour by sorting ConstTag nodes in topological order
 * @param {AST.SvelteNode[]} nodes
 * @param {TransformState} state
 */
function sort_const_tags(nodes, state) {
	/**
	 * @typedef {{
	 *   node: AST.ConstTag;
	 *   deps: Set<Binding>;
	 * }} Tag
	 */

	const other = [];

	/** @type {Map<Binding, Tag>} */
	const tags = new Map();

	for (const node of nodes) {
		if (node.type === 'ConstTag') {
			const declaration = node.declaration.declarations[0];

			const bindings = extract_identifiers(declaration.id).map((id) => {
				return /** @type {Binding} */ (state.scope.get(id.name));
			});

			/** @type {Set<Binding>} */
			const deps = new Set();

			walk$1(declaration.init, state, {
				// @ts-expect-error don't know, don't care
				_: set_scope,
				Identifier(node, context) {
					const parent = /** @type {Expression} */ (context.path.at(-1));

					if (is_reference(node, parent)) {
						const binding = context.state.scope.get(node.name);
						if (binding) deps.add(binding);
					}
				}
			});

			for (const binding of bindings) {
				tags.set(binding, { node, deps });
			}
		} else {
			other.push(node);
		}
	}

	if (tags.size === 0) {
		return nodes;
	}

	/** @type {Array<[Binding, Binding]>} */
	const edges = [];

	for (const [id, tag] of tags) {
		for (const dep of tag.deps) {
			if (tags.has(dep)) {
				edges.push([id, dep]);
			}
		}
	}

	const cycle = check_graph_for_cycles(edges);
	if (cycle?.length) {
		const tag = /** @type {Tag} */ (tags.get(cycle[0]));
		const_tag_cycle(tag.node, cycle.map((binding) => binding.node.name).join(' → '));
	}

	/** @type {AST.ConstTag[]} */
	const sorted = [];

	/** @param {Tag} tag */
	function add(tag) {
		if (sorted.includes(tag.node)) {
			return;
		}

		for (const dep of tag.deps) {
			const dep_tag = tags.get(dep);
			if (dep_tag) add(dep_tag);
		}

		sorted.push(tag.node);
	}

	for (const tag of tags.values()) {
		add(tag);
	}

	return [...sorted, ...other];
}

/**
 * Extract nodes that are hoisted and trim whitespace according to the following rules:
 * - trim leading and trailing whitespace, regardless of surroundings
 * - keep leading / trailing whitespace of inbetween text nodes,
 *   unless it's whitespace-only, in which case collapse to a single whitespace for all cases
 *   except when it's children of certain elements where we know ignore whitespace (like td/option/head),
 *   in which case we remove it entirely
 * @param {AST.SvelteNode} parent
 * @param {AST.SvelteNode[]} nodes
 * @param {AST.SvelteNode[]} path
 * @param {Namespace} namespace
 * @param {TransformState & { options: ValidatedCompileOptions }} state
 * @param {boolean} preserve_whitespace
 * @param {boolean} preserve_comments
 */
function clean_nodes(
	parent,
	nodes,
	path,
	namespace = 'html',
	state,
	// TODO give these defaults (state.options.preserveWhitespace and state.options.preserveComments).
	// first, we need to make `Component(Client|Server)TransformState` inherit from a new `ComponentTransformState`
	// rather than from `ClientTransformState` and `ServerTransformState`
	preserve_whitespace,
	preserve_comments
) {
	if (!state.analysis.runes) {
		nodes = sort_const_tags(nodes, state);
	}

	/** @type {AST.SvelteNode[]} */
	const hoisted = [];

	/** @type {AST.SvelteNode[]} */
	const regular = [];

	for (const node of nodes) {
		if (node.type === 'Comment' && !preserve_comments) {
			continue;
		}

		if (
			node.type === 'ConstTag' ||
			node.type === 'DebugTag' ||
			node.type === 'SvelteBody' ||
			node.type === 'SvelteWindow' ||
			node.type === 'SvelteDocument' ||
			node.type === 'SvelteHead' ||
			node.type === 'TitleElement' ||
			node.type === 'SnippetBlock'
		) {
			// TODO others?
			hoisted.push(node);
		} else {
			regular.push(node);
		}
	}

	let trimmed = regular;

	if (!preserve_whitespace) {
		trimmed = [];

		let first, last;

		while (
			(first = regular[0]) &&
			first.type === 'Text' &&
			!regex_not_whitespace.test(first.data)
		) {
			regular.shift();
		}

		if (first?.type === 'Text') {
			first.raw = first.raw.replace(regex_starts_with_whitespaces, '');
			first.data = first.data.replace(regex_starts_with_whitespaces, '');
		}

		while (
			(last = regular.at(-1)) &&
			last.type === 'Text' &&
			!regex_not_whitespace.test(last.data)
		) {
			regular.pop();
		}

		if (last?.type === 'Text') {
			last.raw = last.raw.replace(regex_ends_with_whitespaces, '');
			last.data = last.data.replace(regex_ends_with_whitespaces, '');
		}

		const can_remove_entirely =
			(namespace === 'svg' &&
				(parent.type !== 'RegularElement' || parent.name !== 'text') &&
				!path.some((n) => n.type === 'RegularElement' && n.name === 'text')) ||
			(parent.type === 'RegularElement' &&
				// TODO others?
				(parent.name === 'select' ||
					parent.name === 'tr' ||
					parent.name === 'table' ||
					parent.name === 'tbody' ||
					parent.name === 'thead' ||
					parent.name === 'tfoot' ||
					parent.name === 'colgroup' ||
					parent.name === 'datalist'));

		// Replace any whitespace between a text and non-text node with a single spaceand keep whitespace
		// as-is within text nodes, or between text nodes and expression tags (because in the end they count
		// as one text). This way whitespace is mostly preserved when using CSS with `white-space: pre-line`
		// and default slot content going into a pre tag (which we can't see).
		for (let i = 0; i < regular.length; i++) {
			const prev = regular[i - 1];
			const node = regular[i];
			const next = regular[i + 1];

			if (node.type === 'Text') {
				if (prev?.type !== 'ExpressionTag') {
					const prev_is_text_ending_with_whitespace =
						prev?.type === 'Text' && regex_ends_with_whitespaces.test(prev.data);
					node.data = node.data.replace(
						regex_starts_with_whitespaces,
						prev_is_text_ending_with_whitespace ? '' : ' '
					);
					node.raw = node.raw.replace(
						regex_starts_with_whitespaces,
						prev_is_text_ending_with_whitespace ? '' : ' '
					);
				}
				if (next?.type !== 'ExpressionTag') {
					node.data = node.data.replace(regex_ends_with_whitespaces, ' ');
					node.raw = node.raw.replace(regex_ends_with_whitespaces, ' ');
				}
				if (node.data && (node.data !== ' ' || !can_remove_entirely)) {
					trimmed.push(node);
				}
			} else {
				trimmed.push(node);
			}
		}
	}

	var first = trimmed[0];

	// if first text node inside a <pre> is a single newline, discard it, because otherwise
	// the browser will do it for us which could break hydration
	if (parent.type === 'RegularElement' && parent.name === 'pre' && first?.type === 'Text') {
		if (first.data === '\n' || first.data === '\r\n') {
			trimmed.shift();
			first = trimmed[0];
		}
	}

	// Special case: Add a comment if this is a lone script tag. This ensures that our run_scripts logic in template.js
	// will always be able to call node.replaceWith() on the script tag in order to make it run. If we don't add this
	// and would still call node.replaceWith() on the script tag, it would be a no-op because the script tag has no parent.
	if (trimmed.length === 1 && first.type === 'RegularElement' && first.name === 'script') {
		trimmed.push({
			type: 'Comment',
			data: '',
			start: -1,
			end: -1
		});
	}

	return {
		hoisted,
		trimmed,
		/**
		 * In a case like `{#if x}<Foo />{/if}`, we don't need to wrap the child in
		 * comments — we can just use the parent block's anchor for the component.
		 * TODO extend this optimisation to other cases
		 */
		is_standalone:
			trimmed.length === 1 &&
			((first.type === 'RenderTag' && !first.metadata.dynamic) ||
				(first.type === 'Component' &&
					!state.options.hmr &&
					!first.metadata.dynamic &&
					!first.attributes.some(
						(attribute) => attribute.type === 'Attribute' && attribute.name.startsWith('--')
					))),
		/** if a component/snippet/each block starts with text, we need to add an anchor comment so that its text node doesn't get fused with its surroundings */
		is_text_first:
			(parent.type === 'Fragment' ||
				parent.type === 'SnippetBlock' ||
				parent.type === 'EachBlock' ||
				parent.type === 'SvelteComponent' ||
				parent.type === 'SvelteBoundary' ||
				parent.type === 'Component' ||
				parent.type === 'SvelteSelf') &&
			first &&
			(first?.type === 'Text' || first?.type === 'ExpressionTag')
	};
}

/**
 * Infers the namespace for the children of a node that should be used when creating the fragment
 * @param {Namespace} namespace
 * @param {AST.SvelteNode} parent
 * @param {AST.SvelteNode[]} nodes
 */
function infer_namespace(namespace, parent, nodes) {
	if (parent.type === 'RegularElement' && parent.name === 'foreignObject') {
		return 'html';
	}

	if (parent.type === 'RegularElement' || parent.type === 'SvelteElement') {
		if (parent.metadata.svg) {
			return 'svg';
		}
		return parent.metadata.mathml ? 'mathml' : 'html';
	}

	// Re-evaluate the namespace inside slot nodes that reset the namespace
	if (
		parent.type === 'Fragment' ||
		parent.type === 'Root' ||
		parent.type === 'Component' ||
		parent.type === 'SvelteComponent' ||
		parent.type === 'SvelteFragment' ||
		parent.type === 'SnippetBlock' ||
		parent.type === 'SlotElement'
	) {
		const new_namespace = check_nodes_for_namespace(nodes, 'keep');
		if (new_namespace !== 'keep' && new_namespace !== 'maybe_html') {
			return new_namespace;
		}
	}

	/** @type {Namespace | null} */
	let new_namespace = null;

	// Check the elements within the fragment and look for consistent namespaces.
	// If we have no namespaces or they are mixed, then fallback to existing namespace
	for (const node of nodes) {
		if (node.type !== 'RegularElement') continue;

		if (node.metadata.mathml) {
			new_namespace = new_namespace === null || new_namespace === 'mathml' ? 'mathml' : 'html';
		} else if (node.metadata.svg) {
			new_namespace = new_namespace === null || new_namespace === 'svg' ? 'svg' : 'html';
		} else {
			return 'html';
		}
	}

	return new_namespace ?? namespace;
}

/**
 * Heuristic: Keep current namespace, unless we find a regular element,
 * in which case we always want html, or we only find svg nodes,
 * in which case we assume svg.
 * @param {AST.SvelteNode[]} nodes
 * @param {Namespace | 'keep' | 'maybe_html'} namespace
 */
function check_nodes_for_namespace(nodes, namespace) {
	/**
	 * @param {AST.SvelteElement | AST.RegularElement} node}
	 * @param {{stop: () => void}} context
	 */
	const RegularElement = (node, { stop }) => {
		if (!node.metadata.svg && !node.metadata.mathml) {
			namespace = 'html';
			stop();
		} else if (namespace === 'keep') {
			namespace = node.metadata.svg ? 'svg' : 'mathml';
		}
	};

	for (const node of nodes) {
		walk$1(
			node,
			{},
			{
				_(node, { next }) {
					if (
						node.type === 'EachBlock' ||
						node.type === 'IfBlock' ||
						node.type === 'AwaitBlock' ||
						node.type === 'Fragment' ||
						node.type === 'KeyBlock' ||
						node.type === 'RegularElement' ||
						node.type === 'SvelteElement' ||
						node.type === 'Text'
					) {
						next();
					}
				},
				SvelteElement: RegularElement,
				RegularElement,
				Text(node) {
					if (node.data.trim() !== '') {
						namespace = 'maybe_html';
					}
				}
			}
		);

		if (namespace === 'html') return namespace;
	}

	return namespace;
}

/**
 * Determines the namespace the children of this node are in.
 * @param {AST.RegularElement | AST.SvelteElement} node
 * @param {Namespace} namespace
 * @returns {Namespace}
 */
function determine_namespace_for_children(node, namespace) {
	if (node.name === 'foreignObject') {
		return 'html';
	}

	if (node.metadata.svg) {
		return 'svg';
	}

	return node.metadata.mathml ? 'mathml' : 'html';
}

/**
 * @param {'$inspect' | '$inspect().with'} rune
 * @param {CallExpression} node
 * @param {(node: AST.SvelteNode) => AST.SvelteNode} visit
 */
function get_inspect_args(rune, node, visit) {
	const call =
		rune === '$inspect'
			? node
			: /** @type {CallExpression} */ (/** @type {MemberExpression} */ (node.callee).object);

	return {
		args: call.arguments.map((arg) => /** @type {Expression} */ (visit(arg))),
		inspector:
			rune === '$inspect' ? 'console.log' : /** @type {Expression} */ (visit(node.arguments[0]))
	};
}

/** @import { CallExpression, Expression, MemberExpression } from 'estree' */
/** @import { Context } from '../types.js' */

/**
 * @param {CallExpression} node
 * @param {Context} context
 */
function CallExpression$1(node, context) {
	const rune = get_rune(node, context.state.scope);

	if (
		rune === '$host' ||
		rune === '$effect' ||
		rune === '$effect.pre' ||
		rune === '$inspect.trace'
	) {
		// we will only encounter `$effect` etc if they are top-level statements in the <script>
		// following an `await`, otherwise they are removed by the ExpressionStatement visitor
		return void0;
	}

	if (rune === '$effect.tracking') {
		return false_instance;
	}

	if (rune === '$effect.root') {
		// ignore $effect.root() calls, just return a noop which mimics the cleanup function
		return arrow([], block([]));
	}

	if (rune === '$effect.pending') {
		return literal(0);
	}

	if (rune === '$state' || rune === '$state.raw') {
		return node.arguments[0] ? context.visit(node.arguments[0]) : void0;
	}

	if (rune === '$derived' || rune === '$derived.by') {
		const fn = /** @type {Expression} */ (context.visit(node.arguments[0]));
		return call('$.derived', rune === '$derived' ? thunk(fn) : fn);
	}

	if (rune === '$state.eager') {
		return node.arguments[0];
	}

	if (rune === '$state.snapshot') {
		return call(
			'$.snapshot',
			/** @type {Expression} */ (context.visit(node.arguments[0])),
			is_ignored(node, 'state_snapshot_uncloneable') && true_instance
		);
	}

	if (rune === '$inspect' || rune === '$inspect().with') {
		if (!dev) return empty;

		const { args, inspector } = get_inspect_args(rune, node, context.visit);

		return rune === '$inspect'
			? call(inspector, literal('$inspect('), ...args, literal(')'))
			: call(inspector, literal('init'), ...args);
	}

	context.next();
}

/** @import { CallExpression, ClassBody, MethodDefinition, PropertyDefinition, StaticBlock } from 'estree' */
/** @import { Context } from '../types.js' */

/**
 * @param {ClassBody} node
 * @param {Context} context
 */
function ClassBody$1(node, context) {
	const state_fields = context.state.analysis.classes.get(node);

	if (!state_fields) {
		// in legacy mode, do nothing
		context.next();
		return;
	}

	/** @type {Array<MethodDefinition | PropertyDefinition | StaticBlock>} */
	const body = [];

	const child_state = { ...context.state, state_fields };

	for (const [name, field] of state_fields) {
		if (name[0] === '#') {
			continue;
		}

		// insert backing fields for stuff declared in the constructor
		if (
			field &&
			field.node.type === 'AssignmentExpression' &&
			(field.type === '$derived' || field.type === '$derived.by')
		) {
			const member$1 = member(this_instance, field.key);

			body.push(
				prop_def(field.key, null),
				method('get', key(name), [], [return_builder(call(member$1))]),
				method('set', key(name), [id('$$value')], [return_builder(call(member$1, id('$$value')))])
			);
		}
	}

	// Replace parts of the class body
	for (const definition of node.body) {
		if (definition.type !== 'PropertyDefinition') {
			body.push(
				/** @type {MethodDefinition | StaticBlock} */ (context.visit(definition, child_state))
			);
			continue;
		}

		const name = get_name(definition.key);
		const field = name && state_fields.get(name);

		if (!field) {
			body.push(/** @type {PropertyDefinition} */ (context.visit(definition, child_state)));
			continue;
		}

		if (name[0] === '#' || field.type === '$state' || field.type === '$state.raw') {
			body.push(/** @type {PropertyDefinition} */ (context.visit(definition, child_state)));
		} else if (field.node === definition) {
			// $derived / $derived.by
			const member$1 = member(this_instance, field.key);

			body.push(
				prop_def(
					field.key,
					/** @type {CallExpression} */ (context.visit(field.value, child_state))
				),

				method('get', definition.key, [], [return_builder(call(member$1))]),
				method('set', key(name), [id('$$value')], [return_builder(call(member$1, id('$$value')))])
			);
		}
	}

	return { ...node, body };
}

/** @import { BlockStatement, Expression, Pattern, Property, SequenceExpression, Statement } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../../types.js' */

/**
 * @param {AST.Component | AST.SvelteComponent | AST.SvelteSelf} node
 * @param {Expression} expression
 * @param {ComponentContext} context
 */
function build_inline_component(node, expression, context) {
	/** @type {Array<Property[] | Expression>} */
	const props_and_spreads = [];
	/** @type {Array<() => void>} */
	const delayed_props = [];

	/** @type {Property[]} */
	const custom_css_props = [];

	/** @type {Record<string, AST.LetDirective[]>} */
	const lets = { default: [] };

	/**
	 * Children in the default slot are evaluated in the component scope,
	 * children in named slots are evaluated in the parent scope
	 */
	const child_state = {
		...context.state,
		scope: node.metadata.scopes.default
	};

	/** @type {Record<string, AST.TemplateNode[]>} */
	const children = {};

	/**
	 * If this component has a slot property, it is a named slot within another component. In this case
	 * the slot scope applies to the component itself, too, and not just its children.
	 */
	const slot_scope_applies_to_itself = node.attributes.some(
		(node) => node.type === 'Attribute' && node.name === 'slot'
	);

	/**
	 * Components may have a children prop and also have child nodes. In this case, we assume
	 * that the child component isn't using render tags yet and pass the slot as $$slots.default.
	 * We're not doing it for spread attributes, as this would result in too many false positives.
	 */
	let has_children_prop = false;

	/**
	 * @param {Property} prop
	 * @param {boolean} [delay]
	 */
	function push_prop(prop, delay = false) {
		const do_push = () => {
			const current = props_and_spreads.at(-1);
			const current_is_props = Array.isArray(current);
			const props = current_is_props ? current : [];
			props.push(prop);
			if (!current_is_props) {
				props_and_spreads.push(props);
			}
		};

		if (delay) {
			delayed_props.push(do_push);
		} else {
			do_push();
		}
	}

	const optimiser = new PromiseOptimiser();

	for (const attribute of node.attributes) {
		if (attribute.type === 'LetDirective') {
			if (!slot_scope_applies_to_itself) {
				lets.default.push(attribute);
			}
		} else if (attribute.type === 'SpreadAttribute') {
			let expression = /** @type {Expression} */ (context.visit(attribute));
			props_and_spreads.push(optimiser.transform(expression, attribute.metadata.expression));
		} else if (attribute.type === 'Attribute') {
			const value = build_attribute_value$1(
				attribute.value,
				context,
				optimiser.transform,
				false,
				true
			);

			if (attribute.name.startsWith('--')) {
				custom_css_props.push(init(attribute.name, value));
				continue;
			}

			if (attribute.name === 'children') {
				has_children_prop = true;
			}

			push_prop(prop('init', key(attribute.name), value));
		} else if (attribute.type === 'BindDirective' && attribute.name !== 'this') {
			// Bindings are a bit special: we don't want to add them to (async) deriveds but we need to check if they have blockers
			optimiser.check_blockers(attribute.metadata.expression);

			if (attribute.expression.type === 'SequenceExpression') {
				const [get, set$1] = /** @type {SequenceExpression} */ (context.visit(attribute.expression))
					.expressions;
				const get_id = id(context.state.scope.generate('bind_get'));
				const set_id = id(context.state.scope.generate('bind_set'));

				context.state.init.push(var_builder(get_id, get));
				context.state.init.push(var_builder(set_id, set$1));

				push_prop(get$1(attribute.name, [return_builder(call(get_id))]));
				push_prop(set(attribute.name, [stmt(call(set_id, id('$$value')))]));
			} else {
				// Delay prop pushes so bindings come at the end, to avoid spreads overwriting them
				push_prop(
					get$1(attribute.name, [
						return_builder(/** @type {Expression} */ (context.visit(attribute.expression)))
					]),
					true
				);

				push_prop(
					set(attribute.name, [
						stmt(
							/** @type {Expression} */ (
								context.visit(assignment('=', attribute.expression, id('$$value')))
							)
						),
						stmt(assignment('=', id('$$settled'), false_instance))
					]),
					true
				);
			}
		} else if (attribute.type === 'AttachTag') {
			// While we don't run attachments on the server, on the client they might generate a surrounding blocker function which generates
			// extra comments, and to prevent hydration mismatches we therefore have to account for them here to generate similar comments on the server.
			optimiser.check_blockers(attribute.metadata.expression);
		}
	}

	delayed_props.forEach((fn) => fn());

	/** @type {Statement[]} */
	const snippet_declarations = [];

	/** @type {Property[]} */
	const serialized_slots = [];

	// Group children by slot
	for (const child of node.fragment.nodes) {
		if (child.type === 'SnippetBlock') {
			// the SnippetBlock visitor adds a declaration to `init`, but if it's directly
			// inside a component then we want to hoist them into a block so that they
			// can be used as props without creating conflicts
			context.visit(child, {
				...context.state,
				init: snippet_declarations
			});

			push_prop(prop('init', child.expression, child.expression));

			// Interop: allows people to pass snippets when component still uses slots
			serialized_slots.push(
				init(child.expression.name === 'children' ? 'default' : child.expression.name, true_instance)
			);

			continue;
		}

		let slot_name = 'default';
		if (is_element_node(child)) {
			const slot = /** @type {AST.Attribute | undefined} */ (
				child.attributes.find(
					(attribute) => attribute.type === 'Attribute' && attribute.name === 'slot'
				)
			);

			if (slot !== undefined) {
				slot_name = /** @type {AST.Text[]} */ (slot.value)[0].data;

				lets[slot_name] = child.attributes.filter((attribute) => attribute.type === 'LetDirective');
			} else if (child.type === 'SvelteFragment') {
				lets.default.push(
					...child.attributes.filter((attribute) => attribute.type === 'LetDirective')
				);
			}
		}

		children[slot_name] = children[slot_name] || [];
		children[slot_name].push(child);
	}

	// Serialize each slot
	for (const slot_name of Object.keys(children)) {
		const block$1 = /** @type {BlockStatement} */ (
			context.visit(
				{
					...node.fragment,
					// @ts-expect-error
					nodes: children[slot_name]
				},
				slot_name === 'default'
					? child_state
					: {
							...context.state,
							scope: node.metadata.scopes[slot_name]
						}
			)
		);

		if (block$1.body.length === 0) continue;

		/** @type {Pattern[]} */
		const params = [id('$$renderer')];

		if (lets[slot_name].length > 0) {
			const pattern = object_pattern(
				lets[slot_name].map((node) => {
					if (node.expression === null) {
						return init(node.name, id(node.name));
					}

					if (node.expression.type === 'ObjectExpression') {
						// @ts-expect-error it gets parsed as an `ObjectExpression` but is really an `ObjectPattern`
						return init(node.name, object_pattern(node.expression.properties));
					}

					if (node.expression.type === 'ArrayExpression') {
						// @ts-expect-error it gets parsed as an `ArrayExpression` but is really an `ArrayPattern`
						return init(node.name, array_pattern(node.expression.elements));
					}

					return init(node.name, node.expression);
				})
			);

			params.push(pattern);
		}

		const slot_fn = arrow(params, block(block$1.body));

		if (slot_name === 'default' && !has_children_prop) {
			if (
				lets.default.length === 0 &&
				children.default.every(
					(node) =>
						node.type !== 'SvelteFragment' ||
						!node.attributes.some((attr) => attr.type === 'LetDirective')
				)
			) {
				// create `children` prop...
				push_prop(
					prop(
						'init',
						id('children'),
						dev ? call('$.prevent_snippet_stringification', slot_fn) : slot_fn
					)
				);

				// and `$$slots.default: true` so that `<slot>` on the child works
				serialized_slots.push(init(slot_name, true_instance));
			} else {
				// create `$$slots.default`...
				serialized_slots.push(init(slot_name, slot_fn));

				// and a `children` prop that errors
				push_prop(init('children', id('$.invalid_default_snippet')));
			}
		} else {
			serialized_slots.push(init(slot_name, slot_fn));
		}
	}

	if (serialized_slots.length > 0) {
		push_prop(prop('init', id('$$slots'), object$2(serialized_slots)));
	}

	const props_expression =
		props_and_spreads.length === 0 ||
		(props_and_spreads.length === 1 && Array.isArray(props_and_spreads[0]))
			? object$2(/** @type {Property[]} */ (props_and_spreads[0] || []))
			: call(
					'$.spread_props',
					array(props_and_spreads.map((p) => (Array.isArray(p) ? object$2(p) : p)))
				);

	/** @type {Statement} */
	let statement = stmt(
		(node.type === 'SvelteComponent' ? maybe_call : call)(
			expression,
			id('$$renderer'),
			props_expression
		)
	);

	if (snippet_declarations.length > 0) {
		statement = block([...snippet_declarations, statement]);
	}

	const dynamic =
		node.type === 'SvelteComponent' || (node.type === 'Component' && node.metadata.dynamic);

	if (custom_css_props.length > 0) {
		statement = stmt(
			call(
				'$.css_props',
				id('$$renderer'),
				literal(context.state.namespace === 'svg' ? false : true),
				object$2(custom_css_props),
				thunk(block([statement])),
				dynamic && true_instance
			)
		);
	}

	if (node.type !== 'SvelteSelf') {
		// Component name itself could be blocked on async values
		optimiser.check_blockers(node.metadata.expression);
	}

	const is_async = optimiser.is_async();

	if (is_async) {
		statement = create_async_block(
			block([
				optimiser.apply(),
				dynamic && custom_css_props.length === 0
					? stmt(call('$$renderer.push', empty_comment))
					: empty,
				statement
			]),
			optimiser.blockers(),
			optimiser.has_await
		);
	} else if (dynamic && custom_css_props.length === 0) {
		context.state.template.push(empty_comment);
	}

	context.state.template.push(statement);

	if (
		!is_async &&
		!context.state.skip_hydration_boundaries &&
		custom_css_props.length === 0 &&
		optimiser.expressions.length === 0
	) {
		context.state.template.push(empty_comment);
	}
}

/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types.js' */

/**
 * @param {AST.Component} node
 * @param {ComponentContext} context
 */
function Component$1(node, context) {
	build_inline_component(node, id(node.name), context);
}

/** @import { Expression, Pattern } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types.js' */

/**
 * @param {AST.ConstTag} node
 * @param {ComponentContext} context
 */
function ConstTag$1(node, context) {
	const declaration = node.declaration.declarations[0];
	const id$1 = /** @type {Pattern} */ (context.visit(declaration.id));
	const init = /** @type {Expression} */ (context.visit(declaration.init));
	const has_await = node.metadata.expression.has_await;

	if (has_await || context.state.async_consts) {
		const run = (context.state.async_consts ??= {
			id: id(context.state.scope.generate('promises')),
			thunks: []
		});

		const identifiers = extract_identifiers(declaration.id);
		const bindings = context.state.scope.get_bindings(declaration);

		for (const identifier of identifiers) {
			context.state.init.push(let_builder(identifier.name));
		}

		const assignment$1 = assignment('=', id$1, init);
		run.thunks.push(thunk(block([stmt(assignment$1)]), has_await));

		const blocker = member(run.id, literal(run.thunks.length - 1), true);
		for (const binding of bindings) {
			binding.blocker = blocker;
		}
	} else {
		context.state.init.push(const_builder(id$1, init));
	}
}

/** @import { Expression } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types.js' */

/**
 * @param {AST.DebugTag} node
 * @param {ComponentContext} context
 */
function DebugTag$1(node, context) {
	context.state.template.push(
		stmt(
			call(
				'console.log',
				object$2(
					node.identifiers.map((identifier) =>
						prop('init', identifier, /** @type {Expression} */ (context.visit(identifier)))
					)
				)
			)
		),
		debugger_builder
	);
}

/** @import { BlockStatement, Expression, Statement } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types.js' */

/**
 * @param {AST.EachBlock} node
 * @param {ComponentContext} context
 */
function EachBlock$1(node, context) {
	const state = context.state;

	const each_node_meta = node.metadata;
	const collection = /** @type {Expression} */ (context.visit(node.expression));
	const index =
		each_node_meta.contains_group_binding || !node.index ? each_node_meta.index : id(node.index);

	const array_id = state.scope.root.unique('each_array');

	/** @type {Statement} */
	let block$1 = block([const_builder(array_id, call('$.ensure_array_like', collection))]);

	/** @type {Statement[]} */
	const each = [];

	if (node.context) {
		each.push(let_builder(node.context, member(array_id, index, true)));
	}

	if (index.name !== node.index && node.index != null) {
		each.push(let_builder(node.index, index));
	}

	const new_body = /** @type {BlockStatement} */ (context.visit(node.body)).body;

	if (node.body) each.push(...new_body);

	const for_loop = for_builder(
		declaration('let', [
			declarator(index, literal(0)),
			declarator('$$length', member(array_id, 'length'))
		]),
		binary$1('<', index, id('$$length')),
		update('++', index, false),
		block(each)
	);

	if (node.fallback) {
		const open = stmt(call(id('$$renderer.push'), block_open));

		const fallback = /** @type {BlockStatement} */ (context.visit(node.fallback));

		fallback.body.unshift(stmt(call(id('$$renderer.push'), block_open_else)));

		block$1.body.push(
			if_builder(
				binary$1('!==', member(array_id, 'length'), literal(0)),
				block([open, for_loop]),
				fallback
			)
		);
	} else {
		state.template.push(block_open);
		block$1.body.push(for_loop);
	}

	if (node.metadata.expression.is_async()) {
		state.template.push(
			create_async_block(
				block$1,
				node.metadata.expression.blockers(),
				node.metadata.expression.has_await
			),
			block_close
		);
	} else {
		state.template.push(...block$1.body, block_close);
	}
}

/** @import { ExpressionStatement } from 'estree' */
/** @import { Context } from '../types.js' */

/**
 * @param {ExpressionStatement} node
 * @param {Context} context
 */
function ExpressionStatement$1(node, context) {
	const rune = get_rune(node.expression, context.state.scope);

	if (
		rune === '$effect' ||
		rune === '$effect.pre' ||
		rune === '$effect.root' ||
		rune === '$inspect.trace'
	) {
		return empty;
	}

	context.next();
}

/** @import { AST } from '#compiler' */
/** @import { ComponentContext, ComponentServerTransformState } from '../types.js' */

/**
 * @param {AST.Fragment} node
 * @param {ComponentContext} context
 */
function Fragment$1(node, context) {
	const parent = context.path.at(-1) ?? node;
	const namespace = infer_namespace(context.state.namespace, parent, node.nodes);

	const { hoisted, trimmed, is_standalone, is_text_first } = clean_nodes(
		parent,
		node.nodes,
		context.path,
		namespace,
		context.state,
		context.state.preserve_whitespace,
		context.state.options.preserveComments
	);

	/** @type {ComponentServerTransformState} */
	const state = {
		...context.state,
		init: [],
		template: [],
		namespace,
		skip_hydration_boundaries: is_standalone,
		async_consts: undefined
	};

	for (const node of hoisted) {
		context.visit(node, state);
	}

	if (is_text_first) {
		// insert `<!---->` to prevent this from being glued to the previous fragment
		state.template.push(empty_comment);
	}

	process_children$1(trimmed, { ...context, state });

	if (state.async_consts && state.async_consts.thunks.length > 0) {
		state.init.push(
			var_builder(state.async_consts.id, call('$$renderer.run', array(state.async_consts.thunks)))
		);
	}

	return block([...state.init, ...build_template(state.template)]);
}

/** @import { Expression } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types.js' */

/**
 * @param {AST.HtmlTag} node
 * @param {ComponentContext} context
 */
function HtmlTag$1(node, context) {
	const expression = /** @type {Expression} */ (context.visit(node.expression));
	const call$1 = call('$.html', expression);

	context.state.template.push(create_push(call$1, node.metadata.expression, true));
}

/** @import { Identifier, Node } from 'estree' */
/** @import { Context } from '../types.js' */

/**
 * @param {Identifier} node
 * @param {Context} context
 */
function Identifier$1(node, context) {
	if (is_reference(node, /** @type {Node} */ (context.path.at(-1)))) {
		if (node.name === '$$props') {
			return id('$$sanitized_props');
		}

		return build_getter(node, context.state);
	}
}

/** @import { BlockStatement, Expression, Statement } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types.js' */

/**
 * @param {AST.IfBlock} node
 * @param {ComponentContext} context
 */
function IfBlock$1(node, context) {
	const test = /** @type {Expression} */ (context.visit(node.test));
	const consequent = /** @type {BlockStatement} */ (context.visit(node.consequent));

	const alternate = node.alternate
		? /** @type {BlockStatement} */ (context.visit(node.alternate))
		: block([]);

	consequent.body.unshift(stmt(call(id('$$renderer.push'), block_open)));

	alternate.body.unshift(stmt(call(id('$$renderer.push'), block_open_else)));

	/** @type {Statement} */
	let statement = if_builder(test, consequent, alternate);

	const is_async = node.metadata.expression.is_async();

	const has_await = node.metadata.expression.has_await;

	if (is_async || has_await) {
		statement = create_async_block(
			block([statement]),
			node.metadata.expression.blockers(),
			!!has_await
		);
	}

	context.state.template.push(statement, block_close);
}

/** @import { BlockStatement } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types.js' */

/**
 * @param {AST.KeyBlock} node
 * @param {ComponentContext} context
 */
function KeyBlock$1(node, context) {
	const is_async = node.metadata.expression.is_async();

	if (is_async) context.state.template.push(block_open);

	context.state.template.push(
		empty_comment,
		/** @type {BlockStatement} */ (context.visit(node.fragment)),
		empty_comment
	);

	if (is_async) context.state.template.push(block_close);
}

/** @import { ExpressionStatement, LabeledStatement } from 'estree' */
/** @import { Context } from '../types.js' */

/**
 * @param {LabeledStatement} node
 * @param {Context} context
 */
function LabeledStatement$1(node, context) {
	if (context.state.analysis.runes || context.path.length > 1 || node.label.name !== '$') {
		return;
	}

	// TODO bail out if we're in module context

	// these statements will be topologically ordered later
	context.state.legacy_reactive_statements.set(
		node,
		// people could do "break $" inside, so we need to keep the label
		labeled('$', /** @type {ExpressionStatement} */ (context.visit(node.body)))
	);

	return empty;
}

/** @import { ClassBody, MemberExpression } from 'estree' */
/** @import { Context } from '../types.js' */

/**
 * @param {MemberExpression} node
 * @param {Context} context
 */
function MemberExpression$1(node, context) {
	if (context.state.analysis.runes && node.property.type === 'PrivateIdentifier') {
		const field = context.state.state_fields?.get(`#${node.property.name}`);

		if (field?.type === '$derived' || field?.type === '$derived.by') {
			return call(node);
		}
	}

	context.next();
}

/** @import * as ESTree from 'estree' */
/** @import { ComponentAnalysis } from '../../types' */

/**
 * Transforms the body of the instance script in such a way that await expressions are made non-blocking as much as possible.
 *
 * Example Transformation:
 * ```js
 * let x = 1;
 * let data = await fetch('/api');
 * let y = data.value;
 * ```
 * becomes:
 * ```js
 * let x = 1;
 * var data, y;
 * var $$promises = $.run([
 *   () => data = await fetch('/api'),
 *   () => y = data.value
 * ]);
 * ```
 * where `$$promises` is an array of promises that are resolved in the order they are declared,
 * and which expressions in the template can await on like `await $$promises[0]` which means they
 * wouldn't have to wait for e.g. `$$promises[1]` to resolve.
 *
 * @param {ComponentAnalysis['instance_body']} instance_body
 * @param {ESTree.Expression} runner
 * @param {(node: ESTree.Node) => ESTree.Node} transform
 * @returns {Array<ESTree.Statement | ESTree.VariableDeclaration>}
 */
function transform_body(instance_body, runner, transform) {
	// Any sync statements before the first await expression
	const statements = instance_body.sync.map(
		(node) => /** @type {ESTree.Statement | ESTree.VariableDeclaration} */ (transform(node))
	);

	// Declarations for the await expressions (they will asign to them; need to be hoisted to be available in whole instance scope)
	if (instance_body.declarations.length > 0) {
		statements.push(
			declaration(
				'var',
				instance_body.declarations.map((id) => declarator(id))
			)
		);
	}

	// Thunks for the await expressions
	if (instance_body.async.length > 0) {
		const thunks = instance_body.async.map((s) => {
			if (s.node.type === 'VariableDeclarator') {
				const visited = /** @type {ESTree.VariableDeclaration} */ (
					transform(var_builder(s.node.id, s.node.init))
				);

				if (visited.declarations.length === 1) {
					return thunk(
						assignment('=', visited.declarations[0].id, visited.declarations[0].init ?? void0),
						s.has_await
					);
				}

				// if we have multiple declarations, it indicates destructuring
				return thunk(
					block([
						var_builder(visited.declarations[0].id, visited.declarations[0].init),
						...visited.declarations
							.slice(1)
							.map((d) => stmt(assignment('=', d.id, d.init ?? void0)))
					]),
					s.has_await
				);
			}

			if (s.node.type === 'ClassDeclaration') {
				return thunk(
					assignment(
						'=',
						s.node.id,
						/** @type {ESTree.ClassExpression} */ ({ ...s.node, type: 'ClassExpression' })
					),
					s.has_await
				);
			}

			if (s.node.type === 'ExpressionStatement') {
				const expression = /** @type {ESTree.Expression} */ (transform(s.node.expression));

				return expression.type === 'AwaitExpression'
					? thunk(expression, true)
					: thunk(unary$1('void', expression), s.has_await);
			}

			return thunk(block([/** @type {ESTree.Statement} */ (transform(s.node))]), s.has_await);
		});

		// TODO get the `$$promises` ID from scope
		statements.push(var_builder('$$promises', call(runner, array(thunks))));
	}

	return statements;
}

/** @import { Node, Program } from 'estree' */
/** @import { Context, ComponentServerTransformState } from '../types' */

/**
 * @param {Program} node
 * @param {Context} context
 */
function Program$1(node, context) {
	if (context.state.is_instance) {
		const state = /** @type {ComponentServerTransformState} */ (context.state);

		return {
			...node,
			body: transform_body(
				state.analysis.instance_body,
				id('$$renderer.run'),
				(node) => /** @type {Node} */ (context.visit(node))
			)
		};
	}

	context.next();
}

/** @import { Expression, PropertyDefinition } from 'estree' */
/** @import { Context } from '../types.js' */

/**
 * @param {PropertyDefinition} node
 * @param {Context} context
 */
function PropertyDefinition(node, context) {
	if (context.state.analysis.runes && node.value != null && node.value.type === 'CallExpression') {
		const rune = get_rune(node.value, context.state.scope);

		if (rune === '$state' || rune === '$state.raw') {
			return {
				...node,
				value:
					node.value.arguments.length === 0
						? null
						: /** @type {Expression} */ (context.visit(node.value.arguments[0]))
			};
		}

		if (rune === '$derived.by' || rune === '$derived') {
			const fn = /** @type {Expression} */ (context.visit(node.value.arguments[0]));
			return {
				...node,
				value:
					node.value.arguments.length === 0
						? null
						: call('$.derived', rune === '$derived' ? thunk(fn) : fn)
			};
		}
	}

	context.next();
}

/** @import { ArrayExpression, Expression, Literal, ObjectExpression } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext, ComponentServerTransformState } from '../../types.js' */

const WHITESPACE_INSENSITIVE_ATTRIBUTES = ['class', 'style'];

/**
 * Writes the output to the template output. Some elements may have attributes on them that require the
 * their output to be the child content instead. In this case, an object is returned.
 * @param {AST.RegularElement | AST.SvelteElement} node
 * @param {import('zimmerframe').Context<AST.SvelteNode, ComponentServerTransformState>} context
 * @param {(expression: Expression, metadata: ExpressionMetadata) => Expression} transform
 */
function build_element_attributes(node, context, transform) {
	/** @type {Array<AST.Attribute | AST.SpreadAttribute>} */
	const attributes = [];

	/** @type {AST.ClassDirective[]} */
	const class_directives = [];

	/** @type {AST.StyleDirective[]} */
	const style_directives = [];

	/** @type {Expression | null} */
	let content = null;

	let has_spread = false;
	let events_to_capture = new Set();

	for (const attribute of node.attributes) {
		if (attribute.type === 'Attribute') {
			if (attribute.name === 'value') {
				if (node.name === 'textarea') {
					if (
						attribute.value !== true &&
						Array.isArray(attribute.value) &&
						attribute.value[0].type === 'Text' &&
						regex_starts_with_newline.test(attribute.value[0].data)
					) {
						// Two or more leading newlines are required to restore the leading newline immediately after `<textarea>`.
						// see https://html.spec.whatwg.org/multipage/syntax.html#element-restrictions
						// also see related code in analysis phase
						attribute.value[0].data = '\n' + attribute.value[0].data;
					}

					content = call('$.escape', build_attribute_value$1(attribute.value, context, transform));
				} else if (node.name !== 'select') {
					// omit value attribute for select elements, it's irrelevant for the initially selected value and has no
					// effect on the selected value after the user interacts with the select element (the value _property_ does, but not the attribute)
					attributes.push(attribute);
				}

				// omit event handlers except for special cases
			} else if (is_event_attribute(attribute)) {
				if (
					(attribute.name === 'onload' || attribute.name === 'onerror') &&
					is_load_error_element(node.name)
				) {
					events_to_capture.add(attribute.name);
				}
				// the defaultValue/defaultChecked properties don't exist as attributes
			} else if (attribute.name !== 'defaultValue' && attribute.name !== 'defaultChecked') {
				if (attribute.name === 'class') {
					if (attribute.metadata.needs_clsx) {
						attributes.push({
							...attribute,
							value: {
								.../** @type {AST.ExpressionTag} */ (attribute.value),
								expression: call(
									'$.clsx',
									/** @type {AST.ExpressionTag} */ (attribute.value).expression
								)
							}
						});
					} else {
						attributes.push(attribute);
					}
				} else {
					attributes.push(attribute);
				}
			}
		} else if (attribute.type === 'BindDirective') {
			if (attribute.name === 'value' && node.name === 'select') continue;
			if (
				attribute.name === 'value' &&
				attributes.some(
					(attr) =>
						attr.type === 'Attribute' &&
						attr.name === 'type' &&
						is_text_attribute(attr) &&
						attr.value[0].data === 'file'
				)
			) {
				continue;
			}
			if (attribute.name === 'this') continue;

			const binding = binding_properties[attribute.name];
			if (binding?.omit_in_ssr) continue;

			let expression = /** @type {Expression} */ (context.visit(attribute.expression));

			if (expression.type === 'SequenceExpression') {
				expression = call(expression.expressions[0]);
			}

			expression = transform(expression, attribute.metadata.expression);

			if (is_content_editable_binding(attribute.name)) {
				content = expression;
			} else if (attribute.name === 'value' && node.name === 'textarea') {
				content = call('$.escape', expression);
			} else if (attribute.name === 'group' && attribute.expression.type !== 'SequenceExpression') {
				const value_attribute = /** @type {AST.Attribute | undefined} */ (
					node.attributes.find((attr) => attr.type === 'Attribute' && attr.name === 'value')
				);
				if (!value_attribute) continue;

				const is_checkbox = node.attributes.some(
					(attr) =>
						attr.type === 'Attribute' &&
						attr.name === 'type' &&
						is_text_attribute(attr) &&
						attr.value[0].data === 'checkbox'
				);

				attributes.push(
					create_attribute('checked', -1, -1, [
						{
							type: 'ExpressionTag',
							start: -1,
							end: -1,
							expression: is_checkbox
								? call(
										member(attribute.expression, 'includes'),
										build_attribute_value$1(value_attribute.value, context, transform)
									)
								: binary$1(
										'===',
										attribute.expression,
										build_attribute_value$1(value_attribute.value, context, transform)
									),
							metadata: {
								expression: new ExpressionMetadata()
							}
						}
					])
				);
			} else {
				attributes.push(
					create_attribute(attribute.name, -1, -1, [
						{
							type: 'ExpressionTag',
							start: -1,
							end: -1,
							expression,
							metadata: {
								expression: new ExpressionMetadata()
							}
						}
					])
				);
			}
		} else if (attribute.type === 'SpreadAttribute') {
			attributes.push(attribute);
			has_spread = true;
			if (is_load_error_element(node.name)) {
				events_to_capture.add('onload');
				events_to_capture.add('onerror');
			}
		} else if (attribute.type === 'UseDirective') {
			if (is_load_error_element(node.name)) {
				events_to_capture.add('onload');
				events_to_capture.add('onerror');
			}
		} else if (attribute.type === 'ClassDirective') {
			class_directives.push(attribute);
		} else if (attribute.type === 'StyleDirective') {
			style_directives.push(attribute);
		} else if (attribute.type === 'LetDirective') ; else {
			context.visit(attribute);
		}
	}

	if (has_spread) {
		build_element_spread_attributes(
			node,
			attributes,
			style_directives,
			class_directives,
			context,
			transform
		);
	} else {
		const css_hash = node.metadata.scoped ? context.state.analysis.css.hash : null;

		for (const attribute of /** @type {AST.Attribute[]} */ (attributes)) {
			const name = get_attribute_name$1(node, attribute);
			const can_use_literal =
				(name !== 'class' || class_directives.length === 0) &&
				(name !== 'style' || style_directives.length === 0);

			if (can_use_literal && (attribute.value === true || is_text_attribute(attribute))) {
				let literal_value = /** @type {Literal} */ (
					build_attribute_value$1(
						attribute.value,
						context,
						transform,
						WHITESPACE_INSENSITIVE_ATTRIBUTES.includes(name)
					)
				).value;

				if (name === 'class' && css_hash) {
					literal_value = (String(literal_value) + ' ' + css_hash).trim();
				}

				if (name !== 'class' || literal_value) {
					context.state.template.push(
						literal(
							` ${attribute.name}${
								is_boolean_attribute(name) && literal_value === true
									? ''
									: `="${literal_value === true ? '' : String(literal_value)}"`
							}`
						)
					);
				}

				continue;
			}

			const value = build_attribute_value$1(
				attribute.value,
				context,
				transform,
				WHITESPACE_INSENSITIVE_ATTRIBUTES.includes(name)
			);

			// pre-escape and inline literal attributes :
			if (can_use_literal && value.type === 'Literal' && typeof value.value === 'string') {
				if (name === 'class' && css_hash) {
					value.value = (value.value + ' ' + css_hash).trim();
				}
				context.state.template.push(literal(` ${name}="${escape_html(value.value, true)}"`));
			} else if (name === 'class') {
				context.state.template.push(
					build_attr_class(class_directives, value, context, css_hash, transform)
				);
			} else if (name === 'style') {
				context.state.template.push(build_attr_style(style_directives, value, context, transform));
			} else {
				context.state.template.push(
					call('$.attr', literal(name), value, is_boolean_attribute(name) && true_instance)
				);
			}
		}
	}

	if (events_to_capture.size !== 0) {
		for (const event of events_to_capture) {
			context.state.template.push(literal(` ${event}="this.__e=event"`));
		}
	}

	return content;
}

/**
 * @param {AST.RegularElement | AST.SvelteElement} element
 * @param {AST.Attribute | AST.BindDirective} attribute
 */
function get_attribute_name$1(element, attribute) {
	let name = attribute.name;
	if (!element.metadata.svg && !element.metadata.mathml) {
		name = name.toLowerCase();
		// don't lookup boolean aliases here, the server runtime function does only
		// check for the lowercase variants of boolean attributes
	}
	return name;
}

/**
 * @param {AST.RegularElement | AST.SvelteElement} element
 * @param {Array<AST.Attribute | AST.SpreadAttribute | AST.BindDirective>} attributes
 * @param {ComponentContext} context
 * @param {(expression: Expression, metadata: ExpressionMetadata) => Expression} transform
 */
function build_spread_object(element, attributes, context, transform) {
	const object = object$2(
		attributes.map((attribute) => {
			if (attribute.type === 'Attribute') {
				const name = get_attribute_name$1(element, attribute);
				const value = build_attribute_value$1(
					attribute.value,
					context,
					transform,
					WHITESPACE_INSENSITIVE_ATTRIBUTES.includes(name)
				);

				return prop('init', key(name), value);
			} else if (attribute.type === 'BindDirective') {
				const name = get_attribute_name$1(element, attribute);
				const value =
					attribute.expression.type === 'SequenceExpression'
						? call(attribute.expression.expressions[0])
						: /** @type {Expression} */ (context.visit(attribute.expression));

				return prop('init', key(name), value);
			}

			return spread(
				transform(
					/** @type {Expression} */ (context.visit(attribute)),
					attribute.metadata.expression
				)
			);
		})
	);

	return object;
}

/**
 *
 * @param {AST.RegularElement | AST.SvelteElement} element
 * @param {Array<AST.Attribute | AST.SpreadAttribute>} attributes
 * @param {AST.StyleDirective[]} style_directives
 * @param {AST.ClassDirective[]} class_directives
 * @param {ComponentContext} context
 * @param {(expression: Expression, metadata: ExpressionMetadata) => Expression} transform
 */
function build_element_spread_attributes(
	element,
	attributes,
	style_directives,
	class_directives,
	context,
	transform
) {
	const args = prepare_element_spread(
		element,
		/** @type {Array<AST.Attribute | AST.SpreadAttribute | AST.BindDirective>} */ (attributes),
		style_directives,
		class_directives,
		context,
		transform
	);

	let call$1 = call('$.attributes', ...args);

	context.state.template.push(call$1);
}

/**
 * Prepare args for $.attributes(...): compute object, css_hash, classes, styles and flags.
 * @param {AST.RegularElement | AST.SvelteElement} element
 * @param {ComponentContext} context
 * @param {(expression: Expression, metadata: ExpressionMetadata) => Expression} transform
 * @returns {[ObjectExpression,Literal | undefined, ObjectExpression | undefined, ObjectExpression | undefined, Literal | undefined]}
 */
function prepare_element_spread_object(element, context, transform) {
	/** @type {Array<AST.Attribute | AST.SpreadAttribute | AST.BindDirective>} */
	const select_attributes = [];
	/** @type {AST.ClassDirective[]} */
	const class_directives = [];
	/** @type {AST.StyleDirective[]} */
	const style_directives = [];

	for (const attribute of element.attributes) {
		if (
			attribute.type === 'Attribute' ||
			attribute.type === 'BindDirective' ||
			attribute.type === 'SpreadAttribute'
		) {
			select_attributes.push(attribute);
		} else if (attribute.type === 'ClassDirective') {
			class_directives.push(attribute);
		} else if (attribute.type === 'StyleDirective') {
			style_directives.push(attribute);
		}
	}

	return prepare_element_spread(
		element,
		select_attributes,
		style_directives,
		class_directives,
		context,
		transform
	);
}

/**
 * Prepare args for $.attributes(...): compute object, css_hash, classes, styles and flags.
 * @param {AST.RegularElement | AST.SvelteElement} element
 * @param {Array<AST.Attribute | AST.SpreadAttribute | AST.BindDirective>} attributes
 * @param {AST.StyleDirective[]} style_directives
 * @param {AST.ClassDirective[]} class_directives
 * @param {ComponentContext} context
 * @param {(expression: Expression, metadata: ExpressionMetadata) => Expression} transform
 * @returns {[ObjectExpression,Literal | undefined, ObjectExpression | undefined, ObjectExpression | undefined, Literal | undefined]}
 */
function prepare_element_spread(
	element,
	attributes,
	style_directives,
	class_directives,
	context,
	transform
) {
	/** @type {ObjectExpression | undefined} */
	let classes;
	/** @type {ObjectExpression | undefined} */
	let styles;
	let flags = 0;

	if (class_directives.length) {
		const properties = class_directives.map((directive) =>
			init(
				directive.name,
				directive.expression.type === 'Identifier' && directive.expression.name === directive.name
					? id(directive.name)
					: transform(
							/** @type {Expression} */ (context.visit(directive.expression)),
							directive.metadata.expression
						)
			)
		);

		classes = object$2(properties);
	}

	if (style_directives.length > 0) {
		const properties = style_directives.map((directive) =>
			init(
				directive.name,
				directive.value === true
					? id(directive.name)
					: build_attribute_value$1(directive.value, context, transform, true)
			)
		);
		styles = object$2(properties);
	}

	if (element.metadata.svg || element.metadata.mathml) {
		flags |= ELEMENT_IS_NAMESPACED | ELEMENT_PRESERVE_ATTRIBUTE_CASE;
	} else if (is_custom_element_node(element)) {
		flags |= ELEMENT_PRESERVE_ATTRIBUTE_CASE;
	} else if (element.type === 'RegularElement' && element.name === 'input') {
		flags |= ELEMENT_IS_INPUT;
	}

	const object = build_spread_object(element, attributes, context, transform);
	const css_hash =
		element.metadata.scoped && context.state.analysis.css.hash
			? literal(context.state.analysis.css.hash)
			: undefined;

	return [object, css_hash, classes, styles, flags ? literal(flags) : undefined];
}

/**
 *
 * @param {AST.ClassDirective[]} class_directives
 * @param {Expression} expression
 * @param {ComponentContext} context
 * @param {string | null} hash
 * @param {(expression: Expression, metadata: ExpressionMetadata) => Expression} transform
 */
function build_attr_class(class_directives, expression, context, hash, transform) {
	/** @type {ObjectExpression | undefined} */
	let directives;

	if (class_directives.length) {
		directives = object$2(
			class_directives.map((directive) =>
				prop(
					'init',
					literal(directive.name),
					transform(
						/** @type {Expression} */ (context.visit(directive.expression, context.state)),
						directive.metadata.expression
					)
				)
			)
		);
	}

	let css_hash;

	if (hash) {
		if (expression.type === 'Literal' && typeof expression.value === 'string') {
			expression.value = (expression.value + ' ' + hash).trim();
		} else {
			css_hash = literal(hash);
		}
	}

	return call('$.attr_class', expression, css_hash, directives);
}

/**
 *
 * @param {AST.StyleDirective[]} style_directives
 * @param {Expression} expression
 * @param {ComponentContext} context,
 * @param {(expression: Expression, metadata: ExpressionMetadata) => Expression} transform
 */
function build_attr_style(style_directives, expression, context, transform) {
	/** @type {ArrayExpression | ObjectExpression | undefined} */
	let directives;

	if (style_directives.length) {
		let normal_properties = [];
		let important_properties = [];

		for (const directive of style_directives) {
			const expression =
				directive.value === true
					? id(directive.name)
					: build_attribute_value$1(directive.value, context, transform, true);

			let name = directive.name;
			if (name[0] !== '-' || name[1] !== '-') {
				name = name.toLowerCase();
			}

			const property = init(directive.name, expression);
			if (directive.modifiers.includes('important')) {
				important_properties.push(property);
			} else {
				normal_properties.push(property);
			}
		}

		if (important_properties.length) {
			directives = array([object$2(normal_properties), object$2(important_properties)]);
		} else {
			directives = object$2(normal_properties);
		}
	}

	return call('$.attr_style', expression, directives);
}

/** @import { Expression } from 'estree' */
/** @import { Location } from 'locate-character' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext, ComponentServerTransformState } from '../types.js' */
/** @import { Scope } from '../../../scope.js' */

/**
 * @param {AST.RegularElement} node
 * @param {ComponentContext} context
 */
function RegularElement$1(node, context) {
	const namespace = determine_namespace_for_children(node, context.state.namespace);

	/** @type {ComponentServerTransformState} */
	const state = {
		...context.state,
		namespace,
		preserve_whitespace:
			context.state.preserve_whitespace || node.name === 'pre' || node.name === 'textarea',
		init: [],
		template: []
	};

	const node_is_void = is_void(node.name);

	const optimiser = new PromiseOptimiser();

	// If this element needs special handling (like <select value> / <option>),
	// avoid calling build_element_attributes here to prevent evaluating/awaiting
	// attribute expressions twice. We'll handle attributes in the special branch.
	const is_select_special =
		node.name === 'select' &&
		node.attributes.some(
			(attribute) =>
				((attribute.type === 'Attribute' || attribute.type === 'BindDirective') &&
					attribute.name === 'value') ||
				attribute.type === 'SpreadAttribute'
		);
	const is_option_special = node.name === 'option';
	const is_special = is_select_special || is_option_special;

	let body = /** @type {Expression | null} */ (null);
	if (!is_special) {
		// only open the tag in the non-special path
		state.template.push(literal(`<${node.name}`));
		body = build_element_attributes(node, { ...context, state }, optimiser.transform);
		state.template.push(literal(node_is_void ? '/>' : '>')); // add `/>` for XHTML compliance
	}

	if ((node.name === 'script' || node.name === 'style') && node.fragment.nodes.length === 1) {
		state.template.push(
			literal(/** @type {AST.Text} */ (node.fragment.nodes[0]).data),
			literal(`</${node.name}>`)
		);

		// TODO this is a real edge case, would be good to DRY this out
		if (optimiser.expressions.length > 0) {
			context.state.template.push(
				create_child_block(
					block([optimiser.apply(), ...state.init, ...build_template(state.template)]),
					true
				)
			);
		} else {
			context.state.init.push(...state.init);
			context.state.template.push(...state.template);
		}

		return;
	}

	const { hoisted, trimmed } = clean_nodes(
		node,
		node.fragment.nodes,
		context.path,
		namespace,
		{
			...state,
			scope: /** @type {Scope} */ (state.scopes.get(node.fragment))
		},
		state.preserve_whitespace,
		state.options.preserveComments
	);

	for (const node of hoisted) {
		context.visit(node, state);
	}

	if (dev) {
		const location = /** @type {Location} */ (locator(node.start));
		state.template.push(
			stmt(
				call(
					'$.push_element',
					id('$$renderer'),
					literal(node.name),
					literal(location.line),
					literal(location.column)
				)
			)
		);
	}

	if (is_select_special) {
		const inner_state = { ...state, template: [], init: [] };
		process_children$1(trimmed, { ...context, state: inner_state });

		const fn = arrow(
			[id('$$renderer')],
			block([...state.init, ...build_template(inner_state.template)])
		);

		const [attributes, ...rest] = prepare_element_spread_object(node, context, optimiser.transform);

		const statement = stmt(call('$$renderer.select', attributes, fn, ...rest));

		if (optimiser.expressions.length > 0) {
			context.state.template.push(
				create_child_block(block([optimiser.apply(), ...state.init, statement]), true)
			);
		} else {
			context.state.template.push(...state.init, statement);
		}

		return;
	}

	if (is_option_special) {
		let body;

		if (node.metadata.synthetic_value_node) {
			body = optimiser.transform(
				node.metadata.synthetic_value_node.expression,
				node.metadata.synthetic_value_node.metadata.expression
			);
		} else {
			const inner_state = { ...state, template: [], init: [] };
			process_children$1(trimmed, { ...context, state: inner_state });

			body = arrow(
				[id('$$renderer')],
				block([...state.init, ...build_template(inner_state.template)])
			);
		}

		const [attributes, ...rest] = prepare_element_spread_object(node, context, optimiser.transform);

		const statement = stmt(call('$$renderer.option', attributes, body, ...rest));

		if (optimiser.expressions.length > 0) {
			context.state.template.push(
				create_child_block(block([optimiser.apply(), ...state.init, statement]), true)
			);
		} else {
			context.state.template.push(...state.init, statement);
		}

		return;
	}

	if (body !== null) {
		// if this is a `<textarea>` value or a contenteditable binding, we only add
		// the body if the attribute/binding is falsy
		const inner_state = { ...state, template: [], init: [] };
		process_children$1(trimmed, { ...context, state: inner_state });

		let id$1 = /** @type {Expression} */ (body);

		if (body.type !== 'Identifier') {
			id$1 = id(state.scope.generate('$$body'));
			state.template.push(const_builder(id$1, body));
		}

		// Use the body expression as the body if it's truthy, otherwise use the inner template
		state.template.push(
			if_builder(
				id$1,
				block(build_template([id$1])),
				block([...inner_state.init, ...build_template(inner_state.template)])
			)
		);
	} else {
		process_children$1(trimmed, { ...context, state });
	}

	if (!node_is_void) {
		state.template.push(literal(`</${node.name}>`));
	}

	if (dev) {
		state.template.push(stmt(call('$.pop_element')));
	}

	if (optimiser.is_async()) {
		let statement = create_child_block(
			block([optimiser.apply(), ...state.init, ...build_template(state.template)]),
			true
		);

		const blockers = optimiser.blockers();

		if (blockers.elements.length > 0) {
			statement = create_async_block(block([statement]), blockers, false, false);
		}

		context.state.template.push(statement);
	} else {
		context.state.init.push(...state.init);
		context.state.template.push(...state.template);
	}
}

/** @import { Expression } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types.js' */

/**
 * @param {AST.RenderTag} node
 * @param {ComponentContext} context
 */
function RenderTag$1(node, context) {
	const optimiser = new PromiseOptimiser();

	const callee = unwrap_optional(node.expression).callee;
	const raw_args = unwrap_optional(node.expression).arguments;

	const snippet_function = optimiser.transform(
		/** @type {Expression} */ (context.visit(callee)),
		node.metadata.expression
	);

	const snippet_args = raw_args.map((arg, i) => {
		return optimiser.transform(
			/** @type {Expression} */ (context.visit(arg)),
			node.metadata.arguments[i]
		);
	});

	let statement = stmt(
		(node.expression.type === 'CallExpression' ? call : maybe_call)(
			snippet_function,
			id('$$renderer'),
			...snippet_args
		)
	);

	if (optimiser.is_async()) {
		statement = create_async_block(
			block([optimiser.apply(), statement]),
			optimiser.blockers(),
			optimiser.has_await
		);
	}

	context.state.template.push(statement);

	if (!context.state.skip_hydration_boundaries) {
		context.state.template.push(empty_comment);
	}
}

/** @import { BlockStatement, Expression, Literal, Property } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types.js' */

/**
 * @param {AST.SlotElement} node
 * @param {ComponentContext} context
 */
function SlotElement$1(node, context) {
	/** @type {Property[]} */
	const props = [];

	/** @type {Expression[]} */
	const spreads = [];

	const optimiser = new PromiseOptimiser();

	let name = literal('default');

	for (const attribute of node.attributes) {
		if (attribute.type === 'SpreadAttribute') {
			let expression = /** @type {Expression} */ (context.visit(attribute));
			spreads.push(optimiser.transform(expression, attribute.metadata.expression));
		} else if (attribute.type === 'Attribute') {
			const value = build_attribute_value$1(
				attribute.value,
				context,
				optimiser.transform,
				false,
				true
			);

			if (attribute.name === 'name') {
				name = /** @type {Literal} */ (value);
			} else if (attribute.name !== 'slot') {
				props.push(init(attribute.name, value));
			}
		}
	}

	const props_expression =
		spreads.length === 0
			? object$2(props)
			: call('$.spread_props', array([object$2(props), ...spreads]));

	const fallback =
		node.fragment.nodes.length === 0
			? null_instance
			: thunk(/** @type {BlockStatement} */ (context.visit(node.fragment)));

	const slot = call(
		'$.slot',
		id('$$renderer'),
		id('$$props'),
		name,
		props_expression,
		fallback
	);

	const statement = optimiser.is_async()
		? create_async_block(
				block([optimiser.apply(), stmt(slot)]),
				optimiser.blockers(),
				optimiser.has_await
			)
		: stmt(slot);

	context.state.template.push(block_open, statement, block_close);
}

/** @import { BlockStatement } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types.js' */

/**
 * @param {AST.SnippetBlock} node
 * @param {ComponentContext} context
 */
function SnippetBlock$1(node, context) {
	let fn = function_declaration(
		node.expression,
		[id('$$renderer'), ...node.parameters],
		/** @type {BlockStatement} */ (context.visit(node.body))
	);

	// @ts-expect-error - TODO remove this hack once $$render_inner for legacy bindings is gone
	fn.___snippet = true;

	const statements = node.metadata.can_hoist ? context.state.hoisted : context.state.init;

	if (dev) {
		fn.body.body.unshift(stmt(call('$.validate_snippet_args', id('$$renderer'))));
		statements.push(stmt(call('$.prevent_snippet_stringification', fn.id)));
	}

	statements.push(fn);
}

/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {AST.SpreadAttribute} node
 * @param {ComponentContext} context
 */
function SpreadAttribute$1(node, context) {
	return context.visit(node.expression);
}

/** @import { Expression } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types.js' */

/**
 * @param {AST.SvelteComponent} node
 * @param {ComponentContext} context
 */
function SvelteComponent$1(node, context) {
	build_inline_component(node, /** @type {Expression} */ (context.visit(node.expression)), context);
}

/** @import { Location } from 'locate-character' */
/** @import { BlockStatement, Expression, Statement } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types.js' */

/**
 * @param {AST.SvelteElement} node
 * @param {ComponentContext} context
 */
function SvelteElement$1(node, context) {
	let tag = /** @type {Expression} */ (context.visit(node.tag));

	if (dev) {
		// Ensure getters/function calls aren't called multiple times.
		// If we ever start referencing `tag` more than once in prod, move this out of the if block.
		if (tag.type !== 'Identifier') {
			const tag_id = context.state.scope.generate('$$tag');
			context.state.init.push(const_builder(tag_id, tag));
			tag = id(tag_id);
		}

		if (node.fragment.nodes.length > 0) {
			context.state.init.push(stmt(call('$.validate_void_dynamic_element', thunk(tag))));
		}
		context.state.init.push(stmt(call('$.validate_dynamic_element_tag', thunk(tag))));
	}

	const state = {
		...context.state,
		namespace: determine_namespace_for_children(node, context.state.namespace),
		template: [],
		init: []
	};

	const optimiser = new PromiseOptimiser();

	/** @type {Statement[]} */
	let statements = [];

	build_element_attributes(node, { ...context, state }, optimiser.transform);

	if (dev) {
		const location = /** @type {Location} */ (locator(node.start));
		statements.push(
			stmt(
				call(
					'$.push_element',
					id('$$renderer'),
					tag,
					literal(location.line),
					literal(location.column)
				)
			)
		);
	}

	const attributes = block([...state.init, ...build_template(state.template)]);
	const children = /** @type {BlockStatement} */ (context.visit(node.fragment, state));

	/** @type {Statement} */
	let statement = stmt(
		call(
			'$.element',
			id('$$renderer'),
			tag,
			attributes.body.length > 0 && thunk(attributes),
			children.body.length > 0 && thunk(children)
		)
	);

	if (optimiser.expressions.length > 0) {
		statement = create_child_block(block([optimiser.apply(), statement]), true);
	}

	statements.push(statement);

	if (dev) {
		statements.push(stmt(call('$.pop_element')));
	}

	if (node.metadata.expression.is_async()) {
		statements = [
			create_async_block(
				block(statements),
				node.metadata.expression.blockers(),
				node.metadata.expression.has_await
			)
		];
	}

	context.state.template.push(...statements);
}

/** @import { BlockStatement } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {AST.SvelteFragment} node
 * @param {ComponentContext} context
 */
function SvelteFragment$1(node, context) {
	context.state.template.push(/** @type {BlockStatement} */ (context.visit(node.fragment)));
}

/** @import { BlockStatement } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types.js' */

/**
 * @param {AST.SvelteHead} node
 * @param {ComponentContext} context
 */
function SvelteHead$1(node, context) {
	const block = /** @type {BlockStatement} */ (context.visit(node.fragment));

	context.state.template.push(
		stmt(
			call(
				'$.head',
				literal(hash(filename)),
				id('$$renderer'),
				arrow([id('$$renderer')], block)
			)
		)
	);
}

/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types.js' */

/**
 * @param {AST.SvelteSelf} node
 * @param {ComponentContext} context
 */
function SvelteSelf$1(node, context) {
	build_inline_component(node, id(context.state.analysis.name), context);
}

/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types.js' */

/**
 * @param {AST.TitleElement} node
 * @param {ComponentContext} context
 */
function TitleElement$1(node, context) {
	// title is guaranteed to contain only text/expression tag children
	const template = [literal('<title>')];
	process_children$1(node.fragment.nodes, { ...context, state: { ...context.state, template } });
	template.push(literal('</title>'));

	context.state.init.push(
		stmt(
			call('$$renderer.title', arrow([id('$$renderer')], block(build_template(template))))
		)
	);
}

/** @import { UpdateExpression } from 'estree' */
/** @import { Context } from '../types.js' */

/**
 * @param {UpdateExpression} node
 * @param {Context} context
 */
function UpdateExpression$1(node, context) {
	const argument = node.argument;

	if (
		argument.type === 'Identifier' &&
		context.state.scope.get(argument.name)?.kind === 'store_sub'
	) {
		return call(
			node.prefix ? '$.update_store_pre' : '$.update_store',
			assignment('??=', id('$$store_subs'), object$2([])),
			literal(argument.name),
			id(argument.name.slice(1)),
			node.operator === '--' && literal(-1)
		);
	}

	return context.next();
}

/** @import { VariableDeclaration, VariableDeclarator, Expression, CallExpression, Pattern, Identifier } from 'estree' */
/** @import { Binding } from '#compiler' */
/** @import { Context } from '../types.js' */
/** @import { ComponentAnalysis } from '../../../types.js' */
/** @import { Scope } from '../../../scope.js' */

/**
 * @param {VariableDeclaration} node
 * @param {Context} context
 */
function VariableDeclaration$1(node, context) {
	/** @type {VariableDeclarator[]} */
	const declarations = [];

	if (context.state.analysis.runes) {
		for (const declarator$1 of node.declarations) {
			const init = declarator$1.init;
			const rune = get_rune(init, context.state.scope);
			if (!rune || rune === '$effect.tracking' || rune === '$inspect' || rune === '$effect.root') {
				declarations.push(/** @type {VariableDeclarator} */ (context.visit(declarator$1)));
				continue;
			}

			if (rune === '$props.id') {
				// skip
				continue;
			}

			if (rune === '$props') {
				let has_rest = false;
				// remove $bindable() from props declaration
				let id$1 = walk$1(declarator$1.id, null, {
					RestElement(node, context) {
						if (context.path.at(-1) === declarator$1.id) {
							has_rest = true;
						}
					},
					AssignmentPattern(node) {
						if (
							node.right.type === 'CallExpression' &&
							get_rune(node.right, context.state.scope) === '$bindable'
						) {
							const right = node.right.arguments.length
								? /** @type {Expression} */ (context.visit(node.right.arguments[0]))
								: void0;
							return assignment_pattern(node.left, right);
						}
					}
				});

				// if `$$slots` is declared separately, deconflict
				const slots_name = /** @type {ComponentAnalysis} */ (context.state.analysis).uses_slots
					? id('$$slots_')
					: id('$$slots');

				if (id$1.type === 'ObjectPattern' && has_rest) {
					// If a rest pattern is used within an object pattern, we need to ensure we don't expose $$slots or $$events
					id$1.properties.splice(
						id$1.properties.length - 1,
						0,
						// @ts-ignore
						prop('init', id('$$slots'), slots_name),
						prop('init', id('$$events'), id('$$events'))
					);
				} else if (id$1.type === 'Identifier') {
					// If $props is referenced as an identifier, we need to ensure we don't expose $$slots or $$events as properties
					// on the identifier reference
					id$1 = object_pattern([
						prop('init', id('$$slots'), slots_name),
						prop('init', id('$$events'), id('$$events')),
						rest(id(id$1.name))
					]);
				}
				declarations.push(
					declarator(/** @type {Pattern} */ (context.visit(id$1)), id('$$props'))
				);
				continue;
			}

			const args = /** @type {CallExpression} */ (init).arguments;
			const value = args.length > 0 ? /** @type {Expression} */ (context.visit(args[0])) : void0;

			if (rune === '$derived.by') {
				declarations.push(
					declarator(/** @type {Pattern} */ (context.visit(declarator$1.id)), call(value))
				);
				continue;
			}

			if (declarator$1.id.type === 'Identifier') {
				declarations.push(declarator(declarator$1.id, value));
				continue;
			}

			if (rune === '$derived') {
				declarations.push(
					declarator(/** @type {Pattern} */ (context.visit(declarator$1.id)), value)
				);
				continue;
			}

			declarations.push(...create_state_declarators$1(declarator$1, context.state.scope, value));
		}
	} else {
		for (const declarator$1 of node.declarations) {
			const bindings = /** @type {Binding[]} */ (context.state.scope.get_bindings(declarator$1));
			const has_state = bindings.some((binding) => binding.kind === 'state');
			const has_props = bindings.some((binding) => binding.kind === 'bindable_prop');

			if (!has_state && !has_props) {
				declarations.push(/** @type {VariableDeclarator} */ (context.visit(declarator$1)));
				continue;
			}

			if (has_props) {
				if (declarator$1.id.type !== 'Identifier') {
					// Turn export let into props. It's really really weird because export let { x: foo, z: [bar]} = ..
					// means that foo and bar are the props (i.e. the leafs are the prop names), not x and z.
					const tmp = id(context.state.scope.generate('tmp'));
					const { inserts, paths } = extract_paths(declarator$1.id, tmp);

					declarations.push(
						declarator(
							tmp,
							/** @type {Expression} */ (context.visit(/** @type {Expression} */ (declarator$1.init)))
						)
					);

					for (const { id, value } of inserts) {
						id.name = context.state.scope.generate('$$array');
						declarations.push(declarator(id, value));
					}

					for (const path of paths) {
						const value = path.expression;
						const name = /** @type {Identifier} */ (path.node).name;
						const binding = /** @type {Binding} */ (context.state.scope.get(name));
						const prop = member(id('$$props'), literal(binding.prop_alias ?? name), true);
						declarations.push(declarator(path.node, build_fallback(prop, value)));
					}

					continue;
				}

				const binding = /** @type {Binding} */ (context.state.scope.get(declarator$1.id.name));
				const prop = member(
					id('$$props'),
					literal(binding.prop_alias ?? declarator$1.id.name),
					true
				);

				/** @type {Expression} */
				let init = prop;
				if (declarator$1.init) {
					const default_value = /** @type {Expression} */ (context.visit(declarator$1.init));
					init = build_fallback(prop, default_value);
				}

				declarations.push(declarator(declarator$1.id, init));

				continue;
			}

			declarations.push(
				...create_state_declarators$1(
					declarator$1,
					context.state.scope,
					/** @type {Expression} */ (declarator$1.init && context.visit(declarator$1.init))
				)
			);
		}
	}

	if (declarations.length === 0) {
		return empty;
	}

	return {
		...node,
		declarations
	};
}

/**
 * @param {VariableDeclarator} declarator
 * @param {Scope} scope
 * @param {Expression} value
 * @returns {VariableDeclarator[]}
 */
function create_state_declarators$1(declarator$1, scope, value) {
	if (declarator$1.id.type === 'Identifier') {
		return [declarator(declarator$1.id, value)];
	}

	const tmp = id(scope.generate('tmp'));
	const { paths, inserts } = extract_paths(declarator$1.id, tmp);
	return [
		declarator(tmp, value), // TODO inject declarator for opts, so we can use it below
		...inserts.map(({ id, value }) => {
			id.name = scope.generate('$$array');
			return declarator(id, value);
		}),
		...paths.map((path) => {
			const value = path.expression;
			return declarator(path.node, value);
		})
	];
}

/** @import { BlockStatement } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {AST.SvelteBoundary} node
 * @param {ComponentContext} context
 */
function SvelteBoundary$1(node, context) {
	// if this has a `pending` snippet, render it
	const pending_attribute = /** @type {AST.Attribute} */ (
		node.attributes.find((node) => node.type === 'Attribute' && node.name === 'pending')
	);
	const is_pending_attr_nullish =
		pending_attribute &&
		typeof pending_attribute.value === 'object' &&
		!Array.isArray(pending_attribute.value) &&
		!context.state.scope.evaluate(pending_attribute.value.expression).is_defined;

	const pending_snippet = /** @type {AST.SnippetBlock} */ (
		node.fragment.nodes.find(
			(node) => node.type === 'SnippetBlock' && node.expression.name === 'pending'
		)
	);

	if (pending_attribute || pending_snippet) {
		if (pending_attribute && is_pending_attr_nullish && !pending_snippet) {
			const callee = build_attribute_value$1(
				pending_attribute.value,
				context,
				(expression) => expression,
				false,
				true
			);
			const pending = call(callee, id('$$renderer'));
			const block$1 = /** @type {BlockStatement} */ (context.visit(node.fragment));
			context.state.template.push(
				if_builder(
					callee,
					block(build_template([block_open_else, stmt(pending), block_close])),
					block(build_template([block_open, block$1, block_close]))
				)
			);
		} else {
			const pending = pending_attribute
				? call(
						build_attribute_value$1(
							pending_attribute.value,
							context,
							(expression) => expression,
							false,
							true
						),
						id('$$renderer')
					)
				: /** @type {BlockStatement} */ (context.visit(pending_snippet.body));
			context.state.template.push(block_open_else, pending, block_close);
		}
	} else {
		const block = /** @type {BlockStatement} */ (context.visit(node.fragment));
		context.state.template.push(block_open, block, block_close);
	}
}

/** @import * as ESTree from 'estree' */
/** @import { AST, ValidatedCompileOptions, ValidatedModuleCompileOptions } from '#compiler' */
/** @import { ComponentServerTransformState, ComponentVisitors, ServerTransformState, Visitors } from './types.js' */
/** @import { Analysis, ComponentAnalysis } from '../../types.js' */

/** @type {Visitors} */
const global_visitors = {
	_: set_scope,
	AssignmentExpression: AssignmentExpression$1,
	AwaitExpression: AwaitExpression$1,
	CallExpression: CallExpression$1,
	ClassBody: ClassBody$1,
	ExpressionStatement: ExpressionStatement$1,
	Identifier: Identifier$1,
	LabeledStatement: LabeledStatement$1,
	MemberExpression: MemberExpression$1,
	Program: Program$1,
	PropertyDefinition,
	UpdateExpression: UpdateExpression$1,
	VariableDeclaration: VariableDeclaration$1
};

/** @type {ComponentVisitors} */
const template_visitors = {
	AwaitBlock: AwaitBlock$1,
	Component: Component$1,
	ConstTag: ConstTag$1,
	DebugTag: DebugTag$1,
	EachBlock: EachBlock$1,
	Fragment: Fragment$1,
	HtmlTag: HtmlTag$1,
	IfBlock: IfBlock$1,
	KeyBlock: KeyBlock$1,
	RegularElement: RegularElement$1,
	RenderTag: RenderTag$1,
	SlotElement: SlotElement$1,
	SnippetBlock: SnippetBlock$1,
	SpreadAttribute: SpreadAttribute$1,
	SvelteComponent: SvelteComponent$1,
	SvelteElement: SvelteElement$1,
	SvelteFragment: SvelteFragment$1,
	SvelteHead: SvelteHead$1,
	SvelteSelf: SvelteSelf$1,
	TitleElement: TitleElement$1,
	SvelteBoundary: SvelteBoundary$1
};

/**
 * @param {ComponentAnalysis} analysis
 * @param {ValidatedCompileOptions} options
 * @returns {ESTree.Program}
 */
function server_component(analysis, options) {
	/** @type {ComponentServerTransformState} */
	const state = {
		analysis,
		options,
		scope: analysis.module.scope,
		scopes: analysis.module.scopes,
		hoisted: [import_all('$', 'svelte/internal/server'), ...analysis.instance_body.hoisted],
		legacy_reactive_statements: new Map(),
		// these are set inside the `Fragment` visitor, and cannot be used until then
		init: /** @type {any} */ (null),
		template: /** @type {any} */ (null),
		namespace: options.namespace,
		preserve_whitespace: options.preserveWhitespace,
		state_fields: new Map(),
		skip_hydration_boundaries: false,
		is_instance: false
	};

	const module = /** @type {ESTree.Program} */ (
		walk$1(/** @type {AST.SvelteNode} */ (analysis.module.ast), state, global_visitors)
	);

	const instance = /** @type {ESTree.Program} */ (
		walk$1(
			/** @type {AST.SvelteNode} */ (analysis.instance.ast),
			{ ...state, scopes: analysis.instance.scopes, is_instance: true },
			{
				...global_visitors,
				ImportDeclaration(node) {
					state.hoisted.push(node);
					return empty;
				},
				ExportNamedDeclaration(node, context) {
					if (node.declaration) {
						return context.visit(node.declaration);
					}

					return empty;
				}
			}
		)
	);

	const template = /** @type {ESTree.Program} */ (
		walk$1(
			/** @type {AST.SvelteNode} */ (analysis.template.ast),
			{ ...state, scopes: analysis.template.scopes },
			// @ts-expect-error don't know, don't care
			{ ...global_visitors, ...template_visitors }
		)
	);

	/** @type {ESTree.VariableDeclarator[]} */
	const legacy_reactive_declarations = [];

	for (const [node] of analysis.reactive_statements) {
		const statement = [...state.legacy_reactive_statements].find(([n]) => n === node);
		if (statement === undefined) {
			throw new Error('Could not find reactive statement');
		}

		if (
			node.body.type === 'ExpressionStatement' &&
			node.body.expression.type === 'AssignmentExpression'
		) {
			for (const id of extract_identifiers(node.body.expression.left)) {
				const binding = analysis.instance.scope.get(id.name);
				if (binding?.kind === 'legacy_reactive') {
					legacy_reactive_declarations.push(declarator(id));
				}
			}
		}

		instance.body.push(statement[1]);
	}

	if (legacy_reactive_declarations.length > 0) {
		instance.body.unshift({
			type: 'VariableDeclaration',
			kind: 'let',
			declarations: legacy_reactive_declarations
		});
	}

	// If the component binds to a child, we need to put the template in a loop and repeat until legacy bindings are stable.
	// We can remove this once the legacy syntax is gone.
	if (analysis.uses_component_bindings) {
		const snippets = template.body.filter(
			// @ts-expect-error
			(node) => node.type === 'FunctionDeclaration' && node.___snippet
		);

		const rest = template.body.filter(
			// @ts-expect-error
			(node) => node.type !== 'FunctionDeclaration' || !node.___snippet
		);

		template.body = [
			...snippets,
			let_builder('$$settled', true_instance),
			let_builder('$$inner_renderer'),
			function_declaration(
				id('$$render_inner'),
				[id('$$renderer')],
				block(/** @type {ESTree.Statement[]} */ (rest))
			),
			do_while(
				unary$1('!', id('$$settled')),
				block([
					stmt(assignment('=', id('$$settled'), true_instance)),
					stmt(assignment('=', id('$$inner_renderer'), call('$$renderer.copy'))),
					stmt(call('$$render_inner', id('$$inner_renderer')))
				])
			),
			stmt(call('$$renderer.subsume', id('$$inner_renderer')))
		];
	}

	if (
		[...analysis.instance.scope.declarations.values()].some(
			(binding) => binding.kind === 'store_sub'
		)
	) {
		instance.body.unshift(var_builder('$$store_subs'));
		template.body.push(
			if_builder(id('$$store_subs'), stmt(call('$.unsubscribe_stores', id('$$store_subs'))))
		);
	}

	// Propagate values of bound props upwards if they're undefined in the parent and have a value.
	// Don't do this as part of the props retrieval because people could eagerly mutate the prop in the instance script.
	/** @type {ESTree.Property[]} */
	const props = [];

	for (const [name, binding] of analysis.instance.scope.declarations) {
		if (binding.kind === 'bindable_prop' && !name.startsWith('$$')) {
			props.push(init(binding.prop_alias ?? name, id(name)));
		}
	}

	for (const { name, alias } of analysis.exports) {
		props.push(init(alias ?? name, id(name)));
	}

	if (props.length > 0) {
		// This has no effect in runes mode other than throwing an error when someone passes
		// undefined to a binding that has a default value.
		template.body.push(stmt(call('$.bind_props', id('$$props'), object$2(props))));
	}

	let component_block = block([
		.../** @type {ESTree.Statement[]} */ (instance.body),
		.../** @type {ESTree.Statement[]} */ (template.body)
	]);

	// trick esrap into including comments
	component_block.loc = instance.loc;

	if (analysis.props_id) {
		// need to be placed on first line of the component for hydration
		component_block.body.unshift(
			const_builder(analysis.props_id, call('$.props_id', id('$$renderer')))
		);
	}

	let should_inject_context = dev || analysis.needs_context;

	if (should_inject_context) {
		component_block = block([
			call_component_renderer(component_block, dev && id(component_name))
		]);
	}

	if (analysis.uses_rest_props) {
		/** @type {string[]} */
		const named_props = analysis.exports.map(({ name, alias }) => alias ?? name);
		for (const [name, binding] of analysis.instance.scope.declarations) {
			if (binding.kind === 'bindable_prop') named_props.push(binding.prop_alias ?? name);
		}

		component_block.body.unshift(
			const_builder(
				'$$restProps',
				call(
					'$.rest_props',
					id('$$sanitized_props'),
					array(named_props.map((name) => literal(name)))
				)
			)
		);
	}

	if (analysis.uses_props || analysis.uses_rest_props) {
		component_block.body.unshift(
			const_builder('$$sanitized_props', call('$.sanitize_props', id('$$props')))
		);
	}

	if (analysis.uses_slots) {
		component_block.body.unshift(const_builder('$$slots', call('$.sanitize_slots', id('$$props'))));
	}

	const body = [...state.hoisted, ...module.body];

	if (analysis.css.ast !== null && options.css === 'injected' && !options.customElement) {
		const hash = literal(analysis.css.hash);
		const code = literal(render_stylesheet(analysis.source, analysis, options).code);

		body.push(const_builder('$$css', object$2([init('hash', hash), init('code', code)])));
		component_block.body.unshift(stmt(call('$$renderer.global.css.add', id('$$css'))));
	}

	let should_inject_props =
		should_inject_context ||
		props.length > 0 ||
		analysis.needs_props ||
		analysis.uses_props ||
		analysis.uses_rest_props ||
		analysis.uses_slots ||
		analysis.slot_names.size > 0;

	const component_function = function_declaration(
		id(analysis.name),
		should_inject_props ? [id('$$renderer'), id('$$props')] : [id('$$renderer')],
		component_block
	);

	if (options.compatibility.componentApi === 4) {
		body.unshift(imports([['render', '$$_render']], 'svelte/server'));
		body.push(
			component_function,
			stmt(
				assignment(
					'=',
					member_id(`${analysis.name}.render`),
					function_builder(
						null,
						[id('$$props'), id('$$opts')],
						block([
							return_builder(
								call(
									'$$_render',
									id(analysis.name),
									object$2([
										init('props', id('$$props')),
										init('context', member(id('$$opts'), 'context', false, true))
									])
								)
							)
						])
					)
				)
			),
			export_default(id(analysis.name))
		);
	} else if (dev) {
		body.push(
			component_function,
			stmt(
				assignment(
					'=',
					member_id(`${analysis.name}.render`),
					function_builder(
						null,
						[],
						block([
							throw_error$1(
								`Component.render(...) is no longer valid in Svelte 5. ` +
									'See https://svelte.dev/docs/svelte/v5-migration-guide#Components-are-no-longer-classes for more information'
							)
						])
					)
				)
			),
			export_default(id(analysis.name))
		);
	} else {
		body.push(export_default(component_function));
	}

	if (dev) {
		// add `App[$.FILENAME] = 'App.svelte'` so that we can print useful messages later
		body.unshift(
			stmt(
				assignment('=', member(id(analysis.name), '$.FILENAME', true), literal(filename))
			)
		);
	}

	if (options.experimental.async) {
		body.unshift(imports([], 'svelte/internal/flags/async'));
	}

	return {
		type: 'Program',
		sourceType: 'module',
		body
	};
}

/**
 * @param {Analysis} analysis
 * @param {ValidatedModuleCompileOptions} options
 * @returns {ESTree.Program}
 */
function server_module(analysis, options) {
	/** @type {ServerTransformState} */
	const state = {
		analysis,
		options,
		scope: analysis.module.scope,
		scopes: analysis.module.scopes,
		// this is an anomaly — it can only be used in components, but it needs
		// to be present for `javascript_visitors_legacy` and so is included in module
		// transform state as well as component transform state
		legacy_reactive_statements: new Map(),
		state_fields: new Map(),
		is_instance: false
	};

	const module = /** @type {ESTree.Program} */ (
		walk$1(/** @type {AST.SvelteNode} */ (analysis.module.ast), state, global_visitors)
	);

	return {
		type: 'Program',
		sourceType: 'module',
		body: [import_all('$', 'svelte/internal/server'), ...module.body]
	};
}

/** @import { AssignmentExpression, Expression, Identifier, MemberExpression, SequenceExpression, Literal, Super, UpdateExpression, ExpressionStatement } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentClientTransformState, ComponentContext, Context } from '../../types' */

/**
 * A utility for extracting complex expressions (such as call expressions)
 * from templates and replacing them with `$0`, `$1` etc
 */
class Memoizer {
	/** @type {Array<{ id: Identifier, expression: Expression }>} */
	#sync = [];

	/** @type {Array<{ id: Identifier, expression: Expression }>} */
	#async = [];

	/** @type {Set<Expression>} */
	#blockers = new Set();

	/**
	 * @param {Expression} expression
	 * @param {ExpressionMetadata} metadata
	 * @param {boolean} memoize_if_state
	 */
	add(expression, metadata, memoize_if_state = false) {
		this.check_blockers(metadata);

		const should_memoize =
			metadata.has_call || metadata.has_await || (memoize_if_state && metadata.has_state);

		if (!should_memoize) {
			// no memoization required
			return expression;
		}

		const id$1 = id('#'); // filled in later

		(metadata.has_await ? this.#async : this.#sync).push({ id: id$1, expression });

		return id$1;
	}

	/**
	 * @param {ExpressionMetadata} metadata
	 */
	check_blockers(metadata) {
		for (const binding of metadata.dependencies) {
			if (binding.blocker) {
				this.#blockers.add(binding.blocker);
			}
		}
	}

	apply() {
		return [...this.#sync, ...this.#async].map((memo, i) => {
			memo.id.name = `$${i}`;
			return memo.id;
		});
	}

	blockers() {
		return this.#blockers.size > 0 ? array([...this.#blockers]) : undefined;
	}

	deriveds(runes = true) {
		return this.#sync.map((memo) =>
			let_builder(memo.id, call(runes ? '$.derived' : '$.derived_safe_equal', thunk(memo.expression)))
		);
	}

	async_ids() {
		return this.#async.map((memo) => memo.id);
	}

	async_values() {
		if (this.#async.length === 0) return;
		return array(this.#async.map((memo) => thunk(memo.expression, true)));
	}

	sync_values() {
		if (this.#sync.length === 0) return;
		return array(this.#sync.map((memo) => thunk(memo.expression)));
	}
}

/**
 * @param {Array<AST.Text | AST.ExpressionTag>} values
 * @param {ComponentContext} context
 * @param {ComponentClientTransformState} state
 * @param {(value: Expression, metadata: ExpressionMetadata) => Expression} memoize
 * @returns {{ value: Expression, has_state: boolean }}
 */
function build_template_chunk(
	values,
	context,
	state = context.state,
	memoize = (value, metadata) => state.memoizer.add(value, metadata)
) {
	/** @type {Expression[]} */
	const expressions = [];

	let quasi$1 = quasi('');
	const quasis = [quasi$1];

	let has_state = false;
	let has_await = false;

	for (let i = 0; i < values.length; i++) {
		const node = values[i];

		if (node.type === 'Text') {
			quasi$1.value.cooked += node.data;
		} else if (node.expression.type === 'Literal') {
			if (node.expression.value != null) {
				quasi$1.value.cooked += node.expression.value + '';
			}
		} else if (
			node.expression.type !== 'Identifier' ||
			node.expression.name !== 'undefined' ||
			state.scope.get('undefined')
		) {
			let value = memoize(
				build_expression(context, node.expression, node.metadata.expression, state),
				node.metadata.expression
			);

			const evaluated = state.scope.evaluate(value);

			has_await ||= node.metadata.expression.has_await;
			has_state ||= has_await || (node.metadata.expression.has_state && !evaluated.is_known);

			if (values.length === 1) {
				// If we have a single expression, then pass that in directly to possibly avoid doing
				// extra work in the template_effect (instead we do the work in set_text).
				if (evaluated.is_known) {
					value = literal((evaluated.value ?? '') + '');
				}

				return { value, has_state };
			}

			if (
				value.type === 'LogicalExpression' &&
				value.right.type === 'Literal' &&
				(value.operator === '??' || value.operator === '||')
			) {
				// `foo ?? null` -=> `foo ?? ''`
				// otherwise leave the expression untouched
				if (value.right.value === null) {
					value = { ...value, right: literal('') };
				}
			}

			if (evaluated.is_known) {
				quasi$1.value.cooked += (evaluated.value ?? '') + '';
			} else {
				if (!evaluated.is_defined) {
					// add `?? ''` where necessary
					value = logical$1('??', value, literal(''));
				}

				expressions.push(value);

				quasi$1 = quasi('', i + 1 === values.length);
				quasis.push(quasi$1);
			}
		}
	}

	for (const quasi of quasis) {
		quasi.value.raw = sanitize_template_string(/** @type {string} */ (quasi.value.cooked));
	}

	const value =
		expressions.length > 0
			? template$1(quasis, expressions)
			: literal(/** @type {string} */ (quasi$1.value.cooked));

	return { value, has_state };
}

/**
 * @param {ComponentClientTransformState} state
 */
function build_render_statement(state) {
	const { memoizer } = state;

	const ids = memoizer.apply();

	return stmt(
		call(
			'$.template_effect',
			arrow(
				ids,
				state.update.length === 1 && state.update[0].type === 'ExpressionStatement'
					? state.update[0].expression
					: block(state.update)
			),
			memoizer.sync_values(),
			memoizer.async_values(),
			memoizer.blockers()
		)
	);
}

/**
 * For unfortunate legacy reasons, directive names can look like this `use:a.b-c`
 * This turns that string into a member expression
 * @param {string} name
 */
function parse_directive_name(name) {
	// this allow for accessing members of an object
	const parts = name.split('.');
	let part = /** @type {string} */ (parts.shift());

	/** @type {Identifier | MemberExpression} */
	let expression = id(part);

	while ((part = /** @type {string} */ (parts.shift()))) {
		const computed = !regex_is_valid_identifier.test(part);
		expression = member(expression, computed ? literal(part) : id(part), computed);
	}

	return expression;
}

/**
 * Serializes `bind:this` for components and elements.
 * @param {Identifier | MemberExpression | SequenceExpression} expression
 * @param {Expression} value
 * @param {import('zimmerframe').Context<AST.SvelteNode, ComponentClientTransformState>} context
 */
function build_bind_this(expression, value, { state, visit }) {
	const [getter, setter] =
		expression.type === 'SequenceExpression' ? expression.expressions : [null, null];

	/** @type {Identifier[]} */
	const ids = [];

	/** @type {Expression[]} */
	const values = [];

	/** @type {string[]} */
	const seen = [];

	const transform = { ...state.transform };

	// Pass in each context variables to the get/set functions, so that we can null out old values on teardown.
	// Note that we only do this for each context variables, the consequence is that the value might be stale in
	// some scenarios where the value is a member expression with changing computed parts or using a combination of multiple
	// variables, but that was the same case in Svelte 4, too. Once legacy mode is gone completely, we can revisit this.
	walk$1(getter ?? expression, null, {
		Identifier(node, { path }) {
			if (seen.includes(node.name)) return;
			seen.push(node.name);

			const parent = /** @type {Expression} */ (path.at(-1));
			if (!is_reference(node, parent)) return;

			const binding = state.scope.get(node.name);
			if (!binding) return;

			for (const [owner, scope] of state.scopes) {
				if (owner.type === 'EachBlock' && scope === binding.scope) {
					ids.push(node);
					values.push(/** @type {Expression} */ (visit(node)));

					if (transform[node.name]) {
						transform[node.name] = {
							...transform[node.name],
							read: (node) => node
						};
					}

					break;
				}
			}
		}
	});

	const child_state = { ...state, transform };

	let get = /** @type {Expression} */ (visit(getter ?? expression, child_state));
	let set = /** @type {Expression} */ (
		visit(
			setter ??
				assignment(
					'=',
					/** @type {Identifier | MemberExpression} */ (expression),
					id('$$value')
				),
			child_state
		)
	);

	// If we're mutating a property, then it might already be non-existent.
	// If we make all the object nodes optional, then it avoids any runtime exceptions.
	/** @type {Expression | Super} */
	let node = get;

	while (node.type === 'MemberExpression') {
		node.optional = true;
		node = node.object;
	}

	get =
		get.type === 'ArrowFunctionExpression'
			? arrow([...ids], get.body)
			: get.type === 'FunctionExpression'
				? function_builder(null, [...ids], get.body)
				: getter
					? get
					: arrow([...ids], get);

	set =
		set.type === 'ArrowFunctionExpression'
			? arrow([set.params[0] ?? id('_'), ...ids], set.body)
			: set.type === 'FunctionExpression'
				? function_builder(null, [set.params[0] ?? id('_'), ...ids], set.body)
				: setter
					? set
					: arrow([id('$$value'), ...ids], set);

	return call('$.bind_this', value, set, get, values.length > 0 && thunk(array(values)));
}

/**
 * @param {ComponentClientTransformState} state
 * @param {AST.BindDirective} binding
 * @param {MemberExpression} expression
 */
function validate_binding(state, binding, expression) {
	if (binding.expression.type === 'SequenceExpression') {
		return;
	}
	// If we are referencing a $store.foo then we don't need to add validation
	const left = object$1(binding.expression);
	const left_binding = left && state.scope.get(left.name);
	if (left_binding?.kind === 'store_sub') return;

	const loc = locator(binding.start);

	const obj = /** @type {Expression} */ (expression.object);

	state.init.push(
		stmt(
			call(
				'$.validate_binding',
				literal(state.analysis.source.slice(binding.start, binding.end)),
				binding.metadata.expression.blockers(),
				thunk(
					state.store_to_invalidate ? sequence([call('$.mark_store_binding'), obj]) : obj
				),
				thunk(
					/** @type {Expression} */ (
						expression.computed
							? expression.property
							: literal(/** @type {Identifier} */ (expression.property).name)
					)
				),
				loc && literal(loc.line),
				loc && literal(loc.column)
			)
		)
	);
}

/**
 * In dev mode validate mutations to props
 * @param {AssignmentExpression | UpdateExpression} node
 * @param {Context} context
 * @param {Expression} expression
 */
function validate_mutation(node, context, expression) {
	let left = /** @type {Expression | Super} */ (
		node.type === 'AssignmentExpression' ? node.left : node.argument
	);

	if (!dev || left.type !== 'MemberExpression' || is_ignored(node, 'ownership_invalid_mutation')) {
		return expression;
	}

	const name = object$1(left);
	if (!name) return expression;

	const binding = context.state.scope.get(name.name);
	if (binding?.kind !== 'prop' && binding?.kind !== 'bindable_prop') return expression;

	const state = /** @type {ComponentClientTransformState} */ (context.state);
	state.analysis.needs_mutation_validation = true;

	/** @type {Array<Identifier | Literal | Expression>} */
	const path = [];

	while (left.type === 'MemberExpression') {
		if (left.property.type === 'Literal') {
			path.unshift(left.property);
		} else if (left.property.type === 'Identifier') {
			const transform = Object.hasOwn(context.state.transform, left.property.name)
				? context.state.transform[left.property.name]
				: null;
			if (left.computed) {
				path.unshift(transform?.read ? transform.read(left.property) : left.property);
			} else {
				path.unshift(literal(left.property.name));
			}
		} else {
			return expression;
		}

		left = left.object;
	}

	path.unshift(literal(name.name));

	const loc = locator(/** @type {number} */ (left.start));

	return call(
		'$$ownership_validator.mutation',
		literal(binding.prop_alias),
		array(path),
		expression,
		loc && literal(loc.line),
		loc && literal(loc.column)
	);
}

/**
 *
 * @param {ComponentContext} context
 * @param {Expression} expression
 * @param {ExpressionMetadata} metadata
 */
function build_expression(context, expression, metadata, state = context.state) {
	const value = /** @type {Expression} */ (context.visit(expression, state));

	// Components not explicitly in legacy mode might be expected to be in runes mode (especially since we didn't
	// adjust this behavior until recently, which broke people's existing components), so we also bail in this case.
	// Kind of an in-between-mode.
	if (context.state.analysis.runes || context.state.analysis.maybe_runes) {
		return value;
	}

	if (!metadata.has_call && !metadata.has_member_expression && !metadata.has_assignment) {
		return value;
	}

	// Legacy reactivity is coarse-grained, looking at the statically visible dependencies. Replicate that here
	const sequence$1 = sequence([]);

	for (const binding of metadata.references) {
		if (binding.kind === 'normal' && binding.declaration_kind !== 'import') {
			continue;
		}

		var getter = build_getter$1({ ...binding.node }, state);

		if (
			binding.kind === 'bindable_prop' ||
			binding.kind === 'template' ||
			binding.declaration_kind === 'import' ||
			binding.node.name === '$$props' ||
			binding.node.name === '$$restProps'
		) {
			getter = call('$.deep_read_state', getter);
		}

		sequence$1.expressions.push(getter);
	}

	sequence$1.expressions.push(call('$.untrack', thunk(value)));

	return sequence$1;
}

/**
 * Wraps a statement/expression with dev stack tracking in dev mode
 * @param {Expression} expression - The function call to wrap (e.g., $.if, $.each, etc.)
 * @param {{ start?: number }} node - AST node for location info
 * @param {'component' | 'if' | 'each' | 'await' | 'key' | 'render'} type - Type of block/component
 * @param {Record<string, number | string>} [additional] - Any additional properties to add to the dev stack entry
 * @returns {ExpressionStatement} - Statement with or without dev stack wrapping
 */
function add_svelte_meta(expression, node, type, additional) {
	if (!dev) {
		return stmt(expression);
	}

	const location = node.start !== undefined && locator(node.start);
	if (!location) {
		return stmt(expression);
	}

	return stmt(
		call(
			'$.add_svelte_meta',
			arrow([], expression),
			literal(type),
			id(component_name),
			literal(location.line),
			literal(location.column),
			additional && object$2(Object.entries(additional).map(([k, v]) => init(k, literal(v))))
		)
	);
}

/** @import { Expression } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {AST.AnimateDirective} node
 * @param {ComponentContext} context
 */
function AnimateDirective(node, context) {
	const expression =
		node.expression === null
			? null_instance
			: thunk(/** @type {Expression} */ (context.visit(node.expression)));

	// in after_update to ensure it always happens after bind:this
	let statement = stmt(
		call(
			'$.animation',
			context.state.node,
			thunk(/** @type {Expression} */ (context.visit(parse_directive_name(node.name)))),
			expression
		)
	);

	if (node.metadata.expression.is_async()) {
		statement = stmt(
			call(
				'$.run_after_blockers',
				node.metadata.expression.blockers(),
				thunk(block([statement]))
			)
		);
	}

	context.state.after_update.push(statement);
}

/** @import { ArrowFunctionExpression, FunctionExpression, Node } from 'estree' */
/** @import { ComponentContext } from '../../types' */

/**
 * @param {ArrowFunctionExpression | FunctionExpression} node
 * @param {ComponentContext} context
 */
const visit_function = (node, context) => {
	let state = { ...context.state, in_constructor: false, in_derived: false };

	if (node.type === 'FunctionExpression') {
		const parent = /** @type {Node} */ (context.path.at(-1));
		state.in_constructor = parent.type === 'MethodDefinition' && parent.kind === 'constructor';
	}

	context.next(state);
};

/** @import { ArrowFunctionExpression } from 'estree' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {ArrowFunctionExpression} node
 * @param {ComponentContext} context
 */
function ArrowFunctionExpression(node, context) {
	return visit_function(node, context);
}

/** @import { AssignmentExpression, AssignmentOperator, Expression, Identifier, Pattern } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { Context } from '../types.js' */

/**
 * @param {AssignmentExpression} node
 * @param {Context} context
 */
function AssignmentExpression(node, context) {
	const expression = /** @type {Expression} */ (
		visit_assignment_expression(node, context, build_assignment) ?? context.next()
	);

	return validate_mutation(node, context, expression);
}

/**
 * Determines whether the value will be coerced on assignment (as with e.g. `+=`).
 * If not, we may need to proxify the value, or warn that the value will not be
 * proxified in time
 * @param {AssignmentOperator} operator
 */
function is_non_coercive_operator(operator) {
	return ['=', '||=', '&&=', '??='].includes(operator);
}

/** @type {Record<string, string>} */
const callees = {
	'=': '$.assign',
	'&&=': '$.assign_and',
	'||=': '$.assign_or',
	'??=': '$.assign_nullish'
};

/**
 * @param {AssignmentOperator} operator
 * @param {Pattern} left
 * @param {Expression} right
 * @param {Context} context
 * @returns {Expression | null}
 */
function build_assignment(operator, left, right, context) {
	if (context.state.analysis.runes && left.type === 'MemberExpression') {
		const name = get_name(left.property);
		const field = name && context.state.state_fields.get(name);

		if (field) {
			// special case — state declaration in class constructor
			if (field.node.type === 'AssignmentExpression' && left === field.node.left) {
				const rune = get_rune(right, context.state.scope);

				if (rune) {
					const child_state = {
						...context.state,
						in_constructor: rune !== '$derived' && rune !== '$derived.by'
					};

					let value = /** @type {Expression} */ (context.visit(right, child_state));

					if (dev) {
						const declaration = context.path.findLast(
							(parent) => parent.type === 'ClassDeclaration' || parent.type === 'ClassExpression'
						);
						value = call(
							'$.tag',
							value,
							literal(`${declaration?.id?.name ?? '[class]'}.${name}`)
						);
					}

					return assignment(operator, member(this_instance, field.key), value);
				}
			}

			// special case — assignment to private state field
			if (left.property.type === 'PrivateIdentifier') {
				let value = /** @type {Expression} */ (
					context.visit(build_assignment_value(operator, left, right))
				);

				const needs_proxy =
					field.type === '$state' &&
					is_non_coercive_operator(operator) &&
					should_proxy(value, context.state.scope);

				return call('$.set', left, value, needs_proxy && true_instance);
			}
		}
	}

	let object = left;

	while (object.type === 'MemberExpression') {
		// @ts-expect-error
		object = object.object;
	}

	if (object.type !== 'Identifier') {
		return null;
	}

	const binding = context.state.scope.get(object.name);
	if (!binding) return null;

	const transform = Object.hasOwn(context.state.transform, object.name)
		? context.state.transform[object.name]
		: null;

	const path = context.path.map((node) => node.type);

	// reassignment
	if (object === left && transform?.assign) {
		// special case — if an element binding, we know it's a primitive

		const is_primitive = path.at(-1) === 'BindDirective' && path.at(-2) === 'RegularElement';

		let value = /** @type {Expression} */ (
			context.visit(build_assignment_value(operator, left, right))
		);

		return transform.assign(
			object,
			value,
			!is_primitive &&
				binding.kind !== 'prop' &&
				binding.kind !== 'bindable_prop' &&
				binding.kind !== 'raw_state' &&
				binding.kind !== 'derived' &&
				binding.kind !== 'store_sub' &&
				context.state.analysis.runes &&
				should_proxy(right, context.state.scope) &&
				is_non_coercive_operator(operator)
		);
	}

	// mutation
	if (transform?.mutate) {
		return transform.mutate(
			object,
			assignment(
				operator,
				/** @type {Pattern} */ (context.visit(left)),
				/** @type {Expression} */ (context.visit(right))
			)
		);
	}

	// in cases like `(object.items ??= []).push(value)`, we may need to warn
	// if the value gets proxified, since the proxy _isn't_ the thing that
	// will be pushed to. we do this by transforming it to something like
	// `$.assign_nullish(object, 'items', [])`
	let should_transform =
		dev && path.at(-1) !== 'ExpressionStatement' && is_non_coercive_operator(operator);

	// special case — ignore `onclick={() => (...)}`
	if (
		path.at(-1) === 'ArrowFunctionExpression' &&
		(path.at(-2) === 'RegularElement' || path.at(-2) === 'SvelteElement')
	) {
		const element = /** @type {AST.RegularElement} */ (context.path.at(-2));

		const attribute = element.attributes.find((attribute) => {
			if (attribute.type !== 'Attribute' || !is_event_attribute(attribute)) {
				return false;
			}

			const expression = get_attribute_expression(attribute);

			return expression === context.path.at(-1);
		});

		if (attribute) {
			should_transform = false;
		}
	}

	// special case — ignore `bind:prop={getter, (v) => (...)}` / `bind:value={x.y}`
	if (
		path.at(-1) === 'BindDirective' ||
		path.at(-1) === 'Component' ||
		path.at(-1) === 'SvelteComponent' ||
		(path.at(-1) === 'ArrowFunctionExpression' &&
			(path.at(-2) === 'BindDirective' ||
				(path.at(-2) === 'Component' && path.at(-3) === 'Fragment') ||
				(path.at(-2) === 'SequenceExpression' &&
					(path.at(-3) === 'Component' ||
						path.at(-3) === 'SvelteComponent' ||
						path.at(-3) === 'BindDirective'))))
	) {
		should_transform = false;
	}

	if (left.type === 'MemberExpression' && should_transform) {
		const callee = callees[operator];
		return /** @type {Expression} */ (
			context.visit(
				call(
					callee,
					/** @type {Expression} */ (left.object),
					/** @type {Expression} */ (
						left.computed
							? left.property
							: literal(/** @type {Identifier} */ (left.property).name)
					),
					right,
					literal(locate_node(left))
				)
			)
		);
	}

	return null;
}

/** @import { Expression } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../../types' */

/**
 * @param {AST.Attribute} node
 * @param {ComponentContext} context
 */
function visit_event_attribute(node, context) {
	let capture = false;

	let event_name = node.name.slice(2);
	if (is_capture_event(event_name)) {
		event_name = event_name.slice(0, -7);
		capture = true;
	}

	// we still need to support the weird `onclick="{() => {...}}" form
	const tag = Array.isArray(node.value)
		? /** @type {AST.ExpressionTag} */ (node.value[0])
		: /** @type {AST.ExpressionTag} */ (node.value);

	let handler = build_event_handler(tag.expression, tag.metadata.expression, context);

	if (node.metadata.delegated) {
		if (!context.state.events.has(event_name)) {
			context.state.events.add(event_name);
		}

		context.state.init.push(
			stmt(assignment('=', member(context.state.node, '__' + event_name), handler))
		);
	} else {
		const statement = stmt(
			build_event(
				event_name,
				context.state.node,
				handler,
				capture,
				is_passive_event(event_name) ? true : undefined
			)
		);

		const type = /** @type {AST.SvelteNode} */ (context.path.at(-1)).type;

		if (type === 'SvelteDocument' || type === 'SvelteWindow' || type === 'SvelteBody') {
			// These nodes are above the component tree, and its events should run parent first
			context.state.init.push(statement);
		} else {
			context.state.after_update.push(statement);
		}
	}
}

/**
 * Creates a `$.event(...)` call for non-delegated event handlers
 * @param {string} event_name
 * @param {Expression} node
 * @param {Expression} handler
 * @param {boolean} capture
 * @param {boolean | undefined} passive
 */
function build_event(event_name, node, handler, capture, passive) {
	return call(
		'$.event',
		literal(event_name),
		node,
		handler,
		capture && true_instance,
		passive === undefined ? undefined : literal(passive)
	);
}

/**
 * Creates an event handler
 * @param {Expression | null} node
 * @param {ExpressionMetadata} metadata
 * @param {ComponentContext} context
 * @returns {Expression}
 */
function build_event_handler(node, metadata, context) {
	if (node === null) {
		// bubble event
		return function_builder(
			null,
			[id('$$arg')],
			block([stmt(call('$.bubble_event.call', this_instance, id('$$props'), id('$$arg')))])
		);
	}

	let handler = /** @type {Expression} */ (context.visit(node));

	// inline handler
	if (handler.type === 'ArrowFunctionExpression' || handler.type === 'FunctionExpression') {
		return handler;
	}

	// function declared in the script
	if (handler.type === 'Identifier') {
		const binding = context.state.scope.get(handler.name);

		if (binding?.is_function()) {
			return handler;
		}

		// local variable can be assigned directly
		// except in dev mode where when need $.apply()
		// in order to handle warnings.
		if (!dev && binding?.declaration_kind !== 'import') {
			return handler;
		}
	}

	if (metadata.has_call) {
		// memoize where necessary
		const id$1 = id(context.state.scope.generate('event_handler'));

		context.state.init.push(var_builder(id$1, call('$.derived', thunk(handler))));
		handler = call('$.get', id$1);
	}

	// wrap the handler in a function, so the expression is re-evaluated for each event
	let call$1 = call(member(handler, 'apply', false, true), this_instance, id('$$args'));

	if (dev) {
		const loc = locator(/** @type {number} */ (node.start));

		const remove_parens =
			node.type === 'CallExpression' &&
			node.arguments.length === 0 &&
			node.callee.type === 'Identifier';

		call$1 = call(
			'$.apply',
			thunk(handler),
			this_instance,
			id('$$args'),
			id(context.state.analysis.name),
			loc && array([literal(loc.line), literal(loc.column)]),
			has_side_effects(node) && true_instance,
			remove_parens && true_instance
		);
	}

	return function_builder(null, [rest(id('$$args'))], block([stmt(call$1)]));
}

/**
 * @param {Expression} node
 */
function has_side_effects(node) {
	if (
		node.type === 'CallExpression' ||
		node.type === 'NewExpression' ||
		node.type === 'AssignmentExpression' ||
		node.type === 'UpdateExpression'
	) {
		return true;
	}

	if (node.type === 'SequenceExpression') {
		return node.expressions.some(has_side_effects);
	}

	return false;
}

/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {AST.Attribute} node
 * @param {ComponentContext} context
 */
function Attribute(node, context) {
	if (is_event_attribute(node)) {
		visit_event_attribute(node, context);
	}
}

/** @import { BlockStatement, Pattern, Statement } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentClientTransformState, ComponentContext } from '../types' */

/**
 * @param {AST.AwaitBlock} node
 * @param {ComponentContext} context
 */
function AwaitBlock(node, context) {
	context.state.template.push_comment();

	// Visit {#await <expression>} first to ensure that scopes are in the correct order
	const expression = thunk(
		build_expression(context, node.expression, node.metadata.expression),
		node.metadata.expression.has_await
	);

	let then_block;
	let catch_block;

	if (node.then) {
		const then_context = {
			...context,
			state: { ...context.state, transform: { ...context.state.transform } }
		};
		const argument = node.value && create_derived_block_argument(node.value, then_context);

		/** @type {Pattern[]} */
		const args = [id('$$anchor')];
		if (argument) args.push(argument.id);

		const declarations = argument?.declarations ?? [];
		const block$1 = /** @type {BlockStatement} */ (then_context.visit(node.then, then_context.state));

		then_block = arrow(args, block([...declarations, ...block$1.body]));
	}

	if (node.catch) {
		const catch_context = { ...context, state: { ...context.state } };
		const argument = node.error && create_derived_block_argument(node.error, catch_context);

		/** @type {Pattern[]} */
		const args = [id('$$anchor')];
		if (argument) args.push(argument.id);

		const declarations = argument?.declarations ?? [];
		const block$1 = /** @type {BlockStatement} */ (
			catch_context.visit(node.catch, catch_context.state)
		);

		catch_block = arrow(args, block([...declarations, ...block$1.body]));
	}

	const stmt$1 = add_svelte_meta(
		call(
			'$.await',
			context.state.node,
			expression,
			node.pending
				? arrow([id('$$anchor')], /** @type {BlockStatement} */ (context.visit(node.pending)))
				: null_instance,
			then_block,
			catch_block
		),
		node,
		'await'
	);

	if (node.metadata.expression.has_blockers()) {
		context.state.init.push(
			stmt(
				call(
					'$.async',
					context.state.node,
					node.metadata.expression.blockers(),
					array([]),
					arrow([context.state.node], block([stmt$1]))
				)
			)
		);
	} else {
		context.state.init.push(stmt$1);
	}
}

/**
 * @param {Pattern} node
 * @param {import('zimmerframe').Context<AST.SvelteNode, ComponentClientTransformState>} context
 * @returns {{ id: Pattern, declarations: null | Statement[] }}
 */
function create_derived_block_argument(node, context) {
	if (node.type === 'Identifier') {
		context.state.transform[node.name] = { read: get_value };
		return { id: node, declarations: null };
	}

	const pattern = /** @type {Pattern} */ (context.visit(node));
	const identifiers = extract_identifiers(node);

	const id$1 = id('$$source');
	const value = id('$$value');

	const block$1 = block([
		var_builder(pattern, call('$.get', id$1)),
		return_builder(object$2(identifiers.map((identifier) => prop('init', identifier, identifier))))
	]);

	const declarations = [var_builder(value, create_derived(context.state, block$1))];

	for (const id of identifiers) {
		context.state.transform[id.name] = { read: get_value };

		declarations.push(
			var_builder(id, create_derived(context.state, member(call('$.get', value), id)))
		);
	}

	return { id: id$1, declarations };
}

/** @import { AwaitExpression, Expression } from 'estree' */
/** @import { Context } from '../types' */

/**
 * @param {AwaitExpression} node
 * @param {Context} context
 */
function AwaitExpression(node, context) {
	const argument = /** @type {Expression} */ (context.visit(node.argument));

	if (context.state.analysis.pickled_awaits.has(node)) {
		return save(argument);
	}

	// in dev, note which values are read inside a reactive expression,
	// but don't track them
	else if (dev && !is_ignored(node, 'await_reactivity_loss')) {
		return call(await_builder(call('$.track_reactivity_loss', argument)));
	}

	return argument === node.argument ? node : { ...node, argument };
}

/** @import { Expression, BinaryExpression } from 'estree' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {BinaryExpression} node
 * @param {ComponentContext} context
 */
function BinaryExpression(node, context) {
	if (dev) {
		const operator = node.operator;

		if (operator === '===' || operator === '!==') {
			return call(
				'$.strict_equals',
				/** @type {Expression} */ (context.visit(node.left)),
				/** @type {Expression} */ (context.visit(node.right)),
				operator === '!==' && false_instance
			);
		}

		if (operator === '==' || operator === '!=') {
			return call(
				'$.equals',
				/** @type {Expression} */ (context.visit(node.left)),
				/** @type {Expression} */ (context.visit(node.right)),
				operator === '!=' && false_instance
			);
		}
	}

	context.next();
}

/** @import { Expression } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../../types' */

/**
 * Processes an array of template nodes, joining sibling text/expression nodes
 * (e.g. `{a} b {c}`) into a single update function. Along the way it creates
 * corresponding template node references these updates are applied to.
 * @param {AST.SvelteNode[]} nodes
 * @param {(is_text: boolean) => Expression} initial
 * @param {boolean} is_element
 * @param {ComponentContext} context
 */
function process_children(nodes, initial, is_element, context) {
	const within_bound_contenteditable = context.state.metadata.bound_contenteditable;
	let prev = initial;
	let skipped = 0;

	/** @typedef {Array<AST.Text | AST.ExpressionTag>} Sequence */
	/** @type {Sequence} */
	let sequence = [];

	/** @param {boolean} is_text */
	function get_node(is_text) {
		if (skipped === 0) {
			return prev(is_text);
		}

		return call(
			'$.sibling',
			prev(false),
			(is_text || skipped !== 1) && literal(skipped),
			is_text && true_instance
		);
	}

	/**
	 * @param {boolean} is_text
	 * @param {string} name
	 */
	function flush_node(is_text, name) {
		const expression = get_node(is_text);
		let id$1 = expression;

		if (id$1.type !== 'Identifier') {
			id$1 = id(context.state.scope.generate(name));
			context.state.init.push(var_builder(id$1, expression));
		}

		prev = () => id$1;
		skipped = 1; // the next node is `$.sibling(id)`

		return id$1;
	}

	/**
	 * @param {Sequence} sequence
	 */
	function flush_sequence(sequence) {
		if (sequence.every((node) => node.type === 'Text')) {
			skipped += 1;
			context.state.template.push_text(sequence);
			return;
		}

		context.state.template.push_text([{ type: 'Text', data: ' ', raw: ' ', start: -1, end: -1 }]);

		const { has_state, value } = build_template_chunk(sequence, context);

		// if this is a standalone `{expression}`, make sure we handle the case where
		// no text node was created because the expression was empty during SSR
		const is_text = sequence.length === 1;
		const id = flush_node(is_text, 'text');

		const update = stmt(call('$.set_text', id, value));

		if (has_state && !within_bound_contenteditable) {
			context.state.update.push(update);
		} else {
			context.state.init.push(stmt(assignment('=', member(id, 'nodeValue'), value)));
		}
	}

	for (const node of nodes) {
		if (node.type === 'Text' || node.type === 'ExpressionTag') {
			sequence.push(node);
		} else {
			if (sequence.length > 0) {
				flush_sequence(sequence);
				sequence = [];
			}

			let child_state = context.state;

			if (is_static_element(node, context.state)) {
				skipped += 1;
			} else if (
				node.type === 'EachBlock' &&
				nodes.length === 1 &&
				is_element &&
				// In case it's wrapped in async the async logic will want to skip sibling nodes up until the end, hence we cannot make this controlled
				// TODO switch this around and instead optimize for elements with a single block child and not require extra comments (neither for async nor normally)
				!node.metadata.expression.is_async()
			) {
				node.metadata.is_controlled = true;
			} else {
				const id = flush_node(false, node.type === 'RegularElement' ? node.name : 'node');
				child_state = { ...context.state, node: id };
			}

			context.visit(node, child_state);
		}
	}

	if (sequence.length > 0) {
		flush_sequence(sequence);
	}

	// if there are trailing static text nodes/elements,
	// traverse to the last (n - 1) one when hydrating
	if (skipped > 1) {
		skipped -= 1;
		context.state.init.push(stmt(call('$.next', skipped !== 1 && literal(skipped))));
	}
}

/**
 * @param {AST.SvelteNode} node
 * @param {ComponentContext["state"]} state
 */
function is_static_element(node, state) {
	if (node.type !== 'RegularElement') return false;
	if (node.fragment.metadata.dynamic) return false;
	if (is_custom_element_node(node)) return false; // we're setting all attributes on custom elements through properties

	for (const attribute of node.attributes) {
		if (attribute.type !== 'Attribute') {
			return false;
		}

		if (is_event_attribute(attribute)) {
			return false;
		}

		if (cannot_be_set_statically(attribute.name)) {
			return false;
		}

		if (attribute.name === 'dir') {
			return false;
		}

		if (
			['input', 'textarea'].includes(node.name) &&
			['value', 'checked'].includes(attribute.name)
		) {
			return false;
		}

		if (node.name === 'option' && attribute.name === 'value') {
			return false;
		}

		// We need to apply src and loading after appending the img to the DOM for lazy loading to work
		if (node.name === 'img' && attribute.name === 'loading') {
			return false;
		}

		if (attribute.value !== true && !is_text_attribute(attribute)) {
			return false;
		}
	}

	return true;
}

/** @import { ArrayExpression, Expression, ExpressionStatement, Identifier, MemberExpression, ObjectExpression } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentClientTransformState, ComponentContext } from '../types' */
/** @import { Scope } from '../../../scope' */

/**
 * @param {AST.RegularElement} node
 * @param {ComponentContext} context
 */
function RegularElement(node, context) {
	context.state.template.push_element(node.name, node.start);

	if (node.name === 'noscript') {
		context.state.template.pop_element();
		return;
	}

	const is_custom_element = is_custom_element_node(node);

	// cloneNode is faster, but it does not instantiate the underlying class of the
	// custom element until the template is connected to the dom, which would
	// cause problems when setting properties on the custom element.
	// Therefore we need to use importNode instead, which doesn't have this caveat.
	// Additionally, Webkit browsers need importNode for video elements for autoplay
	// to work correctly.
	context.state.template.needs_import_node ||= node.name === 'video' || is_custom_element;

	context.state.template.contains_script_tag ||= node.name === 'script';

	/** @type {Array<AST.Attribute | AST.SpreadAttribute>} */
	const attributes = [];

	/** @type {AST.ClassDirective[]} */
	const class_directives = [];

	/** @type {AST.StyleDirective[]} */
	const style_directives = [];

	/** @type {Array<AST.AnimateDirective | AST.BindDirective | AST.OnDirective | AST.TransitionDirective | AST.UseDirective | AST.AttachTag>} */
	const other_directives = [];

	/** @type {ExpressionStatement[]} */
	const lets = [];

	/** @type {Map<string, AST.Attribute>} */
	const lookup = new Map();

	/** @type {Map<string, AST.BindDirective>} */
	const bindings = new Map();

	let has_spread = node.metadata.has_spread;
	let has_use = false;
	let should_remove_defaults = false;

	for (const attribute of node.attributes) {
		switch (attribute.type) {
			case 'AnimateDirective':
				other_directives.push(attribute);
				break;

			case 'Attribute':
				// `is` attributes need to be part of the template, otherwise they break
				if (attribute.name === 'is' && context.state.metadata.namespace === 'html') {
					const { value } = build_attribute_value(attribute.value, context);

					if (value.type === 'Literal' && typeof value.value === 'string') {
						context.state.template.set_prop('is', value.value);
						continue;
					}
				}

				attributes.push(attribute);
				lookup.set(attribute.name, attribute);
				break;

			case 'BindDirective':
				bindings.set(attribute.name, attribute);
				other_directives.push(attribute);
				break;

			case 'ClassDirective':
				class_directives.push(attribute);
				break;

			case 'LetDirective':
				// visit let directives before everything else, to set state
				context.visit(attribute, { ...context.state, let_directives: lets });
				break;

			case 'OnDirective':
				other_directives.push(attribute);
				break;

			case 'SpreadAttribute':
				attributes.push(attribute);
				break;

			case 'StyleDirective':
				style_directives.push(attribute);
				break;

			case 'TransitionDirective':
				other_directives.push(attribute);
				break;

			case 'UseDirective':
				has_use = true;
				other_directives.push(attribute);
				break;

			case 'AttachTag':
				other_directives.push(attribute);
				break;
		}
	}

	/** @type {typeof state} */
	const element_state = { ...context.state, init: [], after_update: [] };

	for (const attribute of other_directives) {
		if (attribute.type === 'OnDirective') {
			const handler = /** @type {Expression} */ (context.visit(attribute));

			if (has_use) {
				element_state.init.push(stmt(call('$.effect', thunk(handler))));
			} else {
				element_state.after_update.push(stmt(handler));
			}
		} else {
			context.visit(attribute, element_state);
		}
	}

	if (node.name === 'input') {
		const has_value_attribute = attributes.some(
			(attribute) =>
				attribute.type === 'Attribute' &&
				(attribute.name === 'value' || attribute.name === 'checked') &&
				!is_text_attribute(attribute)
		);
		const has_default_value_attribute = attributes.some(
			(attribute) =>
				attribute.type === 'Attribute' &&
				(attribute.name === 'defaultValue' || attribute.name === 'defaultChecked')
		);
		if (
			!has_default_value_attribute &&
			(has_spread ||
				bindings.has('value') ||
				bindings.has('checked') ||
				bindings.has('group') ||
				(!bindings.has('group') && has_value_attribute))
		) {
			if (has_spread) {
				// remove_input_defaults will be called inside set_attributes
				should_remove_defaults = true;
			} else {
				context.state.init.push(stmt(call('$.remove_input_defaults', context.state.node)));
			}
		}
	}

	if (node.name === 'textarea') {
		const attribute = lookup.get('value') ?? lookup.get('checked');
		const needs_content_reset = attribute && !is_text_attribute(attribute);

		if (has_spread || bindings.has('value') || needs_content_reset) {
			context.state.init.push(stmt(call('$.remove_textarea_child', context.state.node)));
		}
	}

	if (node.name === 'select' && bindings.has('value')) {
		setup_select_synchronization(/** @type {AST.BindDirective} */ (bindings.get('value')), context);
	}

	// Let bindings first, they can be used on attributes
	context.state.init.push(...lets);

	const node_id = context.state.node;

	/** If true, needs `__value` for inputs */
	const needs_special_value_handling =
		node.name === 'option' ||
		node.name === 'select' ||
		bindings.has('group') ||
		bindings.has('checked');

	if (has_spread) {
		build_attribute_effect(
			attributes,
			class_directives,
			style_directives,
			context,
			node,
			node_id,
			should_remove_defaults
		);
	} else {
		for (const attribute of /** @type {AST.Attribute[]} */ (attributes)) {
			if (is_event_attribute(attribute)) {
				visit_event_attribute(attribute, context);
				continue;
			}

			if (needs_special_value_handling && attribute.name === 'value') {
				continue;
			}

			const name = get_attribute_name(node, attribute);

			if (
				!is_custom_element &&
				!cannot_be_set_statically(attribute.name) &&
				(attribute.value === true || is_text_attribute(attribute)) &&
				(name !== 'class' || class_directives.length === 0) &&
				(name !== 'style' || style_directives.length === 0)
			) {
				let value = is_text_attribute(attribute) ? attribute.value[0].data : true;

				if (name === 'class' && node.metadata.scoped && context.state.analysis.css.hash) {
					if (value === true || value === '') {
						value = context.state.analysis.css.hash;
					} else {
						value += ' ' + context.state.analysis.css.hash;
					}
				}

				if (name !== 'class' || value) {
					context.state.template.set_prop(
						attribute.name,
						is_boolean_attribute(name) && value === true ? undefined : value === true ? '' : value
					);
				}
			} else if (name === 'autofocus') {
				let { value } = build_attribute_value(attribute.value, context);
				context.state.init.push(stmt(call('$.autofocus', node_id, value)));
			} else if (name === 'class') {
				const is_html = context.state.metadata.namespace === 'html' && node.name !== 'svg';
				build_set_class(node, node_id, attribute, class_directives, context, is_html);
			} else if (name === 'style') {
				build_set_style(node_id, attribute, style_directives, context);
			} else if (is_custom_element) {
				build_custom_element_attribute_update_assignment(node_id, attribute, context);
			} else {
				const { value, has_state } = build_attribute_value(
					attribute.value,
					context,
					(value, metadata) => context.state.memoizer.add(value, metadata)
				);

				const update = build_element_attribute_update(node, node_id, name, value, attributes);

				(has_state ? context.state.update : context.state.init).push(stmt(update));
			}
		}
	}

	if (
		is_load_error_element(node.name) &&
		(has_spread || has_use || lookup.has('onload') || lookup.has('onerror'))
	) {
		context.state.after_update.push(stmt(call('$.replay_events', node_id)));
	}

	const metadata = {
		...context.state.metadata,
		namespace: determine_namespace_for_children(node, context.state.metadata.namespace)
	};

	if (bindings.has('innerHTML') || bindings.has('innerText') || bindings.has('textContent')) {
		const contenteditable = lookup.get('contenteditable');

		if (
			contenteditable &&
			(contenteditable.value === true ||
				(is_text_attribute(contenteditable) && contenteditable.value[0].data === 'true'))
		) {
			metadata.bound_contenteditable = true;
		}
	}

	/** @type {ComponentClientTransformState} */
	const state = {
		...context.state,
		metadata,
		scope: /** @type {Scope} */ (context.state.scopes.get(node.fragment)),
		preserve_whitespace:
			context.state.preserve_whitespace || node.name === 'pre' || node.name === 'textarea'
	};

	const { hoisted, trimmed } = clean_nodes(
		node,
		node.fragment.nodes,
		context.path,
		state.metadata.namespace,
		state,
		node.name === 'script' || state.preserve_whitespace,
		state.options.preserveComments
	);

	/** @type {typeof state} */
	const child_state = { ...state, init: [], update: [], after_update: [] };

	for (const node of hoisted) {
		context.visit(node, child_state);
	}

	// special case — if an element that only contains text, we don't need
	// to descend into it if the text is non-reactive
	// in the rare case that we have static text that can't be inlined
	// (e.g. `<span>{location}</span>`), set `textContent` programmatically
	const use_text_content =
		trimmed.every((node) => node.type === 'Text' || node.type === 'ExpressionTag') &&
		trimmed.every(
			(node) =>
				node.type === 'Text' ||
				(!node.metadata.expression.has_state && !node.metadata.expression.has_await)
		) &&
		trimmed.some((node) => node.type === 'ExpressionTag');

	if (use_text_content) {
		const { value } = build_template_chunk(trimmed, context, child_state);
		const empty_string = value.type === 'Literal' && value.value === '';

		if (!empty_string) {
			child_state.init.push(
				stmt(assignment('=', member(context.state.node, 'textContent'), value))
			);
		}
	} else {
		/** @type {Expression} */
		let arg = context.state.node;

		// If `hydrate_node` is set inside the element, we need to reset it
		// after the element has been hydrated
		let needs_reset = trimmed.some((node) => node.type !== 'Text');

		// The same applies if it's a `<template>` element, since we need to
		// set the value of `hydrate_node` to `node.content`
		if (node.name === 'template') {
			needs_reset = true;
			child_state.init.push(stmt(call('$.hydrate_template', arg)));
			arg = member(arg, 'content');
		}

		process_children(trimmed, (is_text) => call('$.child', arg, is_text && true_instance), true, {
			...context,
			state: child_state
		});

		if (needs_reset) {
			child_state.init.push(stmt(call('$.reset', context.state.node)));
		}
	}

	if (node.fragment.nodes.some((node) => node.type === 'SnippetBlock')) {
		// Wrap children in `{...}` to avoid declaration conflicts
		context.state.init.push(
			block([
				...child_state.init,
				...element_state.init,
				child_state.update.length > 0 ? build_render_statement(child_state) : empty,
				...child_state.after_update,
				...element_state.after_update
			])
		);
	} else if (node.fragment.metadata.dynamic) {
		context.state.init.push(...child_state.init, ...element_state.init);
		context.state.update.push(...child_state.update);
		context.state.after_update.push(...child_state.after_update, ...element_state.after_update);
	} else {
		context.state.init.push(...element_state.init);
		context.state.after_update.push(...element_state.after_update);
	}

	if (lookup.has('dir')) {
		// This fixes an issue with Chromium where updates to text content within an element
		// does not update the direction when set to auto. If we just re-assign the dir, this fixes it.
		const dir = member(node_id, 'dir');
		context.state.update.push(stmt(assignment('=', dir, dir)));
	}

	if (!has_spread && needs_special_value_handling) {
		if (node.metadata.synthetic_value_node) {
			const synthetic_node = node.metadata.synthetic_value_node;
			const synthetic_attribute = create_attribute(
				'value',
				synthetic_node.start,
				synthetic_node.end,
				[synthetic_node]
			);
			// this node is an `option` that didn't have a `value` attribute, but had
			// a single-expression child, so we treat the value of that expression as
			// the value of the option
			build_element_special_value_attribute(node.name, node_id, synthetic_attribute, context, true);
		} else {
			for (const attribute of /** @type {AST.Attribute[]} */ (attributes)) {
				if (attribute.name === 'value') {
					build_element_special_value_attribute(node.name, node_id, attribute, context);
					break;
				}
			}
		}
	}

	context.state.template.pop_element();
}

/**
 * Special case: if we have a value binding on a select element, we need to set up synchronization
 * between the value binding and inner signals, for indirect updates
 * @param {AST.BindDirective} value_binding
 * @param {ComponentContext} context
 */
function setup_select_synchronization(value_binding, context) {
	if (context.state.analysis.runes) return;

	let bound = value_binding.expression;

	if (bound.type === 'SequenceExpression') {
		return;
	}

	while (bound.type === 'MemberExpression') {
		bound = /** @type {Identifier | MemberExpression} */ (bound.object);
	}

	/** @type {string[]} */
	const names = [];

	for (const [name, refs] of context.state.scope.references) {
		if (
			refs.length > 0 &&
			// prevent infinite loop
			name !== bound.name
		) {
			names.push(name);
		}
	}

	const invalidator = call(
		'$.invalidate_inner_signals',
		thunk(
			block(
				names.map((name) => {
					const serialized = build_getter$1(id(name), context.state);
					return stmt(serialized);
				})
			)
		)
	);

	context.state.init.push(
		stmt(
			call(
				'$.template_effect',
				thunk(
					block([stmt(/** @type {Expression} */ (context.visit(bound))), stmt(invalidator)])
				)
			)
		)
	);
}

/**
 * @param {AST.ClassDirective[]} class_directives
 * @param {ComponentContext} context
 * @param {Memoizer} memoizer
 */
function build_class_directives_object(
	class_directives,
	context,
	memoizer = context.state.memoizer
) {
	let properties = [];

	const metadata = new ExpressionMetadata();

	for (const d of class_directives) {
		metadata.merge(d.metadata.expression);

		const expression = /** @type Expression */ (context.visit(d.expression));
		properties.push(init(d.name, expression));
	}

	const directives = object$2(properties);

	return memoizer.add(directives, metadata);
}

/**
 * @param {AST.StyleDirective[]} style_directives
 * @param {ComponentContext} context
 * @param {Memoizer} memoizer
 */
function build_style_directives_object(
	style_directives,
	context,
	memoizer = context.state.memoizer
) {
	const normal = object$2([]);
	const important = object$2([]);

	const metadata = new ExpressionMetadata();

	for (const d of style_directives) {
		metadata.merge(d.metadata.expression);

		const expression =
			d.value === true
				? build_getter$1(id(d.name), context.state)
				: build_attribute_value(d.value, context).value;

		const object = d.modifiers.includes('important') ? important : normal;
		object.properties.push(init(d.name, expression));
	}

	const directives = important.properties.length ? array([normal, important]) : normal;

	return memoizer.add(directives, metadata);
}

/**
 * Serializes an assignment to an element property by adding relevant statements to either only
 * the init or the init and update arrays, depending on whether or not the value is dynamic.
 * Resulting code for static looks something like this:
 * ```js
 * element.property = value;
 * // or
 * $.set_attribute(element, property, value);
 * });
 * ```
 * Resulting code for dynamic looks something like this:
 * ```js
 * let value;
 * $.template_effect(() => {
 * 	if (value !== (value = 'new value')) {
 * 		element.property = value;
 * 		// or
 * 		$.set_attribute(element, property, value);
 * 	}
 * });
 * ```
 * Returns true if attribute is deemed reactive, false otherwise.
 * @param {AST.RegularElement} element
 * @param {Identifier} node_id
 * @param {string} name
 * @param {Expression} value
 * @param {Array<AST.Attribute | AST.SpreadAttribute>} attributes
 */
function build_element_attribute_update(element, node_id, name, value, attributes) {
	if (name === 'muted') {
		// Special case for Firefox who needs it set as a property in order to work
		return assignment('=', member(node_id, id('muted')), value);
	}

	if (name === 'value') {
		return call('$.set_value', node_id, value);
	}

	if (name === 'checked') {
		return call('$.set_checked', node_id, value);
	}

	if (name === 'selected') {
		return call('$.set_selected', node_id, value);
	}

	if (
		// If we would just set the defaultValue property, it would override the value property,
		// because it is set in the template which implicitly means it's also setting the default value,
		// and if one updates the default value while the input is pristine it will also update the
		// current value, which is not what we want, which is why we need to do some extra work.
		name === 'defaultValue' &&
		(attributes.some(
			(attr) => attr.type === 'Attribute' && attr.name === 'value' && is_text_attribute(attr)
		) ||
			(element.name === 'textarea' && element.fragment.nodes.length > 0))
	) {
		return call('$.set_default_value', node_id, value);
	}

	if (
		// See defaultValue comment
		name === 'defaultChecked' &&
		attributes.some(
			(attr) => attr.type === 'Attribute' && attr.name === 'checked' && attr.value === true
		)
	) {
		return call('$.set_default_checked', node_id, value);
	}

	if (is_dom_property(name)) {
		return assignment('=', member(node_id, name), value);
	}

	return call(
		name.startsWith('xlink') ? '$.set_xlink_attribute' : '$.set_attribute',
		node_id,
		literal(name),
		value,
		is_ignored(element, 'hydration_attribute_changed') && true_instance
	);
}

/**
 * Like `build_element_attribute_update` but without any special attribute treatment.
 * @param {Identifier}	node_id
 * @param {AST.Attribute} attribute
 * @param {ComponentContext} context
 */
function build_custom_element_attribute_update_assignment(node_id, attribute, context) {
	const { value, has_state } = build_attribute_value(attribute.value, context);

	// don't lowercase name, as we set the element's property, which might be case sensitive
	const call$1 = call('$.set_custom_element_data', node_id, literal(attribute.name), value);

	// this is different from other updates — it doesn't get grouped,
	// because set_custom_element_data may not be idempotent
	const update = has_state ? call('$.template_effect', thunk(call$1)) : call$1;

	context.state.init.push(stmt(update));
}

/**
 * Serializes an assignment to the value property of a `<select>`, `<option>` or `<input>` element
 * that needs the hidden `__value` property.
 * Returns true if attribute is deemed reactive, false otherwise.
 * @param {string} element
 * @param {Identifier} node_id
 * @param {AST.Attribute} attribute
 * @param {ComponentContext} context
 * @param {boolean} [synthetic] - true if this should not sync to the DOM
 */
function build_element_special_value_attribute(
	element,
	node_id,
	attribute,
	context,
	synthetic = false
) {
	const state = context.state;
	const is_select_with_value =
		// attribute.metadata.dynamic would give false negatives because even if the value does not change,
		// the inner options could still change, so we need to always treat it as reactive
		element === 'select' && attribute.value !== true && !is_text_attribute(attribute);

	const { value, has_state } = build_attribute_value(attribute.value, context, (value, metadata) =>
		state.memoizer.add(value, metadata)
	);

	const evaluated = context.state.scope.evaluate(value);
	const assignment$1 = assignment('=', member(node_id, '__value'), value);

	const set_value_assignment = assignment(
		'=',
		member(node_id, 'value'),
		evaluated.is_defined ? assignment$1 : logical$1('??', assignment$1, literal(''))
	);

	const update = stmt(
		is_select_with_value
			? sequence([
					set_value_assignment,
					// This ensures a one-way street to the DOM in case it's <select {value}>
					// and not <select bind:value>. We need it in addition to $.init_select
					// because the select value is not reflected as an attribute, so the
					// mutation observer wouldn't notice.
					call('$.select_option', node_id, value)
				])
			: synthetic
				? assignment$1
				: set_value_assignment
	);

	if (has_state) {
		const id$1 = id(state.scope.generate(`${node_id.name}_value`));

		// `<option>` is a special case: The value property reflects to the DOM. If the value is set to undefined,
		// that means the value should be set to the empty string. To be able to do that when the value is
		// initially undefined, we need to set a value that is guaranteed to be different.
		const init = element === 'option' ? object$2([]) : undefined;

		state.init.push(var_builder(id$1, init));
		state.update.push(if_builder(binary$1('!==', id$1, assignment('=', id$1, value)), block([update])));
	} else {
		state.init.push(update);
	}

	if (is_select_with_value) {
		state.init.push(stmt(call('$.init_select', node_id)));
	}
}

/** @import { Expression, Identifier, ObjectExpression } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../../types' */

/**
 * @param {Array<AST.Attribute | AST.SpreadAttribute>} attributes
 * @param {AST.ClassDirective[]} class_directives
 * @param {AST.StyleDirective[]} style_directives
 * @param {ComponentContext} context
 * @param {AST.RegularElement | AST.SvelteElement} element
 * @param {Identifier} element_id
 * @param {boolean} [should_remove_defaults]
 */
function build_attribute_effect(
	attributes,
	class_directives,
	style_directives,
	context,
	element,
	element_id,
	should_remove_defaults = false
) {
	/** @type {ObjectExpression['properties']} */
	const values = [];

	const memoizer = new Memoizer();

	for (const attribute of attributes) {
		if (attribute.type === 'Attribute') {
			const { value } = build_attribute_value(attribute.value, context, (value, metadata) =>
				memoizer.add(value, metadata)
			);

			if (
				is_event_attribute(attribute) &&
				(value.type === 'ArrowFunctionExpression' || value.type === 'FunctionExpression')
			) {
				// Give the event handler a stable ID so it isn't removed and readded on every update
				const id$1 = context.state.scope.generate('event_handler');
				context.state.init.push(var_builder(id$1, value));
				values.push(init(attribute.name, id(id$1)));
			} else {
				values.push(init(attribute.name, value));
			}
		} else {
			let value = /** @type {Expression} */ (context.visit(attribute));

			value = memoizer.add(value, attribute.metadata.expression);

			values.push(spread(value));
		}
	}

	if (class_directives.length) {
		values.push(
			prop(
				'init',
				array([id('$.CLASS')]),
				build_class_directives_object(class_directives, context, memoizer)
			)
		);
	}

	if (style_directives.length) {
		values.push(
			prop(
				'init',
				array([id('$.STYLE')]),
				build_style_directives_object(style_directives, context, memoizer)
			)
		);
	}

	const ids = memoizer.apply();

	context.state.init.push(
		stmt(
			call(
				'$.attribute_effect',
				element_id,
				arrow(ids, object$2(values)),
				memoizer.sync_values(),
				memoizer.async_values(),
				memoizer.blockers(),
				element.metadata.scoped &&
					context.state.analysis.css.hash !== '' &&
					literal(context.state.analysis.css.hash),
				should_remove_defaults && true_instance,
				is_ignored(element, 'hydration_attribute_changed') && true_instance
			)
		)
	);
}

/**
 * @param {AST.Attribute['value']} value
 * @param {ComponentContext} context
 * @param {(value: Expression, metadata: ExpressionMetadata) => Expression} memoize
 * @returns {{ value: Expression, has_state: boolean }}
 */
function build_attribute_value(value, context, memoize = (value) => value) {
	if (value === true) {
		return { value: true_instance, has_state: false };
	}

	if (!Array.isArray(value) || value.length === 1) {
		const chunk = Array.isArray(value) ? value[0] : value;

		if (chunk.type === 'Text') {
			return { value: literal(chunk.data), has_state: false };
		}

		let expression = build_expression(context, chunk.expression, chunk.metadata.expression);

		return {
			value: memoize(expression, chunk.metadata.expression),
			has_state: chunk.metadata.expression.has_state || chunk.metadata.expression.is_async()
		};
	}

	return build_template_chunk(value, context, context.state, memoize);
}

/**
 * @param {AST.RegularElement | AST.SvelteElement} element
 * @param {AST.Attribute} attribute
 */
function get_attribute_name(element, attribute) {
	if (!element.metadata.svg && !element.metadata.mathml) {
		return normalize_attribute(attribute.name);
	}

	return attribute.name;
}

/**
 * @param {AST.RegularElement | AST.SvelteElement} element
 * @param {Identifier} node_id
 * @param {AST.Attribute} attribute
 * @param {AST.ClassDirective[]} class_directives
 * @param {ComponentContext} context
 * @param {boolean} is_html
 */
function build_set_class(element, node_id, attribute, class_directives, context, is_html) {
	let { value, has_state } = build_attribute_value(attribute.value, context, (value, metadata) => {
		if (attribute.metadata.needs_clsx) {
			value = call('$.clsx', value);
		}

		return context.state.memoizer.add(value, metadata);
	});

	/** @type {Identifier | undefined} */
	let previous_id;

	/** @type {ObjectExpression | Identifier | undefined} */
	let prev;

	/** @type {Expression | undefined} */
	let next;

	if (class_directives.length) {
		next = build_class_directives_object(class_directives, context);
		has_state ||= class_directives.some(
			(d) => d.metadata.expression.has_state || d.metadata.expression.is_async()
		);

		if (has_state) {
			previous_id = id(context.state.scope.generate('classes'));
			context.state.init.push(declaration('let', [declarator(previous_id)]));
			prev = previous_id;
		} else {
			prev = object$2([]);
		}
	}

	/** @type {Expression | undefined} */
	let css_hash;

	if (element.metadata.scoped && context.state.analysis.css.hash) {
		if (value.type === 'Literal' && (value.value === '' || value.value === null)) {
			value = literal(context.state.analysis.css.hash);
		} else if (value.type === 'Literal' && typeof value.value === 'string') {
			value = literal(escape_html(value.value, true) + ' ' + context.state.analysis.css.hash);
		} else {
			css_hash = literal(context.state.analysis.css.hash);
		}
	}

	if (!css_hash && next) {
		css_hash = null_instance;
	}

	/** @type {Expression} */
	let set_class = call(
		'$.set_class',
		node_id,
		is_html ? literal(1) : literal(0),
		value,
		css_hash,
		prev,
		next
	);

	if (previous_id) {
		set_class = assignment('=', previous_id, set_class);
	}

	(has_state ? context.state.update : context.state.init).push(stmt(set_class));
}

/**
 * @param {Identifier} node_id
 * @param {AST.Attribute} attribute
 * @param {AST.StyleDirective[]} style_directives
 * @param {ComponentContext} context
 */
function build_set_style(node_id, attribute, style_directives, context) {
	let { value, has_state } = build_attribute_value(attribute.value, context, (value, metadata) =>
		context.state.memoizer.add(value, metadata)
	);

	/** @type {Identifier | undefined} */
	let previous_id;

	/** @type {ObjectExpression | Identifier | undefined} */
	let prev;

	/** @type {Expression | undefined} */
	let next;

	if (style_directives.length) {
		next = build_style_directives_object(style_directives, context);
		has_state ||= style_directives.some(
			(d) => d.metadata.expression.has_state || d.metadata.expression.is_async()
		);

		if (has_state) {
			previous_id = id(context.state.scope.generate('styles'));
			context.state.init.push(declaration('let', [declarator(previous_id)]));
			prev = previous_id;
		} else {
			prev = object$2([]);
		}
	}

	/** @type {Expression} */
	let set_style = call('$.set_style', node_id, value, prev, next);

	if (previous_id) {
		set_style = assignment('=', previous_id, set_style);
	}

	(has_state ? context.state.update : context.state.init).push(stmt(set_style));
}

/** @import { CallExpression, Expression, Pattern } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {AST.BindDirective} node
 * @param {ComponentContext} context
 */
function BindDirective(node, context) {
	const expression = /** @type {Expression} */ (context.visit(node.expression));
	const property = binding_properties[node.name];

	const parent = /** @type {AST.SvelteNode} */ (context.path.at(-1));

	let get, set;

	if (expression.type === 'SequenceExpression') {
		[get, set] = expression.expressions;
	} else {
		if (
			dev &&
			context.state.analysis.runes &&
			expression.type === 'MemberExpression' &&
			(node.name !== 'this' ||
				context.path.some(
					({ type }) =>
						type === 'IfBlock' ||
						type === 'EachBlock' ||
						type === 'AwaitBlock' ||
						type === 'KeyBlock'
				)) &&
			!is_ignored(node, 'binding_property_non_reactive')
		) {
			validate_binding(context.state, node, expression);
		}

		get = thunk(expression);

		/** @type {Expression | undefined} */
		set = unthunk(
			arrow(
				[id('$$value')],
				/** @type {Expression} */ (
					context.visit(
						assignment('=', /** @type {Pattern} */ (node.expression), id('$$value'))
					)
				)
			)
		);

		if (get === set) {
			set = undefined;
		}
	}

	/** @type {CallExpression} */
	let call$1;

	if (property?.event) {
		call$1 = call(
			'$.bind_property',
			literal(node.name),
			literal(property.event),
			context.state.node,
			set ?? get,
			property.bidirectional && get
		);
	} else {
		// special cases
		switch (node.name) {
			// window
			case 'online':
				call$1 = call(`$.bind_online`, set ?? get);
				break;

			case 'scrollX':
			case 'scrollY':
				call$1 = call(
					'$.bind_window_scroll',
					literal(node.name === 'scrollX' ? 'x' : 'y'),
					get,
					set
				);
				break;

			case 'innerWidth':
			case 'innerHeight':
			case 'outerWidth':
			case 'outerHeight':
				call$1 = call('$.bind_window_size', literal(node.name), set ?? get);
				break;

			// document
			case 'activeElement':
				call$1 = call('$.bind_active_element', set ?? get);
				break;

			// media
			case 'muted':
				call$1 = call(`$.bind_muted`, context.state.node, get, set);
				break;
			case 'paused':
				call$1 = call(`$.bind_paused`, context.state.node, get, set);
				break;
			case 'volume':
				call$1 = call(`$.bind_volume`, context.state.node, get, set);
				break;
			case 'playbackRate':
				call$1 = call(`$.bind_playback_rate`, context.state.node, get, set);
				break;
			case 'currentTime':
				call$1 = call(`$.bind_current_time`, context.state.node, get, set);
				break;
			case 'buffered':
				call$1 = call(`$.bind_buffered`, context.state.node, set ?? get);
				break;
			case 'played':
				call$1 = call(`$.bind_played`, context.state.node, set ?? get);
				break;
			case 'seekable':
				call$1 = call(`$.bind_seekable`, context.state.node, set ?? get);
				break;
			case 'seeking':
				call$1 = call(`$.bind_seeking`, context.state.node, set ?? get);
				break;
			case 'ended':
				call$1 = call(`$.bind_ended`, context.state.node, set ?? get);
				break;
			case 'readyState':
				call$1 = call(`$.bind_ready_state`, context.state.node, set ?? get);
				break;

			// dimensions
			case 'contentRect':
			case 'contentBoxSize':
			case 'borderBoxSize':
			case 'devicePixelContentBoxSize':
				call$1 = call(
					'$.bind_resize_observer',
					context.state.node,
					literal(node.name),
					set ?? get
				);
				break;

			case 'clientWidth':
			case 'clientHeight':
			case 'offsetWidth':
			case 'offsetHeight':
				call$1 = call('$.bind_element_size', context.state.node, literal(node.name), set ?? get);
				break;

			// various
			case 'value': {
				if (parent?.type === 'RegularElement' && parent.name === 'select') {
					call$1 = call(`$.bind_select_value`, context.state.node, get, set);
				} else {
					call$1 = call(`$.bind_value`, context.state.node, get, set);
				}
				break;
			}

			case 'files':
				call$1 = call(`$.bind_files`, context.state.node, get, set);
				break;

			case 'this':
				call$1 = build_bind_this(node.expression, context.state.node, context);
				break;

			case 'textContent':
			case 'innerHTML':
			case 'innerText':
				call$1 = call(
					'$.bind_content_editable',
					literal(node.name),
					context.state.node,
					get,
					set
				);
				break;

			// checkbox/radio
			case 'checked':
				call$1 = call(`$.bind_checked`, context.state.node, get, set);
				break;

			case 'focused':
				call$1 = call(`$.bind_focused`, context.state.node, set ?? get);
				break;

			case 'group': {
				const indexes = node.metadata.parent_each_blocks.map((each) => {
					// if we have a keyed block with an index, the index is wrapped in a source
					return each.metadata.keyed && each.index
						? call('$.get', each.metadata.index)
						: each.metadata.index;
				});

				// We need to additionally invoke the value attribute signal to register it as a dependency,
				// so that when the value is updated, the group binding is updated
				let group_getter = get;

				if (parent?.type === 'RegularElement') {
					const value = /** @type {any[]} */ (
						/** @type {AST.Attribute} */ (
							parent.attributes.find(
								(a) =>
									a.type === 'Attribute' &&
									a.name === 'value' &&
									!is_text_attribute(a) &&
									a.value !== true
							)
						)?.value
					);

					if (value !== undefined) {
						group_getter = thunk(
							block([stmt(build_attribute_value(value, context).value), return_builder(expression)])
						);
					}
				}

				call$1 = call(
					'$.bind_group',
					node.metadata.binding_group_name,
					array(indexes),
					context.state.node,
					group_getter,
					set ?? get
				);
				break;
			}

			default:
				throw new Error('unknown binding ' + node.name);
		}
	}

	const defer =
		node.name !== 'this' &&
		parent.type === 'RegularElement' &&
		parent.attributes.find((a) => a.type === 'UseDirective');

	let statement = defer ? stmt(call('$.effect', thunk(call$1))) : stmt(call$1);

	if (node.metadata.expression.is_async()) {
		statement = stmt(
			call(
				'$.run_after_blockers',
				node.metadata.expression.blockers(),
				thunk(block([statement]))
			)
		);
	}

	// Bindings need to happen after attribute updates, therefore after the render effect, and in order with events/actions.
	// bind:this is a special case as it's one-way and could influence the render effect.
	if (node.name === 'this') {
		context.state.init.push(statement);
	} else {
		if (defer) {
			context.state.init.push(statement);
		} else {
			context.state.after_update.push(statement);
		}
	}
}

/** @import { ArrowFunctionExpression, BlockStatement, Expression, FunctionDeclaration, FunctionExpression, Statement } from 'estree' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {BlockStatement} node
 * @param {ComponentContext} context
 */
function BlockStatement(node, context) {
	add_state_transformers(context);
	const tracing = context.state.scope.tracing;

	if (tracing !== null) {
		const parent =
			/** @type {ArrowFunctionExpression | FunctionDeclaration | FunctionExpression} */ (
				context.path.at(-1)
			);

		const is_async = parent.async;

		const call$1 = call(
			'$.trace',
			/** @type {Expression} */ (tracing),
			thunk(block(node.body.map((n) => /** @type {Statement} */ (context.visit(n)))), is_async)
		);

		return block([return_builder(is_async ? await_builder(call$1) : call$1)]);
	}

	context.next();
}

/** @import { BreakStatement } from 'estree' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {BreakStatement} node
 * @param {ComponentContext} context
 */
function BreakStatement(node, context) {
	if (context.state.analysis.runes || !node.label || node.label.name !== '$') {
		return;
	}

	const in_reactive_statement =
		context.path[1].type === 'LabeledStatement' && context.path[1].label.name === '$';

	if (in_reactive_statement) {
		return return_builder();
	}
}

/** @import { CallExpression, Expression } from 'estree' */
/** @import { Context } from '../types' */

/**
 * @param {CallExpression} node
 * @param {Context} context
 */
function CallExpression(node, context) {
	const rune = get_rune(node, context.state.scope);

	switch (rune) {
		case '$host':
			return id('$$props.$$host');

		case '$effect.tracking':
			return call('$.effect_tracking');

		// transform state field assignments in constructors
		case '$state':
		case '$state.raw': {
			let arg = node.arguments[0];

			/** @type {Expression | undefined} */
			let value = undefined;

			if (arg) {
				value = /** @type {Expression} */ (context.visit(node.arguments[0]));

				if (
					rune === '$state' &&
					should_proxy(/** @type {Expression} */ (arg), context.state.scope)
				) {
					value = call('$.proxy', value);
				}
			}

			return call('$.state', value);
		}

		case '$derived':
		case '$derived.by': {
			let fn = /** @type {Expression} */ (context.visit(node.arguments[0]));

			return call('$.derived', rune === '$derived' ? thunk(fn) : fn);
		}

		case '$state.eager':
			return call(
				'$.eager',
				thunk(/** @type {Expression} */ (context.visit(node.arguments[0])))
			);

		case '$state.snapshot':
			return call(
				'$.snapshot',
				/** @type {Expression} */ (context.visit(node.arguments[0])),
				is_ignored(node, 'state_snapshot_uncloneable') && true_instance
			);

		case '$effect':
		case '$effect.pre': {
			const callee = rune === '$effect' ? '$.user_effect' : '$.user_pre_effect';
			const func = /** @type {Expression} */ (context.visit(node.arguments[0]));

			const expr = call(callee, /** @type {Expression} */ (func));
			expr.callee.loc = node.callee.loc; // ensure correct mapping

			return expr;
		}

		case '$effect.root':
			return call(
				'$.effect_root',
				.../** @type {Expression[]} */ (node.arguments.map((arg) => context.visit(arg)))
			);

		case '$effect.pending':
			return call('$.eager', thunk(call('$.pending')));

		case '$inspect':
		case '$inspect().with':
			return transform_inspect_rune(rune, node, context);
	}

	if (
		dev &&
		node.callee.type === 'MemberExpression' &&
		node.callee.object.type === 'Identifier' &&
		node.callee.object.name === 'console' &&
		context.state.scope.get('console') === null &&
		node.callee.property.type === 'Identifier' &&
		['debug', 'dir', 'error', 'group', 'groupCollapsed', 'info', 'log', 'trace', 'warn'].includes(
			node.callee.property.name
		) &&
		node.arguments.some(
			(arg) => arg.type === 'SpreadElement' || context.state.scope.evaluate(arg).has_unknown
		)
	) {
		return call(
			node.callee,
			spread(
				call(
					'$.log_if_contains_state',
					literal(node.callee.property.name),
					.../** @type {Expression[]} */ (node.arguments.map((arg) => context.visit(arg)))
				)
			)
		);
	}

	context.next();
}

/**
 * @param {'$inspect' | '$inspect().with'} rune
 * @param {CallExpression} node
 * @param {Context} context
 */
function transform_inspect_rune(rune, node, context) {
	if (!dev) return empty;

	const { args, inspector } = get_inspect_args(rune, node, context.visit);

	// by passing an arrow function, the log appears to come from the `$inspect` callsite
	// rather than the `inspect.js` file containing the utility
	const id$1 = id('$$args');
	const fn = arrow([rest(id$1)], call(inspector, spread(id$1)));

	return call('$.inspect', thunk(array(args)), fn, rune === '$inspect' && true_instance);
}

/** @import { CallExpression, ClassBody, ClassDeclaration, ClassExpression, MethodDefinition, PropertyDefinition, StaticBlock } from 'estree' */
/** @import { StateField } from '#compiler' */
/** @import { Context } from '../types' */

/**
 * @param {ClassBody} node
 * @param {Context} context
 */
function ClassBody(node, context) {
	const state_fields = context.state.analysis.classes.get(node);

	if (!state_fields) {
		// in legacy mode, do nothing
		context.next();
		return;
	}

	/** @type {Array<MethodDefinition | PropertyDefinition | StaticBlock>} */
	const body = [];

	const child_state = { ...context.state, state_fields };

	for (const [name, field] of state_fields) {
		if (name[0] === '#') {
			continue;
		}

		// insert backing fields for stuff declared in the constructor
		if (field.node.type === 'AssignmentExpression') {
			const member$1 = member(this_instance, field.key);

			const should_proxy = field.type === '$state' && true; // TODO

			const key$1 = key(name);

			body.push(
				prop_def(field.key, null),

				method('get', key$1, [], [return_builder(call('$.get', member$1))]),

				method(
					'set',
					key$1,
					[id('value')],
					[stmt(call('$.set', member$1, id('value'), should_proxy && true_instance))]
				)
			);
		}
	}

	const declaration = /** @type {ClassDeclaration | ClassExpression} */ (
		get_parent(context.path, -1)
	);

	// Replace parts of the class body
	for (const definition of node.body) {
		if (definition.type !== 'PropertyDefinition') {
			body.push(
				/** @type {MethodDefinition | StaticBlock} */ (context.visit(definition, child_state))
			);
			continue;
		}

		const name = get_name(definition.key);
		const field = name && /** @type {StateField} */ (state_fields.get(name));

		if (!field) {
			body.push(/** @type {PropertyDefinition} */ (context.visit(definition, child_state)));
			continue;
		}

		if (name[0] === '#') {
			let value = definition.value
				? /** @type {CallExpression} */ (context.visit(definition.value, child_state))
				: undefined;

			if (dev && field.node === definition) {
				value = call('$.tag', value, literal(`${declaration.id?.name ?? '[class]'}.${name}`));
			}

			body.push(prop_def(definition.key, value));
		} else if (field.node === definition) {
			let call$1 = /** @type {CallExpression} */ (context.visit(field.value, child_state));

			if (dev) {
				call$1 = call('$.tag', call$1, literal(`${declaration.id?.name ?? '[class]'}.${name}`));
			}
			const member$1 = member(this_instance, field.key);
			const should_proxy = field.type === '$state' && true; // TODO

			body.push(
				prop_def(field.key, call$1),

				method('get', definition.key, [], [return_builder(call('$.get', member$1))]),

				method(
					'set',
					definition.key,
					[id('value')],
					[stmt(call('$.set', member$1, id('value'), should_proxy && true_instance))]
				)
			);
		}
	}

	return { ...node, body };
}

/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {AST.Comment} node
 * @param {ComponentContext} context
 */
function Comment(node, context) {
	// We'll only get here if comments are not filtered out, which they are unless preserveComments is true
	context.state.template.push_comment(node.data);
}

/** @import { BlockStatement, Expression, ExpressionStatement, Identifier, MemberExpression, Pattern, Property, SequenceExpression, Statement } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../../types.js' */

/**
 * @param {AST.Component | AST.SvelteComponent | AST.SvelteSelf} node
 * @param {string} component_name
 * @param {ComponentContext} context
 * @returns {Statement}
 */
function build_component(node, component_name, context) {
	/** @type {Expression} */
	const anchor = context.state.node;

	/** @type {Array<Property[] | Expression>} */
	const props_and_spreads = [];

	/** @type {Array<() => void>} */
	const delayed_props = [];

	/** @type {ExpressionStatement[]} */
	const lets = [];

	/** @type {Record<string, typeof context.state>} */
	const states = {
		default: {
			...context.state,
			scope: node.metadata.scopes.default,
			transform: { ...context.state.transform }
		}
	};

	/** @type {Record<string, AST.TemplateNode[]>} */
	const children = {};

	/** @type {Record<string, Expression[]>} */
	const events = {};

	const memoizer = new Memoizer();

	/** @type {Property[]} */
	const custom_css_props = [];

	/** @type {Identifier | MemberExpression | SequenceExpression | null} */
	let bind_this = null;

	/** @type {ExpressionStatement[]} */
	const binding_initializers = [];

	const is_component_dynamic =
		node.type === 'SvelteComponent' || (node.type === 'Component' && node.metadata.dynamic);

	// The variable name used for the component inside $.component()
	const intermediate_name =
		node.type === 'Component' && node.metadata.dynamic
			? context.state.scope.generate(node.name)
			: '$$component';

	/**
	 * If this component has a slot property, it is a named slot within another component. In this case
	 * the slot scope applies to the component itself, too, and not just its children.
	 */
	let slot_scope_applies_to_itself = !!determine_slot(node);

	/**
	 * Components may have a children prop and also have child nodes. In this case, we assume
	 * that the child component isn't using render tags yet and pass the slot as $$slots.default.
	 * We're not doing it for spread attributes, as this would result in too many false positives.
	 */
	let has_children_prop = false;

	/**
	 * @param {Property} prop
	 * @param {boolean} [delay]
	 */
	function push_prop(prop, delay = false) {
		const do_push = () => {
			const current = props_and_spreads.at(-1);
			const current_is_props = Array.isArray(current);
			const props = current_is_props ? current : [];
			props.push(prop);
			if (!current_is_props) {
				props_and_spreads.push(props);
			}
		};

		if (delay) {
			delayed_props.push(do_push);
		} else {
			do_push();
		}
	}

	if (slot_scope_applies_to_itself) {
		for (const attribute of node.attributes) {
			if (attribute.type === 'LetDirective') {
				context.visit(attribute, { ...context.state, let_directives: lets });
			}
		}
	}

	for (const attribute of node.attributes) {
		if (attribute.type === 'LetDirective') {
			if (!slot_scope_applies_to_itself) {
				context.visit(attribute, { ...states.default, let_directives: lets });
			}
		} else if (attribute.type === 'OnDirective') {
			if (!attribute.expression) {
				context.state.analysis.needs_props = true;
			}

			let handler = build_event_handler(
				attribute.expression,
				attribute.metadata.expression,
				context
			);

			if (attribute.modifiers.includes('once')) {
				handler = call('$.once', handler);
			}

			(events[attribute.name] ||= []).push(handler);
		} else if (attribute.type === 'SpreadAttribute') {
			const expression = /** @type {Expression} */ (context.visit(attribute));
			const memoized_expression = memoizer.add(expression, attribute.metadata.expression);
			const is_memoized = expression !== memoized_expression;

			if (
				is_memoized ||
				attribute.metadata.expression.has_state ||
				attribute.metadata.expression.has_await
			) {
				props_and_spreads.push(
					thunk(is_memoized ? call('$.get', memoized_expression) : expression)
				);
			} else {
				props_and_spreads.push(expression);
			}
		} else if (attribute.type === 'Attribute') {
			if (attribute.name.startsWith('--')) {
				custom_css_props.push(
					init(
						attribute.name,
						build_attribute_value(attribute.value, context, (value, metadata) => {
							const memoized = memoizer.add(value, metadata);

							// TODO put the derived in the local block
							return value !== memoized ? call('$.get', memoized) : value;
						}).value
					)
				);
				continue;
			}

			if (attribute.name === 'slot') {
				slot_scope_applies_to_itself = true;
			}

			if (attribute.name === 'children') {
				has_children_prop = true;
			}

			const { value, has_state } = build_attribute_value(
				attribute.value,
				context,
				(value, metadata) => {
					// When we have a non-simple computation, anything other than an Identifier or Member expression,
					// then there's a good chance it needs to be memoized to avoid over-firing when read within the
					// child component (e.g. `active={i === index}`)
					const should_wrap_in_derived =
						metadata.has_await ||
						get_attribute_chunks(attribute.value).some((n) => {
							return (
								n.type === 'ExpressionTag' &&
								n.expression.type !== 'Identifier' &&
								n.expression.type !== 'MemberExpression'
							);
						});

					const memoized = memoizer.add(value, metadata, should_wrap_in_derived);

					return value !== memoized ? call('$.get', memoized) : value;
				}
			);

			if (has_state) {
				push_prop(get$1(attribute.name, [return_builder(value)]));
			} else {
				push_prop(init(attribute.name, value));
			}
		} else if (attribute.type === 'BindDirective') {
			const expression = /** @type {Expression} */ (
				context.visit(attribute.expression, { ...context.state, memoizer })
			);

			// Bindings are a bit special: we don't want to add them to (async) deriveds but we need to check if they have blockers
			memoizer.check_blockers(attribute.metadata.expression);

			if (
				dev &&
				attribute.name !== 'this' &&
				!is_ignored(node, 'ownership_invalid_binding') &&
				// bind:x={() => x.y, y => x.y = y} will be handled by the assignment expression binding validation
				attribute.expression.type !== 'SequenceExpression'
			) {
				const left = object$1(attribute.expression);
				const binding = left && context.state.scope.get(left.name);

				if (binding?.kind === 'bindable_prop' || binding?.kind === 'prop') {
					context.state.analysis.needs_mutation_validation = true;
					binding_initializers.push(
						stmt(
							call(
								'$$ownership_validator.binding',
								literal(binding.node.name),
								id(is_component_dynamic ? intermediate_name : component_name),
								thunk(expression)
							)
						)
					);
				}
			}

			if (expression.type === 'SequenceExpression') {
				if (attribute.name === 'this') {
					bind_this = attribute.expression;
				} else {
					const [get, set$1] = expression.expressions;
					const get_id = id(context.state.scope.generate('bind_get'));
					const set_id = id(context.state.scope.generate('bind_set'));

					context.state.init.push(var_builder(get_id, get));
					context.state.init.push(var_builder(set_id, set$1));

					push_prop(get$1(attribute.name, [return_builder(call(get_id))]));
					push_prop(set(attribute.name, [stmt(call(set_id, id('$$value')))]));
				}
			} else {
				if (
					dev &&
					expression.type === 'MemberExpression' &&
					context.state.analysis.runes &&
					!is_ignored(node, 'binding_property_non_reactive')
				) {
					validate_binding(context.state, attribute, expression);
				}

				if (attribute.name === 'this') {
					bind_this = attribute.expression;
				} else {
					const is_store_sub =
						attribute.expression.type === 'Identifier' &&
						context.state.scope.get(attribute.expression.name)?.kind === 'store_sub';

					// Delay prop pushes so bindings come at the end, to avoid spreads overwriting them
					if (is_store_sub) {
						push_prop(
							get$1(attribute.name, [stmt(call('$.mark_store_binding')), return_builder(expression)]),
							true
						);
					} else {
						push_prop(get$1(attribute.name, [return_builder(expression)]), true);
					}

					const assignment$1 = assignment(
						'=',
						/** @type {Pattern} */ (attribute.expression),
						id('$$value')
					);

					push_prop(
						set(attribute.name, [stmt(/** @type {Expression} */ (context.visit(assignment$1)))]),
						true
					);
				}
			}
		} else if (attribute.type === 'AttachTag') {
			const evaluated = context.state.scope.evaluate(attribute.expression);

			let expression = /** @type {Expression} */ (context.visit(attribute.expression));

			if (attribute.metadata.expression.has_state) {
				expression = arrow(
					[id('$$node')],
					call(
						evaluated.is_function ? expression : logical$1('||', expression, id('$.noop')),
						id('$$node')
					)
				);
			}

			// TODO also support await expressions here?
			memoizer.check_blockers(attribute.metadata.expression);

			push_prop(prop('init', call('$.attachment'), expression, true));
		}
	}

	delayed_props.forEach((fn) => fn());

	if (slot_scope_applies_to_itself) {
		context.state.init.push(...lets);
	}

	if (Object.keys(events).length > 0) {
		const events_expression = object$2(
			Object.keys(events).map((name) =>
				init(name, events[name].length > 1 ? array(events[name]) : events[name][0])
			)
		);
		push_prop(init('$$events', events_expression));
	}

	/** @type {Statement[]} */
	const snippet_declarations = [];

	/** @type {import('estree').Property[]} */
	const serialized_slots = [];

	// Group children by slot
	for (const child of node.fragment.nodes) {
		if (child.type === 'SnippetBlock') {
			// the SnippetBlock visitor adds a declaration to `init`, but if it's directly
			// inside a component then we want to hoist them into a block so that they
			// can be used as props without creating conflicts
			context.visit(child, {
				...context.state,
				init: snippet_declarations
			});

			push_prop(prop('init', child.expression, child.expression));

			// Interop: allows people to pass snippets when component still uses slots
			serialized_slots.push(
				init(child.expression.name === 'children' ? 'default' : child.expression.name, true_instance)
			);

			continue;
		}

		let slot_name = determine_slot(child) ?? 'default';

		(children[slot_name] ||= []).push(child);
	}

	// Serialize each slot
	for (const slot_name of Object.keys(children)) {
		const block$1 = /** @type {BlockStatement} */ (
			context.visit(
				{
					...node.fragment,
					// @ts-expect-error
					nodes: children[slot_name]
				},
				slot_name === 'default'
					? slot_scope_applies_to_itself
						? context.state
						: states.default
					: {
							...context.state,
							scope: node.metadata.scopes[slot_name],
							transform: { ...context.state.transform }
						}
			)
		);

		if (block$1.body.length === 0) continue;

		const slot_fn = arrow(
			[id('$$anchor'), id('$$slotProps')],
			block([
				...(slot_name === 'default' && !slot_scope_applies_to_itself ? lets : []),
				...block$1.body
			])
		);

		if (slot_name === 'default' && !has_children_prop) {
			if (
				lets.length === 0 &&
				children.default.every(
					(node) =>
						node.type !== 'SvelteFragment' ||
						!node.attributes.some((attr) => attr.type === 'LetDirective')
				)
			) {
				// create `children` prop...
				push_prop(
					init(
						'children',
						dev ? call('$.wrap_snippet', id(context.state.analysis.name), slot_fn) : slot_fn
					)
				);

				// and `$$slots.default: true` so that `<slot>` on the child works
				serialized_slots.push(init(slot_name, true_instance));
			} else {
				// create `$$slots.default`...
				serialized_slots.push(init(slot_name, slot_fn));

				// and a `children` prop that errors
				push_prop(init('children', id('$.invalid_default_snippet')));
			}
		} else {
			serialized_slots.push(init(slot_name, slot_fn));
		}
	}

	if (serialized_slots.length > 0) {
		push_prop(init('$$slots', object$2(serialized_slots)));
	}

	if (
		!context.state.analysis.runes &&
		node.attributes.some((attribute) => attribute.type === 'BindDirective')
	) {
		push_prop(init('$$legacy', true_instance));
	}

	const props_expression =
		props_and_spreads.length === 0 ||
		(props_and_spreads.length === 1 && Array.isArray(props_and_spreads[0]))
			? object$2(/** @type {Property[]} */ (props_and_spreads[0]) || [])
			: call(
					'$.spread_props',
					...props_and_spreads.map((p) => (Array.isArray(p) ? object$2(p) : p))
				);

	/** @param {Expression} node_id */
	let fn = (node_id) => {
		return call(
			// TODO We can remove this ternary once we remove legacy mode, since in runes mode dynamic components
			// will be handled separately through the `$.component` function, and then the component name will
			// always be referenced through just the identifier here.
			is_component_dynamic
				? intermediate_name
				: /** @type {Expression} */ (context.visit(member_id(component_name))),
			node_id,
			props_expression
		);
	};

	if (bind_this !== null) {
		const prev = fn;

		fn = (node_id) => {
			return build_bind_this(bind_this, prev(node_id), context);
		};
	}

	if (node.type !== 'SvelteSelf') {
		// Component name itself could be blocked on async values
		memoizer.check_blockers(node.metadata.expression);
	}

	const statements = [...snippet_declarations, ...memoizer.deriveds(context.state.analysis.runes)];

	if (is_component_dynamic) {
		const prev = fn;

		fn = (node_id) => {
			return call(
				'$.component',
				node_id,
				thunk(
					/** @type {Expression} */ (
						context.visit(node.type === 'Component' ? member_id(component_name) : node.expression)
					)
				),
				arrow(
					[id('$$anchor'), id(intermediate_name)],
					block([...binding_initializers, stmt(prev(id('$$anchor')))])
				)
			);
		};
	} else {
		statements.push(...binding_initializers);
	}

	if (Object.keys(custom_css_props).length > 0) {
		if (context.state.metadata.namespace === 'svg') {
			// this boils down to <g><!></g>
			context.state.template.push_element('g', node.start);
		} else {
			// this boils down to <svelte-css-wrapper style='display: contents'><!></svelte-css-wrapper>
			context.state.template.push_element('svelte-css-wrapper', node.start);
			context.state.template.set_prop('style', 'display: contents');
		}

		context.state.template.push_comment();
		context.state.template.pop_element();

		statements.push(
			stmt(call('$.css_props', anchor, thunk(object$2(custom_css_props)))),
			stmt(fn(member(anchor, 'lastChild'))),
			stmt(call('$.reset', anchor))
		);
	} else {
		context.state.template.push_comment();

		statements.push(add_svelte_meta(fn(anchor), node, 'component', { componentTag: node.name }));
	}

	memoizer.apply();

	const async_values = memoizer.async_values();
	const blockers = memoizer.blockers();

	if (async_values || blockers) {
		return stmt(
			call(
				'$.async',
				anchor,
				blockers,
				async_values,
				arrow([id('$$anchor'), ...memoizer.async_ids()], block(statements))
			)
		);
	}

	return statements.length > 1 ? block(statements) : statements[0];
}

/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {AST.Component} node
 * @param {ComponentContext} context
 */
function Component(node, context) {
	const component = build_component(node, node.name, context);
	context.state.init.push(component);
}

/** @import { Pattern } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {AST.ConstTag} node
 * @param {ComponentContext} context
 */
function ConstTag(node, context) {
	const declaration = node.declaration.declarations[0];
	// TODO we can almost certainly share some code with $derived(...)
	if (declaration.id.type === 'Identifier') {
		const init = build_expression(context, declaration.init, node.metadata.expression);

		let expression = create_derived(context.state, init, node.metadata.expression.has_await);

		if (dev) {
			expression = call('$.tag', expression, literal(declaration.id.name));
		}

		context.state.transform[declaration.id.name] = { read: get_value };

		add_const_declaration(
			context.state,
			declaration.id,
			expression,
			node.metadata.expression.has_await,
			context.state.scope.get_bindings(declaration)
		);
	} else {
		const identifiers = extract_identifiers(declaration.id);
		const tmp = id(context.state.scope.generate('computed_const'));

		const transform = { ...context.state.transform };

		// Make all identifiers that are declared within the following computed regular
		// variables, as they are not signals in that context yet
		for (const node of identifiers) {
			delete transform[node.name];
		}

		const child_state = /** @type {ComponentContext['state']} */ ({
			...context.state,
			transform
		});

		// TODO optimise the simple `{ x } = y` case — we can just return `y`
		// instead of destructuring it only to return a new object
		const init = build_expression(
			{ ...context, state: child_state },
			declaration.init,
			node.metadata.expression
		);

		const block$1 = block([
			const_builder(/** @type {Pattern} */ (context.visit(declaration.id, child_state)), init),
			return_builder(object$2(identifiers.map((node) => prop('init', node, node))))
		]);

		let expression = create_derived(context.state, block$1, node.metadata.expression.has_await);

		if (dev) {
			expression = call('$.tag', expression, literal('[@const]'));
		}

		add_const_declaration(
			context.state,
			tmp,
			expression,
			node.metadata.expression.has_await,
			context.state.scope.get_bindings(declaration)
		);

		for (const node of identifiers) {
			context.state.transform[node.name] = {
				read: (node) => member(call('$.get', tmp), node)
			};
		}
	}
}

/**
 * @param {ComponentContext['state']} state
 * @param {import('estree').Identifier} id
 * @param {import('estree').Expression} expression
 * @param {boolean} has_await
 * @param {import('#compiler').Binding[]} bindings
 */
function add_const_declaration(state, id$1, expression, has_await, bindings) {
	// we need to eagerly evaluate the expression in order to hit any
	// 'Cannot access x before initialization' errors
	const after = dev ? [stmt(call('$.get', id$1))] : [];

	if (has_await || state.async_consts) {
		const run = (state.async_consts ??= {
			id: id(state.scope.generate('promises')),
			thunks: []
		});

		state.consts.push(let_builder(id$1));

		const assignment$1 = assignment('=', id$1, expression);
		const body = after.length === 0 ? assignment$1 : block([stmt(assignment$1), ...after]);

		run.thunks.push(thunk(body, has_await));

		const blocker = member(run.id, literal(run.thunks.length - 1), true);

		for (const binding of bindings) {
			binding.blocker = blocker;
		}
	} else {
		state.consts.push(const_builder(id$1, expression));
		state.consts.push(...after);
	}
}

/** @import { Expression} from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {AST.DebugTag} node
 * @param {ComponentContext} context
 */
function DebugTag(node, context) {
	const object = object$2(
		node.identifiers.map((identifier) => {
			const visited = call('$.snapshot', /** @type {Expression} */ (context.visit(identifier)));

			return prop(
				'init',
				identifier,
				context.state.analysis.runes ? visited : call('$.untrack', thunk(visited))
			);
		})
	);

	const call$1 = call('console.log', object);

	context.state.init.push(
		stmt(call('$.template_effect', thunk(block([stmt(call$1), debugger_builder]))))
	);
}

/** @import { BlockStatement, Expression, Identifier, Pattern, Statement } from 'estree' */
/** @import { AST, Binding } from '#compiler' */
/** @import { ComponentContext } from '../types' */
/** @import { Scope } from '../../../scope' */

/**
 * @param {AST.EachBlock} node
 * @param {ComponentContext} context
 */
function EachBlock(node, context) {
	const each_node_meta = node.metadata;

	// expression should be evaluated in the parent scope, not the scope
	// created by the each block itself
	const parent_scope_state = {
		...context.state,
		scope: /** @type {Scope} */ (context.state.scope.parent)
	};

	const collection = build_expression(
		{
			...context,
			state: parent_scope_state
		},
		node.expression,
		node.metadata.expression
	);

	if (!each_node_meta.is_controlled) {
		context.state.template.push_comment();
	}

	let flags = 0;

	if (node.metadata.keyed && node.index) {
		flags |= EACH_INDEX_REACTIVE;
	}

	const key_is_item =
		node.key?.type === 'Identifier' &&
		node.context?.type === 'Identifier' &&
		node.context?.name === node.key.name;

	// if the each block expression references a store subscription, we need
	// to use mutable stores internally
	let uses_store;

	for (const binding of node.metadata.expression.dependencies) {
		if (binding.kind === 'store_sub') {
			uses_store = true;
			break;
		}
	}

	for (const binding of node.metadata.expression.dependencies) {
		// if the expression doesn't reference any external state, we don't need to
		// create a source for the item. TODO cover more cases (e.g. `x.filter(y)`
		// should also qualify if `y` doesn't reference state, and non-state
		// bindings should also be fine
		if (binding.scope.function_depth >= context.state.scope.function_depth) {
			continue;
		}

		if (!context.state.analysis.runes || !key_is_item || uses_store) {
			flags |= EACH_ITEM_REACTIVE;
			break;
		}
	}

	if (context.state.analysis.runes && !uses_store) {
		flags |= EACH_ITEM_IMMUTABLE;
	}

	// Since `animate:` can only appear on elements that are the sole child of a keyed each block,
	// we can determine at compile time whether the each block is animated or not (in which
	// case it should measure animated elements before and after reconciliation).
	if (
		node.key &&
		node.body.nodes.some((child) => {
			if (child.type !== 'RegularElement' && child.type !== 'SvelteElement') return false;
			return child.attributes.some((attr) => attr.type === 'AnimateDirective');
		})
	) {
		flags |= EACH_IS_ANIMATED;
	}

	if (each_node_meta.is_controlled) {
		flags |= EACH_IS_CONTROLLED;
	}

	// If the array is a store expression, we need to invalidate it when the array is changed.
	// This doesn't catch all cases, but all the ones that Svelte 4 catches, too.
	let store_to_invalidate = '';
	if (node.expression.type === 'Identifier' || node.expression.type === 'MemberExpression') {
		const id = object$1(node.expression);
		if (id) {
			const binding = context.state.scope.get(id.name);
			if (binding?.kind === 'store_sub') {
				store_to_invalidate = id.name;
			}
		}
	}

	/** @type {Identifier | null} */
	let collection_id = null;

	// Check if inner scope shadows something from outer scope.
	// This is necessary because we need access to the array expression of the each block
	// in the inner scope if bindings are used, in order to invalidate the array.
	for (const [name] of context.state.scope.declarations) {
		if (context.state.scope.parent?.get(name) != null) {
			collection_id = context.state.scope.root.unique('$$array');
			break;
		}
	}

	const child_state = {
		...context.state,
		transform: { ...context.state.transform },
		store_to_invalidate
	};

	/** The state used when generating the key function, if necessary */
	const key_state = {
		...context.state,
		transform: { ...context.state.transform }
	};

	// We need to generate a unique identifier in case there's a bind:group below
	// which needs a reference to the index
	const index =
		each_node_meta.contains_group_binding || !node.index ? each_node_meta.index : id(node.index);
	const item = node.context?.type === 'Identifier' ? node.context : id('$$item');

	let uses_index = each_node_meta.contains_group_binding;
	let key_uses_index = false;

	if (node.index) {
		child_state.transform[node.index] = {
			read: (node) => {
				uses_index = true;
				return (flags & EACH_INDEX_REACTIVE) !== 0 ? get_value(node) : node;
			}
		};

		key_state.transform[node.index] = {
			read: (node) => {
				key_uses_index = true;
				return node;
			}
		};
	}

	/** @type {Statement[]} */
	const declarations = [];

	const invalidate_store = store_to_invalidate
		? call('$.invalidate_store', id('$$stores'), literal(store_to_invalidate))
		: undefined;

	/** @type {Expression[]} */
	const sequence$1 = [];

	if (!context.state.analysis.runes) {
		/** @type {Set<Identifier>} */
		const transitive_deps = new Set();

		if (collection_id) {
			transitive_deps.add(collection_id);
			child_state.transform[collection_id.name] = { read: call };
		} else {
			for (const binding of each_node_meta.transitive_deps) {
				transitive_deps.add(binding.node);
			}
		}

		for (const block of collect_parent_each_blocks(context)) {
			for (const binding of block.metadata.transitive_deps) {
				transitive_deps.add(binding.node);
			}
		}

		if (transitive_deps.size > 0) {
			const invalidate = call(
				'$.invalidate_inner_signals',
				thunk(
					sequence(
						[...transitive_deps].map(
							(node) => /** @type {Expression} */ (context.visit({ ...node }, child_state))
						)
					)
				)
			);

			sequence$1.push(invalidate);
		}
	}

	if (invalidate_store) {
		sequence$1.push(invalidate_store);
	}

	if (node.context?.type === 'Identifier') {
		const binding = /** @type {Binding} */ (context.state.scope.get(node.context.name));

		child_state.transform[node.context.name] = {
			read: (node) => {
				if (binding.reassigned) {
					// we need to do `array[$$index]` instead of `$$item` or whatever
					// TODO 6.0 this only applies in legacy mode, reassignments are
					// forbidden in runes mode
					return member(
						collection_id ? call(collection_id) : collection,
						(flags & EACH_INDEX_REACTIVE) !== 0 ? get_value(index) : index,
						true
					);
				}

				return (flags & EACH_ITEM_REACTIVE) !== 0 ? get_value(node) : node;
			},
			assign: (_, value) => {
				uses_index = true;

				const left = member(
					collection_id ? call(collection_id) : collection,
					(flags & EACH_INDEX_REACTIVE) !== 0 ? get_value(index) : index,
					true
				);

				return sequence([assignment('=', left, value), ...sequence$1]);
			},
			mutate: (_, mutation) => {
				uses_index = true;
				return sequence([mutation, ...sequence$1]);
			}
		};

		delete key_state.transform[node.context.name];
	} else if (node.context) {
		const unwrapped = (flags & EACH_ITEM_REACTIVE) !== 0 ? call('$.get', item) : item;

		const { inserts, paths } = extract_paths(node.context, unwrapped);

		for (const { id, value } of inserts) {
			id.name = context.state.scope.generate('$$array');
			child_state.transform[id.name] = { read: get_value };

			const expression = /** @type {Expression} */ (context.visit(thunk(value), child_state));
			declarations.push(var_builder(id, call('$.derived', expression)));
		}

		for (const path of paths) {
			const name = /** @type {Identifier} */ (path.node).name;
			const needs_derived = path.has_default_value; // to ensure that default value is only called once

			const fn = thunk(/** @type {Expression} */ (context.visit(path.expression, child_state)));

			declarations.push(let_builder(path.node, needs_derived ? call('$.derived_safe_equal', fn) : fn));

			const read = needs_derived ? get_value : call;

			child_state.transform[name] = {
				read,
				assign: (_, value) => {
					const left = /** @type {Pattern} */ (path.update_expression);
					return sequence([assignment('=', left, value), ...sequence$1]);
				},
				mutate: (_, mutation) => {
					return sequence([mutation, ...sequence$1]);
				}
			};

			// we need to eagerly evaluate the expression in order to hit any
			// 'Cannot access x before initialization' errors
			if (dev) {
				declarations.push(stmt(read(id(name))));
			}

			delete key_state.transform[name];
		}
	}

	const block$1 = /** @type {BlockStatement} */ (context.visit(node.body, child_state));

	/** @type {Expression} */
	let key_function = id('$.index');

	if (node.metadata.keyed) {
		const pattern = /** @type {Pattern} */ (node.context); // can only be keyed when a context is provided
		const expression = /** @type {Expression} */ (
			context.visit(/** @type {Expression} */ (node.key), key_state)
		);

		key_function = arrow(key_uses_index ? [pattern, index] : [pattern], expression);
	}

	if (node.index && each_node_meta.contains_group_binding) {
		// We needed to create a unique identifier for the index above, but we want to use the
		// original index name in the template, therefore create another binding
		declarations.push(let_builder(node.index, index));
	}

	const is_async = node.metadata.expression.is_async();

	const get_collection = thunk(collection, node.metadata.expression.has_await);
	const thunk$1 = is_async ? thunk(call('$.get', id('$$collection'))) : get_collection;

	const render_args = [id('$$anchor'), item];
	if (uses_index || collection_id) render_args.push(index);
	if (collection_id) render_args.push(collection_id);

	/** @type {Expression[]} */
	const args = [
		context.state.node,
		literal(flags),
		thunk$1,
		key_function,
		arrow(render_args, block(declarations.concat(block$1.body)))
	];

	if (node.fallback) {
		args.push(
			arrow([id('$$anchor')], /** @type {BlockStatement} */ (context.visit(node.fallback)))
		);
	}

	const statements = [add_svelte_meta(call('$.each', ...args), node, 'each')];

	if (dev && node.metadata.keyed) {
		statements.unshift(stmt(call('$.validate_each_keys', thunk$1, key_function)));
	}

	if (is_async) {
		context.state.init.push(
			stmt(
				call(
					'$.async',
					context.state.node,
					node.metadata.expression.blockers(),
					array([get_collection]),
					arrow([context.state.node, id('$$collection')], block(statements))
				)
			)
		);
	} else {
		context.state.init.push(...statements);
	}
}

/**
 * @param {ComponentContext} context
 */
function collect_parent_each_blocks(context) {
	return /** @type {AST.EachBlock[]} */ (context.path.filter((node) => node.type === 'EachBlock'));
}

/** @import { ExportNamedDeclaration } from 'estree' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {ExportNamedDeclaration} node
 * @param {ComponentContext} context
 */
function ExportNamedDeclaration(node, context) {
	if (context.state.is_instance) {
		if (node.declaration) {
			return context.visit(node.declaration);
		}

		return empty;
	}

	return context.next();
}

/** @import { ExpressionStatement } from 'estree' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {ExpressionStatement} node
 * @param {ComponentContext} context
 */
function ExpressionStatement(node, context) {
	if (node.expression.type === 'CallExpression') {
		const rune = get_rune(node.expression, context.state.scope);

		if (rune === '$inspect.trace') {
			return empty;
		}
	}

	context.next();
}

/** @import { Expression, ForOfStatement, Pattern, Statement, VariableDeclaration } from 'estree' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {ForOfStatement} node
 * @param {ComponentContext} context
 */
function ForOfStatement(node, context) {
	if (
		node.await &&
		dev &&
		!is_ignored(node, 'await_reactivity_loss') &&
		context.state.options.experimental.async
	) {
		const left = /** @type {VariableDeclaration | Pattern} */ (context.visit(node.left));
		const argument = /** @type {Expression} */ (context.visit(node.right));
		const body = /** @type {Statement} */ (context.visit(node.body));
		const right = call('$.for_await_track_reactivity_loss', argument);
		return for_of(left, right, body, true);
	}

	context.next();
}

/** @import { Location } from 'locate-character' */
/** @import { Namespace } from '#compiler' */
/** @import { ComponentClientTransformState } from '../types.js' */
/** @import { Node } from './types.js' */

/**
 * @param {Node[]} nodes
 */
function build_locations(nodes) {
	const array$1 = array([]);

	for (const node of nodes) {
		if (node.type !== 'element') continue;

		const { line, column } = /** @type {Location} */ (locator(node.start));

		const expression = array([literal(line), literal(column)]);
		const children = build_locations(node.children);

		if (children.elements.length > 0) {
			expression.elements.push(children);
		}

		array$1.elements.push(expression);
	}

	return array$1;
}

/**
 * @param {ComponentClientTransformState} state
 * @param {Namespace} namespace
 * @param {number} [flags]
 */
function transform_template(state, namespace, flags = 0) {
	const tree = state.options.fragments === 'tree';

	const expression = tree ? state.template.as_tree() : state.template.as_html();

	if (tree) {
		if (namespace === 'svg') flags |= TEMPLATE_USE_SVG;
		if (namespace === 'mathml') flags |= TEMPLATE_USE_MATHML;
	}

	let call$1 = call(
		tree ? `$.from_tree` : `$.from_${namespace}`,
		expression,
		flags ? literal(flags) : undefined
	);

	if (state.template.contains_script_tag) {
		call$1 = call(`$.with_script`, call$1);
	}

	if (dev) {
		call$1 = call(
			'$.add_locations',
			call$1,
			member(id(state.analysis.name), '$.FILENAME', true),
			build_locations(state.template.nodes)
		);
	}

	return call$1;
}

const svg_attributes =
	'accent-height accumulate additive alignment-baseline allowReorder alphabetic amplitude arabic-form ascent attributeName attributeType autoReverse azimuth baseFrequency baseline-shift baseProfile bbox begin bias by calcMode cap-height class clip clipPathUnits clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering contentScriptType contentStyleType cursor cx cy d decelerate descent diffuseConstant direction display divisor dominant-baseline dur dx dy edgeMode elevation enable-background end exponent externalResourcesRequired fill fill-opacity fill-rule filter filterRes filterUnits flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight format from fr fx fy g1 g2 glyph-name glyph-orientation-horizontal glyph-orientation-vertical glyphRef gradientTransform gradientUnits hanging height href horiz-adv-x horiz-origin-x id ideographic image-rendering in in2 intercept k k1 k2 k3 k4 kernelMatrix kernelUnitLength kerning keyPoints keySplines keyTimes lang lengthAdjust letter-spacing lighting-color limitingConeAngle local marker-end marker-mid marker-start markerHeight markerUnits markerWidth mask maskContentUnits maskUnits mathematical max media method min mode name numOctaves offset onabort onactivate onbegin onclick onend onerror onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup onrepeat onresize onscroll onunload opacity operator order orient orientation origin overflow overline-position overline-thickness panose-1 paint-order pathLength patternContentUnits patternTransform patternUnits pointer-events points pointsAtX pointsAtY pointsAtZ preserveAlpha preserveAspectRatio primitiveUnits r radius refX refY rendering-intent repeatCount repeatDur requiredExtensions requiredFeatures restart result rotate rx ry scale seed shape-rendering slope spacing specularConstant specularExponent speed spreadMethod startOffset stdDeviation stemh stemv stitchTiles stop-color stop-opacity strikethrough-position strikethrough-thickness string stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style surfaceScale systemLanguage tabindex tableValues target targetX targetY text-anchor text-decoration text-rendering textLength to transform type u1 u2 underline-position underline-thickness unicode unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical values version vert-adv-y vert-origin-x vert-origin-y viewBox viewTarget visibility width widths word-spacing writing-mode x x-height x1 x2 xChannelSelector xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y y1 y2 yChannelSelector z zoomAndPan'.split(
		' '
	);

const svg_attribute_lookup = new Map();

svg_attributes.forEach((name) => {
	svg_attribute_lookup.set(name.toLowerCase(), name);
});

/**
 * @param {string} name
 */
function fix_attribute_casing(name) {
	name = name.toLowerCase();
	return svg_attribute_lookup.get(name) || name;
}

/** @import { AST } from '#compiler' */
/** @import { Node, Element } from './types'; */

class Template {
	/**
	 * `true` if HTML template contains a `<script>` tag. In this case we need to invoke a special
	 * template instantiation function (see `create_fragment_with_script_from_html` for more info)
	 */
	contains_script_tag = false;

	/** `true` if the HTML template needs to be instantiated with `importNode` */
	needs_import_node = false;

	/** @type {Node[]} */
	nodes = [];

	/** @type {Node[][]} */
	#stack = [this.nodes];

	/** @type {Element | undefined} */
	#element;

	#fragment = this.nodes;

	/**
	 * @param {string} name
	 * @param {number} start
	 */
	push_element(name, start) {
		this.#element = {
			type: 'element',
			name,
			attributes: {},
			children: [],
			start
		};

		this.#fragment.push(this.#element);

		this.#fragment = /** @type {Element} */ (this.#element).children;
		this.#stack.push(this.#fragment);
	}

	/** @param {string} [data] */
	push_comment(data) {
		this.#fragment.push({ type: 'comment', data });
	}

	/** @param {AST.Text[]} nodes */
	push_text(nodes) {
		this.#fragment.push({ type: 'text', nodes });
	}

	pop_element() {
		this.#stack.pop();
		this.#fragment = /** @type {Node[]} */ (this.#stack.at(-1));
	}

	/**
	 * @param {string} key
	 * @param {string | undefined} value
	 */
	set_prop(key, value) {
		/** @type {Element} */ (this.#element).attributes[key] = value;
	}

	as_html() {
		return template$1([quasi(this.nodes.map(stringify).join(''), true)], []);
	}

	as_tree() {
		// if the first item is a comment we need to add another comment for effect.start
		if (this.nodes[0].type === 'comment') {
			this.nodes.unshift({ type: 'comment', data: undefined });
		}

		return array(this.nodes.map(objectify));
	}
}

/**
 * @param {Node} item
 */
function stringify(item) {
	if (item.type === 'text') {
		return item.nodes.map((node) => node.raw).join('');
	}

	if (item.type === 'comment') {
		return item.data ? `<!--${item.data}-->` : '<!>';
	}

	let str = `<${item.name}`;

	for (const key in item.attributes) {
		const value = item.attributes[key];

		str += ` ${key}`;
		if (value !== undefined) str += `="${escape_html(value, true)}"`;
	}

	if (is_void(item.name)) {
		str += '/>'; // XHTML compliance
	} else {
		str += `>`;
		str += item.children.map(stringify).join('');
		str += `</${item.name}>`;
	}

	return str;
}

/** @param {Node} item */
function objectify(item) {
	if (item.type === 'text') {
		return literal(item.nodes.map((node) => node.data).join(''));
	}

	if (item.type === 'comment') {
		return item.data ? array([literal(`// ${item.data}`)]) : null;
	}

	const element = array([literal(item.name)]);

	const attributes = object$2([]);

	for (const key$1 in item.attributes) {
		const value = item.attributes[key$1];

		attributes.properties.push(
			prop(
				'init',
				key(fix_attribute_casing(key$1)),
				value === undefined ? void0 : literal(value)
			)
		);
	}

	if (attributes.properties.length > 0 || item.children.length > 0) {
		element.elements.push(attributes.properties.length > 0 ? attributes : null_instance);
	}

	if (item.children.length > 0) {
		const children = item.children.map(objectify);
		element.elements.push(...children);

		// special case — strip leading newline from `<pre>` and `<textarea>`
		if (item.name === 'pre' || item.name === 'textarea') {
			const first = children[0];
			if (first?.type === 'Literal') {
				first.value = /** @type {string} */ (first.value).replace(regex_starts_with_newline, '');
			}
		}
	}

	return element;
}

/** @import { Expression, Statement } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentClientTransformState, ComponentContext } from '../types' */

/**
 * @param {AST.Fragment} node
 * @param {ComponentContext} context
 */
function Fragment(node, context) {
	// Creates a new block which looks roughly like this:
	// ```js
	// // hoisted:
	// const block_name = $.from_html(`...`);
	//
	// // for the main block:
	// const id = block_name();
	// // init stuff and possibly render effect
	// $.append($$anchor, id);
	// ```
	// Adds the hoisted parts to `context.state.hoisted` and returns the statements of the main block.

	const parent = context.path.at(-1) ?? node;

	const namespace = infer_namespace(context.state.metadata.namespace, parent, node.nodes);

	const { hoisted, trimmed, is_standalone, is_text_first } = clean_nodes(
		parent,
		node.nodes,
		context.path,
		namespace,
		context.state,
		context.state.preserve_whitespace,
		context.state.options.preserveComments
	);

	if (hoisted.length === 0 && trimmed.length === 0) {
		return block([]);
	}

	const is_single_element = trimmed.length === 1 && trimmed[0].type === 'RegularElement';
	const is_single_child_not_needing_template =
		trimmed.length === 1 &&
		(trimmed[0].type === 'SvelteFragment' || trimmed[0].type === 'TitleElement');
	const template_name = context.state.scope.root.unique('root'); // TODO infer name from parent

	/** @type {Statement[]} */
	const body = [];

	/** @type {Statement | undefined} */
	let close = undefined;

	/** @type {ComponentClientTransformState} */
	const state = {
		...context.state,
		init: [],
		consts: [],
		let_directives: [],
		update: [],
		after_update: [],
		memoizer: new Memoizer(),
		template: new Template(),
		transform: { ...context.state.transform },
		metadata: {
			namespace,
			bound_contenteditable: context.state.metadata.bound_contenteditable
		},
		async_consts: undefined
	};

	for (const node of hoisted) {
		context.visit(node, state);
	}

	if (is_single_element) {
		const element = /** @type {AST.RegularElement} */ (trimmed[0]);

		const id$1 = id(context.state.scope.generate(element.name));

		context.visit(element, {
			...state,
			node: id$1
		});

		let flags = state.template.needs_import_node ? TEMPLATE_USE_IMPORT_NODE : undefined;

		const template = transform_template(state, namespace, flags);
		state.hoisted.push(var_builder(template_name, template));

		state.init.unshift(var_builder(id$1, call(template_name)));
		close = stmt(call('$.append', id('$$anchor'), id$1));
	} else if (is_single_child_not_needing_template) {
		context.visit(trimmed[0], state);
	} else if (trimmed.length === 1 && trimmed[0].type === 'Text') {
		const id$1 = id(context.state.scope.generate('text'));
		state.init.unshift(var_builder(id$1, call('$.text', literal(trimmed[0].data))));
		close = stmt(call('$.append', id('$$anchor'), id$1));
	} else if (trimmed.length > 0) {
		const id$1 = id(context.state.scope.generate('fragment'));

		const use_space_template =
			trimmed.some((node) => node.type === 'ExpressionTag') &&
			trimmed.every((node) => node.type === 'Text' || node.type === 'ExpressionTag');

		if (use_space_template) {
			// special case — we can use `$.text` instead of creating a unique template
			const id$1 = id(context.state.scope.generate('text'));

			process_children(trimmed, () => id$1, false, {
				...context,
				state
			});

			state.init.unshift(var_builder(id$1, call('$.text')));
			close = stmt(call('$.append', id('$$anchor'), id$1));
		} else {
			if (is_standalone) {
				// no need to create a template, we can just use the existing block's anchor
				process_children(trimmed, () => id('$$anchor'), false, { ...context, state });
			} else {
				/** @type {(is_text: boolean) => Expression} */
				const expression = (is_text) => call('$.first_child', id$1, is_text && true_instance);

				process_children(trimmed, expression, false, { ...context, state });

				let flags = TEMPLATE_FRAGMENT;

				if (state.template.needs_import_node) {
					flags |= TEMPLATE_USE_IMPORT_NODE;
				}

				if (state.template.nodes.length === 1 && state.template.nodes[0].type === 'comment') {
					// special case — we can use `$.comment` instead of creating a unique template
					state.init.unshift(var_builder(id$1, call('$.comment')));
				} else {
					const template = transform_template(state, namespace, flags);
					state.hoisted.push(var_builder(template_name, template));

					state.init.unshift(var_builder(id$1, call(template_name)));
				}

				close = stmt(call('$.append', id('$$anchor'), id$1));
			}
		}
	}

	body.push(...state.let_directives, ...state.consts);

	if (state.async_consts && state.async_consts.thunks.length > 0) {
		body.push(var_builder(state.async_consts.id, call('$.run', array(state.async_consts.thunks))));
	}

	if (is_text_first) {
		// skip over inserted comment
		body.push(stmt(call('$.next')));
	}

	body.push(...state.init);

	if (state.update.length > 0) {
		body.push(build_render_statement(state));
	}

	body.push(...state.after_update);

	if (close !== undefined) {
		// It's important that close is the last statement in the block, as any previous statements
		// could contain element insertions into the template, which the close statement needs to
		// know of when constructing the list of current inner elements.
		body.push(close);
	}

	return block(body);
}

/** @import { FunctionDeclaration } from 'estree' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {FunctionDeclaration} node
 * @param {ComponentContext} context
 */
function FunctionDeclaration(node, context) {
	const state = { ...context.state, in_constructor: false, in_derived: false };

	context.next(state);
}

/** @import { FunctionExpression } from 'estree' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {FunctionExpression} node
 * @param {ComponentContext} context
 */
function FunctionExpression(node, context) {
	return visit_function(node, context);
}

/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {AST.HtmlTag} node
 * @param {ComponentContext} context
 */
function HtmlTag(node, context) {
	context.state.template.push_comment();

	const is_async = node.metadata.expression.is_async();

	const expression = build_expression(context, node.expression, node.metadata.expression);
	const html = is_async ? call('$.get', id('$$html')) : expression;

	const is_svg = context.state.metadata.namespace === 'svg';
	const is_mathml = context.state.metadata.namespace === 'mathml';

	const statement = stmt(
		call(
			'$.html',
			context.state.node,
			thunk(html),
			is_svg && true_instance,
			is_mathml && true_instance,
			is_ignored(node, 'hydration_html_changed') && true_instance
		)
	);

	// push into init, so that bindings run afterwards, which might trigger another run and override hydration
	if (is_async) {
		context.state.init.push(
			stmt(
				call(
					'$.async',
					context.state.node,
					node.metadata.expression.blockers(),
					array([thunk(expression, node.metadata.expression.has_await)]),
					arrow([context.state.node, id('$$html')], block([statement]))
				)
			)
		);
	} else {
		context.state.init.push(statement);
	}
}

/** @import { Identifier, Node } from 'estree' */
/** @import { Context } from '../types' */

/**
 * @param {Identifier} node
 * @param {Context} context
 */
function Identifier(node, context) {
	const parent = /** @type {Node} */ (context.path.at(-1));

	if (is_reference(node, parent)) {
		if (node.name === '$$props') {
			return id('$$sanitized_props');
		}

		// Optimize prop access: If it's a member read access, we can use the $$props object directly
		const binding = context.state.scope.get(node.name);
		if (
			context.state.analysis.runes && // can't do this in legacy mode because the proxy does more than just read/write
			binding !== null &&
			node !== binding.node &&
			binding.kind === 'rest_prop'
		) {
			const grand_parent = context.path.at(-2);

			if (
				parent?.type === 'MemberExpression' &&
				!parent.computed &&
				grand_parent?.type !== 'AssignmentExpression' &&
				grand_parent?.type !== 'UpdateExpression'
			) {
				const key = /** @type {Identifier} */ (parent.property);

				if (!binding.metadata?.exclude_props?.includes(key.name)) {
					return id('$$props');
				}
			}
		}

		return build_getter$1(node, context.state);
	}
}

/** @import { BlockStatement, Expression } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {AST.IfBlock} node
 * @param {ComponentContext} context
 */
function IfBlock(node, context) {
	context.state.template.push_comment();
	const statements = [];

	const consequent = /** @type {BlockStatement} */ (context.visit(node.consequent));
	const consequent_id = id(context.state.scope.generate('consequent'));

	statements.push(var_builder(consequent_id, arrow([id('$$anchor')], consequent)));

	let alternate_id;

	if (node.alternate) {
		const alternate = /** @type {BlockStatement} */ (context.visit(node.alternate));
		alternate_id = id(context.state.scope.generate('alternate'));
		statements.push(var_builder(alternate_id, arrow([id('$$anchor')], alternate)));
	}

	const is_async = node.metadata.expression.is_async();

	const expression = build_expression(context, node.test, node.metadata.expression);
	const test = is_async ? call('$.get', id('$$condition')) : expression;

	/** @type {Expression[]} */
	const args = [
		context.state.node,
		arrow(
			[id('$$render')],
			block([
				if_builder(
					test,
					stmt(call('$$render', consequent_id)),
					alternate_id && stmt(call('$$render', alternate_id, literal(false)))
				)
			])
		)
	];

	if (node.elseif) {
		// We treat this...
		//
		//   {#if x}
		//     ...
		//   {:else}
		//     {#if y}
		//       <div transition:foo>...</div>
		//     {/if}
		//   {/if}
		//
		// ...slightly differently to this...
		//
		//   {#if x}
		//     ...
		//   {:else if y}
		//     <div transition:foo>...</div>
		//   {/if}
		//
		// ...even though they're logically equivalent. In the first case, the
		// transition will only play when `y` changes, but in the second it
		// should play when `x` or `y` change — both are considered 'local'
		args.push(true_instance);
	}

	statements.push(add_svelte_meta(call('$.if', ...args), node, 'if'));

	if (is_async) {
		context.state.init.push(
			stmt(
				call(
					'$.async',
					context.state.node,
					node.metadata.expression.blockers(),
					array([thunk(expression, node.metadata.expression.has_await)]),
					arrow([context.state.node, id('$$condition')], block(statements))
				)
			)
		);
	} else {
		context.state.init.push(block(statements));
	}
}

/** @import { Expression } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {AST.KeyBlock} node
 * @param {ComponentContext} context
 */
function KeyBlock(node, context) {
	context.state.template.push_comment();

	const is_async = node.metadata.expression.is_async();

	const expression = build_expression(context, node.expression, node.metadata.expression);
	const key = thunk(is_async ? call('$.get', id('$$key')) : expression);
	const body = /** @type {Expression} */ (context.visit(node.fragment));

	let statement = add_svelte_meta(
		call('$.key', context.state.node, key, arrow([id('$$anchor')], body)),
		node,
		'key'
	);

	if (is_async) {
		statement = stmt(
			call(
				'$.async',
				context.state.node,
				node.metadata.expression.blockers(),
				array([thunk(expression, node.metadata.expression.has_await)]),
				arrow([context.state.node, id('$$key')], block([statement]))
			)
		);
	}

	context.state.init.push(statement);
}

/** @import { Expression, LabeledStatement, Statement } from 'estree' */
/** @import { ReactiveStatement } from '#compiler' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {LabeledStatement} node
 * @param {ComponentContext} context
 */
function LabeledStatement(node, context) {
	if (context.state.analysis.runes || context.path.length > 1 || node.label.name !== '$') {
		context.next();
		return;
	}

	// To recreate Svelte 4 behaviour, we track the dependencies
	// the compiler can 'see', but we untrack the effect itself
	const reactive_statement = /** @type {ReactiveStatement} */ (
		context.state.analysis.reactive_statements.get(node)
	);

	if (!reactive_statement) return; // not the instance context

	let serialized_body = /** @type {Statement} */ (context.visit(node.body));

	if (serialized_body.type !== 'BlockStatement') {
		serialized_body = block([serialized_body]);
	}

	const body = serialized_body.body;

	/** @type {Expression[]} */
	const sequence$1 = [];

	for (const binding of reactive_statement.dependencies) {
		if (binding.kind === 'normal' && binding.declaration_kind !== 'import') continue;

		const name = binding.node.name;
		let serialized = build_getter$1(id(name), context.state);

		// If the binding is a prop, we need to deep read it because it could be fine-grained $state
		// from a runes-component, where mutations don't trigger an update on the prop as a whole.
		if (name === '$$props' || name === '$$restProps' || binding.kind === 'bindable_prop') {
			serialized = call('$.deep_read_state', serialized);
		}

		sequence$1.push(serialized);
	}

	// these statements will be topologically ordered later
	context.state.legacy_reactive_statements.set(
		node,
		stmt(
			call(
				'$.legacy_pre_effect',
				sequence$1.length > 0 ? thunk(sequence(sequence$1)) : thunk(block([])),
				thunk(block(body))
			)
		)
	);

	return empty;
}

/** @import { Expression } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {AST.LetDirective} node
 * @param {ComponentContext} context
 */
function LetDirective(node, context) {
	// let:x        -->  const x = $.derived(() => $$slotProps.x);
	// let:x={{y, z}}  -->  const derived_x = $.derived(() => { const { y, z } = $$slotProps.x; return { y, z }));
	if (node.expression && node.expression.type !== 'Identifier') {
		const name = context.state.scope.generate(node.name);
		const bindings = context.state.scope.get_bindings(node);

		for (const binding of bindings) {
			context.state.transform[binding.node.name] = {
				read: (node) => member(call('$.get', id(name)), node)
			};
		}

		context.state.let_directives.push(
			const_builder(
				name,
				call(
					'$.derived',
					thunk(
						block([
							let_builder(
								/** @type {Expression} */ (node.expression).type === 'ObjectExpression'
									? // @ts-expect-error types don't match, but it can't contain spread elements and the structure is otherwise fine
										object_pattern(node.expression.properties)
									: // @ts-expect-error types don't match, but it can't contain spread elements and the structure is otherwise fine
										array_pattern(node.expression.elements),
								member(id('$$slotProps'), node.name)
							),
							return_builder(object$2(bindings.map((binding) => init(binding.node.name, binding.node))))
						])
					)
				)
			)
		);
	} else {
		const name = node.expression === null ? node.name : node.expression.name;
		context.state.transform[name] = {
			read: (node) => call('$.get', node)
		};

		context.state.let_directives.push(
			const_builder(name, create_derived(context.state, member(id('$$slotProps'), node.name)))
		);
	}
}

/** @import { MemberExpression } from 'estree' */
/** @import { Context } from '../types' */

/**
 * @param {MemberExpression} node
 * @param {Context} context
 */
function MemberExpression(node, context) {
	// rewrite `this.#foo` as `this.#foo.v` inside a constructor
	if (node.property.type === 'PrivateIdentifier') {
		const field = context.state.state_fields.get('#' + node.property.name);

		if (field) {
			return context.state.in_constructor &&
				(field.type === '$state.raw' || field.type === '$state')
				? member(node, 'v')
				: call('$.get', node);
		}
	}

	context.next();
}

/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */

const modifiers = /** @type {const} */ ([
	'stopPropagation',
	'stopImmediatePropagation',
	'preventDefault',
	'self',
	'trusted',
	'once'
]);

/**
 * @param {AST.OnDirective} node
 * @param {ComponentContext} context
 */
function OnDirective(node, context) {
	if (!node.expression) {
		context.state.analysis.needs_props = true;
	}

	let handler = build_event_handler(node.expression, node.metadata.expression, context);

	for (const modifier of modifiers) {
		if (node.modifiers.includes(modifier)) {
			handler = call('$.' + modifier, handler);
		}
	}

	const capture = node.modifiers.includes('capture');
	const passive =
		node.modifiers.includes('passive') ||
		(node.modifiers.includes('nonpassive') ? false : undefined);

	return build_event(node.name, context.state.node, handler, capture, passive);
}

/** @import { Expression, ImportDeclaration, MemberExpression, Node, Program } from 'estree' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {Program} node
 * @param {ComponentContext} context
 */
function Program(node, context) {
	if (!context.state.analysis.runes) {
		context.state.transform['$$props'] = {
			read: (node) => ({ ...node, name: '$$sanitized_props' })
		};

		for (const [name, binding] of context.state.scope.declarations) {
			if (binding.declaration_kind === 'import' && binding.mutated) {
				// the declaration itself is hoisted to the module scope, so we need
				// to resort to cruder measures to differentiate instance/module imports
				const { start, end } = context.state.analysis.instance.ast;
				const node = /** @type {ImportDeclaration} */ (binding.initial);
				const is_instance_import =
					/** @type {number} */ (node.start) > /** @type {number} */ (start) &&
					/** @type {number} */ (node.end) < /** @type {number} */ (end);

				if (is_instance_import) {
					const id$1 = id('$$_import_' + name);

					context.state.transform[name] = {
						read: (_) => call(id$1),
						mutate: (_, mutation) => call(id$1, mutation)
					};

					context.state.legacy_reactive_imports.push(
						var_builder(id$1, call('$.reactive_import', thunk(id(name))))
					);
				}
			}
		}
	}

	for (const [name, binding] of context.state.scope.declarations) {
		if (binding.kind === 'store_sub') {
			// read lazily, so that transforms added later are still applied
			/** @type {Expression} */
			let cached;

			const get_store = () => {
				return (cached ??= /** @type {Expression} */ (context.visit(id(name.slice(1)))));
			};

			context.state.transform[name] = {
				read: call,
				assign: (_, value) => call('$.store_set', get_store(), value),
				mutate: (node, mutation) => {
					// We need to untrack the store read, for consistency with Svelte 4
					const untracked = call('$.untrack', node);

					/**
					 *
					 * @param {Expression} n
					 * @returns {Expression}
					 */
					function replace(n) {
						if (n.type === 'MemberExpression') {
							return {
								...n,
								object: replace(/** @type {Expression} */ (n.object)),
								property: n.property
							};
						}

						return untracked;
					}

					return call(
						'$.store_mutate',
						get_store(),
						mutation.type === 'AssignmentExpression'
							? assignment(
									mutation.operator,
									/** @type {MemberExpression} */ (
										replace(/** @type {MemberExpression} */ (mutation.left))
									),
									mutation.right
								)
							: update(mutation.operator, replace(mutation.argument), mutation.prefix),
						untracked
					);
				},
				update: (node) => {
					return call(
						node.prefix ? '$.update_pre_store' : '$.update_store',
						build_getter$1(id(name.slice(1)), context.state),
						call(node.argument),
						node.operator === '--' && literal(-1)
					);
				}
			};
		}

		if (binding.kind === 'prop' || binding.kind === 'bindable_prop') {
			if (is_prop_source(binding, context.state)) {
				context.state.transform[name] = {
					read: call,
					assign: (node, value) => call(node, value),
					mutate: (node, value) => {
						if (binding.kind === 'bindable_prop') {
							// only necessary for interop with legacy parent bindings
							return call(node, value, true_instance);
						}

						return value;
					},
					update: (node) => {
						return call(
							node.prefix ? '$.update_pre_prop' : '$.update_prop',
							node.argument,
							node.operator === '--' && literal(-1)
						);
					}
				};
			} else if (binding.prop_alias) {
				const key$1 = key(binding.prop_alias);

				context.state.transform[name] = {
					read: (_) => member(id('$$props'), key$1, key$1.type === 'Literal')
				};
			} else {
				context.state.transform[name] = {
					read: (node) => member(id('$$props'), node)
				};
			}
		}
	}

	add_state_transformers(context);

	if (context.state.is_instance) {
		return {
			...node,
			body: transform_body(
				context.state.analysis.instance_body,
				id('$.run'),
				(node) => /** @type {Node} */ (context.visit(node))
			)
		};
	}

	context.next();
}

/** @import { Expression, Statement } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {AST.RenderTag} node
 * @param {ComponentContext} context
 */
function RenderTag(node, context) {
	context.state.template.push_comment();

	const call$1 = unwrap_optional(node.expression);

	/** @type {Expression[]} */
	let args = [];

	const memoizer = new Memoizer();

	for (let i = 0; i < call$1.arguments.length; i++) {
		const arg = /** @type {Expression} */ (call$1.arguments[i]);
		const metadata = node.metadata.arguments[i];
		let expression = build_expression(context, arg, metadata);
		const memoized = memoizer.add(expression, metadata);

		if (expression !== memoized) {
			expression = call('$.get', memoized);
		}

		args.push(thunk(expression));
	}

	memoizer.apply();

	/** @type {Statement[]} */
	const statements = memoizer.deriveds(context.state.analysis.runes);

	let snippet_function = build_expression(
		context,
		/** @type {Expression} */ (call$1.callee),
		node.metadata.expression
	);

	if (node.metadata.dynamic) {
		// If we have a chain expression then ensure a nullish snippet function gets turned into an empty one
		if (node.expression.type === 'ChainExpression') {
			snippet_function = logical$1('??', snippet_function, id('$.noop'));
		}

		statements.push(
			add_svelte_meta(
				call('$.snippet', context.state.node, thunk(snippet_function), ...args),
				node,
				'render'
			)
		);
	} else {
		statements.push(
			add_svelte_meta(
				(node.expression.type === 'CallExpression' ? call : maybe_call)(
					snippet_function,
					context.state.node,
					...args
				),
				node,
				'render'
			)
		);
	}

	const async_values = memoizer.async_values();
	const blockers = memoizer.blockers();

	if (async_values || blockers) {
		context.state.init.push(
			stmt(
				call(
					'$.async',
					context.state.node,
					blockers,
					memoizer.async_values(),
					arrow([context.state.node, ...memoizer.async_ids()], block(statements))
				)
			)
		);
	} else {
		context.state.init.push(statements.length === 1 ? statements[0] : block(statements));
	}
}

/** @import { BlockStatement, Expression, ExpressionStatement, Literal, Property, Statement } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {AST.SlotElement} node
 * @param {ComponentContext} context
 */
function SlotElement(node, context) {
	// <slot {a}>fallback</slot>  -->   $.slot($$slots.default, { get a() { .. } }, () => ...fallback);
	context.state.template.push_comment();

	/** @type {Property[]} */
	const props = [];

	/** @type {Expression[]} */
	const spreads = [];

	/** @type {ExpressionStatement[]} */
	const lets = [];

	const memoizer = new Memoizer();

	let name = literal('default');

	for (const attribute of node.attributes) {
		if (attribute.type === 'SpreadAttribute') {
			spreads.push(thunk(/** @type {Expression} */ (context.visit(attribute))));
		} else if (attribute.type === 'Attribute') {
			const { value, has_state } = build_attribute_value(
				attribute.value,
				context,
				(value, metadata) =>
					metadata.has_call || metadata.has_await
						? call('$.get', memoizer.add(value, metadata))
						: value
			);

			if (attribute.name === 'name') {
				name = /** @type {Literal} */ (value);
			} else if (attribute.name !== 'slot') {
				if (has_state) {
					props.push(get$1(attribute.name, [return_builder(value)]));
				} else {
					props.push(init(attribute.name, value));
				}
			}
		} else if (attribute.type === 'LetDirective') {
			context.visit(attribute, { ...context.state, let_directives: lets });
		}
	}

	memoizer.apply();

	// Let bindings first, they can be used on attributes
	context.state.init.push(...lets);

	/** @type {Statement[]} */
	const statements = memoizer.deriveds(context.state.analysis.runes);

	const props_expression =
		spreads.length === 0 ? object$2(props) : call('$.spread_props', object$2(props), ...spreads);

	const fallback =
		node.fragment.nodes.length === 0
			? null_instance
			: arrow([id('$$anchor')], /** @type {BlockStatement} */ (context.visit(node.fragment)));

	statements.push(
		stmt(call('$.slot', context.state.node, id('$$props'), name, props_expression, fallback))
	);

	const async_values = memoizer.async_values();
	const blockers = memoizer.blockers();

	if (async_values || blockers) {
		context.state.init.push(
			stmt(
				call(
					'$.async',
					context.state.node,
					blockers,
					async_values,
					arrow([context.state.node, ...memoizer.async_ids()], block(statements))
				)
			)
		);
	} else {
		context.state.init.push(statements.length === 1 ? statements[0] : block(statements));
	}
}

/** @import { AssignmentPattern, BlockStatement, Expression, Identifier, Statement } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {AST.SnippetBlock} node
 * @param {ComponentContext} context
 */
function SnippetBlock(node, context) {
	// TODO hoist where possible
	/** @type {(Identifier | AssignmentPattern)[]} */
	const args = [id('$$anchor')];
	/** @type {BlockStatement} */
	let body;

	/** @type {Statement[]} */
	const declarations = [];

	const transform = { ...context.state.transform };
	const child_state = { ...context.state, transform };

	for (let i = 0; i < node.parameters.length; i++) {
		const argument = node.parameters[i];

		if (!argument) continue;

		if (argument.type === 'Identifier') {
			args.push(assignment_pattern(argument, id('$.noop')));
			transform[argument.name] = { read: call };

			continue;
		}

		let arg_alias = `$$arg${i}`;
		args.push(id(arg_alias));

		const { inserts, paths } = extract_paths(argument, maybe_call(id(arg_alias)));

		for (const { id, value } of inserts) {
			id.name = context.state.scope.generate('$$array');
			transform[id.name] = { read: get_value };

			declarations.push(
				var_builder(id, call('$.derived', /** @type {Expression} */ (context.visit(thunk(value)))))
			);
		}

		for (const path of paths) {
			const name = /** @type {Identifier} */ (path.node).name;
			const needs_derived = path.has_default_value; // to ensure that default value is only called once
			const fn = thunk(/** @type {Expression} */ (context.visit(path.expression, child_state)));

			declarations.push(let_builder(path.node, needs_derived ? call('$.derived_safe_equal', fn) : fn));

			transform[name] = {
				read: needs_derived ? get_value : call
			};

			// we need to eagerly evaluate the expression in order to hit any
			// 'Cannot access x before initialization' errors
			if (dev) {
				declarations.push(stmt(transform[name].read(id(name))));
			}
		}
	}
	const block$1 = /** @type {BlockStatement} */ (context.visit(node.body, child_state)).body;
	body = block([
		dev ? stmt(call('$.validate_snippet_args', spread(id('arguments')))) : empty,
		...declarations,
		...block$1
	]);

	// in dev we use a FunctionExpression (not arrow function) so we can use `arguments`
	let snippet = dev
		? call('$.wrap_snippet', id(context.state.analysis.name), function_builder(null, args, body))
		: arrow(args, body);

	const declaration = const_builder(node.expression, snippet);

	// Top-level snippets are hoisted so they can be referenced in the `<script>`
	if (context.path.length === 1 && context.path[0].type === 'Fragment') {
		if (node.metadata.can_hoist) {
			context.state.module_level_snippets.push(declaration);
		} else {
			context.state.instance_level_snippets.push(declaration);
		}
	} else {
		context.state.init.push(declaration);
	}
}

/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {AST.SpreadAttribute} node
 * @param {ComponentContext} context
 */
function SpreadAttribute(node, context) {
	return context.visit(node.expression);
}

/** @import { Expression } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../../types' */

/**
 *
 * @param {AST.SvelteBody | AST.SvelteDocument | AST.SvelteWindow} node
 * @param {string} id
 * @param {ComponentContext} context
 */
function visit_special_element(node, id$1, context) {
	const state = { ...context.state, node: id(id$1) };

	for (const attribute of node.attributes) {
		if (attribute.type === 'OnDirective') {
			context.state.init.push(stmt(/** @type {Expression} */ (context.visit(attribute, state))));
		} else {
			context.visit(attribute, state);
		}
	}
}

/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {AST.SvelteBody} node
 * @param {ComponentContext} context
 */
function SvelteBody(node, context) {
	visit_special_element(node, '$.document.body', context);
}

/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {AST.SvelteComponent} node
 * @param {ComponentContext} context
 */
function SvelteComponent(node, context) {
	const component = build_component(node, '$$component', context);
	context.state.init.push(component);
}

/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {AST.SvelteDocument} node
 * @param {ComponentContext} context
 */
function SvelteDocument(node, context) {
	visit_special_element(node, '$.document', context);
}

/** @import { BlockStatement, Expression, ExpressionStatement, Statement } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {AST.SvelteElement} node
 * @param {ComponentContext} context
 */
function SvelteElement(node, context) {
	context.state.template.push_comment();

	/** @type {Array<AST.Attribute | AST.SpreadAttribute>} */
	const attributes = [];

	/** @type {AST.Attribute['value'] | undefined} */
	let dynamic_namespace = undefined;

	/** @type {AST.ClassDirective[]} */
	const class_directives = [];

	/** @type {AST.StyleDirective[]} */
	const style_directives = [];

	/** @type {ExpressionStatement[]} */
	const statements = [];

	// Create a temporary context which picks up the init/update statements.
	// They'll then be added to the function parameter of $.element
	const element_id = id(context.state.scope.generate('$$element'));

	/** @type {ComponentContext} */
	const inner_context = {
		...context,
		state: {
			...context.state,
			node: element_id,
			init: [],
			update: [],
			after_update: [],
			memoizer: new Memoizer()
		}
	};

	for (const attribute of node.attributes) {
		if (attribute.type === 'Attribute') {
			if (attribute.name === 'xmlns' && !is_text_attribute(attribute)) {
				dynamic_namespace = attribute.value;
			}
			attributes.push(attribute);
		} else if (attribute.type === 'SpreadAttribute') {
			attributes.push(attribute);
		} else if (attribute.type === 'ClassDirective') {
			class_directives.push(attribute);
		} else if (attribute.type === 'StyleDirective') {
			style_directives.push(attribute);
		} else if (attribute.type === 'LetDirective') {
			statements.push(/** @type {ExpressionStatement} */ (context.visit(attribute)));
		} else if (attribute.type === 'OnDirective') {
			const handler = /** @type {Expression} */ (context.visit(attribute, inner_context.state));
			inner_context.state.after_update.push(stmt(handler));
		} else {
			context.visit(attribute, inner_context.state);
		}
	}

	if (
		attributes.length === 1 &&
		attributes[0].type === 'Attribute' &&
		attributes[0].name.toLowerCase() === 'class' &&
		is_text_attribute(attributes[0])
	) {
		build_set_class(node, element_id, attributes[0], class_directives, inner_context, false);
	} else if (attributes.length) {
		// Always use spread because we don't know whether the element is a custom element or not,
		// therefore we need to do the "how to set an attribute" logic at runtime.
		build_attribute_effect(
			attributes,
			class_directives,
			style_directives,
			inner_context,
			node,
			element_id
		);
	}

	const is_async = node.metadata.expression.is_async();

	const expression = /** @type {Expression} */ (context.visit(node.tag));
	const get_tag = thunk(is_async ? call('$.get', id('$$tag')) : expression);

	/** @type {Statement[]} */
	const inner = inner_context.state.init;
	if (inner_context.state.update.length > 0) {
		inner.push(build_render_statement(inner_context.state));
	}
	inner.push(...inner_context.state.after_update);
	inner.push(
		.../** @type {BlockStatement} */ (
			context.visit(node.fragment, {
				...context.state,
				metadata: {
					...context.state.metadata,
					namespace: determine_namespace_for_children(node, context.state.metadata.namespace)
				}
			})
		).body
	);

	if (dev) {
		if (node.fragment.nodes.length > 0) {
			statements.push(stmt(call('$.validate_void_dynamic_element', get_tag)));
		}
		statements.push(stmt(call('$.validate_dynamic_element_tag', get_tag)));
	}

	const location = dev && locator(node.start);

	statements.push(
		stmt(
			call(
				'$.element',
				context.state.node,
				get_tag,
				node.metadata.svg || node.metadata.mathml ? true_instance : false_instance,
				inner.length > 0 && arrow([element_id, id('$$anchor')], block(inner)),
				dynamic_namespace && thunk(build_attribute_value(dynamic_namespace, context).value),
				location && array([literal(location.line), literal(location.column)])
			)
		)
	);

	if (is_async) {
		context.state.init.push(
			stmt(
				call(
					'$.async',
					context.state.node,
					node.metadata.expression.blockers(),
					array([thunk(expression, node.metadata.expression.has_await)]),
					arrow([context.state.node, id('$$tag')], block(statements))
				)
			)
		);
	} else {
		context.state.init.push(statements.length === 1 ? statements[0] : block(statements));
	}
}

/** @import { BlockStatement, ExpressionStatement } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {AST.SvelteFragment} node
 * @param {ComponentContext} context
 */
function SvelteFragment(node, context) {
	for (const attribute of node.attributes) {
		if (attribute.type === 'LetDirective') {
			context.visit(attribute);
		}
	}

	context.state.init.push(.../** @type {BlockStatement} */ (context.visit(node.fragment)).body);
}

/** @import { BlockStatement, Statement, Expression, VariableDeclaration } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {AST.SvelteBoundary} node
 * @param {ComponentContext} context
 */
function SvelteBoundary(node, context) {
	const props = object$2([]);

	for (const attribute of node.attributes) {
		if (attribute.type !== 'Attribute' || attribute.value === true) {
			// these can't exist, because they would have caused validation
			// to fail, but typescript doesn't know that
			continue;
		}

		const chunk = Array.isArray(attribute.value)
			? /** @type {AST.ExpressionTag} */ (attribute.value[0])
			: attribute.value;

		const expression = /** @type {Expression} */ (context.visit(chunk.expression, context.state));

		if (chunk.metadata.expression.has_state) {
			props.properties.push(get$1(attribute.name, [return_builder(expression)]));
		} else {
			props.properties.push(init(attribute.name, expression));
		}
	}

	const nodes = [];

	/** @type {Statement[]} */
	const const_tags = [];

	/** @type {Statement[]} */
	const hoisted = [];

	let has_const = false;

	// const tags need to live inside the boundary, but might also be referenced in hoisted snippets.
	// to resolve this we cheat: we duplicate const tags inside snippets
	// We'll revert this behavior in the future, it was a mistake to allow this (Component snippets also don't do this).
	for (const child of node.fragment.nodes) {
		if (child.type === 'ConstTag') {
			has_const = true;
			if (!context.state.options.experimental.async) {
				context.visit(child, {
					...context.state,
					consts: const_tags,
					scope: context.state.scopes.get(node.fragment) ?? context.state.scope
				});
			}
		}
	}

	for (const child of node.fragment.nodes) {
		if (child.type === 'ConstTag') {
			if (context.state.options.experimental.async) {
				nodes.push(child);
			}
			continue;
		}

		if (child.type === 'SnippetBlock') {
			if (
				context.state.options.experimental.async &&
				has_const &&
				!['failed', 'pending'].includes(child.expression.name)
			) {
				// we can't hoist snippets as they may reference const tags, so we just keep them in the fragment
				nodes.push(child);
			} else {
				/** @type {Statement[]} */
				const statements = [];

				context.visit(child, { ...context.state, init: statements });

				const snippet = /** @type {VariableDeclaration} */ (statements[0]);

				const snippet_fn = dev
					? // @ts-expect-error we know this shape is correct
						snippet.declarations[0].init.arguments[1]
					: snippet.declarations[0].init;

				if (!context.state.options.experimental.async) {
					snippet_fn.body.body.unshift(
						...const_tags.filter((node) => node.type === 'VariableDeclaration')
					);
				}

				if (['failed', 'pending'].includes(child.expression.name)) {
					props.properties.push(prop('init', child.expression, child.expression));
				}

				hoisted.push(snippet);
			}

			continue;
		}

		nodes.push(child);
	}

	const block$1 = /** @type {BlockStatement} */ (
		context.visit(
			{ ...node.fragment, nodes },
			// Since we're creating a new fragment the reference in scopes can't match, so we gotta attach the right scope manually
			{ ...context.state, scope: context.state.scopes.get(node.fragment) ?? context.state.scope }
		)
	);

	if (!context.state.options.experimental.async) {
		block$1.body.unshift(...const_tags);
	}

	const boundary = stmt(
		call('$.boundary', context.state.node, props, arrow([id('$$anchor')], block$1))
	);

	context.state.template.push_comment();
	context.state.init.push(hoisted.length > 0 ? block([...hoisted, boundary]) : boundary);
}

/** @import { BlockStatement } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {AST.SvelteHead} node
 * @param {ComponentContext} context
 */
function SvelteHead(node, context) {
	// TODO attributes?
	context.state.init.push(
		stmt(
			call(
				'$.head',
				literal(hash(filename)),
				arrow([id('$$anchor')], /** @type {BlockStatement} */ (context.visit(node.fragment)))
			)
		)
	);
}

/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {AST.SvelteSelf} node
 * @param {ComponentContext} context
 */
function SvelteSelf(node, context) {
	const component = build_component(node, context.state.analysis.name, context);
	context.state.init.push(component);
}

/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {AST.SvelteWindow} node
 * @param {ComponentContext} context
 */
function SvelteWindow(node, context) {
	visit_special_element(node, '$.window', context);
}

/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {AST.TitleElement} node
 * @param {ComponentContext} context
 */
function TitleElement(node, context) {
	const memoizer = new Memoizer();
	const { has_state, value } = build_template_chunk(
		/** @type {any} */ (node.fragment.nodes),
		context,
		context.state,
		(value, metadata) => memoizer.add(value, metadata)
	);
	const evaluated = context.state.scope.evaluate(value);

	const statement = stmt(
		assignment(
			'=',
			id('$.document.title'),
			evaluated.is_known
				? literal(evaluated.value)
				: evaluated.is_defined
					? value
					: logical$1('??', value, literal(''))
		)
	);

	// Make sure it only changes the title once async work is done
	if (has_state) {
		context.state.after_update.push(
			stmt(
				call(
					'$.deferred_template_effect',
					arrow(memoizer.apply(), block([statement])),
					memoizer.sync_values(),
					memoizer.async_values(),
					memoizer.blockers()
				)
			)
		);
	} else {
		context.state.after_update.push(stmt(call('$.effect', thunk(block([statement])))));
	}
}

/** @import { Expression } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {AST.TransitionDirective} node
 * @param {ComponentContext} context
 */
function TransitionDirective(node, context) {
	let flags = node.modifiers.includes('global') ? TRANSITION_GLOBAL : 0;
	if (node.intro) flags |= TRANSITION_IN;
	if (node.outro) flags |= TRANSITION_OUT;

	const args = [
		literal(flags),
		context.state.node,
		thunk(/** @type {Expression} */ (context.visit(parse_directive_name(node.name))))
	];

	if (node.expression) {
		args.push(thunk(/** @type {Expression} */ (context.visit(node.expression))));
	}

	// in after_update to ensure it always happens after bind:this
	let statement = stmt(call('$.transition', ...args));

	if (node.metadata.expression.is_async()) {
		statement = stmt(
			call(
				'$.run_after_blockers',
				node.metadata.expression.blockers(),
				thunk(block([statement]))
			)
		);
	}

	context.state.after_update.push(statement);
}

/** @import { AssignmentExpression, Expression, UpdateExpression } from 'estree' */
/** @import { Context } from '../types' */

/**
 * @param {UpdateExpression} node
 * @param {Context} context
 */
function UpdateExpression(node, context) {
	const argument = node.argument;

	if (
		argument.type === 'MemberExpression' &&
		argument.object.type === 'ThisExpression' &&
		argument.property.type === 'PrivateIdentifier' &&
		context.state.state_fields.has('#' + argument.property.name)
	) {
		let fn = '$.update';
		if (node.prefix) fn += '_pre';

		/** @type {Expression[]} */
		const args = [argument];
		if (node.operator === '--') {
			args.push(literal(-1));
		}

		return call(fn, ...args);
	}

	if (argument.type !== 'Identifier' && argument.type !== 'MemberExpression') {
		throw new Error('An impossible state was reached');
	}

	const left = object$1(argument);
	const transformers = left && context.state.transform[left.name];

	if (left === argument && transformers?.update) {
		// we don't need to worry about ownership_invalid_mutation here, because
		// we're not mutating but reassigning
		return transformers.update(node);
	}

	let update = /** @type {Expression} */ (context.next());

	if (left && transformers?.mutate) {
		update = transformers.mutate(
			left,
			/** @type {AssignmentExpression | UpdateExpression} */ (update)
		);
	}

	return validate_mutation(node, context, update);
}

/** @import { Expression } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {AST.UseDirective} node
 * @param {ComponentContext} context
 */
function UseDirective(node, context) {
	const params = [id('$$node')];

	if (node.expression) {
		params.push(id('$$action_arg'));
	}

	/** @type {Expression[]} */
	const args = [
		context.state.node,
		arrow(
			params,
			maybe_call(
				/** @type {Expression} */ (context.visit(parse_directive_name(node.name))),
				...params
			)
		)
	];

	if (node.expression) {
		args.push(thunk(/** @type {Expression} */ (context.visit(node.expression))));
	}

	// actions need to run after attribute updates in order with bindings/events
	let statement = stmt(call('$.action', ...args));

	if (node.metadata.expression.is_async()) {
		statement = stmt(
			call(
				'$.run_after_blockers',
				node.metadata.expression.blockers(),
				thunk(block([statement]))
			)
		);
	}

	context.state.init.push(statement);
	context.next();
}

/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {AST.AttachTag} node
 * @param {ComponentContext} context
 */
function AttachTag(node, context) {
	const expression = build_expression(context, node.expression, node.metadata.expression);
	let statement = stmt(call('$.attach', context.state.node, thunk(expression)));

	if (node.metadata.expression.is_async()) {
		statement = stmt(
			call(
				'$.run_after_blockers',
				node.metadata.expression.blockers(),
				thunk(block([statement]))
			)
		);
	}

	context.state.init.push(statement);
	context.next();
}

/** @import { CallExpression, Expression, Identifier, Literal, VariableDeclaration, VariableDeclarator } from 'estree' */
/** @import { Binding } from '#compiler' */
/** @import { ComponentContext } from '../types' */

/**
 * @param {VariableDeclaration} node
 * @param {ComponentContext} context
 */
function VariableDeclaration(node, context) {
	/** @type {VariableDeclarator[]} */
	const declarations = [];

	if (context.state.analysis.runes) {
		for (const declarator$1 of node.declarations) {
			const init = /** @type {Expression} */ (declarator$1.init);
			const rune = get_rune(init, context.state.scope);

			if (
				!rune ||
				rune === '$effect.tracking' ||
				rune === '$effect.root' ||
				rune === '$inspect' ||
				rune === '$inspect.trace' ||
				rune === '$state.snapshot' ||
				rune === '$host'
			) {
				declarations.push(/** @type {VariableDeclarator} */ (context.visit(declarator$1)));
				continue;
			}

			if (rune === '$props.id') {
				// skip
				continue;
			}

			if (rune === '$props') {
				/** @type {string[]} */
				const seen = ['$$slots', '$$events', '$$legacy'];

				if (context.state.analysis.custom_element) {
					seen.push('$$host');
				}

				if (declarator$1.id.type === 'Identifier') {
					/** @type {Expression[]} */
					const args = [id('$$props'), array(seen.map((name) => literal(name)))];

					if (dev) {
						// include rest name, so we can provide informative error messages
						args.push(literal(declarator$1.id.name));
					}

					declarations.push(declarator(declarator$1.id, call('$.rest_props', ...args)));
				} else {
					equal(declarator$1.id.type, 'ObjectPattern');

					for (const property of declarator$1.id.properties) {
						if (property.type === 'Property') {
							const key = /** @type {Identifier | Literal} */ (property.key);
							const name = key.type === 'Identifier' ? key.name : /** @type {string} */ (key.value);

							seen.push(name);

							let id =
								property.value.type === 'AssignmentPattern' ? property.value.left : property.value;
							equal(id.type, 'Identifier');
							const binding = /** @type {Binding} */ (context.state.scope.get(id.name));
							let initial =
								binding.initial && /** @type {Expression} */ (context.visit(binding.initial));
							// We're adding proxy here on demand and not within the prop runtime function so that
							// people not using proxied state anywhere in their code don't have to pay the additional bundle size cost
							if (
								initial &&
								binding.kind === 'bindable_prop' &&
								should_proxy(initial, context.state.scope)
							) {
								initial = call('$.proxy', initial);

								if (dev) {
									initial = call('$.tag_proxy', initial, literal(id.name));
								}
							}

							if (is_prop_source(binding, context.state)) {
								declarations.push(
									declarator(id, get_prop_source(binding, context.state, name, initial))
								);
							}
						} else {
							// RestElement
							/** @type {Expression[]} */
							const args = [id('$$props'), array(seen.map((name) => literal(name)))];

							if (dev) {
								// include rest name, so we can provide informative error messages
								args.push(literal(/** @type {Identifier} */ (property.argument).name));
							}

							declarations.push(declarator(property.argument, call('$.rest_props', ...args)));
						}
					}
				}

				// TODO
				continue;
			}

			const args = /** @type {CallExpression} */ (init).arguments;
			const value = /** @type {Expression} */ (args[0]) ?? void0; // TODO do we need the void 0? can we just omit it altogether?

			if (rune === '$state' || rune === '$state.raw') {
				/**
				 * @param {Identifier} id
				 * @param {Expression} value
				 */
				const create_state_declarator = (id, value) => {
					const binding = /** @type {import('#compiler').Binding} */ (
						context.state.scope.get(id.name)
					);
					const is_state = is_state_source(binding, context.state.analysis);
					const is_proxy = should_proxy(value, context.state.scope);

					if (rune === '$state' && is_proxy) {
						value = call('$.proxy', value);

						if (dev && !is_state) {
							value = call('$.tag_proxy', value, literal(id.name));
						}
					}

					if (is_state) {
						value = call('$.state', value);

						if (dev) {
							value = call('$.tag', value, literal(id.name));
						}
					}

					return value;
				};

				if (declarator$1.id.type === 'Identifier') {
					const expression = /** @type {Expression} */ (context.visit(value));

					declarations.push(
						declarator(declarator$1.id, create_state_declarator(declarator$1.id, expression))
					);
				} else {
					const tmp = id(context.state.scope.generate('tmp'));
					const { inserts, paths } = extract_paths(declarator$1.id, tmp);

					declarations.push(
						declarator(tmp, /** @type {Expression} */ (context.visit(value))),
						...inserts.map(({ id, value }) => {
							id.name = context.state.scope.generate('$$array');
							context.state.transform[id.name] = { read: get_value };

							const expression = /** @type {Expression} */ (context.visit(thunk(value)));
							let call$1 = call('$.derived', expression);

							if (dev) {
								const label = `[$state ${declarator$1.id.type === 'ArrayPattern' ? 'iterable' : 'object'}]`;
								call$1 = call('$.tag', call$1, literal(label));
							}

							return declarator(id, call$1);
						}),
						...paths.map((path) => {
							const value = /** @type {Expression} */ (context.visit(path.expression));
							const binding = context.state.scope.get(/** @type {Identifier} */ (path.node).name);
							return declarator(
								path.node,
								binding?.kind === 'state' || binding?.kind === 'raw_state'
									? create_state_declarator(binding.node, value)
									: value
							);
						})
					);
				}

				continue;
			}

			if (rune === '$derived' || rune === '$derived.by') {
				const is_async = context.state.analysis.async_deriveds.has(
					/** @type {CallExpression} */ (init)
				);

				// for now, only wrap async derived in $.save if it's not
				// a top-level instance derived. TODO in future maybe we
				// can dewaterfall all of them?
				const should_save = context.state.is_instance && context.state.scope.function_depth > 1;

				if (declarator$1.id.type === 'Identifier') {
					let expression = /** @type {Expression} */ (context.visit(value));

					if (is_async) {
						const location = dev && !is_ignored(init, 'await_waterfall') && locate_node(init);

						/** @type {Expression} */
						let call$1 = call(
							'$.async_derived',
							thunk(expression, true),
							location ? literal(location) : undefined
						);

						call$1 = should_save ? save(call$1) : await_builder(call$1);
						if (dev) call$1 = call('$.tag', call$1, literal(declarator$1.id.name));

						declarations.push(declarator(declarator$1.id, call$1));
					} else {
						if (rune === '$derived') expression = thunk(expression);

						let call$1 = call('$.derived', expression);
						if (dev) call$1 = call('$.tag', call$1, literal(declarator$1.id.name));

						declarations.push(declarator(declarator$1.id, call$1));
					}
				} else {
					const init = /** @type {CallExpression} */ (declarator$1.init);
					let expression = /** @type {Expression} */ (context.visit(value));

					let rhs = value;

					if (rune !== '$derived' || init.arguments[0].type !== 'Identifier') {
						const id$1 = id(context.state.scope.generate('$$d'));

						/** @type {Expression} */
						let call$1 = call('$.derived', rune === '$derived' ? thunk(expression) : expression);

						rhs = call('$.get', id$1);

						if (is_async) {
							const location = dev && !is_ignored(init, 'await_waterfall') && locate_node(init);

							call$1 = call(
								'$.async_derived',
								thunk(expression, true),
								location ? literal(location) : undefined
							);

							call$1 = should_save ? save(call$1) : await_builder(call$1);
						}

						if (dev) {
							const label = `[$derived ${declarator$1.id.type === 'ArrayPattern' ? 'iterable' : 'object'}]`;
							call$1 = call('$.tag', call$1, literal(label));
						}

						declarations.push(declarator(id$1, call$1));
					}

					const { inserts, paths } = extract_paths(declarator$1.id, rhs);

					for (const { id, value } of inserts) {
						id.name = context.state.scope.generate('$$array');
						context.state.transform[id.name] = { read: get_value };

						const expression = /** @type {Expression} */ (context.visit(thunk(value)));
						let call$1 = call('$.derived', expression);

						if (dev) {
							const label = `[$derived ${declarator$1.id.type === 'ArrayPattern' ? 'iterable' : 'object'}]`;
							call$1 = call('$.tag', call$1, literal(label));
						}

						declarations.push(declarator(id, call$1));
					}

					for (const path of paths) {
						const expression = /** @type {Expression} */ (context.visit(path.expression));
						const call$1 = call('$.derived', thunk(expression));
						declarations.push(
							declarator(
								path.node,
								dev
									? call('$.tag', call$1, literal(/** @type {Identifier} */ (path.node).name))
									: call$1
							)
						);
					}
				}

				continue;
			}
		}
	} else {
		for (const declarator$1 of node.declarations) {
			const bindings = /** @type {Binding[]} */ (context.state.scope.get_bindings(declarator$1));
			const has_state = bindings.some((binding) => binding.kind === 'state');
			const has_props = bindings.some((binding) => binding.kind === 'bindable_prop');

			if (!has_state && !has_props) {
				declarations.push(/** @type {VariableDeclarator} */ (context.visit(declarator$1)));
				continue;
			}

			if (has_props) {
				if (declarator$1.id.type !== 'Identifier') {
					// Turn export let into props. It's really really weird because export let { x: foo, z: [bar]} = ..
					// means that foo and bar are the props (i.e. the leafs are the prop names), not x and z.
					const tmp = id(context.state.scope.generate('tmp'));
					const { inserts, paths } = extract_paths(declarator$1.id, tmp);

					declarations.push(
						declarator(
							tmp,
							/** @type {Expression} */ (context.visit(/** @type {Expression} */ (declarator$1.init)))
						)
					);

					for (const { id, value } of inserts) {
						id.name = context.state.scope.generate('$$array');
						context.state.transform[id.name] = { read: get_value };

						const expression = /** @type {Expression} */ (context.visit(thunk(value)));
						declarations.push(declarator(id, call('$.derived', expression)));
					}

					for (const path of paths) {
						const name = /** @type {Identifier} */ (path.node).name;
						const binding = /** @type {Binding} */ (context.state.scope.get(name));
						const value = /** @type {Expression} */ (context.visit(path.expression));

						declarations.push(
							declarator(
								path.node,
								binding.kind === 'bindable_prop'
									? get_prop_source(binding, context.state, binding.prop_alias ?? name, value)
									: value
							)
						);
					}

					continue;
				}

				const binding = /** @type {Binding} */ (context.state.scope.get(declarator$1.id.name));

				declarations.push(
					declarator(
						declarator$1.id,
						get_prop_source(
							binding,
							context.state,
							binding.prop_alias ?? declarator$1.id.name,
							declarator$1.init && /** @type {Expression} */ (context.visit(declarator$1.init))
						)
					)
				);

				continue;
			}

			declarations.push(
				...create_state_declarators(
					declarator$1,
					context,
					/** @type {Expression} */ (declarator$1.init && context.visit(declarator$1.init))
				)
			);
		}
	}

	if (declarations.length === 0) {
		return empty;
	}

	return {
		...node,
		declarations
	};
}

/**
 * Creates the output for a state declaration in legacy mode.
 * @param {VariableDeclarator} declarator
 * @param {ComponentContext} context
 * @param {Expression} value
 */
function create_state_declarators(declarator$1, context, value) {
	if (declarator$1.id.type === 'Identifier') {
		return [
			declarator(
				declarator$1.id,
				call('$.mutable_source', value, context.state.analysis.immutable ? true_instance : undefined)
			)
		];
	}

	const tmp = id(context.state.scope.generate('tmp'));
	const { inserts, paths } = extract_paths(declarator$1.id, tmp);

	return [
		declarator(tmp, value),
		...inserts.map(({ id, value }) => {
			id.name = context.state.scope.generate('$$array');
			context.state.transform[id.name] = { read: get_value };

			const expression = /** @type {Expression} */ (context.visit(thunk(value)));
			return declarator(id, call('$.derived', expression));
		}),
		...paths.map((path) => {
			const value = /** @type {Expression} */ (context.visit(path.expression));
			const binding = context.state.scope.get(/** @type {Identifier} */ (path.node).name);

			return declarator(
				path.node,
				binding?.kind === 'state'
					? call('$.mutable_source', value, context.state.analysis.immutable ? true_instance : undefined)
					: value
			);
		})
	];
}

/** @import * as ESTree from 'estree' */
/** @import { AST, ValidatedCompileOptions, ValidatedModuleCompileOptions } from '#compiler' */
/** @import { ComponentAnalysis, Analysis } from '../../types' */
/** @import { Visitors, ComponentClientTransformState, ClientTransformState } from './types' */

/** @type {Visitors} */
const visitors = {
	_: function set_scope(node, { next, state }) {
		const scope = state.scopes.get(node);

		if (scope && scope !== state.scope) {
			const transform = { ...state.transform };

			for (const [name, binding] of scope.declarations) {
				if (
					binding.kind === 'normal' ||
					// Reads of `$state(...)` declarations are not
					// transformed if they are never reassigned
					(binding.kind === 'state' && !is_state_source(binding, state.analysis))
				) {
					delete transform[name];
				}
			}

			next({ ...state, transform, scope });
		} else {
			next();
		}
	},
	AnimateDirective,
	ArrowFunctionExpression,
	AssignmentExpression,
	Attribute,
	AwaitBlock,
	AwaitExpression,
	BinaryExpression,
	BindDirective,
	BlockStatement,
	BreakStatement,
	CallExpression,
	ClassBody,
	Comment,
	Component,
	ConstTag,
	DebugTag,
	EachBlock,
	ExportNamedDeclaration,
	ExpressionStatement,
	ForOfStatement,
	Fragment,
	FunctionDeclaration,
	FunctionExpression,
	HtmlTag,
	Identifier,
	IfBlock,
	KeyBlock,
	LabeledStatement,
	LetDirective,
	MemberExpression,
	OnDirective,
	Program,
	RegularElement,
	RenderTag,
	SlotElement,
	SnippetBlock,
	SpreadAttribute,
	SvelteBody,
	SvelteComponent,
	SvelteDocument,
	SvelteElement,
	SvelteFragment,
	SvelteBoundary,
	SvelteHead,
	SvelteSelf,
	SvelteWindow,
	TitleElement,
	TransitionDirective,
	UpdateExpression,
	UseDirective,
	AttachTag,
	VariableDeclaration
};

/**
 * @param {ComponentAnalysis} analysis
 * @param {ValidatedCompileOptions} options
 * @returns {ESTree.Program}
 */
function client_component(analysis, options) {
	/** @type {ComponentClientTransformState} */
	const state = {
		analysis,
		options,
		scope: analysis.module.scope,
		scopes: analysis.module.scopes,
		is_instance: false,
		hoisted: [import_all('$', 'svelte/internal/client'), ...analysis.instance_body.hoisted],
		node: /** @type {any} */ (null), // populated by the root node
		legacy_reactive_imports: [],
		legacy_reactive_statements: new Map(),
		metadata: {
			namespace: options.namespace,
			bound_contenteditable: false
		},
		events: new Set(),
		preserve_whitespace: options.preserveWhitespace,
		state_fields: new Map(),
		transform: {},
		in_constructor: false,
		instance_level_snippets: [],
		module_level_snippets: [],

		// these are set inside the `Fragment` visitor, and cannot be used until then
		init: /** @type {any} */ (null),
		consts: /** @type {any} */ (null),
		let_directives: /** @type {any} */ (null),
		update: /** @type {any} */ (null),
		after_update: /** @type {any} */ (null),
		template: /** @type {any} */ (null),
		memoizer: /** @type {any} */ (null)
	};

	const module = /** @type {ESTree.Program} */ (
		walk$1(/** @type {AST.SvelteNode} */ (analysis.module.ast), state, visitors)
	);

	const instance_state = {
		...state,
		transform: { ...state.transform },
		scope: analysis.instance.scope,
		scopes: analysis.instance.scopes,
		is_instance: true
	};

	const instance = /** @type {ESTree.Program} */ (
		walk$1(/** @type {AST.SvelteNode} */ (analysis.instance.ast), instance_state, visitors)
	);

	const template = /** @type {ESTree.Program} */ (
		walk$1(
			/** @type {AST.SvelteNode} */ (analysis.template.ast),
			{
				...state,
				transform: instance_state.transform,
				scope: analysis.instance.scope,
				scopes: analysis.template.scopes
			},
			visitors
		)
	);

	module.body.unshift(...state.legacy_reactive_imports);

	/** @type {ESTree.Statement[]} */
	const store_setup = [];
	/** @type {ESTree.Statement} */
	let store_init = empty;
	/** @type {ESTree.VariableDeclaration[]} */
	const legacy_reactive_declarations = [];

	let needs_store_cleanup = false;

	for (const [name, binding] of analysis.instance.scope.declarations) {
		if (binding.kind === 'legacy_reactive') {
			legacy_reactive_declarations.push(
				const_builder(
					name,
					call('$.mutable_source', undefined, analysis.immutable ? true_instance : undefined)
				)
			);
		}
		if (binding.kind === 'store_sub') {
			if (store_setup.length === 0) {
				needs_store_cleanup = true;
				store_init = const_builder(
					array_pattern([id('$$stores'), id('$$cleanup')]),
					call('$.setup_stores')
				);
			}

			// We're creating an arrow function that gets the store value which minifies better for two or more references
			const store_reference = build_getter$1(id(name.slice(1)), instance_state);
			const store_get = call('$.store_get', store_reference, literal(name), id('$$stores'));
			store_setup.push(
				const_builder(
					binding.node,
					dev
						? thunk(
								sequence([
									call('$.validate_store', store_reference, literal(name.slice(1))),
									store_get
								])
							)
						: thunk(store_get)
				)
			);
		}
	}

	for (const [node] of analysis.reactive_statements) {
		const statement = [...state.legacy_reactive_statements].find(([n]) => n === node);
		if (statement === undefined) {
			throw new Error('Could not find reactive statement');
		}
		instance.body.push(statement[1]);
	}

	if (analysis.reactive_statements.size > 0) {
		instance.body.push(stmt(call('$.legacy_pre_effect_reset')));
	}

	/**
	 * Used to store the group nodes
	 * @type {ESTree.VariableDeclaration[]}
	 */
	const group_binding_declarations = [];
	for (const group of analysis.binding_groups.values()) {
		group_binding_declarations.push(const_builder(group.name, array([])));
	}

	/** @type {Array<ESTree.Property | ESTree.SpreadElement>} */
	const component_returned_object = analysis.exports.flatMap(({ name, alias }) => {
		const binding = instance_state.scope.get(name);
		const expression = build_getter$1(id(name), instance_state);
		const getter = get$1(alias ?? name, [return_builder(expression)]);

		if (expression.type === 'Identifier') {
			if (binding?.declaration_kind === 'let' || binding?.declaration_kind === 'var') {
				return [
					getter,
					set(alias ?? name, [stmt(assignment('=', expression, id('$$value')))])
				];
			} else if (!dev) {
				return init(alias ?? name, expression);
			}
		}

		if (binding?.kind === 'prop' || binding?.kind === 'bindable_prop') {
			return [getter, set(alias ?? name, [stmt(call(name, id('$$value')))])];
		}

		if (binding?.kind === 'state' || binding?.kind === 'raw_state') {
			const value = binding.kind === 'state' ? call('$.proxy', id('$$value')) : id('$$value');
			return [getter, set(alias ?? name, [stmt(call('$.set', id(name), value))])];
		}

		return getter;
	});

	const properties = [...analysis.instance.scope.declarations].filter(
		([name, binding]) =>
			(binding.kind === 'prop' || binding.kind === 'bindable_prop') && !name.startsWith('$$')
	);

	if (analysis.accessors) {
		for (const [name, binding] of properties) {
			const key = binding.prop_alias ?? name;

			const getter = get$1(key, [return_builder(call(id(name)))]);

			const setter = set(key, [
				stmt(call(id(name), id('$$value'))),
				stmt(call('$.flush'))
			]);

			if (analysis.runes && binding.initial) {
				// turn `set foo($$value)` into `set foo($$value = expression)`
				setter.value.params[0] = {
					type: 'AssignmentPattern',
					left: id('$$value'),
					right: /** @type {ESTree.Expression} */ (binding.initial)
				};
			}

			component_returned_object.push(getter, setter);
		}
	}

	if (options.compatibility.componentApi === 4) {
		component_returned_object.push(
			init('$set', id('$.update_legacy_props')),
			init(
				'$on',
				arrow(
					[id('$$event_name'), id('$$event_cb')],
					call(
						'$.add_legacy_event_listener',
						id('$$props'),
						id('$$event_name'),
						id('$$event_cb')
					)
				)
			)
		);
	} else if (dev) {
		component_returned_object.push(spread(call(id('$.legacy_api'))));
	}

	const push_args = [id('$$props'), literal(analysis.runes)];
	if (dev) push_args.push(id(analysis.name));

	let component_block = block([
		store_init,
		...legacy_reactive_declarations,
		...group_binding_declarations
	]);

	const should_inject_context =
		dev ||
		analysis.needs_context ||
		analysis.reactive_statements.size > 0 ||
		component_returned_object.length > 0;

	component_block.body.push(
		...state.instance_level_snippets,
		.../** @type {ESTree.Statement[]} */ (instance.body)
	);

	if (should_inject_context && component_returned_object.length > 0) {
		component_block.body.push(var_builder('$$exports', object$2(component_returned_object)));
	}
	component_block.body.unshift(...store_setup);

	if (!analysis.runes && analysis.needs_context) {
		component_block.body.push(stmt(call('$.init', analysis.immutable ? true_instance : undefined)));
	}

	component_block.body.push(.../** @type {ESTree.Statement[]} */ (template.body));

	if (analysis.needs_mutation_validation) {
		component_block.body.unshift(
			var_builder('$$ownership_validator', call('$.create_ownership_validator', id('$$props')))
		);
	}

	let should_inject_props =
		should_inject_context ||
		analysis.needs_props ||
		analysis.uses_props ||
		analysis.uses_rest_props ||
		analysis.uses_slots ||
		analysis.slot_names.size > 0;

	// trick esrap into including comments
	component_block.loc = instance.loc;

	if (!analysis.runes) {
		// Bind static exports to props so that people can access them with bind:x
		for (const { name, alias } of analysis.exports) {
			component_block.body.push(
				stmt(
					call(
						'$.bind_prop',
						id('$$props'),
						literal(alias ?? name),
						build_getter$1(id(name), instance_state)
					)
				)
			);
		}
	}

	if (analysis.css.ast !== null && analysis.inject_styles) {
		const hash = literal(analysis.css.hash);
		const code = literal(render_stylesheet(analysis.source, analysis, options).code);

		state.hoisted.push(const_builder('$$css', object$2([init('hash', hash), init('code', code)])));

		component_block.body.unshift(
			stmt(call('$.append_styles', id('$$anchor'), id('$$css')))
		);
	}

	// we want the cleanup function for the stores to run as the very last thing
	// so that it can effectively clean up the store subscription even after the user effects runs
	if (should_inject_context) {
		component_block.body.unshift(stmt(call('$.push', ...push_args)));

		let to_push;

		if (component_returned_object.length > 0) {
			let pop_call = call('$.pop', id('$$exports'));
			to_push = needs_store_cleanup ? var_builder('$$pop', pop_call) : return_builder(pop_call);
		} else {
			to_push = stmt(call('$.pop'));
		}

		component_block.body.push(to_push);
	}

	if (needs_store_cleanup) {
		component_block.body.push(stmt(call('$$cleanup')));

		if (component_returned_object.length > 0) {
			component_block.body.push(return_builder(id('$$pop')));
		}
	}

	if (analysis.uses_rest_props) {
		const named_props = analysis.exports.map(({ name, alias }) => alias ?? name);
		for (const [name, binding] of analysis.instance.scope.declarations) {
			if (binding.kind === 'bindable_prop') named_props.push(binding.prop_alias ?? name);
		}

		component_block.body.unshift(
			const_builder(
				'$$restProps',
				call(
					'$.legacy_rest_props',
					id('$$sanitized_props'),
					array(named_props.map((name) => literal(name)))
				)
			)
		);
	}

	if (analysis.uses_props || analysis.uses_rest_props) {
		const to_remove = [
			literal('children'),
			literal('$$slots'),
			literal('$$events'),
			literal('$$legacy')
		];
		if (analysis.custom_element) {
			to_remove.push(literal('$$host'));
		}

		component_block.body.unshift(
			const_builder(
				'$$sanitized_props',
				call('$.legacy_rest_props', id('$$props'), array(to_remove))
			)
		);
	}

	if (analysis.uses_slots) {
		component_block.body.unshift(const_builder('$$slots', call('$.sanitize_slots', id('$$props'))));
	}

	// Merge hoisted statements into module body.
	// Ensure imports are on top, with the order preserved, then module body, then hoisted statements
	/** @type {ESTree.ImportDeclaration[]} */
	const imports$1 = [];
	/** @type {ESTree.Program['body']} */
	let body = [];

	for (const entry of [...module.body, ...state.hoisted]) {
		if (entry.type === 'ImportDeclaration') {
			imports$1.push(entry);
		} else {
			body.push(entry);
		}
	}

	body = [...imports$1, ...state.module_level_snippets, ...body];

	const component = function_declaration(
		id(analysis.name),
		should_inject_props ? [id('$$anchor'), id('$$props')] : [id('$$anchor')],
		component_block
	);

	if (options.hmr) {
		const id$1 = id(analysis.name);
		const HMR = id('$.HMR');

		const existing = member(id$1, HMR, true);
		const incoming = member(id('module.default'), HMR, true);

		const accept_fn_body = [
			stmt(assignment('=', member(incoming, 'source'), member(existing, 'source'))),
			stmt(call('$.set', member(existing, 'source'), member(incoming, 'original')))
		];

		if (analysis.css.hash) {
			// remove existing `<style>` element, in case CSS changed
			accept_fn_body.unshift(stmt(call('$.cleanup_styles', literal(analysis.css.hash))));
		}

		const hmr = block([
			stmt(assignment('=', id$1, call('$.hmr', id$1, thunk(member(existing, 'source'))))),

			stmt(call('import.meta.hot.accept', arrow([id('module')], block(accept_fn_body))))
		]);

		body.push(component, if_builder(id('import.meta.hot'), hmr), export_default(id(analysis.name)));
	} else {
		body.push(export_default(component));
	}

	if (dev) {
		// add `App[$.FILENAME] = 'App.svelte'` so that we can print useful messages later
		body.unshift(
			stmt(
				assignment('=', member(id(analysis.name), '$.FILENAME', true), literal(filename))
			)
		);
	}

	if (options.experimental.async) {
		body.unshift(imports([], 'svelte/internal/flags/async'));
	}

	if (!analysis.runes) {
		body.unshift(imports([], 'svelte/internal/flags/legacy'));
	}

	if (analysis.tracing) {
		body.unshift(imports([], 'svelte/internal/flags/tracing'));
	}

	if (options.discloseVersion) {
		body.unshift(imports([], 'svelte/internal/disclose-version'));
	}

	if (options.compatibility.componentApi === 4) {
		body.unshift(imports([['createClassComponent', '$$_createClassComponent']], 'svelte/legacy'));
		component_block.body.unshift(
			if_builder(
				id('new.target'),
				return_builder(
					call(
						'$$_createClassComponent',
						// When called with new, the first argument is the constructor options
						object$2([init('component', id(analysis.name)), spread(id('$$anchor'))])
					)
				)
			)
		);
	} else if (dev) {
		component_block.body.unshift(stmt(call('$.check_target', id('new.target'))));
	}

	if (analysis.props_id) {
		// need to be placed on first line of the component for hydration
		component_block.body.unshift(const_builder(analysis.props_id, call('$.props_id')));
	}

	if (state.events.size > 0) {
		body.push(
			stmt(call('$.delegate', array(Array.from(state.events).map((name) => literal(name)))))
		);
	}

	const ce = options.customElementOptions ?? options.customElement;

	if (ce) {
		const ce_props = typeof ce === 'boolean' ? {} : ce.props || {};

		/** @type {ESTree.Property[]} */
		const props_str = [];

		for (const [name, prop_def] of Object.entries(ce_props)) {
			const binding = analysis.instance.scope.get(name);
			const key = binding?.prop_alias ?? name;

			if (
				!prop_def.type &&
				binding?.initial?.type === 'Literal' &&
				typeof binding?.initial.value === 'boolean'
			) {
				prop_def.type = 'Boolean';
			}

			const value = object$2(
				/** @type {ESTree.Property[]} */ (
					[
						prop_def.attribute ? init('attribute', literal(prop_def.attribute)) : undefined,
						prop_def.reflect ? init('reflect', true_instance) : undefined,
						prop_def.type ? init('type', literal(prop_def.type)) : undefined
					].filter(Boolean)
				)
			);

			props_str.push(init(key, value));
		}

		for (const [name, binding] of properties) {
			const key = binding.prop_alias ?? name;
			if (ce_props[key]) continue;

			props_str.push(init(key, object$2([])));
		}

		const slots_str = array([...analysis.slot_names.keys()].map((name) => literal(name)));
		const accessors_str = array(
			analysis.exports.map(({ name, alias }) => literal(alias ?? name))
		);
		const use_shadow_dom = typeof ce === 'boolean' || ce.shadow !== 'none' ? true : false;

		const create_ce = call(
			'$.create_custom_element',
			id(analysis.name),
			object$2(props_str),
			slots_str,
			accessors_str,
			literal(use_shadow_dom),
			/** @type {any} */ (typeof ce !== 'boolean' ? ce.extend : undefined)
		);

		// If a tag name is provided, call `customElements.define`, otherwise leave to the user
		if (typeof ce !== 'boolean' && typeof ce.tag === 'string') {
			const define = stmt(call('customElements.define', literal(ce.tag), create_ce));

			if (options.hmr) {
				body.push(
					if_builder(binary$1('==', call('customElements.get', literal(ce.tag)), null_instance), define)
				);
			} else {
				body.push(define);
			}
		} else {
			body.push(stmt(create_ce));
		}
	}

	return {
		type: 'Program',
		sourceType: 'module',
		body
	};
}

/**
 * @param {Analysis} analysis
 * @param {ValidatedModuleCompileOptions} options
 * @returns {ESTree.Program}
 */
function client_module(analysis, options) {
	/** @type {ClientTransformState} */
	const state = {
		analysis,
		options,
		scope: analysis.module.scope,
		scopes: analysis.module.scopes,
		state_fields: new Map(),
		transform: {},
		in_constructor: false,
		is_instance: false
	};

	const module = /** @type {ESTree.Program} */ (
		walk$1(/** @type {AST.SvelteNode} */ (analysis.module.ast), state, visitors)
	);

	const body = [import_all('$', 'svelte/internal/client')];

	if (analysis.tracing) {
		body.push(imports([], 'svelte/internal/flags/tracing'));
	}

	return {
		type: 'Program',
		sourceType: 'module',
		body: [...body, ...module.body]
	};
}

/** @import { Node } from 'esrap/languages/ts' */
/** @import { ValidatedCompileOptions, CompileResult, ValidatedModuleCompileOptions } from '#compiler' */
/** @import { ComponentAnalysis, Analysis } from '../types' */

/**
 * @param {ComponentAnalysis} analysis
 * @param {string} source
 * @param {ValidatedCompileOptions} options
 * @returns {CompileResult}
 */
function transform_component(analysis, source, options) {
	if (options.generate === false) {
		return {
			js: /** @type {any} */ (null),
			css: null,
			warnings: warnings, // set afterwards
			metadata: {
				runes: analysis.runes
			},
			ast: /** @type {any} */ (null) // set afterwards
		};
	}

	const program =
		options.generate === 'server'
			? server_component(analysis, options)
			: client_component(analysis, options);

	const js_source_name = get_source_name(options.filename, options.outputFilename);

	const js = print(/** @type {Node} */ (program), ts({ comments: analysis.comments }), {
		// include source content; makes it easier/more robust looking up the source map code
		// (else esrap does return null for source and sourceMapContent which may trip up tooling)
		sourceMapContent: source,
		sourceMapSource: js_source_name
	});

	merge_with_preprocessor_map(js, options, js_source_name);

	const css =
		analysis.css.ast && !analysis.inject_styles
			? render_stylesheet(source, analysis, options)
			: null;

	return {
		js,
		css,
		warnings: warnings, // set afterwards. TODO apply preprocessor sourcemap
		metadata: {
			runes: analysis.runes
		},
		ast: /** @type {any} */ (null) // set afterwards
	};
}

/**
 * @param {Analysis} analysis
 * @param {string} source
 * @param {ValidatedModuleCompileOptions} options
 * @returns {CompileResult}
 */
function transform_module(analysis, source, options) {
	if (options.generate === false) {
		return {
			js: /** @type {any} */ (null),
			css: null,
			warnings: warnings, // set afterwards
			metadata: {
				runes: true
			},
			ast: /** @type {any} */ (null) // set afterwards
		};
	}

	const program =
		options.generate === 'server'
			? server_module(analysis, options)
			: client_module(analysis, options);

	const basename = options.filename.split(/[/\\]/).at(-1);
	if (program.body.length > 0) {
		program.body[0].leadingComments = [
			{
				type: 'Block',
				value: ` ${basename} generated by Svelte v${VERSION} `
			}
		];
	}

	const js = print(/** @type {Node} */ (program), ts({ comments: analysis.comments }), {
		// include source content; makes it easier/more robust looking up the source map code
		// (else esrap does return null for source and sourceMapContent which may trip up tooling)
		sourceMapContent: source,
		sourceMapSource: get_source_name(options.filename, undefined)
	});

	// prepend comment
	js.code = `/* ${basename} generated by Svelte v${VERSION} */\n${js.code}`;
	js.map.mappings = ';' + js.map.mappings;

	return {
		js,
		css: null,
		metadata: {
			runes: true
		},
		warnings: warnings, // set afterwards
		ast: /** @type {any} */ (null) // set afterwards
	};
}

/** @import { ModuleCompileOptions, ValidatedModuleCompileOptions, CompileOptions, ValidatedCompileOptions } from '#compiler' */

/**
 * @template [Input=any]
 * @template [Output=Input]
 * @typedef {(input: Input, keypath: string) => Required<Output>} Validator
 */

const common_options = {
	filename: string('(unknown)'),

	// default to process.cwd() where it exists to replicate svelte4 behavior (and make Deno work with this as well)
	// see https://github.com/sveltejs/svelte/blob/b62fc8c8fd2640c9b99168f01b9d958cb2f7574f/packages/svelte/src/compiler/compile/Component.js#L211
	/* eslint-disable */
	rootDir: string(
		typeof process !== 'undefined'
			? process.cwd?.()
			: // @ts-expect-error
				typeof Deno !== 'undefined'
				? // @ts-expect-error
					Deno.cwd()
				: undefined
	),
	/* eslint-enable */

	dev: boolean(false),

	generate: validator('client', (input, keypath) => {
		if (input === 'dom' || input === 'ssr') {
			warn_once(options_renamed_ssr_dom);
			return input === 'dom' ? 'client' : 'server';
		}

		// TODO deprecate `false` in favour of `analyze`/`analyzeModule` https://github.com/sveltejs/svelte-octane/issues/655
		if (input !== 'client' && input !== 'server' && input !== false) {
			throw_error(`${keypath} must be "client", "server" or false`);
		}

		return input;
	}),

	warningFilter: fun(() => true),

	experimental: object({
		async: boolean(false)
	})
};

const component_options = {
	accessors: deprecate(options_deprecated_accessors, boolean(false)),

	css: validator('external', (input) => {
		if (input === true || input === false) {
			throw_error(
				'The boolean options have been removed from the css option. Use "external" instead of false and "injected" instead of true'
			);
		}
		if (input === 'none') {
			throw_error(
				'css: "none" is no longer a valid option. If this was crucial for you, please open an issue on GitHub with your use case.'
			);
		}

		if (input !== 'external' && input !== 'injected') {
			throw_error(`css should be either "external" (default, recommended) or "injected"`);
		}

		return input;
	}),

	cssHash: fun(({ css, filename, hash }) => {
		return `svelte-${hash(filename === '(unknown)' ? css : filename ?? css)}`;
	}),

	// TODO this is a sourcemap option, would be good to put under a sourcemap namespace
	cssOutputFilename: string(undefined),

	customElement: boolean(false),

	discloseVersion: boolean(true),

	immutable: deprecate(options_deprecated_immutable, boolean(false)),

	legacy: removed(
		'The legacy option has been removed. If you are using this because of legacy.componentApi, use compatibility.componentApi instead'
	),

	compatibility: object({
		componentApi: list([4, 5], 5)
	}),

	loopGuardTimeout: warn_removed(options_removed_loop_guard_timeout),

	name: string(undefined),

	namespace: list(['html', 'mathml', 'svg']),

	modernAst: boolean(false),

	outputFilename: string(undefined),

	preserveComments: boolean(false),

	fragments: list(['html', 'tree']),

	preserveWhitespace: boolean(false),

	runes: boolean(undefined),

	hmr: boolean(false),

	sourcemap: validator(undefined, (input) => {
		// Source maps can take on a variety of values, including string, JSON, map objects from magic-string and source-map,
		// so there's no good way to check type validity here
		return input;
	}),

	enableSourcemap: warn_removed(options_removed_enable_sourcemap),

	hydratable: warn_removed(options_removed_hydratable),

	format: removed(
		'The format option has been removed in Svelte 4, the compiler only outputs ESM now. Remove "format" from your compiler options. ' +
			'If you did not set this yourself, bump the version of your bundler plugin (vite-plugin-svelte/rollup-plugin-svelte/svelte-loader)'
	),

	tag: removed(
		'The tag option has been removed in Svelte 5. Use `<svelte:options customElement="tag-name" />` inside the component instead. ' +
			'If that does not solve your use case, please open an issue on GitHub with details.'
	),

	sveltePath: removed(
		'The sveltePath option has been removed in Svelte 5. ' +
			'If this option was crucial for you, please open an issue on GitHub with your use case.'
	),

	// These two were primarily created for svelte-preprocess (https://github.com/sveltejs/svelte/pull/6194),
	// but with new TypeScript compilation modes strictly separating types it's not necessary anymore
	errorMode: removed(
		'The errorMode option has been removed. If you are using this through svelte-preprocess with TypeScript, ' +
			'use the https://www.typescriptlang.org/tsconfig#verbatimModuleSyntax setting instead'
	),

	varsReport: removed(
		'The vars option has been removed. If you are using this through svelte-preprocess with TypeScript, ' +
			'use the https://www.typescriptlang.org/tsconfig#verbatimModuleSyntax setting instead'
	)
};

const validate_module_options =
	/** @type {Validator<ModuleCompileOptions, ValidatedModuleCompileOptions>} */ (
		object({
			...common_options,
			...Object.fromEntries(Object.keys(component_options).map((key) => [key, () => {}]))
		})
	);

const validate_component_options =
	/** @type {Validator<CompileOptions, ValidatedCompileOptions>} */ (
		object({
			...common_options,
			...component_options
		})
	);

/**
 * @param {string} msg
 * @returns {Validator}
 */
function removed(msg) {
	return (input) => {
		if (input !== undefined) {
			options_removed(null, msg);
		}
		return /** @type {any} */ (undefined);
	};
}

const warned = new Set();

/** @param {(node: null) => void} fn */
function warn_once(fn) {
	if (!warned.has(fn)) {
		warned.add(fn);
		fn(null);
	}
}

/**
 * @param {(node: null) => void} fn
 * @returns {Validator}
 */
function warn_removed(fn) {
	return (input) => {
		if (input !== undefined) warn_once(fn);
		return /** @type {any} */ (undefined);
	};
}

/**
 * @param {(node: null) => void} fn
 * @param {Validator} validator
 * @returns {Validator}
 */
function deprecate(fn, validator) {
	return (input, keypath) => {
		if (input !== undefined) warn_once(fn);
		return validator(input, keypath);
	};
}

/**
 * @param {Record<string, Validator>} children
 * @param {boolean} [allow_unknown]
 * @returns {Validator}
 */
function object(children, allow_unknown = false) {
	return (input, keypath) => {
		/** @type {Record<string, any>} */
		const output = {};

		if ((input && typeof input !== 'object') || Array.isArray(input)) {
			throw_error(`${keypath} should be an object`);
		}

		for (const key in input) {
			if (!(key in children)) {
				if (allow_unknown) {
					output[key] = input[key];
				} else {
					options_unrecognised(null, `${keypath ? `${keypath}.${key}` : key}`);
				}
			}
		}

		for (const key in children) {
			const validator = children[key];
			output[key] = validator(input && input[key], keypath ? `${keypath}.${key}` : key);
		}

		return output;
	};
}

/**
 * @param {any} fallback
 * @param {(value: any, keypath: string) => any} fn
 * @returns {Validator}
 */
function validator(fallback, fn) {
	return (input, keypath) => {
		return input === undefined ? fallback : fn(input, keypath);
	};
}

/**
 * @param {string | undefined} fallback
 * @param {boolean} allow_empty
 * @returns {Validator}
 */
function string(fallback, allow_empty = true) {
	return validator(fallback, (input, keypath) => {
		if (typeof input !== 'string') {
			throw_error(`${keypath} should be a string, if specified`);
		}

		if (!allow_empty && input === '') {
			throw_error(`${keypath} cannot be empty`);
		}

		return input;
	});
}

/**
 * @param {boolean | undefined} fallback
 * @returns {Validator}
 */
function boolean(fallback) {
	return validator(fallback, (input, keypath) => {
		if (typeof input !== 'boolean') {
			throw_error(`${keypath} should be true or false, if specified`);
		}
		return input;
	});
}

/**
 * @param {Array<boolean | string | number>} options
 * @returns {Validator}
 */
function list(options, fallback = options[0]) {
	return validator(fallback, (input, keypath) => {
		if (!options.includes(input)) {
			// prettier-ignore
			const msg = options.length > 2
				? `${keypath} should be one of ${options.slice(0, -1).map(input => `"${input}"`).join(', ')} or "${options[options.length - 1]}"`
				: `${keypath} should be either "${options[0]}" or "${options[1]}"`;

			throw_error(msg);
		}
		return input;
	});
}

/**
 * @param {(...args: any) => any} fallback
 * @returns {Validator}
 */
function fun(fallback) {
	return validator(fallback, (input, keypath) => {
		if (typeof input !== 'function') {
			throw_error(`${keypath} should be a function, if specified`);
		}
		return input;
	});
}

/** @param {string} msg */
function throw_error(msg) {
	options_invalid_value(null, msg);
}

/** @import { Processed } from './public.js' */

/**
 * Import decoded sourcemap from mozilla/source-map/SourceMapGenerator
 * Forked from source-map/lib/source-map-generator.js
 * from methods _serializeMappings and toJSON.
 * We cannot use source-map.d.ts types, because we access hidden properties.
 * @param {any} generator
 */
function decoded_sourcemap_from_generator(generator) {
	let previous_generated_line = 1;
	/** @type {number[][][]} */
	const converted_mappings = [[]];
	let result_line = converted_mappings[0];
	let result_segment;
	let mapping;
	const source_idx = generator._sources
		.toArray()
		// @ts-ignore
		.reduce((acc, val, idx) => ((acc[val] = idx), acc), {});
	const name_idx = generator._names
		.toArray()
		// @ts-ignore
		.reduce((acc, val, idx) => ((acc[val] = idx), acc), {});
	const mappings = generator._mappings.toArray();
	for (let i = 0, len = mappings.length; i < len; i++) {
		mapping = mappings[i];
		if (mapping.generatedLine > previous_generated_line) {
			while (mapping.generatedLine > previous_generated_line) {
				converted_mappings.push([]);
				previous_generated_line++;
			}
			result_line = converted_mappings[mapping.generatedLine - 1]; // line is one-based
		} else if (i > 0) {
			const previous_mapping = mappings[i - 1];
			if (
				// sorted by selectivity
				mapping.generatedColumn === previous_mapping.generatedColumn &&
				mapping.originalColumn === previous_mapping.originalColumn &&
				mapping.name === previous_mapping.name &&
				mapping.generatedLine === previous_mapping.generatedLine &&
				mapping.originalLine === previous_mapping.originalLine &&
				mapping.source === previous_mapping.source
			) {
				continue;
			}
		}
		result_line.push([mapping.generatedColumn]);
		result_segment = result_line[result_line.length - 1];
		if (mapping.source != null) {
			result_segment.push(
				...[source_idx[mapping.source], mapping.originalLine - 1, mapping.originalColumn]
			);
			if (mapping.name != null) {
				result_segment.push(name_idx[mapping.name]);
			}
		}
	}

	/**
	 * @type {{
	 *  version: number;
	 * sources: string[];
	 * names: string[];
	 * mappings: number[][][];
	 * file?: string;
	 * }}
	 */
	const map = {
		version: generator._version,
		sources: generator._sources.toArray(),
		names: generator._names.toArray(),
		mappings: converted_mappings
	};
	if (generator._file != null) {
		map.file = generator._file;
	}
	// not needed: map.sourcesContent and map.sourceRoot
	return map;
}

/**
 * @param {Processed} processed
 */
function decode_map(processed) {
	let decoded_map = typeof processed.map === 'string' ? JSON.parse(processed.map) : processed.map;
	if (typeof decoded_map.mappings === 'string') {
		decoded_map.mappings = decode(decoded_map.mappings);
	}
	if (decoded_map._mappings && decoded_map.constructor.name === 'SourceMapGenerator') {
		// import decoded sourcemap from mozilla/source-map/SourceMapGenerator
		decoded_map = decoded_sourcemap_from_generator(decoded_map);
	}
	return decoded_map;
}

/** @import { Source, Replacement } from './private.js' */

/**
 * @param {string} code_slice
 * @param {number} offset
 * @param {Source} opts
 * @returns {Source}
 */
function slice_source(code_slice, offset, { file_basename, filename, get_location }) {
	return {
		source: code_slice,
		get_location: (index) => get_location(index + offset),
		file_basename,
		filename
	};
}

/**
 * @param {RegExp} re
 * @param {(...match: any[]) => Promise<MappedCode>} get_replacement
 * @param {string} source
 */
function calculate_replacements(re, get_replacement, source) {
	/**
	 * @type {Array<Promise<Replacement>>}
	 */
	const replacements = [];
	source.replace(re, (...match) => {
		replacements.push(
			get_replacement(...match).then((replacement) => {
				const matched_string = match[0];
				const offset = match[match.length - 2];
				return { offset, length: matched_string.length, replacement };
			})
		);
		return '';
	});
	return Promise.all(replacements);
}

/**
 * @param {Replacement[]} replacements
 * @param {Source} source
 * @returns {MappedCode}
 */
function perform_replacements(replacements, source) {
	const out = new MappedCode();
	let last_end = 0;
	for (const { offset, length, replacement } of replacements) {
		const unchanged_prefix = MappedCode.from_source(
			slice_source(source.source.slice(last_end, offset), last_end, source)
		);
		out.concat(unchanged_prefix).concat(replacement);
		last_end = offset + length;
	}
	const unchanged_suffix = MappedCode.from_source(
		slice_source(source.source.slice(last_end), last_end, source)
	);
	return out.concat(unchanged_suffix);
}

/**
 * @param {RegExp} regex
 * @param {(...match: any[]) => Promise<MappedCode>} get_replacement
 * @param {Source} location
 * @returns {Promise<MappedCode>}
 */
async function replace_in_code(regex, get_replacement, location) {
	const replacements = await calculate_replacements(regex, get_replacement, location.source);
	return perform_replacements(replacements, location);
}

/** @import { Processed, Preprocessor, MarkupPreprocessor, PreprocessorGroup } from './public.js' */
/** @import { SourceUpdate, Source } from './private.js' */
/** @import { DecodedSourceMap, RawSourceMap } from '@jridgewell/remapping' */

/**
 * Represents intermediate states of the preprocessing.
 * Implements the Source interface.
 */
class PreprocessResult {
	/** @type {string} */
	source;

	/** @type {string | undefined} The filename passed as-is to preprocess */
	filename;

	// sourcemap_list is sorted in reverse order from last map (index 0) to first map (index -1)
	// so we use sourcemap_list.unshift() to add new maps
	// https://github.com/jridgewell/sourcemaps/tree/main/packages/remapping#multiple-transformations-of-a-file

	/**
	 * @default []
	 * @type {Array<DecodedSourceMap | RawSourceMap>}
	 */
	sourcemap_list = [];

	/**
	 * @default []
	 * @type {string[]}
	 */
	dependencies = [];

	/**
	 * @type {string | null} last part of the filename, as used for `sources` in sourcemaps
	 */
	file_basename = /** @type {any} */ (undefined);

	/**
	 * @type {ReturnType<typeof getLocator>}
	 */
	get_location = /** @type {any} */ (undefined);

	/**
	 * @param {string} source
	 * @param {string} [filename]
	 */
	constructor(source, filename) {
		this.source = source;
		this.filename = filename;
		this.update_source({ string: source });
		// preprocess source must be relative to itself or equal null
		this.file_basename = filename == null ? null : get_basename(filename);
	}

	/**
	 * @param {SourceUpdate} opts
	 */
	update_source({ string: source, map, dependencies }) {
		if (source != null) {
			this.source = source;
			this.get_location = getLocator$1(source);
		}
		if (map) {
			this.sourcemap_list.unshift(map);
		}
		if (dependencies) {
			this.dependencies.push(...dependencies);
		}
	}

	/**
	 * @returns {Processed}
	 */
	to_processed() {
		// Combine all the source maps for each preprocessor function into one
		// @ts-expect-error TODO there might be a bug in hiding here
		const map = combine_sourcemaps(this.file_basename, this.sourcemap_list);
		return {
			// TODO return separated output, in future version where svelte.compile supports it:
			// style: { code: styleCode, map: styleMap },
			// script { code: scriptCode, map: scriptMap },
			// markup { code: markupCode, map: markupMap },
			code: this.source,
			dependencies: [...new Set(this.dependencies)],
			// @ts-expect-error TODO there might be a bug in hiding here
			map,
			toString: () => this.source
		};
	}
}
/**
 * Convert preprocessor output for the tag content into MappedCode
 * @param {Processed} processed
 * @param {{ line: number; column: number; }} location
 * @param {string} file_basename
 * @returns {MappedCode}
 */
function processed_content_to_code(processed, location, file_basename) {
	// Convert the preprocessed code and its sourcemap to a MappedCode

	/**
	 * @type {DecodedSourceMap | undefined}
	 */
	let decoded_map = undefined;
	if (processed.map) {
		decoded_map = decode_map(processed);
		// decoded map may not have sources for empty maps like `{ mappings: '' }`
		if (decoded_map?.sources) {
			// offset only segments pointing at original component source
			const source_index = decoded_map.sources.indexOf(file_basename);
			if (source_index !== -1) {
				sourcemap_add_offset(decoded_map, location, source_index);
			}
		}
	}
	return MappedCode.from_processed(processed.code, decoded_map);
}
/**
 * Given the whole tag including content, return a `MappedCode`
 * representing the tag content replaced with `processed`.
 * @param {Processed} processed
 * @param {'style' | 'script'} tag_name
 * @param {string} original_attributes
 * @param {string} generated_attributes
 * @param {Source} source
 * @returns {MappedCode}
 */
function processed_tag_to_code(
	processed,
	tag_name,
	original_attributes,
	generated_attributes,
	source
) {
	const { file_basename, get_location } = source;

	/**
	 * @param {string} code
	 * @param {number} offset
	 */
	const build_mapped_code = (code, offset) =>
		MappedCode.from_source(slice_source(code, offset, source));

	// To map the open/close tag and content starts positions correctly, we need to
	// differentiate between the original attributes and the generated attributes:
	// `source` contains the original attributes and its get_location maps accordingly.
	const original_tag_open = `<${tag_name}${original_attributes}>`;
	const tag_open = `<${tag_name}${generated_attributes}>`;
	/** @type {MappedCode} */
	let tag_open_code;

	if (original_tag_open.length !== tag_open.length) {
		// Generate a source map for the open tag
		/** @type {DecodedSourceMap['mappings']} */
		const mappings = [
			[
				// start of tag
				[0, 0, 0, 0],
				// end of tag start
				[`<${tag_name}`.length, 0, 0, `<${tag_name}`.length]
			]
		];

		const line = tag_open.split('\n').length - 1;
		const column = tag_open.length - (line === 0 ? 0 : tag_open.lastIndexOf('\n')) - 1;

		while (mappings.length <= line) {
			// end of tag start again, if this is a multi line mapping
			mappings.push([[0, 0, 0, `<${tag_name}`.length]]);
		}

		// end of tag
		mappings[line].push([
			column,
			0,
			original_tag_open.split('\n').length - 1,
			original_tag_open.length - original_tag_open.lastIndexOf('\n') - 1
		]);

		/** @type {DecodedSourceMap} */
		const map = {
			version: 3,
			names: [],
			sources: [file_basename],
			mappings
		};
		sourcemap_add_offset(map, get_location(0), 0);
		tag_open_code = MappedCode.from_processed(tag_open, map);
	} else {
		tag_open_code = build_mapped_code(tag_open, 0);
	}

	const tag_close = `</${tag_name}>`;
	const tag_close_code = build_mapped_code(
		tag_close,
		original_tag_open.length + source.source.length
	);

	parse_attached_sourcemap(processed, tag_name);
	const content_code = processed_content_to_code(
		processed,
		get_location(original_tag_open.length),
		file_basename
	);

	return tag_open_code.concat(content_code).concat(tag_close_code);
}

const attribute_pattern = /([\w-$]+\b)(?:=(?:"([^"]*)"|'([^']*)'|(\S+)))?/g;

/**
 * @param {string} str
 */
function parse_tag_attributes(str) {
	/** @type {Record<string, string | boolean>} */
	const attrs = {};

	/** @type {RegExpMatchArray | null} */
	let match;
	while ((match = attribute_pattern.exec(str)) !== null) {
		const name = match[1];
		const value = match[2] || match[3] || match[4];
		attrs[name] = !value || value;
	}

	return attrs;
}

/**
 * @param {Record<string, string | boolean> | undefined} attributes
 */
function stringify_tag_attributes(attributes) {
	if (!attributes) return;

	let value = Object.entries(attributes)
		.map(([key, value]) => (value === true ? key : `${key}="${value}"`))
		.join(' ');
	if (value) {
		value = ' ' + value;
	}
	return value;
}

const regex_style_tags$1 =
	/<!--[^]*?-->|<style((?:\s+[^=>'"/\s]+=(?:"[^"]*"|'[^']*'|[^>\s]+)|\s+[^=>'"/\s]+)*\s*)(?:\/>|>([\S\s]*?)<\/style>)/g;
const regex_script_tags =
	/<!--[^]*?-->|<script((?:\s+[^=>'"/\s]+=(?:"[^"]*"|'[^']*'|[^>\s]+)|\s+[^=>'"/\s]+)*\s*)(?:\/>|>([\S\s]*?)<\/script>)/g;

/**
 * Calculate the updates required to process all instances of the specified tag.
 * @param {'style' | 'script'} tag_name
 * @param {Preprocessor} preprocessor
 * @param {Source} source
 * @returns {Promise<SourceUpdate>}
 */
async function process_tag(tag_name, preprocessor, source) {
	const { filename, source: markup } = source;
	const tag_regex = tag_name === 'style' ? regex_style_tags$1 : regex_script_tags;

	/**
	 * @type {string[]}
	 */
	const dependencies = [];

	/**
	 * @param {string} tag_with_content
	 * @param {number} tag_offset
	 * @returns {Promise<MappedCode>}
	 */
	async function process_single_tag(tag_with_content, attributes = '', content = '', tag_offset) {
		const no_change = () =>
			MappedCode.from_source(slice_source(tag_with_content, tag_offset, source));
		if (!attributes && !content) return no_change();
		const processed = await preprocessor({
			content: content || '',
			attributes: parse_tag_attributes(attributes || ''),
			markup,
			filename
		});
		if (!processed) return no_change();
		if (processed.dependencies) dependencies.push(...processed.dependencies);
		if (!processed.map && processed.code === content) return no_change();
		return processed_tag_to_code(
			processed,
			tag_name,
			attributes,
			stringify_tag_attributes(processed.attributes) ?? attributes,
			slice_source(content, tag_offset, source)
		);
	}
	const { string, map } = await replace_in_code(tag_regex, process_single_tag, source);
	return { string, map, dependencies };
}

/**
 * @param {MarkupPreprocessor} process
 * @param {Source} source
 */
async function process_markup(process, source) {
	const processed = await process({
		content: source.source,
		filename: source.filename
	});
	if (processed) {
		return {
			string: processed.code,
			map: processed.map
				? // TODO: can we use decode_sourcemap?
					typeof processed.map === 'string'
					? JSON.parse(processed.map)
					: processed.map
				: undefined,
			dependencies: processed.dependencies
		};
	} else {
		return {};
	}
}

/**
 * The preprocess function provides convenient hooks for arbitrarily transforming component source code.
 * For example, it can be used to convert a `<style lang="sass">` block into vanilla CSS.
 *
 * @param {string} source
 * @param {PreprocessorGroup | PreprocessorGroup[]} preprocessor
 * @param {{ filename?: string }} [options]
 * @returns {Promise<Processed>}
 */
async function preprocess(source, preprocessor, options) {
	/**
	 * @type {string | undefined}
	 */
	const filename = (options && options.filename) || /** @type {any} */ (preprocessor).filename; // legacy
	const preprocessors = preprocessor
		? Array.isArray(preprocessor)
			? preprocessor
			: [preprocessor]
		: [];
	const result = new PreprocessResult(source, filename);

	// TODO keep track: what preprocessor generated what sourcemap?
	// to make debugging easier = detect low-resolution sourcemaps in fn combine_mappings
	for (const preprocessor of preprocessors) {
		if (preprocessor.markup) {
			// @ts-expect-error TODO there might be a bug in hiding here
			result.update_source(await process_markup(preprocessor.markup, result));
		}
		if (preprocessor.script) {
			// @ts-expect-error TODO there might be a bug in hiding here
			result.update_source(await process_tag('script', preprocessor.script, result));
		}
		if (preprocessor.style) {
			// @ts-expect-error TODO there might be a bug in hiding here
			result.update_source(await process_tag('style', preprocessor.style, result));
		}
	}

	return result.to_processed();
}

/** @import { VariableDeclarator, Node, Identifier, AssignmentExpression, LabeledStatement, ExpressionStatement } from 'estree' */
/** @import { Visitors } from 'zimmerframe' */
/** @import { ComponentAnalysis } from '../phases/types.js' */
/** @import { Scope } from '../phases/scope.js' */
/** @import { AST, Binding, ValidatedCompileOptions } from '#compiler' */

const regex_style_tags = /(<style[^>]+>)([\S\s]*?)(<\/style>)/g;
const style_placeholder = '/*$$__STYLE_CONTENT__$$*/';

let has_migration_task = false;

class MigrationError extends Error {
	/**
	 * @param {string} msg
	 */
	constructor(msg) {
		super(msg);
	}
}

/**
 *
 * @param {State} state
 */
function migrate_css(state) {
	if (!state.analysis.css.ast?.start) return;
	const css_contents = state.str
		.snip(state.analysis.css.ast.start, /** @type {number} */ (state.analysis.css.ast?.end))
		.toString();
	let code = css_contents;
	let starting = 0;

	// since we already blank css we can't work directly on `state.str` so we will create a copy that we can update
	const str = new MagicString(code);
	while (code) {
		if (
			code.startsWith(':has') ||
			code.startsWith(':is') ||
			code.startsWith(':where') ||
			code.startsWith(':not')
		) {
			let start = code.indexOf('(') + 1;
			let is_global = false;

			const global_str = ':global';
			const next_global = code.indexOf(global_str);
			const str_between = code.substring(start, next_global);
			if (!str_between.trim()) {
				is_global = true;
				start += global_str.length;
			} else {
				const prev_global = css_contents.lastIndexOf(global_str, starting);
				if (prev_global > -1) {
					const end =
						find_closing_parenthesis(css_contents.indexOf('(', prev_global) + 1, css_contents) -
						starting;
					if (end > start) {
						starting += end;
						code = code.substring(end);
						continue;
					}
				}
			}

			const end = find_closing_parenthesis(start, code);
			if (start && end) {
				if (!is_global && !code.startsWith(':not')) {
					str.prependLeft(starting + start, ':global(');
					str.appendRight(starting + end - 1, ')');
				}
				starting += end - 1;
				code = code.substring(end - 1);
				continue;
			}
		}
		starting++;
		code = code.substring(1);
	}
	state.str.update(state.analysis.css.ast?.start, state.analysis.css.ast?.end, str.toString());
}

/**
 * @param {number} start
 * @param {string} code
 */
function find_closing_parenthesis(start, code) {
	let parenthesis = 1;
	let end = start;
	let char = code[end];
	// find the closing parenthesis
	while (parenthesis !== 0 && char) {
		if (char === '(') parenthesis++;
		if (char === ')') parenthesis--;
		end++;
		char = code[end];
	}
	return end;
}

/**
 * Does a best-effort migration of Svelte code towards using runes, event attributes and render tags.
 * May throw an error if the code is too complex to migrate automatically.
 *
 * @param {string} source
 * @param {{ filename?: string, use_ts?: boolean }} [options]
 * @returns {{ code: string; }}
 */
function migrate(source, { filename, use_ts } = {}) {
	let og_source = source;
	try {
		has_migration_task = false;
		// Blank CSS, could contain SCSS or similar that needs a preprocessor.
		// Since we don't care about CSS in this migration, we'll just ignore it.
		/** @type {Array<[number, string]>} */
		const style_contents = [];
		source = source.replace(regex_style_tags, (_, start, content, end, idx) => {
			style_contents.push([idx + start.length, content]);
			return start + style_placeholder + end;
		});

		reset({ warning: () => false, filename });

		let parsed = parse$2(source);

		const { customElement: customElementOptions, ...parsed_options } = parsed.options || {};

		/** @type {ValidatedCompileOptions} */
		const combined_options = {
			...validate_component_options({}, ''),
			...parsed_options,
			customElementOptions,
			filename: filename ?? UNKNOWN_FILENAME,
			experimental: {
				async: true
			}
		};

		const str = new MagicString(source);
		const analysis = analyze_component(parsed, source, combined_options);
		const indent = guess_indent(source);

		str.replaceAll(/(<svelte:options\s.*?\s?)accessors\s?/g, (_, $1) => $1);

		for (const content of style_contents) {
			str.overwrite(content[0], content[0] + style_placeholder.length, content[1]);
		}

		/** @type {State} */
		let state = {
			scope: analysis.instance.scope,
			analysis,
			filename,
			str,
			indent,
			props: [],
			props_insertion_point: parsed.instance?.content.start ?? 0,
			has_props_rune: false,
			has_type_or_fallback: false,
			end: source.length,
			names: {
				props: analysis.root.unique('props').name,
				rest: analysis.root.unique('rest').name,

				// event stuff
				run: analysis.root.unique('run').name,
				handlers: analysis.root.unique('handlers').name,
				stopImmediatePropagation: analysis.root.unique('stopImmediatePropagation').name,
				preventDefault: analysis.root.unique('preventDefault').name,
				stopPropagation: analysis.root.unique('stopPropagation').name,
				once: analysis.root.unique('once').name,
				self: analysis.root.unique('self').name,
				trusted: analysis.root.unique('trusted').name,
				createBubbler: analysis.root.unique('createBubbler').name,
				bubble: analysis.root.unique('bubble').name,
				passive: analysis.root.unique('passive').name,
				nonpassive: analysis.root.unique('nonpassive').name
			},
			legacy_imports: new Set(),
			script_insertions: new Set(),
			derived_components: new Map(),
			derived_conflicting_slots: new Map(),
			derived_labeled_statements: new Set(),
			has_svelte_self: false,
			uses_ts:
				// Some people could use jsdoc but have a tsconfig.json, so double-check file for jsdoc indicators
				(use_ts && !source.includes('@type {')) ||
				!!parsed.instance?.attributes.some(
					(attr) => attr.name === 'lang' && /** @type {any} */ (attr).value[0].data === 'ts'
				)
		};

		if (parsed.module) {
			const context = parsed.module.attributes.find((attr) => attr.name === 'context');
			if (context) {
				state.str.update(context.start, context.end, 'module');
			}
		}

		if (parsed.instance) {
			walk$1(parsed.instance.content, state, instance_script);
		}

		state = { ...state, scope: analysis.template.scope };
		walk$1(parsed.fragment, state, template);

		let insertion_point = parsed.instance
			? /** @type {number} */ (parsed.instance.content.start)
			: 0;

		const need_script =
			state.legacy_imports.size > 0 ||
			state.derived_components.size > 0 ||
			state.derived_conflicting_slots.size > 0 ||
			state.script_insertions.size > 0 ||
			state.props.length > 0 ||
			analysis.uses_rest_props ||
			analysis.uses_props ||
			state.has_svelte_self;

		const need_ts_tag =
			state.uses_ts &&
			(!parsed.instance || !parsed.instance.attributes.some((attr) => attr.name === 'lang'));

		if (!parsed.instance && need_script) {
			str.appendRight(0, need_ts_tag ? '<script lang="ts">' : '<script>');
		}

		if (state.has_svelte_self && filename) {
			const file = filename.split('/').pop();
			str.appendRight(
				insertion_point,
				`\n${indent}import ${state.analysis.name} from './${file}';`
			);
		}

		const specifiers = [...state.legacy_imports].map((imported) => {
			const local = state.names[imported];
			return imported === local ? imported : `${imported} as ${local}`;
		});

		const legacy_import = `import { ${specifiers.join(', ')} } from 'svelte/legacy';\n`;

		if (state.legacy_imports.size > 0) {
			str.appendRight(insertion_point, `\n${indent}${legacy_import}`);
		}

		if (state.script_insertions.size > 0) {
			str.appendRight(
				insertion_point,
				`\n${indent}${[...state.script_insertions].join(`\n${indent}`)}`
			);
		}

		insertion_point = state.props_insertion_point;

		/**
		 * @param {"derived"|"props"|"bindable"} rune
		 */
		function check_rune_binding(rune) {
			const has_rune_binding = !!state.scope.get(rune);
			if (has_rune_binding) {
				throw new MigrationError(
					`migrating this component would require adding a \`$${rune}\` rune but there's already a variable named ${rune}.\n     Rename the variable and try again or migrate by hand.`
				);
			}
		}

		if (state.props.length > 0 || analysis.uses_rest_props || analysis.uses_props) {
			const has_many_props = state.props.length > 3;
			const newline_separator = `\n${indent}${indent}`;
			const props_separator = has_many_props ? newline_separator : ' ';
			let props = '';
			if (analysis.uses_props) {
				props = `...${state.names.props}`;
			} else {
				props = state.props
					.filter((prop) => !prop.type_only)
					.map((prop) => {
						let prop_str =
							prop.local === prop.exported ? prop.local : `${prop.exported}: ${prop.local}`;
						if (prop.bindable) {
							check_rune_binding('bindable');
							prop_str += ` = $bindable(${prop.init})`;
						} else if (prop.init) {
							prop_str += ` = ${prop.init}`;
						}
						return prop_str;
					})
					.join(`,${props_separator}`);

				if (analysis.uses_rest_props) {
					props += `${state.props.length > 0 ? `,${props_separator}` : ''}...${state.names.rest}`;
				}
			}

			if (state.has_props_rune) {
				// some render tags or forwarded event attributes to add
				str.appendRight(insertion_point, ` ${props},`);
			} else {
				const type_name = state.scope.root.unique('Props').name;
				let type = '';

				// Try to infer when we don't want to add types (e.g. user doesn't use types, or this is a zero-types +page.svelte)
				if (state.has_type_or_fallback || state.props.every((prop) => prop.slot_name)) {
					if (state.uses_ts) {
						type = `interface ${type_name} {${newline_separator}${state.props
							.map((prop) => {
								const comment = prop.comment ? `${prop.comment}${newline_separator}` : '';
								return `${comment}${prop.exported}${prop.optional ? '?' : ''}: ${prop.type};${prop.trailing_comment ? ' ' + prop.trailing_comment : ''}`;
							})
							.join(newline_separator)}`;
						if (analysis.uses_props || analysis.uses_rest_props) {
							type += `${state.props.length > 0 ? newline_separator : ''}[key: string]: any`;
						}
						type += `\n${indent}}`;
					} else {
						type = `/**\n${indent} * @typedef {Object} ${type_name}${state.props
							.map((prop) => {
								return `\n${indent} * @property {${prop.type}} ${prop.optional ? `[${prop.exported}]` : prop.exported}${prop.comment ? ` - ${prop.comment}` : ''}${prop.trailing_comment ? ` - ${prop.trailing_comment.trim()}` : ''}`;
							})
							.join(``)}\n${indent} */`;
					}
				}

				let props_declaration = `let {${props_separator}${props}${has_many_props ? `\n${indent}` : ' '}}`;
				if (state.uses_ts) {
					if (type) {
						props_declaration = `${type}\n\n${indent}${props_declaration}`;
					}
					check_rune_binding('props');
					props_declaration = `${props_declaration}${type ? `: ${type_name}` : ''} = $props();`;
				} else {
					if (type) {
						props_declaration = `${state.props.length > 0 ? `${type}\n\n${indent}` : ''}/** @type {${state.props.length > 0 ? type_name : ''}${analysis.uses_props || analysis.uses_rest_props ? `${state.props.length > 0 ? ' & ' : ''}{ [key: string]: any }` : ''}} */\n${indent}${props_declaration}`;
					}
					check_rune_binding('props');
					props_declaration = `${props_declaration} = $props();`;
				}

				props_declaration = `\n${indent}${props_declaration}`;
				str.appendRight(insertion_point, props_declaration);
			}

			if (parsed.instance && need_ts_tag) {
				str.appendRight(parsed.instance.start + '<script'.length, ' lang="ts"');
			}
		}

		/**
		 * If true, then we need to move all reactive statements to the end of the script block,
		 * in their correct order. Svelte 4 reordered reactive statements, $derived/$effect.pre
		 * don't have this behavior.
		 */
		let needs_reordering = false;

		for (const [node, { dependencies }] of state.analysis.reactive_statements) {
			/** @type {Binding[]} */
			let ids = [];
			if (
				node.body.type === 'ExpressionStatement' &&
				node.body.expression.type === 'AssignmentExpression'
			) {
				ids = extract_identifiers(node.body.expression.left)
					.map((id) => state.scope.get(id.name))
					.filter((id) => !!id);
			}

			if (
				dependencies.some(
					(dep) =>
						!ids.includes(dep) &&
						(dep.kind === 'prop' || dep.kind === 'bindable_prop'
							? state.props_insertion_point
							: /** @type {number} */ (dep.node.start)) > /** @type {number} */ (node.start)
				)
			) {
				needs_reordering = true;
				break;
			}
		}

		if (needs_reordering) {
			const nodes = Array.from(state.analysis.reactive_statements.keys());
			for (const node of nodes) {
				const { start, end } = get_node_range(source, node);
				str.appendLeft(end, '\n');
				str.move(start, end, /** @type {number} */ (parsed.instance?.content.end));
				str.update(start - (source[start - 2] === '\r' ? 2 : 1), start, '');
			}
		}

		insertion_point = parsed.instance
			? /** @type {number} */ (parsed.instance.content.end)
			: insertion_point;

		if (state.derived_components.size > 0) {
			check_rune_binding('derived');
			str.appendRight(
				insertion_point,
				`\n${indent}${[...state.derived_components.entries()].map(([init, name]) => `const ${name} = $derived(${init});`).join(`\n${indent}`)}\n`
			);
		}

		if (state.derived_conflicting_slots.size > 0) {
			check_rune_binding('derived');
			str.appendRight(
				insertion_point,
				`\n${indent}${[...state.derived_conflicting_slots.entries()].map(([name, init]) => `const ${name} = $derived(${init});`).join(`\n${indent}`)}\n`
			);
		}

		if (state.props.length > 0 && state.analysis.accessors) {
			str.appendRight(
				insertion_point,
				`\n${indent}export {${state.props.reduce((acc, prop) => (prop.slot_name || prop.type_only ? acc : `${acc}\n${indent}\t${prop.local},`), '')}\n${indent}}\n`
			);
		}

		if (!parsed.instance && need_script) {
			str.appendRight(insertion_point, '\n</script>\n\n');
		}
		migrate_css(state);
		return {
			code: str.toString()
		};
	} catch (e) {
		if (!(e instanceof MigrationError)) {
			// eslint-disable-next-line no-console
			console.error('Error while migrating Svelte code', e);
		}
		has_migration_task = true;
		return {
			code: `<!-- @migration-task Error while migrating Svelte code: ${/** @type {any} */ (e).message} -->\n${og_source}`
		};
	} finally {
		if (has_migration_task) {
			// eslint-disable-next-line no-console
			console.log(
				`One or more \`@migration-task\` comments were added to ${filename ? `\`${filename}\`` : "a file (unfortunately we don't know the name)"}, please check them and complete the migration manually.`
			);
		}
	}
}

/**
 * @typedef {{
 *  scope: Scope;
 *  str: MagicString;
 *  analysis: ComponentAnalysis;
 *  filename?: string;
 *  indent: string;
 *  props: Array<{ local: string; exported: string; init: string; bindable: boolean; slot_name?: string; optional: boolean; type: string; comment?: string; trailing_comment?: string; type_only?: boolean; needs_refine_type?: boolean; }>;
 *  props_insertion_point: number;
 *  has_props_rune: boolean;
 *  has_type_or_fallback: boolean;
 *  end: number;
 * 	names: Record<string, string>;
 * 	legacy_imports: Set<string>;
 * 	script_insertions: Set<string>;
 *  derived_components: Map<string, string>;
 *  derived_conflicting_slots: Map<string, string>;
 * 	derived_labeled_statements: Set<LabeledStatement>;
 *  has_svelte_self: boolean;
 *  uses_ts: boolean;
 * }} State
 */

/** @type {Visitors<AST.SvelteNode, State>} */
const instance_script = {
	_(node, { state, next }) {
		// @ts-expect-error
		const comments = node.leadingComments;
		if (comments) {
			for (const comment of comments) {
				if (comment.type === 'Line') {
					const migrated = migrate_svelte_ignore(comment.value);
					if (migrated !== comment.value) {
						state.str.overwrite(comment.start + '//'.length, comment.end, migrated);
					}
				}
			}
		}
		next();
	},
	Identifier(node, { state, path }) {
		handle_identifier(node, state, path);
	},
	ImportDeclaration(node, { state }) {
		state.props_insertion_point = node.end ?? state.props_insertion_point;
		if (node.source.value === 'svelte') {
			let illegal_specifiers = [];
			let removed_specifiers = 0;
			for (let specifier of node.specifiers) {
				if (
					specifier.type === 'ImportSpecifier' &&
					specifier.imported.type === 'Identifier' &&
					['beforeUpdate', 'afterUpdate'].includes(specifier.imported.name)
				) {
					const references = state.scope.references.get(specifier.local.name);
					if (!references) {
						let end = /** @type {number} */ (
							state.str.original.indexOf(',', specifier.end) !== -1 &&
							state.str.original.indexOf(',', specifier.end) <
								state.str.original.indexOf('}', specifier.end)
								? state.str.original.indexOf(',', specifier.end) + 1
								: specifier.end
						);
						while (state.str.original[end].trim() === '') end++;
						state.str.remove(/** @type {number} */ (specifier.start), end);
						removed_specifiers++;
						continue;
					}
					illegal_specifiers.push(specifier.imported.name);
				}
			}
			if (removed_specifiers === node.specifiers.length) {
				state.str.remove(/** @type {number} */ (node.start), /** @type {number} */ (node.end));
			}
			if (illegal_specifiers.length > 0) {
				throw new MigrationError(
					`Can't migrate code with ${illegal_specifiers.join(' and ')}. Please migrate by hand.`
				);
			}
		}
	},
	ExportNamedDeclaration(node, { state, next }) {
		if (node.declaration) {
			next();
			return;
		}

		let count_removed = 0;
		for (const specifier of node.specifiers) {
			if (specifier.local.type !== 'Identifier') continue;

			const binding = state.scope.get(specifier.local.name);
			if (binding?.kind === 'bindable_prop') {
				state.str.remove(
					/** @type {number} */ (specifier.start),
					/** @type {number} */ (specifier.end)
				);
				count_removed++;
			}
		}
		if (count_removed === node.specifiers.length) {
			state.str.remove(/** @type {number} */ (node.start), /** @type {number} */ (node.end));
		}
	},
	VariableDeclaration(node, { state, path, visit, next }) {
		if (state.scope !== state.analysis.instance.scope) {
			return;
		}

		let nr_of_props = 0;

		for (let i = 0; i < node.declarations.length; i++) {
			const declarator = node.declarations[i];
			if (state.analysis.runes) {
				if (get_rune(declarator.init, state.scope) === '$props') {
					state.props_insertion_point = /** @type {number} */ (declarator.id.start) + 1;
					state.has_props_rune = true;
				}
				continue;
			}

			let bindings;
			try {
				bindings = state.scope.get_bindings(declarator);
			} catch (e) {
				// no bindings, so we can skip this
				next();
				continue;
			}
			const has_state = bindings.some((binding) => binding.kind === 'state');
			const has_props = bindings.some((binding) => binding.kind === 'bindable_prop');

			if (!has_state && !has_props) {
				next();
				continue;
			}

			if (has_props) {
				nr_of_props++;

				if (declarator.id.type !== 'Identifier') {
					// TODO invest time in this?
					throw new MigrationError(
						'Encountered an export declaration pattern that is not supported for automigration.'
					);
					// Turn export let into props. It's really really weird because export let { x: foo, z: [bar]} = ..
					// means that foo and bar are the props (i.e. the leafs are the prop names), not x and z.
					// const tmp = b.id(state.scope.generate('tmp'));
					// const paths = extract_paths(declarator.id, tmp);
					// state.props_pre.push(
					// 	b.declaration('const', tmp, visit(declarator.init!) as Expression)
					// );
					// for (const path of paths) {
					// 	const name = (path.node as Identifier).name;
					// 	const binding = state.scope.get(name)!;
					// 	const value = path.expression;
					// 	if (binding.kind === 'bindable_prop' || binding.kind === 'rest_prop') {
					// 		state.props.push({
					// 			local: name,
					// 			exported: binding.prop_alias ? binding.prop_alias : name,
					// 			init: value
					// 		});
					// 		state.props_insertion_point = /** @type {number} */(declarator.end);
					// 	} else {
					// 		declarations.push(b.declarator(path.node, value));
					// 	}
					// }
				}

				const name = declarator.id.name;
				const binding = /** @type {Binding} */ (state.scope.get(name));

				if (state.analysis.uses_props && (declarator.init || binding.updated)) {
					throw new MigrationError(
						'$$props is used together with named props in a way that cannot be automatically migrated.'
					);
				}

				const prop = state.props.find((prop) => prop.exported === (binding.prop_alias || name));
				if (prop) {
					next();
					// $$Props type was used
					prop.init = declarator.init
						? state.str
								.snip(
									/** @type {number} */ (declarator.init.start),
									/** @type {number} */ (declarator.init.end)
								)
								.toString()
						: '';
					prop.bindable = binding.updated;
					prop.exported = binding.prop_alias || name;
					prop.type_only = false;
				} else {
					next();
					state.props.push({
						local: name,
						exported: binding.prop_alias ? binding.prop_alias : name,
						init: declarator.init
							? state.str
									.snip(
										/** @type {number} */ (declarator.init.start),
										/** @type {number} */ (declarator.init.end)
									)
									.toString()
							: '',
						optional: !!declarator.init,
						bindable: binding.updated,
						...extract_type_and_comment(declarator, state, path)
					});
				}

				let start = /** @type {number} */ (declarator.start);
				let end = /** @type {number} */ (declarator.end);

				// handle cases like let a,b,c; where only some are exported
				if (node.declarations.length > 1) {
					// move the insertion point after the node itself;
					state.props_insertion_point = /** @type {number} */ (node.end);
					// if it's not the first declaration remove from the , of the previous declaration
					if (i !== 0) {
						start = state.str.original.indexOf(
							',',
							/** @type {number} */ (node.declarations[i - 1].end)
						);
					}
					// if it's not the last declaration remove either from up until the
					// start of the next declaration (if it's the first declaration) or
					// up until the last index of , from the next declaration
					if (i !== node.declarations.length - 1) {
						if (i === 0) {
							end = /** @type {number} */ (node.declarations[i + 1].start);
						} else {
							end = state.str.original.lastIndexOf(
								',',
								/** @type {number} */ (node.declarations[i + 1].start)
							);
						}
					}
				} else {
					state.props_insertion_point = /** @type {number} */ (declarator.end);
				}

				state.str.update(start, end, '');

				continue;
			}

			/**
			 * @param {"state"|"derived"} rune
			 */
			function check_rune_binding(rune) {
				const has_rune_binding = !!state.scope.get(rune);
				if (has_rune_binding) {
					throw new MigrationError(
						`can't migrate \`${state.str.original.substring(/** @type {number} */ (node.start), node.end)}\` to \`$${rune}\` because there's a variable named ${rune}.\n     Rename the variable and try again or migrate by hand.`
					);
				}
			}

			// state
			if (declarator.init) {
				let { start, end } = /** @type {{ start: number, end: number }} */ (declarator.init);

				if (declarator.init.type === 'SequenceExpression') {
					while (state.str.original[start] !== '(') start -= 1;
					while (state.str.original[end - 1] !== ')') end += 1;
				}

				check_rune_binding('state');

				state.str.prependLeft(start, '$state(');
				state.str.appendRight(end, ')');
			} else {
				/**
				 * @type {AssignmentExpression | undefined}
				 */
				let assignment_in_labeled;
				/**
				 * @type {LabeledStatement | undefined}
				 */
				let labeled_statement;

				// Analyze declaration bindings to see if they're exclusively updated within a single reactive statement
				const possible_derived = bindings.every((binding) =>
					binding.references.every((reference) => {
						const declaration = reference.path.find((el) => el.type === 'VariableDeclaration');
						const assignment = reference.path.find((el) => el.type === 'AssignmentExpression');
						const update = reference.path.find((el) => el.type === 'UpdateExpression');
						const labeled = /** @type {LabeledStatement | undefined} */ (
							reference.path.find((el) => el.type === 'LabeledStatement' && el.label.name === '$')
						);

						if (
							assignment &&
							labeled &&
							// ensure that $: foo = bar * 2 is not counted as a reassignment of bar
							(labeled.body.type !== 'ExpressionStatement' ||
								labeled.body.expression !== assignment ||
								(assignment.left.type === 'Identifier' &&
									assignment.left.name === binding.node.name))
						) {
							if (assignment_in_labeled) return false;
							assignment_in_labeled = /** @type {AssignmentExpression} */ (assignment);
							labeled_statement = labeled;
						}

						return (
							!update &&
							((declaration && binding.initial) ||
								(labeled && assignment) ||
								(!labeled && !assignment))
						);
					})
				);

				const labeled_has_single_assignment =
					labeled_statement?.body.type === 'BlockStatement' &&
					labeled_statement.body.body.length === 1 &&
					labeled_statement.body.body[0].type === 'ExpressionStatement';

				const is_expression_assignment =
					labeled_statement?.body.type === 'ExpressionStatement' &&
					labeled_statement.body.expression.type === 'AssignmentExpression';

				let should_be_state = false;

				if (is_expression_assignment) {
					const body = /**@type {ExpressionStatement}*/ (labeled_statement?.body);
					const expression = /**@type {AssignmentExpression}*/ (body.expression);
					const [, ids] = extract_all_identifiers_from_expression(expression.right);
					if (ids.length === 0) {
						should_be_state = true;
						state.derived_labeled_statements.add(
							/** @type {LabeledStatement} */ (labeled_statement)
						);
					}
				}

				if (
					!should_be_state &&
					possible_derived &&
					assignment_in_labeled &&
					labeled_statement &&
					(labeled_has_single_assignment || is_expression_assignment)
				) {
					const indent = state.str.original.substring(
						state.str.original.lastIndexOf('\n', /** @type {number} */ (node.start)) + 1,
						/** @type {number} */ (node.start)
					);
					// transfer all the leading comments
					if (
						labeled_statement.body.type === 'BlockStatement' &&
						labeled_statement.body.body[0].leadingComments
					) {
						for (let comment of labeled_statement.body.body[0].leadingComments) {
							state.str.prependLeft(
								/** @type {number} */ (node.start),
								comment.type === 'Block'
									? `/*${comment.value}*/\n${indent}`
									: `// ${comment.value}\n${indent}`
							);
						}
					}

					check_rune_binding('derived');

					// Someone wrote a `$: { ... }` statement which we can turn into a `$derived`
					state.str.appendRight(
						/** @type {number} */ (declarator.id.typeAnnotation?.end ?? declarator.id.end),
						' = $derived('
					);
					visit(assignment_in_labeled.right);
					state.str.appendRight(
						/** @type {number} */ (declarator.id.typeAnnotation?.end ?? declarator.id.end),
						state.str
							.snip(
								/** @type {number} */ (assignment_in_labeled.right.start),
								/** @type {number} */ (assignment_in_labeled.right.end)
							)
							.toString()
					);
					state.str.remove(
						/** @type {number} */ (labeled_statement.start),
						/** @type {number} */ (labeled_statement.end)
					);
					state.str.appendRight(
						/** @type {number} */ (declarator.id.typeAnnotation?.end ?? declarator.id.end),
						')'
					);
					state.derived_labeled_statements.add(labeled_statement);

					// transfer all the trailing comments
					if (
						labeled_statement.body.type === 'BlockStatement' &&
						labeled_statement.body.body[0].trailingComments
					) {
						for (let comment of labeled_statement.body.body[0].trailingComments) {
							state.str.appendRight(
								/** @type {number} */ (declarator.id.typeAnnotation?.end ?? declarator.id.end),
								comment.type === 'Block'
									? `\n${indent}/*${comment.value}*/`
									: `\n${indent}// ${comment.value}`
							);
						}
					}
				} else {
					check_rune_binding('state');

					state.str.prependLeft(
						/** @type {number} */ (declarator.id.typeAnnotation?.end ?? declarator.id.end),
						' = $state('
					);
					if (should_be_state) {
						// someone wrote a `$: foo = ...` statement which we can turn into `let foo = $state(...)`
						state.str.appendRight(
							/** @type {number} */ (declarator.id.typeAnnotation?.end ?? declarator.id.end),
							state.str
								.snip(
									/** @type {number} */ (
										/** @type {AssignmentExpression} */ (assignment_in_labeled).right.start
									),
									/** @type {number} */ (
										/** @type {AssignmentExpression} */ (assignment_in_labeled).right.end
									)
								)
								.toString()
						);
						state.str.remove(
							/** @type {number} */ (/** @type {LabeledStatement} */ (labeled_statement).start),
							/** @type {number} */ (/** @type {LabeledStatement} */ (labeled_statement).end)
						);
					}
					state.str.appendRight(
						/** @type {number} */ (declarator.id.typeAnnotation?.end ?? declarator.id.end),
						')'
					);
				}
			}
		}

		if (nr_of_props === node.declarations.length) {
			let start = /** @type {number} */ (node.start);
			let end = /** @type {number} */ (node.end);

			const parent = path.at(-1);
			if (parent?.type === 'ExportNamedDeclaration') {
				start = /** @type {number} */ (parent.start);
				end = /** @type {number} */ (parent.end);
			}
			while (state.str.original[start] !== '\n') start--;
			while (state.str.original[end] !== '\n') end++;
			state.str.update(start, end, '');
		}
	},
	BreakStatement(node, { state, path }) {
		if (path[1].type !== 'LabeledStatement') return;
		if (node.label?.name !== '$') return;
		state.str.update(
			/** @type {number} */ (node.start),
			/** @type {number} */ (node.end),
			'return;'
		);
	},
	LabeledStatement(node, { path, state, next }) {
		if (state.analysis.runes) return;
		if (path.length > 1) return;
		if (node.label.name !== '$') return;
		if (state.derived_labeled_statements.has(node)) return;

		next();

		/**
		 * @param {"state"|"derived"} rune
		 */
		function check_rune_binding(rune) {
			const has_rune_binding = state.scope.get(rune);
			if (has_rune_binding) {
				throw new MigrationError(
					`can't migrate \`$: ${state.str.original.substring(/** @type {number} */ (node.body.start), node.body.end)}\` to \`$${rune}\` because there's a variable named ${rune}.\n     Rename the variable and try again or migrate by hand.`
				);
			}
		}

		if (
			node.body.type === 'ExpressionStatement' &&
			node.body.expression.type === 'AssignmentExpression'
		) {
			const { left, right } = node.body.expression;

			const ids = extract_identifiers(left);
			const [, expression_ids] = extract_all_identifiers_from_expression(right);
			const bindings = ids.map((id) => /** @type {Binding} */ (state.scope.get(id.name)));

			if (bindings.every((b) => b.kind === 'legacy_reactive')) {
				if (
					right.type !== 'Literal' &&
					bindings.every((b) => b.kind !== 'store_sub') &&
					left.type !== 'MemberExpression'
				) {
					let { start, end } = /** @type {{ start: number, end: number }} */ (right);

					check_rune_binding('derived');

					// $derived
					state.str.update(
						/** @type {number} */ (node.start),
						/** @type {number} */ (node.body.expression.start),
						'let '
					);

					if (right.type === 'SequenceExpression') {
						while (state.str.original[start] !== '(') start -= 1;
						while (state.str.original[end - 1] !== ')') end += 1;
					}

					state.str.prependRight(start, `$derived(`);

					// in a case like `$: ({ a } = b())`, there's already a trailing parenthesis.
					// otherwise, we need to add one
					if (state.str.original[/** @type {number} */ (node.body.start)] !== '(') {
						state.str.appendLeft(end, `)`);
					}

					return;
				}

				for (const binding of bindings) {
					if (binding.reassigned && (ids.includes(binding.node) || expression_ids.length === 0)) {
						check_rune_binding('state');
						const init =
							binding.kind === 'state'
								? ' = $state()'
								: expression_ids.length === 0
									? ` = $state(${state.str.original.substring(/** @type {number} */ (right.start), right.end)})`
									: '';
						// implicitly-declared variable which we need to make explicit
						state.str.prependLeft(
							/** @type {number} */ (node.start),
							`let ${binding.node.name}${init};\n${state.indent}`
						);
					}
				}

				if (expression_ids.length === 0 && bindings.every((b) => b.kind !== 'store_sub')) {
					state.str.remove(/** @type {number} */ (node.start), /** @type {number} */ (node.end));
					return;
				}
			}
		}

		state.legacy_imports.add('run');
		const is_block_stmt = node.body.type === 'BlockStatement';
		const start_end = /** @type {number} */ (node.body.start);
		// TODO try to find out if we can use $derived.by instead?
		if (is_block_stmt) {
			state.str.update(
				/** @type {number} */ (node.start),
				start_end + 1,
				`${state.names.run}(() => {`
			);
			const end = /** @type {number} */ (node.body.end);
			state.str.update(end - 1, end, '});');
		} else {
			state.str.update(
				/** @type {number} */ (node.start),
				start_end,
				`${state.names.run}(() => {\n${state.indent}`
			);
			state.str.indent(state.indent, {
				exclude: [
					[0, /** @type {number} */ (node.body.start)],
					[/** @type {number} */ (node.body.end), state.end]
				]
			});
			state.str.appendLeft(/** @type {number} */ (node.end), `\n${state.indent}});`);
		}
	}
};

/**
 *
 * @param {State} state
 * @param {number} start
 * @param {number} end
 */
function trim_block(state, start, end) {
	const original = state.str.snip(start, end).toString();
	const without_parens = original.substring(1, original.length - 1);
	if (without_parens.trim().length !== without_parens.length) {
		state.str.update(start + 1, end - 1, without_parens.trim());
	}
}

/** @type {Visitors<AST.SvelteNode, State>} */
const template = {
	Identifier(node, { state, path }) {
		handle_identifier(node, state, path);
	},
	RegularElement(node, { state, path, next }) {
		// Strip off any namespace from the beginning of the node name.
		const node_name = node.name.replace(/[a-zA-Z-]*:/g, '');

		if (state.analysis.source[node.end - 2] === '/' && !is_void(node_name) && !is_svg(node_name)) {
			let trimmed_position = node.end - 2;
			while (state.str.original.charAt(trimmed_position - 1) === ' ') trimmed_position--;
			state.str.remove(trimmed_position, node.end - 1);
			state.str.appendLeft(node.end, `</${node.name}>`);
		}

		migrate_slot_usage(node, path, state);
		handle_events(node, state);

		next();
	},
	SvelteSelf(node, { state, next }) {
		const source = state.str.original.substring(node.start, node.end);
		if (!state.filename) {
			const indent = guess_indent(source);
			has_migration_task = true;
			state.str.prependRight(
				node.start,
				`<!-- @migration-task: svelte:self is deprecated, import this Svelte file into itself instead -->\n${indent}`
			);
			next();
			return;
		}
		// overwrite the open tag
		state.str.overwrite(
			node.start + 1,
			node.start + 1 + 'svelte:self'.length,
			`${state.analysis.name}`
		);
		// if it has a fragment we need to overwrite the closing tag too
		if (node.fragment.nodes.length > 0) {
			state.str.overwrite(
				state.str.original.lastIndexOf('<', node.end) + 2,
				node.end - 1,
				`${state.analysis.name}`
			);
		} else if (!source.endsWith('/>')) {
			// special case for case `<svelte:self></svelte:self>` it has no fragment but
			// we still need to overwrite the end tag
			state.str.overwrite(
				node.start + source.lastIndexOf('</', node.end) + 2,
				node.end - 1,
				`${state.analysis.name}`
			);
		}
		state.has_svelte_self = true;
		next();
	},
	SvelteElement(node, { state, path, next }) {
		migrate_slot_usage(node, path, state);
		if (node.tag.type === 'Literal') {
			let is_static = true;

			let a = /** @type {number} */ (node.tag.start);
			let b = /** @type {number} */ (node.tag.end);
			let quote_mark = state.str.original[a - 1];

			while (state.str.original[--a] !== '=') {
				if (state.str.original[a] === '{') {
					is_static = false;
					break;
				}
			}

			if (is_static && state.str.original[b] === quote_mark) {
				state.str.prependLeft(a + 1, '{');
				state.str.appendRight(/** @type {number} */ (node.tag.end) + 1, '}');
			}
		}

		handle_events(node, state);
		next();
	},
	Component(node, { state, path, next }) {
		next();
		migrate_slot_usage(node, path, state);
	},
	SvelteComponent(node, { state, next, path }) {
		next();

		migrate_slot_usage(node, path, state);

		let expression = state.str
			.snip(
				/** @type {number} */ (node.expression.start),
				/** @type {number} */ (node.expression.end)
			)
			.toString();

		if (
			(node.expression.type !== 'Identifier' && node.expression.type !== 'MemberExpression') ||
			!regex_valid_component_name.test(expression)
		) {
			let current_expression = expression;
			expression = state.scope.generate('SvelteComponent');
			let needs_derived = true;
			for (let i = path.length - 1; i >= 0; i--) {
				const part = path[i];
				if (
					part.type === 'EachBlock' ||
					part.type === 'AwaitBlock' ||
					part.type === 'IfBlock' ||
					part.type === 'SnippetBlock' ||
					part.type === 'Component' ||
					part.type === 'SvelteComponent'
				) {
					let position = node.start;
					if (i !== path.length - 1) {
						for (let modifier = 1; modifier < path.length - i; modifier++) {
							const path_part = path[i + modifier];
							if ('start' in path_part) {
								position = /** @type {number} */ (path_part.start);
								break;
							}
						}
					}
					const indent = state.str.original.substring(
						state.str.original.lastIndexOf('\n', position) + 1,
						position
					);
					state.str.appendRight(
						position,
						`{@const ${expression} = ${current_expression}}\n${indent}`
					);
					needs_derived = false;
					break;
				}
			}
			if (needs_derived) {
				if (state.derived_components.has(current_expression)) {
					expression = /** @type {string} */ (state.derived_components.get(current_expression));
				} else {
					state.derived_components.set(current_expression, expression);
				}
			}
		}

		state.str.overwrite(node.start + 1, node.start + node.name.length + 1, expression);

		if (state.str.original.substring(node.end - node.name.length - 1, node.end - 1) === node.name) {
			state.str.overwrite(node.end - node.name.length - 1, node.end - 1, expression);
		}
		let this_pos = state.str.original.lastIndexOf('this', node.expression.start);
		while (!state.str.original.charAt(this_pos - 1).trim()) this_pos--;
		const end_pos = state.str.original.indexOf('}', node.expression.end) + 1;
		state.str.remove(this_pos, end_pos);
	},
	SvelteFragment(node, { state, path, next }) {
		migrate_slot_usage(node, path, state);
		next();
	},
	SvelteWindow(node, { state, next }) {
		handle_events(node, state);
		next();
	},
	SvelteBody(node, { state, next }) {
		handle_events(node, state);
		next();
	},
	SvelteDocument(node, { state, next }) {
		handle_events(node, state);
		next();
	},
	SlotElement(node, { state, path, next, visit }) {
		migrate_slot_usage(node, path, state);

		if (state.analysis.custom_element) return;
		let name = 'children';
		let slot_name = 'default';
		let slot_props = '{ ';
		let aliased_slot_name;

		for (const attr of node.attributes) {
			if (attr.type === 'SpreadAttribute') {
				slot_props += `...${state.str.original.substring(/** @type {number} */ (attr.expression.start), attr.expression.end)}, `;
			} else if (attr.type === 'Attribute') {
				if (attr.name === 'slot') {
					continue;
				}

				if (attr.name === 'name') {
					slot_name = /** @type {any} */ (attr.value)[0].data;
					// if some of the parents or this node itself har a slot
					// attribute with the sane name of this slot
					// we want to create a derived or the migrated snippet
					// will shadow the slot prop
					if (
						path.some(
							(parent) =>
								(parent.type === 'RegularElement' ||
									parent.type === 'SvelteElement' ||
									parent.type === 'Component' ||
									parent.type === 'SvelteComponent' ||
									parent.type === 'SvelteFragment') &&
								parent.attributes.some(
									(attribute) =>
										attribute.type === 'Attribute' &&
										attribute.name === 'slot' &&
										is_text_attribute(attribute) &&
										attribute.value[0].data === slot_name
								)
						) ||
						node.attributes.some(
							(attribute) =>
								attribute.type === 'Attribute' &&
								attribute.name === 'slot' &&
								is_text_attribute(attribute) &&
								attribute.value[0].data === slot_name
						)
					) {
						aliased_slot_name = `${slot_name}_render`;
						state.derived_conflicting_slots.set(aliased_slot_name, slot_name);
					}
				} else {
					const attr_value =
						attr.value === true || Array.isArray(attr.value) ? attr.value : [attr.value];
					let value = 'true';
					if (attr_value !== true) {
						const first = attr_value[0];
						const last = attr_value[attr_value.length - 1];
						for (const attr of attr_value) {
							visit(attr);
						}
						value = state.str
							.snip(
								first.type === 'Text'
									? first.start - 1
									: /** @type {number} */ (first.expression.start),
								last.type === 'Text' ? last.end + 1 : /** @type {number} */ (last.expression.end)
							)
							.toString();
					}
					slot_props += value === attr.name ? `${value}, ` : `${attr.name}: ${value}, `;
				}
			}
		}

		slot_props += '}';
		if (slot_props === '{ }') {
			slot_props = '';
		}

		const existing_prop = state.props.find((prop) => prop.slot_name === slot_name);
		if (existing_prop) {
			name = existing_prop.local;
		} else if (slot_name !== 'default') {
			name = state.scope.generate(slot_name);
			if (name !== slot_name) {
				throw new MigrationError(
					`This migration would change the name of a slot (${slot_name} to ${name}) making the component unusable`
				);
			}
		}

		if (!existing_prop) {
			state.props.push({
				local: name,
				exported: name,
				init: '',
				bindable: false,
				optional: true,
				slot_name,
				type: `import('svelte').${slot_props ? 'Snippet<[any]>' : 'Snippet'}`
			});
		} else if (existing_prop.needs_refine_type) {
			existing_prop.type = `import('svelte').${slot_props ? 'Snippet<[any]>' : 'Snippet'}`;
			existing_prop.needs_refine_type = false;
		}

		if (
			slot_name === 'default' &&
			path.some(
				(parent) =>
					(parent.type === 'SvelteComponent' ||
						parent.type === 'Component' ||
						parent.type === 'RegularElement' ||
						parent.type === 'SvelteElement' ||
						parent.type === 'SvelteFragment') &&
					parent.attributes.some((attr) => attr.type === 'LetDirective')
			)
		) {
			aliased_slot_name = `${name}_render`;
			state.derived_conflicting_slots.set(aliased_slot_name, name);
		}
		name = aliased_slot_name ?? name;

		if (node.fragment.nodes.length > 0) {
			next();
			state.str.update(
				node.start,
				node.fragment.nodes[0].start,
				`{#if ${name}}{@render ${state.analysis.uses_props ? `${state.names.props}.` : ''}${name}(${slot_props})}{:else}`
			);
			state.str.update(node.fragment.nodes[node.fragment.nodes.length - 1].end, node.end, '{/if}');
		} else {
			state.str.update(
				node.start,
				node.end,
				`{@render ${state.analysis.uses_props ? `${state.names.props}.` : ''}${name}?.(${slot_props})}`
			);
		}
	},
	Comment(node, { state }) {
		const migrated = migrate_svelte_ignore(node.data);
		if (migrated !== node.data) {
			state.str.overwrite(node.start + '<!--'.length, node.end - '-->'.length, migrated);
		}
	},
	HtmlTag(node, { state, next }) {
		trim_block(state, node.start, node.end);
		next();
	},
	ConstTag(node, { state, next }) {
		trim_block(state, node.start, node.end);
		next();
	},
	IfBlock(node, { state, next }) {
		const start = node.start;
		const end = state.str.original.indexOf('}', node.test.end) + 1;
		trim_block(state, start, end);
		next();
	},
	AwaitBlock(node, { state, next }) {
		const start = node.start;
		const end =
			state.str.original.indexOf(
				'}',
				node.pending !== null ? node.expression.end : node.value?.end
			) + 1;
		trim_block(state, start, end);
		if (node.pending !== null) {
			const start = state.str.original.lastIndexOf('{', node.value?.start);
			const end = state.str.original.indexOf('}', node.value?.end) + 1;
			trim_block(state, start, end);
		}
		if (node.catch !== null) {
			const start = state.str.original.lastIndexOf('{', node.error?.start);
			const end = state.str.original.indexOf('}', node.error?.end) + 1;
			trim_block(state, start, end);
		}
		next();
	},
	KeyBlock(node, { state, next }) {
		const start = node.start;
		const end = state.str.original.indexOf('}', node.expression.end) + 1;
		trim_block(state, start, end);
		next();
	}
};

/**
 * @param {AST.RegularElement | AST.SvelteElement | AST.SvelteComponent | AST.Component | AST.SlotElement | AST.SvelteFragment} node
 * @param {AST.SvelteNode[]} path
 * @param {State} state
 */
function migrate_slot_usage(node, path, state) {
	const parent = path.at(-2);
	// Bail on custom element slot usage
	if (
		parent?.type !== 'Component' &&
		parent?.type !== 'SvelteComponent' &&
		node.type !== 'Component' &&
		node.type !== 'SvelteComponent'
	) {
		return;
	}

	let snippet_name = 'children';
	let snippet_props = [];

	// if we stop the transform because the name is not correct we don't want to
	// remove the let directive and they could come before the name
	let removal_queue = [];

	for (let attribute of node.attributes) {
		if (
			attribute.type === 'Attribute' &&
			attribute.name === 'slot' &&
			is_text_attribute(attribute)
		) {
			snippet_name = attribute.value[0].data;
			// the default slot in svelte 4 if what the children slot is for svelte 5
			if (snippet_name === 'default') {
				snippet_name = 'children';
			}
			if (!regex_is_valid_identifier.test(snippet_name) || is_reserved(snippet_name)) {
				has_migration_task = true;
				state.str.appendLeft(
					node.start,
					`<!-- @migration-task: migrate this slot by hand, \`${snippet_name}\` is an invalid identifier -->\n${state.indent}`
				);
				return;
			}
			if (parent?.type === 'Component' || parent?.type === 'SvelteComponent') {
				for (let attribute of parent.attributes) {
					if (attribute.type === 'Attribute' || attribute.type === 'BindDirective') {
						if (attribute.name === snippet_name) {
							state.str.appendLeft(
								node.start,
								`<!-- @migration-task: migrate this slot by hand, \`${snippet_name}\` would shadow a prop on the parent component -->\n${state.indent}`
							);
							return;
						}
					}
				}
			}
			// flush the queue after we found the name
			for (let remove_let of removal_queue) {
				remove_let();
			}
			state.str.remove(attribute.start, attribute.end);
		}
		if (attribute.type === 'LetDirective') {
			snippet_props.push(
				attribute.name +
					(attribute.expression
						? `: ${state.str.original.substring(/** @type {number} */ (attribute.expression.start), /** @type {number} */ (attribute.expression.end))}`
						: '')
			);
			// we just add to the queue to remove them after we found if we need to migrate or we bail
			removal_queue.push(() => state.str.remove(attribute.start, attribute.end));
		}
	}

	if (removal_queue.length > 0) {
		for (let remove_let of removal_queue) {
			remove_let();
		}
	}

	if (node.type === 'SvelteFragment' && node.fragment.nodes.length > 0) {
		// remove node itself, keep content
		state.str.remove(node.start, node.fragment.nodes[0].start);
		state.str.remove(node.fragment.nodes[node.fragment.nodes.length - 1].end, node.end);
	}

	const props = snippet_props.length > 0 ? `{ ${snippet_props.join(', ')} }` : '';

	if (snippet_name === 'children' && node.type !== 'SvelteFragment') {
		if (snippet_props.length === 0) return; // nothing to do

		let inner_start = 0;
		let inner_end = 0;
		for (let i = 0; i < node.fragment.nodes.length; i++) {
			const inner = node.fragment.nodes[i];
			const is_empty_text = inner.type === 'Text' && !inner.data.trim();

			if (
				(inner.type === 'RegularElement' ||
					inner.type === 'SvelteElement' ||
					inner.type === 'Component' ||
					inner.type === 'SvelteComponent' ||
					inner.type === 'SlotElement' ||
					inner.type === 'SvelteFragment') &&
				inner.attributes.some((attr) => attr.type === 'Attribute' && attr.name === 'slot')
			) {
				if (inner_start && !inner_end) {
					// End of default slot content
					inner_end = inner.start;
				}
			} else if (!inner_start && !is_empty_text) {
				// Start of default slot content
				inner_start = inner.start;
			} else if (inner_end && !is_empty_text) {
				// There was default slot content before, then some named slot content, now some default slot content again.
				// We're moving the last character back by one to avoid the closing {/snippet} tag inserted afterwards
				// to come before the opening {#snippet} tag of the named slot.
				state.str.update(inner_end - 1, inner_end, '');
				state.str.prependLeft(inner_end - 1, state.str.original[inner_end - 1]);
				state.str.move(inner.start, inner.end, inner_end - 1);
			}
		}

		if (!inner_end) {
			inner_end = node.fragment.nodes[node.fragment.nodes.length - 1].end;
		}

		state.str.appendLeft(
			inner_start,
			`{#snippet ${snippet_name}(${props})}\n${state.indent.repeat(path.length)}`
		);
		state.str.indent(state.indent, {
			exclude: [
				[0, inner_start],
				[inner_end, state.str.original.length]
			]
		});
		if (inner_end < node.fragment.nodes[node.fragment.nodes.length - 1].end) {
			// Named slots coming afterwards
			state.str.prependLeft(inner_end, `{/snippet}\n${state.indent.repeat(path.length)}`);
		} else {
			// No named slots coming afterwards
			state.str.prependLeft(
				inner_end,
				`${state.indent.repeat(path.length)}{/snippet}\n${state.indent.repeat(path.length - 1)}`
			);
		}
	} else {
		// Named slot or `svelte:fragment`: wrap element itself in a snippet
		state.str.prependLeft(
			node.start,
			`{#snippet ${snippet_name}(${props})}\n${state.indent.repeat(path.length - 2)}`
		);
		state.str.indent(state.indent, {
			exclude: [
				[0, node.start],
				[node.end, state.str.original.length]
			]
		});
		const str = `\n${state.indent.repeat(path.length - 2)}{/snippet}`;

		if (node.type === 'SlotElement') {
			state.str.appendRight(node.end, str);
		} else {
			state.str.appendLeft(node.end, str);
		}
	}
}

/**
 * @param {VariableDeclarator} declarator
 * @param {State} state
 * @param {AST.SvelteNode[]} path
 */
function extract_type_and_comment(declarator, state, path) {
	const str = state.str;
	const parent = path.at(-1);

	// Try to find jsdoc above the declaration
	let comment_node = /** @type {Node} */ (parent)?.leadingComments?.at(-1);

	const comment_start = /** @type {any} */ (comment_node)?.start;
	const comment_end = /** @type {any} */ (comment_node)?.end;
	let comment = comment_node && str.original.substring(comment_start, comment_end);
	if (comment_node) {
		str.update(comment_start, comment_end, '');
	}

	// Find trailing comments
	const trailing_comment_node = /** @type {Node} */ (parent)?.trailingComments?.at(0);
	const trailing_comment_start = /** @type {any} */ (trailing_comment_node)?.start;
	const trailing_comment_end = /** @type {any} */ (trailing_comment_node)?.end;
	let trailing_comment =
		trailing_comment_node && str.original.substring(trailing_comment_start, trailing_comment_end);

	if (trailing_comment_node) {
		str.update(trailing_comment_start, trailing_comment_end, '');
	}

	if (declarator.id.typeAnnotation) {
		state.has_type_or_fallback = true;
		let start = declarator.id.typeAnnotation.start + 1; // skip the colon
		while (str.original[start] === ' ') {
			start++;
		}
		return {
			type: str.original.substring(start, declarator.id.typeAnnotation.end),
			comment,
			trailing_comment
		};
	}

	let cleaned_comment_arr = comment
		?.split('\n')
		.map((line) =>
			line
				.trim()
				// replace `// ` for one liners
				.replace(/^\/\/\s*/g, '')
				// replace `\**` for the initial JSDoc
				.replace(/^\/\*\*?\s*/g, '')
				// migrate `*/` for the end of JSDoc
				.replace(/\s*\*\/$/g, '')
				// remove any initial `* ` to clean the comment
				.replace(/^\*\s*/g, '')
		)
		.filter(Boolean);
	const first_at_comment = cleaned_comment_arr?.findIndex((line) => line.startsWith('@'));
	let cleaned_comment = cleaned_comment_arr
		?.slice(0, first_at_comment !== -1 ? first_at_comment : cleaned_comment_arr.length)
		.join('\n');

	let cleaned_comment_arr_trailing = trailing_comment
		?.split('\n')
		.map((line) =>
			line
				.trim()
				// replace `// ` for one liners
				.replace(/^\/\/\s*/g, '')
				// replace `\**` for the initial JSDoc
				.replace(/^\/\*\*?\s*/g, '')
				// migrate `*/` for the end of JSDoc
				.replace(/\s*\*\/$/g, '')
				// remove any initial `* ` to clean the comment
				.replace(/^\*\s*/g, '')
		)
		.filter(Boolean);
	const first_at_comment_trailing = cleaned_comment_arr_trailing?.findIndex((line) =>
		line.startsWith('@')
	);
	let cleaned_comment_trailing = cleaned_comment_arr_trailing
		?.slice(
			0,
			first_at_comment_trailing !== -1
				? first_at_comment_trailing
				: cleaned_comment_arr_trailing.length
		)
		.join('\n');

	// try to find a comment with a type annotation, hinting at jsdoc
	if (parent?.type === 'ExportNamedDeclaration' && comment_node) {
		state.has_type_or_fallback = true;
		const match = /@type {(.+)}/.exec(comment_node.value);
		if (match) {
			// try to find JSDoc comments after a hyphen `-`
			const jsdoc_comment = /@type {.+} (?:\w+|\[.*?\]) - (.+)/.exec(comment_node.value);
			if (jsdoc_comment) {
				cleaned_comment += jsdoc_comment[1]?.trim();
			}
			return {
				type: match[1],
				comment: cleaned_comment,
				trailing_comment: cleaned_comment_trailing
			};
		}
	}

	// try to infer it from the init
	if (declarator.init?.type === 'Literal') {
		state.has_type_or_fallback = true; // only assume type if it's trivial to infer - else someone would've added a type annotation
		const type = typeof declarator.init.value;
		if (type === 'string' || type === 'number' || type === 'boolean') {
			return {
				type,
				comment: state.uses_ts ? comment : cleaned_comment,
				trailing_comment: state.uses_ts ? trailing_comment : cleaned_comment_trailing
			};
		}
	}
	return {
		type: 'any',
		comment: state.uses_ts ? comment : cleaned_comment,
		trailing_comment: state.uses_ts ? trailing_comment : cleaned_comment_trailing
	};
}

// Ensure modifiers are applied in the same order as Svelte 4
const modifier_order = /** @type {const} */ ([
	'preventDefault',
	'stopPropagation',
	'stopImmediatePropagation',
	'self',
	'trusted',
	'once'
]);

/**
 * @param {AST.RegularElement | AST.SvelteElement | AST.SvelteWindow | AST.SvelteDocument | AST.SvelteBody} element
 * @param {State} state
 */
function handle_events(element, state) {
	/** @type {Map<string, AST.OnDirective[]>} */
	const handlers = new Map();
	for (const attribute of element.attributes) {
		if (attribute.type !== 'OnDirective') continue;

		let name = `on${attribute.name}`;
		if (attribute.modifiers.includes('capture')) {
			name += 'capture';
		}

		const nodes = handlers.get(name) || [];
		nodes.push(attribute);
		handlers.set(name, nodes);
	}

	for (const [name, nodes] of handlers) {
		const handlers = [];

		let first = null;

		for (const node of nodes) {
			/** @type {string} */
			let body;

			if (node.expression) {
				body = state.str.original.substring(
					/** @type {number} */ (node.expression.start),
					/** @type {number} */ (node.expression.end)
				);
			} else {
				body = `${state.names.bubble}('${node.name}')`;
				state.legacy_imports.add('createBubbler');
				state.script_insertions.add(
					`const ${state.names.bubble} = ${state.names.createBubbler}();`
				);
			}

			const has_passive = node.modifiers.includes('passive');
			const has_nonpassive = node.modifiers.includes('nonpassive');

			const modifiers = modifier_order.filter((modifier) => node.modifiers.includes(modifier));

			for (const modifier of modifiers) {
				state.legacy_imports.add(modifier);
				body = `${state.names[modifier]}(${body})`;
			}

			if (has_passive || has_nonpassive) {
				const action = has_passive ? 'passive' : 'nonpassive';
				state.legacy_imports.add(action);

				state.str.overwrite(
					node.start,
					node.end,
					`use:${state.names[action]}={['${node.name}', () => ${body}]}`
				);
			} else {
				if (first) {
					let start = node.start;
					let end = node.end;

					while (/[\s\n]/.test(state.str.original[start - 1])) start -= 1;
					state.str.remove(start, end);
				} else {
					first = node;
				}

				handlers.push(body);
			}
		}

		if (first) {
			/** @type {string} */
			let replacement;

			if (handlers.length > 1) {
				state.legacy_imports.add('handlers');
				replacement = `${name}={${state.names.handlers}(${handlers.join(', ')})}`;
			} else {
				const handler = handlers[0];
				replacement = handler === name ? `{${handler}}` : `${name}={${handler}}`;
			}

			state.str.overwrite(first.start, first.end, replacement);
		}
	}
}

/**
 * Returns start and end of the node. If the start is preceeded with white-space-only before a line break,
 * the start will be the start of the line.
 * @param {string} source
 * @param {LabeledStatement} node
 */
function get_node_range(source, node) {
	const first_leading_comment = node.leadingComments?.[0];
	const last_trailing_comment = node.trailingComments?.[node.trailingComments.length - 1];

	// @ts-expect-error the type of `Comment` seems to be wrong...the node actually contains
	// start and end but the type seems to only contain a `range` (which doesn't actually exists)
	let start = /** @type {number} */ (first_leading_comment?.start ?? node.start);
	// @ts-expect-error the type of `Comment` seems to be wrong...the node actually contains
	// start and end but the type seems to only contain a `range` (which doesn't actually exists)
	let end = /** @type {number} */ (last_trailing_comment?.end ?? node.end);

	let idx = start;
	while (source[idx - 1] !== '\n' && source[idx - 1] !== '\r') {
		idx--;
		if (source[idx] !== ' ' && source[idx] !== '\t') {
			idx = start;
			break;
		}
	}

	start = idx;

	return { start, end };
}

/**
 * @param {Identifier} node
 * @param {State} state
 * @param {any[]} path
 */
function handle_identifier(node, state, path) {
	const parent = path.at(-1);
	if (parent?.type === 'MemberExpression' && parent.property === node) return;

	if (state.analysis.uses_props && node.name !== '$$slots') {
		if (node.name === '$$props' || node.name === '$$restProps') {
			// not 100% correct for $$restProps but it'll do
			state.str.update(
				/** @type {number} */ (node.start),
				/** @type {number} */ (node.end),
				state.names.props
			);
		} else {
			const binding = state.scope.get(node.name);
			if (binding?.kind === 'bindable_prop' && binding.node !== node) {
				state.str.prependLeft(/** @type {number} */ (node.start), `${state.names.props}.`);
			}
		}
	} else if (node.name === '$$restProps' && state.analysis.uses_rest_props) {
		state.str.update(
			/** @type {number} */ (node.start),
			/** @type {number} */ (node.end),
			state.names.rest
		);
	} else if (node.name === '$$slots' && state.analysis.uses_slots) {
		if (parent?.type === 'MemberExpression') {
			if (state.analysis.custom_element) return;

			let name = parent.property.type === 'Literal' ? parent.property.value : parent.property.name;
			let slot_name = name;
			const existing_prop = state.props.find((prop) => prop.slot_name === name);
			if (existing_prop) {
				name = existing_prop.local;
			} else if (name !== 'default') {
				let new_name = state.scope.generate(name);
				if (new_name !== name) {
					throw new MigrationError(
						`This migration would change the name of a slot (${name} to ${new_name}) making the component unusable`
					);
				}
			}

			name = name === 'default' ? 'children' : name;

			if (!existing_prop) {
				state.props.push({
					local: name,
					exported: name,
					init: '',
					bindable: false,
					optional: true,
					slot_name,
					// if it's the first time we encounter this slot
					// we start with any and delegate to when the slot
					// is actually rendered (it might not happen in that case)
					// any is still a safe bet
					type: `import('svelte').Snippet<[any]>`,
					needs_refine_type: true
				});
			}

			state.str.update(
				/** @type {number} */ (node.start),
				parent.property.start,
				state.analysis.uses_props ? `${state.names.props}.` : ''
			);
			state.str.update(parent.property.start, parent.end, name);
		}
		// else passed as identifier, we don't know what to do here, so let it error
	} else if (
		parent?.type === 'TSInterfaceDeclaration' ||
		parent?.type === 'TSTypeAliasDeclaration'
	) {
		const members =
			parent.type === 'TSInterfaceDeclaration' ? parent.body.body : parent.typeAnnotation?.members;
		if (Array.isArray(members)) {
			if (node.name === '$$Props') {
				state.has_type_or_fallback = true;

				for (const member of members) {
					const prop = state.props.find((prop) => prop.exported === member.key.name);

					const type = state.str.original.substring(
						member.typeAnnotation.typeAnnotation.start,
						member.typeAnnotation.typeAnnotation.end
					);

					let comment;
					const comment_node = member.leadingComments?.at(-1);
					if (comment_node?.type === 'Block') {
						comment = state.str.original.substring(comment_node.start, comment_node.end);
					}

					const trailing_comment = member.trailingComments?.at(0)?.value;

					if (prop) {
						prop.type = type;
						prop.optional = member.optional;
						prop.comment = comment ?? prop.comment;
						prop.trailing_comment = trailing_comment ?? prop.trailing_comment;
					} else {
						state.props.push({
							local: member.key.name,
							exported: member.key.name,
							init: '',
							bindable: false,
							optional: member.optional,
							type,
							comment,
							trailing_comment,
							type_only: true
						});
					}
				}

				state.str.remove(parent.start, parent.end);
			}
		}
	}
}

/** @param {string} content */
function guess_indent(content) {
	const lines = content.split('\n');

	const tabbed = lines.filter((line) => /^\t+/.test(line));
	const spaced = lines.filter((line) => /^ {2,}/.test(line));

	if (tabbed.length === 0 && spaced.length === 0) {
		return '\t';
	}

	// More lines tabbed than spaced? Assume tabs, and
	// default to tabs in the case of a tie (or nothing
	// to go on)
	if (tabbed.length >= spaced.length) {
		return '\t';
	}

	// Otherwise, we need to guess the multiple
	const min = spaced.reduce((previous, current) => {
		const count = /^ +/.exec(current)?.[0].length ?? 0;
		return Math.min(count, previous);
	}, Infinity);

	return ' '.repeat(min);
}

/** @import { LegacyRoot } from './types/legacy-nodes.js' */
/** @import { CompileOptions, CompileResult, ValidatedCompileOptions, ModuleCompileOptions } from '#compiler' */
/** @import { AST } from './public.js' */

/**
 * `compile` converts your `.svelte` source code into a JavaScript module that exports a component
 *
 * @param {string} source The component source code
 * @param {CompileOptions} options The compiler options
 * @returns {CompileResult}
 */
function compile(source, options) {
	source = remove_bom(source);
	reset({ warning: options.warningFilter, filename: options.filename });
	const validated = validate_component_options(options, '');

	let parsed = parse$2(source);

	const { customElement: customElementOptions, ...parsed_options } = parsed.options || {};

	/** @type {ValidatedCompileOptions} */
	const combined_options = {
		...validated,
		...parsed_options,
		customElementOptions
	};

	if (parsed.metadata.ts) {
		parsed = {
			...parsed,
			fragment: parsed.fragment && remove_typescript_nodes(parsed.fragment),
			instance: parsed.instance && remove_typescript_nodes(parsed.instance),
			module: parsed.module && remove_typescript_nodes(parsed.module)
		};
		if (combined_options.customElementOptions?.extend) {
			combined_options.customElementOptions.extend = remove_typescript_nodes(
				combined_options.customElementOptions?.extend
			);
		}
	}

	const analysis = analyze_component(parsed, source, combined_options);
	const result = transform_component(analysis, source, combined_options);
	result.ast = to_public_ast(source, parsed, options.modernAst);
	return result;
}

/**
 * `compileModule` takes your JavaScript source code containing runes, and turns it into a JavaScript module.
 *
 * @param {string} source The component source code
 * @param {ModuleCompileOptions} options
 * @returns {CompileResult}
 */
function compileModule(source, options) {
	source = remove_bom(source);
	reset({ warning: options.warningFilter, filename: options.filename });
	const validated = validate_module_options(options, '');

	const analysis = analyze_module(source, validated);
	return transform_module(analysis, source, validated);
}

/**
 * The parse function parses a component, returning only its abstract syntax tree.
 *
 * The `modern` option (`false` by default in Svelte 5) makes the parser return a modern AST instead of the legacy AST.
 * `modern` will become `true` by default in Svelte 6, and the option will be removed in Svelte 7.
 *
 * @overload
 * @param {string} source
 * @param {{ filename?: string; modern: true; loose?: boolean }} options
 * @returns {AST.Root}
 */

/**
 * The parse function parses a component, returning only its abstract syntax tree.
 *
 * The `modern` option (`false` by default in Svelte 5) makes the parser return a modern AST instead of the legacy AST.
 * `modern` will become `true` by default in Svelte 6, and the option will be removed in Svelte 7.
 *
 * @overload
 * @param {string} source
 * @param {{ filename?: string; modern?: false; loose?: boolean }} [options]
 * @returns {Record<string, any>}
 */

// TODO 6.0 remove unused `filename`
/**
 * The parse function parses a component, returning only its abstract syntax tree.
 *
 * The `modern` option (`false` by default in Svelte 5) makes the parser return a modern AST instead of the legacy AST.
 * `modern` will become `true` by default in Svelte 6, and the option will be removed in Svelte 7.
 *
 * The `loose` option, available since 5.13.0, tries to always return an AST even if the input will not successfully compile.
 *
 * The `filename` option is unused and will be removed in Svelte 6.0.
 *
 * @param {string} source
 * @param {{ filename?: string; rootDir?: string; modern?: boolean; loose?: boolean }} [options]
 * @returns {AST.Root | LegacyRoot}
 */
function parse(source, { modern, loose } = {}) {
	source = remove_bom(source);
	reset({ warning: () => false, filename: undefined });

	const ast = parse$2(source, loose);
	return to_public_ast(source, ast, modern);
}

/**
 * @param {string} source
 * @param {AST.Root} ast
 * @param {boolean | undefined} modern
 */
function to_public_ast(source, ast, modern) {
	if (modern) {
		const clean = (/** @type {any} */ node) => {
			delete node.metadata;
		};

		ast.options?.attributes.forEach((attribute) => {
			clean(attribute);
			clean(attribute.value);
			if (Array.isArray(attribute.value)) {
				attribute.value.forEach(clean);
			}
		});

		// remove things that we don't want to treat as public API
		return walk$1(ast, null, {
			_(node, { next }) {
				clean(node);
				next();
			}
		});
	}

	return convert(source, ast);
}

/**
 * Remove the byte order mark from a string if it's present since it would mess with our template generation logic
 * @param {string} source
 */
function remove_bom(source) {
	if (source.charCodeAt(0) === 0xfeff) {
		return source.slice(1);
	}
	return source;
}

/**
 * @deprecated Replace this with `import { walk } from 'estree-walker'`
 * @returns {never}
 */
function walk() {
	throw new Error(
		`'svelte/compiler' no longer exports a \`walk\` utility — please import it directly from 'estree-walker' instead`
	);
}

export { VERSION, compile, compileModule, migrate, parse, preprocess, walk };
