parseObjectExpression = (parser, expr) => {
					/** @type {Values} */
					const values = {};
					/** @type {Record<string, Expression | Pattern>} */
					const expressions = {};
					/** @type {(Property | SpreadElement)[]} */
					const otherElements = [];
					let spread = false;
					for (const prop of expr.properties) {
						if (prop.type === "SpreadElement") {
							spread = true;
						} else if (
							prop.type === "Property" &&
							!prop.method &&
							!prop.computed &&
							prop.key.type === "Identifier"
						) {
							expressions[prop.key.name] = prop.value;
							if (!prop.shorthand && !prop.value.type.endsWith("Pattern")) {
								const value = parser.evaluateExpression(
									/** @type {Expression} */
									(prop.value)
								);
								if (value.isCompileTimeValue())
									values[prop.key.name] = value.asCompileTimeValue();
							}
						} else {
							otherElements.push(prop);
						}
					}
					const insertType = expr.properties.length > 0 ? "comma" : "single";
					const insertLocation = /** @type {Range} */ (
						expr.properties[expr.properties.length - 1].range
					)[1];
					return {
						expressions,
						otherElements,
						values,
						spread,
						insertType,
						insertLocation
					};
				}
@param {JavascriptParser} parser the parser
@param {ObjectExpression} expr expression
@returns {{ expressions: Record<string, Expression | Pattern>, otherElements: (Property | SpreadElement)[], values: Values, spread: boolean, insertType: "comma" | "single", insertLocation: number }} parsed object