class RoundRectangle implements IModel {
        origin: IPoint;
        paths: IPathMap;
        /**
         * Create a round rectangle from width, height, and corner radius.
         *
         * Example:
         * ```
         * var r = new makerjs.models.RoundRectangle(100, 50, 5);
         * ```
         *
         * @param width Width of the rectangle.
         * @param height Height of the rectangle.
         * @param radius Corner radius.
         */
        constructor(width: number, height: number, radius: number);
        /**
         * Create a round rectangle which will surround a model.
         *
         * Example:
         * ```
         * var b = new makerjs.models.BoltRectangle(30, 20, 1); //draw a bolt rectangle so we have something to surround
         * var r = new makerjs.models.RoundRectangle(b, 2.5);   //surround it
         * ```
         *
         * @param modelToSurround IModel object.
         * @param margin Distance from the model. This will also become the corner radius.
         */
        constructor(modelToSurround: IModel, margin: number);
    }


class Oval implements IModel {
        paths: IPathMap;
        constructor(width: number, height: number);
    }


class OvalArc implements IModel {
        paths: IPathMap;
        models: IModelMap;
        constructor(startAngle: number, endAngle: number, sweepRadius: number, slotRadius: number, selfIntersect?: boolean, isolateCaps?: boolean);
    }


class Rectangle implements IModel {
        paths: IPathMap;
        origin: IPoint;
        /**
         * Create a rectangle from width and height.
         *
         * Example:
         * ```
         * var r = new makerjs.models.Rectangle(100, 50);
         * ```
         *
         * @param width Width of the rectangle.
         * @param height Height of the rectangle.
         */
        constructor(width: number, height: number);
        /**
         * Create a rectangle which will surround a model.
         *
         * Example:
         * ```
         * var e = new makerjs.models.Ellipse(17, 10); // draw an ellipse so we have something to surround.
         * var r = new makerjs.models.Rectangle(e, 3); // draws a rectangle surrounding the ellipse by 3 units.
         * ```
         *
         * @param modelToSurround IModel object.
         * @param margin Optional distance from the model.
         */
        constructor(modelToSurround: IModel, margin?: number);
        /**
         * Create a rectangle from a measurement.
         *
         * Example:
         * ```
         * var e = new makerjs.models.Ellipse(17, 10); // draw an ellipse so we have something to measure.
         * var m = makerjs.measure.modelExtents(e);    // measure the ellipse.
         * var r = new makerjs.models.Rectangle(m);    // draws a rectangle surrounding the ellipse.
         * ```
         *
         * @param measurement IMeasure object. See http://microsoft.github.io/maker.js/docs/api/modules/makerjs.measure.html#pathextents and http://microsoft.github.io/maker.js/docs/api/modules/makerjs.measure.html#modelextents to get measurements of paths and models.
         */
        constructor(measurement: IMeasure);
    }


class Ring implements IModel {
        paths: IPathMap;
        constructor(outerRadius: number, innerRadius: number);
    }


class SCurve implements IModel {
        paths: IPathMap;
        constructor(width: number, height: number);
    }


class Slot implements IModel {
        paths: IPathMap;
        origin: IPoint;
        models: IModelMap;
        constructor(origin: IPoint, endPoint: IPoint, radius: number, isolateCaps?: boolean);
    }


class Square implements IModel {
        paths: IPathMap;
        constructor(side: number);
    }


class Star implements IModel {
        paths: IPathMap;
        constructor(numberOfPoints: number, outerRadius: number, innerRadius?: number, skipPoints?: number);
        static InnerRadiusRatio(numberOfPoints: number, skipPoints: number): number;
    }


class Text implements IModel {
        models: IModelMap;
        constructor(font: opentypejs.Font, text: string, fontSize: number, combine?: boolean);
    }


/**
     * An x-y point in a two-dimensional space.
     * Implemented as an array with 2 elements. The first element is x, the second element is y.
     *
     * Examples:
     * ```
     * var p: IPoint = [0, 0];   //typescript
     * var p = [0, 0];   //javascript
     * ```
     */
interface IPoint {
        [index: number]: number;
    }


/**
     * A measurement of extents, the high and low points.
     */
interface IMeasure {
        /**
         * The point containing both the lowest x and y values of the rectangle containing the item being measured.
         */
        low: IPoint;
        /**
         * The point containing both the highest x and y values of the rectangle containing the item being measured.
         */
        high: IPoint;
    }


/**
     * A map of measurements.
     */
interface IMeasureMap {
        [key: string]: IMeasure;
    }


/**
     * A line, curved line or other simple two dimensional shape.
     */
interface IPath {
        /**
         * The type of the path, e.g. "line", "circle", or "arc". These strings are enumerated in pathType.
         */
        "type": string;
        /**
         * The main point of reference for this path.
         */
        origin: IPoint;
        /**
         * Optional layer of this path.
         */
        layer?: string;
    }


/**
     * A line path.
     *
     * Examples:
     * ```
     * var line: IPathLine = { type: 'line', origin: [0, 0], end: [1, 1] };   //typescript
     * var line = { type: 'line', origin: [0, 0], end: [1, 1] };   //javascript
     * ```
     */
interface IPathLine extends IPath {
        /**
         * The end point defining the line. The start point is the origin.
         */
        end: IPoint;
    }


/**
     * A circle path.
     *
     * Examples:
     * ```
     * var circle: IPathCircle = { type: 'circle', origin: [0, 0], radius: 7 };   //typescript
     * var circle = { type: 'circle', origin: [0, 0], radius: 7 };   //javascript
     * ```
     */
interface IPathCircle extends IPath {
        /**
         * The radius of the circle.
         */
        radius: number;
    }


/**
     * An arc path.
     *
     * Examples:
     * ```
     * var arc: IPathArc = { type: 'arc', origin: [0, 0], radius: 7, startAngle: 0, endAngle: 45 };   //typescript
     * var arc = { type: 'arc', origin: [0, 0], radius: 7, startAngle: 0, endAngle: 45 };   //javascript
     * ```
     */
interface IPathArc extends IPathCircle {
        /**
         * The angle (in degrees) to begin drawing the arc, in polar (counter-clockwise) direction.
         */
        startAngle: number;
        /**
         * The angle (in degrees) to end drawing the arc, in polar (counter-clockwise) direction. May be less than start angle if it past 360.
         */
        endAngle: number;
    }


/**
     * A bezier seed defines the endpoints and control points of a bezier curve.
     */
interface IPathBezierSeed extends IPathLine {
        /**
         * The bezier control points. One point for quadratic, 2 points for cubic.
         */
        controls: IPoint[];
        /**
         * T values of the parent if this is a child that represents a split.
         */
        parentRange?: IBezierRange;
    }


/**
     * Bezier t values for an arc path segment in a bezier curve.
     */
interface IBezierRange {
        /**
         * The bezier t-value at the starting point.
         */
        startT: number;
        /**
         * The bezier t-value at the end point.
         */
        endT: number;
    }


/**
     * An arc path segment in a bezier curve.
     */
interface IPathArcInBezierCurve extends IPathArc {
        bezierData: IBezierRange;
    }


/**
     * A map of functions which accept a path as a parameter.
     */
interface IPathFunctionMap {
        /**
         * Key is the type of a path, value is a function which accepts a path object as its parameter.
         */
        [type: string]: (pathValue: IPath) => void;
    }


/**
     * A map of functions which accept a path and an origin point as parameters.
     */
interface IPathOriginFunctionMap {
        /**
         * Key is the type of a path, value is a function which accepts a path object a point object as its parameters.
         */
        [type: string]: (id: string, pathValue: IPath, origin: IPoint, layer: string) => void;
    }


/**
     * Slope and y-intercept of a line.
     */
interface ISlope {
        /**
         * Boolean to see if line has slope or is vertical.
         */
        hasSlope: boolean;
        /**
         * Optional value of non-vertical slope.
         */
        slope?: number;
        /**
         * Line used to calculate this slope.
         */
        line: IPathLine;
        /**
         * Optional value of y when x = 0.
         */
        yIntercept?: number;
    }


/**
     * Options to pass to path.intersection()
     */
interface IPathIntersectionBaseOptions {
        /**
         * Optional boolean to only return deep intersections, i.e. not on an end point or tangent.
         */
        excludeTangents?: boolean;
        /**
         * Optional output variable which will be set to true if the paths are overlapped.
         */
        out_AreOverlapped?: boolean;
    }


/**
     * Options to pass to path.intersection()
     */
interface IPathIntersectionOptions extends IPathIntersectionBaseOptions {
        /**
         * Optional boolean to only return deep intersections, i.e. not on an end point or tangent.
         */
        path1Offset?: IPoint;
        /**
         * Optional output variable which will be set to true if the paths are overlapped.
         */
        path2Offset?: IPoint;
    }


/**
     * An intersection of two paths.
     */
interface IPathIntersection {
        /**
         * Array of points where the two paths intersected. The length of the array may be either 1 or 2 points.
         */
        intersectionPoints: IPoint[];
        /**
         * This Array property will only be defined if the first parameter passed to pathIntersection is either an Arc or a Circle.
         * It contains the angles of intersection relative to the first path parameter.
         * The length of the array may be either 1 or 2.
         */
        path1Angles?: number[];
        /**
         * This Array property will only be defined if the second parameter passed to pathIntersection is either an Arc or a Circle.
         * It contains the angles of intersection relative to the second path parameter.
         * The length of the array may be either 1 or 2.
         */
        path2Angles?: number[];
    }


/**
     * Options when matching points
     */
interface IPointMatchOptions {
        /**
         * Max distance to consider two points as the same.
         */
        pointMatchingDistance?: number;
    }


/**
     * Options to pass to model.combine.
     */
interface ICombineOptions extends IPointMatchOptions {
        /**
         * Flag to remove paths which are not part of a loop.
         */
        trimDeadEnds?: boolean;
        /**
         * Point which is known to be outside of the model.
         */
        farPoint?: IPoint;
        /**
         * Cached measurements for model A.
         */
        measureA?: measure.Atlas;
        /**
         * Cached measurements for model B.
         */
        measureB?: measure.Atlas;
    }


/**
     * Options to pass to model.findLoops.
     */
interface IFindLoopsOptions extends IPointMatchOptions {
        /**
         * Flag to remove looped paths from the original model.
         */
        removeFromOriginal?: boolean;
    }


/**
     * Options to pass to model.simplify()
     */
interface ISimplifyOptions {
        /**
         * Optional
         */
        pointMatchingDistance?: number;
        /**
         * Optional
         */
        scalarMatchingDistance?: number;
    }


/**
     * A path that may be indicated to "flow" in either direction between its endpoints.
     */
interface IPathDirectional extends IPath {
        /**
         * The endpoints of the path.
         */
        endPoints: IPoint[];
        /**
         * Path flows forwards or reverse.
         */
        reversed?: boolean;
    }


/**
     * Path objects by id.
     */
interface IPathMap {
        [id: string]: IPath;
    }


/**
     * Model objects by id.
     */
interface IModelMap {
        [id: string]: IModel;
    }


/**
     * A model is a composite object which may contain an array of paths, or an array of models recursively.
     *
     * Example:
     * ```
     * var m = {
     *   paths: {
     *     "line1": { type: 'line', origin: [0, 0], end: [1, 1] },
     *     "line2": { type: 'line', origin: [0, 0], end: [-1, -1] }
     *   }
     * };
     * ```
     */
interface IModel {
        /**
         * Optional origin location of this model.
         */
        origin?: IPoint;
        /**
         * A model may want to specify its type, but this value is not employed yet.
         */
        "type"?: string;
        /**
         * Optional array of path objects in this model.
         */
        paths?: IPathMap;
        /**
         * Optional array of models within this model.
         */
        models?: IModelMap;
        /**
         * Optional unit system of this model. See UnitType for possible values.
         */
        units?: string;
        /**
         * An author may wish to add notes to this model instance.
         */
        notes?: string;
        /**
         * Optional layer of this model.
         */
        layer?: string;
        /**
         * Optional exporter options for this model.
         */
        exporterOptions?: {
            [exporterName: string]: any;
        };
    }


/**
     * Callback signature for model.walkPaths().
     */
interface IModelPathCallback {
        (modelContext: IModel, pathId: string, pathContext: IPath): void;
    }


/**
     * Reference to a path id within a model.
     */
interface IRefPathIdInModel {
        modelContext: IModel;
        pathId: string;
    }


/**
     * A route to either a path or a model, and the absolute offset of it.
     */
interface IRouteOffset {
        layer: string;
        offset: IPoint;
        route: string[];
        routeKey: string;
    }


/**
     * A path reference in a walk.
     */
interface IWalkPath extends IRefPathIdInModel, IRouteOffset {
        pathContext: IPath;
    }


/**
     * Callback signature for path in model.walk().
     */
interface IWalkPathCallback {
        (context: IWalkPath): void;
    }


/**
     * Callback for returning a boolean from an IWalkPath.
     */
interface IWalkPathBooleanCallback {
        (context: IWalkPath): boolean;
    }


/**
     * A link in a chain, with direction of flow.
     */
interface IChainLink {
        /**
         * Reference to the path.
         */
        walkedPath: IWalkPath;
        /**
         * Path flows forwards or reverse.
         */
        reversed: boolean;
        /**
         * The endpoints of the path, in absolute coords.
         */
        endPoints: IPoint[];
    }


/**
     * A chain of paths which connect end to end.
     */
interface IChain {
        /**
         * The links in this chain.
         */
        links: IChainLink[];
        /**
         * Flag if this chain forms a loop end to end.
         */
        endless?: boolean;
    }


/**
     * Callback to model.findChains() with resulting array of chains and unchained paths.
     */
interface IChainCallback {
        (chains: IChain[], loose: IWalkPath[], layer: string): void;
    }


/**
     * Options to pass to model.findLoops.
     */
interface IFindChainsOptions extends IPointMatchOptions {
        /**
         * Flag to separate chains by layers.
         */
        byLayers?: boolean;
        /**
         * Flag to not recurse models, look only within current model's immediate paths.
         */
        shallow?: boolean;
    }


/**
     * Reference to a model within a model.
     */
interface IRefModelInModel {
        parentModel: IModel;
        childId: string;
        childModel: IModel;
    }


/**
     * A model reference in a walk.
     */
interface IWalkModel extends IRefModelInModel, IRouteOffset {
    }


/**
     * Callback signature for model.walk().
     */
interface IWalkModelCallback {
        (context: IWalkModel): void;
    }


/**
     * Callback signature for model.walk(), which may return false to halt any further walking.
     */
interface IWalkModelCancellableCallback {
        (context: IWalkModel): boolean;
    }


/**
     * Options to pass to model.walk().
     */
interface IWalkOptions {
        onPath?: IWalkPathCallback;
        beforeChildWalk?: IWalkModelCancellableCallback;
        afterChildWalk?: IWalkModelCallback;
    }


/**
     * Describes a parameter and its limits.
     */
interface IMetaParameter {
        /**
         * Display text of the parameter.
         */
        title: string;
        /**
         * Type of the parameter. Currently supports "range".
         */
        type: string;
        /**
         * Optional minimum value of the range.
         */
        min?: number;
        /**
         * Optional maximum value of the range.
         */
        max?: number;
        /**
         * Optional step value between min and max.
         */
        step?: number;
        /**
         * Initial sample value for this parameter.
         */
        value: any;
    }


/**
     * An IKit is a model-producing class with some sample parameters. Think of it as a packaged model with instructions on how to best use it.
     */
interface IKit {
        /**
         * The constructor. The kit must be "new-able" and it must produce an IModel.
         * It can have any number of any type of parameters.
         */
        new (...args: any[]): IModel;
        /**
         * Attached to the constructor is a property named metaParameters which is an array of IMetaParameter objects.
         * Each element of the array corresponds to a parameter of the constructor, in order.
         */
        metaParameters?: IMetaParameter[];
        /**
         * Information about this kit, in plain text or markdown format.
         */
        notes?: string;
    }


/**
     * Compare keys to see if they are equal.
     */
interface ICollectionKeyComparer<K> {
        (a: K, b: K): boolean;
    }


/**
     * A collection for items that share a common key.
     */
interface ICollection<K, T> {
        key: K;
        items: T[];
    }


/**
     * @private
     */
interface IExportOptions {
        /**
         * Unit system to embed in exported file.
         */
        units?: string;
    }


/**
     * DXF rendering options.
     */
interface IDXFRenderOptions extends IExportOptions {
    }


/**
     * Attributes for an XML tag.
     * @private
     */
interface IXmlTagAttrs {
        [name: string]: any;
    }


/**
     * OpenJsCad export options.
     */
interface IOpenJsCadOptions extends IFindLoopsOptions {
        /**
         * Optional depth of 3D extrusion.
         */
        extrusion?: number;
        /**
         * Optional size of curve facets.
         */
        facetSize?: number;
        /**
         * Optional override of function name, default is "main".
         */
        functionName?: string;
        /**
         * Optional options applied to specific first-child models by model id.
         */
        modelMap?: IOpenJsCadOptionsMap;
    }


interface IOpenJsCadOptionsMap {
        [modelId: string]: IOpenJsCadOptions;
    }


/**
     * PDF rendering options.
     */
interface IPDFRenderOptions extends IExportOptions {
        /**
         * Rendered reference origin.
         */
        origin?: IPoint;
        /**
         * SVG color of the rendered paths.
         */
        stroke?: string;
    }


/**
     * Map of MakerJs unit system to SVG unit system
     */
interface svgUnitConversion {
        [unitType: string]: {
            svgUnitType: string;
            scaleConversion: number;
        };
    }


/**
     * SVG rendering options.
     */
interface ISVGRenderOptions extends IExportOptions {
        /**
         * Optional attributes to add to the root svg tag.
         */
        svgAttrs?: IXmlTagAttrs;
        /**
         * SVG fill color.
         */
        fill?: string;
        /**
         * SVG font size and font size units.
         */
        fontSize?: string;
        /**
         * SVG stroke width of paths. This may have a unit type suffix, if not, the value will be in the same unit system as the units property.
         */
        strokeWidth?: string;
        /**
         * SVG color of the rendered paths.
         */
        stroke?: string;
        /**
         * Scale of the SVG rendering.
         */
        scale?: number;
        /**
         *  Indicate that the id's of paths should be rendered as SVG text elements.
         */
        annotate?: boolean;
        /**
         * Rendered reference origin.
         */
        origin?: IPoint;
        /**
         * Use SVG < path > elements instead of < line >, < circle > etc.
         */
        useSvgPathOnly?: boolean;
        /**
         * Flag to use SVG viewbox.
         */
        viewBox?: boolean;
    }


addItemToCollection(key: K, item: T): void;


findCollection(key: K, action?: (index: number) => void): T[];


removeCollection(key: K): boolean;


removeItemFromCollection(key: K, item: T): boolean;


getCollectionsOfMultiple(cb: (key: K, items: T[]) => void): void;


measureModels(): void;


/**
         * Export a path.
         *
         * @param pathToExport The path to export.
         * @param offset The offset position of the path.
         */
exportPath(id: string, pathToExport: IPath, offset: IPoint, layer: string): void;


/**
         * Export a model.
         *
         * @param modelToExport The model to export.
         * @param offset The offset position of the model.
         */
exportModel(modelId: string, modelToExport: IModel, offset: IPoint): void;


/**
         * Export an object.
         *
         * @param item The object to export. May be a path, an array of paths, a model, or an array of models.
         * @param offset The offset position of the object.
         */
exportItem(itemId: string, itemToExport: any, origin: IPoint): void;


/**
         * Escapes certain characters within a string so that it can appear in a tag or its attribute.
         *
         * @returns Escaped string.
         */
static escapeString(value: string): string;


/**
         * Get the opening tag.
         *
         * @param selfClose Flag to determine if opening tag should be self closing.
         */
getOpeningTag(selfClose: boolean): string;


/**
         * Get the inner text.
         */
getInnerText(): string;


/**
         * Get the closing tag.
         */
getClosingTag(): string;


/**
         * Output the entire tag as a string.
         */
toString(): string;


static getBezierSeeds(curve: BezierCurve, options?: IFindChainsOptions): IPathBezierSeed[];


static computePoint(seed: IPathBezierSeed, t: number): IPoint;


static circumscribedRadius(radius: number, angleInRadians: number): number;


static getPoints(numberOfSides: number, radius: number, firstCornerAngleInDegrees?: number, circumscribed?: boolean): IPoint[];


static InnerRadiusRatio(numberOfPoints: number, skipPoints: number): number;


export class MultiCompilerMain {
  /**
   * create a multi-compiler `Compiler` instance.
   * @param compilers list of compilers to include.
   */
  createCompiler(compilers: Compiler[], options: Partial<CompilerOptions> = {}) {
    return new MultiCompiler(MultiCompilerAspect.id, compilers, options, {});
  }

  static runtime = MainRuntime;

  static async provider() {
    return new MultiCompilerMain();
  }
}


/**
   * create a multi-compiler `Compiler` instance.
   * @param compilers list of compilers to include.
   */
createCompiler(compilers: Compiler[], options: Partial<CompilerOptions> = {}) {
    return new MultiCompiler(MultiCompilerAspect.id, compilers, options, {});
  }


static async provider() {
    return new MultiCompilerMain();
  }


export function Input<
  T extends React.ElementType = 'input',
  U extends HTMLElement = HTMLInputElement
>({
  // @ts-ignore
  component = 'input',
  className,
  invalid = false,
  required = false,
  variant,
  icon,
  style,
  rightSectionWidth = 36,
  rightSection,
  rightSectionProps = {},
  radius = 'sm',
  size = 'sm',
  themeOverride,
  wrapperProps,
  elementRef,
  classNames,
  styles,
  __staticSelector = 'input',
  multiline = false,
  ...others
}: InputProps &
  Omit<React.ComponentPropsWithoutRef<T>, 'size'> & {
    /** Element or component that will be used as root element */
    component?: T;

    /** Input size */
    size?: MantineSize;

    /** Get element ref */
    elementRef?: React.ForwardedRef<U>;
  }) {
  const theme = useMantineTheme(themeOverride);
  const _variant = variant || (theme.colorScheme === 'dark' ? 'filled' : 'default');
  const classes = useStyles(
    { radius, theme, size, multiline, variant: _variant, invalid },
    classNames,
    __staticSelector
  );
  const _styles = mergeStyles(classes, styles);
  const Element: any = component;

  return (
    <div
      className={cx(classes.root, classes[_variant], className)}
      style={{
        ...style,
        ..._styles.root,
        ..._styles[variant],
      }}


export interface InputBaseProps {
  /** Sets border color to red and aria-invalid=true on input element */
  invalid?: boolean;

  /** Adds icon on the left side of input */
  icon?: React.ReactNode;

  /** Right section of input, similar to icon but on the right */
  rightSection?: React.ReactNode;

  /** Width of right section, is used to calculate input padding-right */
  rightSectionWidth?: number;

  /** Props spread to rightSection div element */
  rightSectionProps?: Record<string, any>;

  /** Properties spread to root element */
  wrapperProps?: Record<string, any>;

  /** Sets aria-required=true on input element */
  required?: boolean;

  /** Input border-radius from theme or number to set border-radius in px */
  radius?: MantineNumberSize;

  /** Defines input appearance, defaults to default in light color scheme and filled in dark */
  variant?: 'default' | 'filled' | 'unstyled';

  /** Static css selector base */
  __staticSelector?: string;

  /** Will input have multiple lines? */
  multiline?: boolean;
}


export interface InputProps extends InputBaseProps, DefaultProps<typeof useStyles> {}


export type InputVariant = typeof INPUT_VARIANTS[number];


export type InputStylesNames = Exclude<keyof ReturnType<typeof useStyles>, InputVariant>;


cx({ [classes.withIcon]: icon }, classes


function mockOutputPathFn(locale: string, relativePath: string) {
  return `/translations/${locale}/${relativePath}`;
}


() => {
  describe('canTranslate()', () => {
    it('should always return true', () => {
      const handler = new AssetTranslationHandler();
      expect(handler.canTranslate('relative/path', Buffer.from('contents'))).toBe(true);
    });
  });

  describe('translate()', () => {
    beforeEach(() => {
      spyOn(FileUtils, 'writeFile');
      spyOn(FileUtils, 'ensureDir');
    });

    it('should write the translated file for each translation locale', () => {
      const diagnostics = new Diagnostics();
      const handler = new AssetTranslationHandler();
      const translations = [
        {locale: 'en', translations: {}},
        {locale: 'fr', translations: {}},
      ];
      const contents = Buffer.from('contents');
      handler.translate(
          diagnostics, '/root/path', 'relative/path', contents, mockOutputPathFn, translations);

      expect(FileUtils.writeFile).toHaveBeenCalledWith('/translations/en/relative/path', contents);
      expect(FileUtils.writeFile).toHaveBeenCalledWith('/translations/fr/relative/path', contents);
    });

    it('should write the translated file to the source locale if provided', () => {
      const diagnostics = new Diagnostics();
      const handler = new AssetTranslationHandler();
      const translations: TranslationBundle[] = [];
      const contents = Buffer.from('contents');
      const sourceLocale = 'en-US';
      handler.translate(
          diagnostics, '/root/path', 'relative/path', contents, mockOutputPathFn, translations,
          sourceLocale);

      expect(FileUtils.writeFile)
          .toHaveBeenCalledWith('/translations/en-US/relative/path', contents);
    });
  });
}


() => {
    it('should always return true', () => {
      const handler = new AssetTranslationHandler();
      expect(handler.canTranslate('relative/path', Buffer.from('contents'))).toBe(true);
    });
  }


() => {
      const handler = new AssetTranslationHandler();
      expect(handler.canTranslate('relative/path', Buffer.from('contents'))).toBe(true);
    }


() => {
    beforeEach(() => {
      spyOn(FileUtils, 'writeFile');
      spyOn(FileUtils, 'ensureDir');
    });

    it('should write the translated file for each translation locale', () => {
      const diagnostics = new Diagnostics();
      const handler = new AssetTranslationHandler();
      const translations = [
        {locale: 'en', translations: {}},
        {locale: 'fr', translations: {}},
      ];
      const contents = Buffer.from('contents');
      handler.translate(
          diagnostics, '/root/path', 'relative/path', contents, mockOutputPathFn, translations);

      expect(FileUtils.writeFile).toHaveBeenCalledWith('/translations/en/relative/path', contents);
      expect(FileUtils.writeFile).toHaveBeenCalledWith('/translations/fr/relative/path', contents);
    });

    it('should write the translated file to the source locale if provided', () => {
      const diagnostics = new Diagnostics();
      const handler = new AssetTranslationHandler();
      const translations: TranslationBundle[] = [];
      const contents = Buffer.from('contents');
      const sourceLocale = 'en-US';
      handler.translate(
          diagnostics, '/root/path', 'relative/path', contents, mockOutputPathFn, translations,
          sourceLocale);

      expect(FileUtils.writeFile)
          .toHaveBeenCalledWith('/translations/en-US/relative/path', contents);
    });
  }


() => {
      spyOn(FileUtils, 'writeFile');
      spyOn(FileUtils, 'ensureDir');
    }


() => {
      const diagnostics = new Diagnostics();
      const handler = new AssetTranslationHandler();
      const translations = [
        {locale: 'en', translations: {}},
        {locale: 'fr', translations: {}},
      ];
      const contents = Buffer.from('contents');
      handler.translate(
          diagnostics, '/root/path', 'relative/path', contents, mockOutputPathFn, translations);

      expect(FileUtils.writeFile).toHaveBeenCalledWith('/translations/en/relative/path', contents);
      expect(FileUtils.writeFile).toHaveBeenCalledWith('/translations/fr/relative/path', contents);
    }


() => {
      const diagnostics = new Diagnostics();
      const handler = new AssetTranslationHandler();
      const translations: TranslationBundle[] = [];
      const contents = Buffer.from('contents');
      const sourceLocale = 'en-US';
      handler.translate(
          diagnostics, '/root/path', 'relative/path', contents, mockOutputPathFn, translations,
          sourceLocale);

      expect(FileUtils.writeFile)
          .toHaveBeenCalledWith('/translations/en-US/relative/path', contents);
    }


export interface TaskCreationResultDto {
    success: boolean,
    task: TaskDto
}


interface MPBase {
  /** A Node.js package name that provides the maker or publisher functionality. */
  name: string,
  /** Overrides the platform that this maker or publisher will be used on.  */
  platforms?: ForgePlatform[] | null;
  /** A maker or publisher specific configuration object, usually containing the `options` property. */
  config?: MPConfig;
}


// Maker types
interface MakerAppImage extends MPBase {
  name: "electron-forge-maker-appimage",
  config?: MakerAppImageConfig
}


interface MakerDeb extends MPBase {
  name: "@electron-forge/maker-deb";
  config?: MakerDebConfig;
}


interface MakerRpm extends MPBase {
  name: "@electron-forge/maker-rpm",
  config?: MakerRpmConfig
}


/*interface MakerSnap extends MPBase {
  name: "@electron-forge/maker-snap",
  config?: MakerSnapConfig
}

interface MakerFlatpak extends MPBase {
  name: "@electron-forge/maker-flatpak",
  config?: MakerFlatpakConfig
}*/
interface MakerZIP extends MPBase {
  name: "@electron-forge/maker-zip",
  config?: MakerZIPConfig
}


interface MakerDMG extends MPBase {
  name: "@electron-forge/maker-dmg",
  config?: MakerDMGConfig
}


// Publisher types
interface PublisherGitHub extends MPBase {
  name: "@electron-forge/publisher-github",
  config?: PublisherGitHubConfig
}


type Redeclare<I, M> = Omit<I, keyof M> & M;


// Base types for makers / publishers
type MPConfig = unknown | {
  /** Maker or publisher specific set of options. */
  options?: unknown
}


// Config type
export type ForgeConfigFile = Redeclare<Partial<ForgeConfig>, {
  makers?: (
    MakerZIP | MakerAppImage | MakerDeb | MakerRpm | MakerDMG //| MakerSnap | MakerFlatpak
  )[];
  publishers?: (
    PublisherGitHub
  )[];
}>;


export interface FacadeBaseContext extends Koa.Context {
  logger: Logger;
  facade: Facade;
}


export interface FacadeModuleBase<TContext extends FacadeBaseContext = FacadeBaseContext> {
  moduleName: string;
}


export interface FacadeModule<TContext extends FacadeBaseContext = FacadeBaseContext> extends FacadeModuleBase<TContext> {
  (facade: Facade<[FacadeModule<TContext>]>): void;
}


export interface FacadeModuleFactory<TConfig = any, TContext extends FacadeBaseContext = FacadeBaseContext> extends FacadeModuleBase<TContext> {
  (config: TConfig): FacadeModule<TContext>;
}


export interface Facade<TModules extends FacadeModuleBase[] = []> {
  readonly logger: Logger;
  readonly koa: Koa<any, FacadeModulesContext<TModules>>;
  readonly server?: Server;
  readonly address?: string | AddressInfo;
  readonly listening: boolean;
  readonly env: string;
  start(): Promise<void>;
  onStart(fn: () => Promise<void>): void;
  onStop(fn: () => Promise<void>): void;
  stop(): Promise<void>;
  addApolloService({name, schema, url}: RequireAtLeastOne<{name: string, url: string, schema: any}, 'url' | 'schema'>): void;
  useMiddleware<TNewState extends object = {}, TNewContext extends object = {}>(middleware: Koa.Middleware<TNewState, TNewContext & FacadeModulesContext<TModules>>):
    Facade<TModules>;
  useModule<TNewModule extends FacadeModule>(module: TNewModule):
    Facade<[...TModules, TNewModule]>;
  supportsModule<TSupportedModule extends FacadeModuleBase>(module: TSupportedModule):
    this is Facade<[TSupportedModule, ...TModules]> /* Required for type completion */ & Facade<[...TModules]>;
}


type RequireAtLeastOne<T, Keys extends keyof T> =
  Pick<T, Exclude<keyof T, Keys>> & {
    [K in Keys]-?: Required<Pick<T, K>> & Partial<Pick<T, Exclude<Keys, K>>>
  }[Keys];


// Extract module context
export type ExtractModuleContext<TModule> =
    TModule extends FacadeModuleFactory<infer TConfig, infer TContext> ? TContext :
    TModule extends FacadeModule<infer TContext> ? TContext :
    never;


export type FacadeModulesContext<T extends FacadeModuleBase[]> = (T[0] extends FacadeModuleBase ? ExtractModuleContext<T[0]> : FacadeBaseContext) &
                                                                 (T[1] extends FacadeModuleBase ? ExtractModuleContext<T[1]> : FacadeBaseContext) &
                                                                 (T[2] extends FacadeModuleBase ? ExtractModuleContext<T[2]> : FacadeBaseContext) &
                                                                 (T[3] extends FacadeModuleBase ? ExtractModuleContext<T[3]> : FacadeBaseContext) &
                                                                 (T[4] extends FacadeModuleBase ? ExtractModuleContext<T[4]> : FacadeBaseContext) &
                                                                 (T[5] extends FacadeModuleBase ? ExtractModuleContext<T[5]> : FacadeBaseContext) &
                                                                 (T[6] extends FacadeModuleBase ? ExtractModuleContext<T[6]> : FacadeBaseContext) &
                                                                 (T[7] extends FacadeModuleBase ? ExtractModuleContext<T[7]> : FacadeBaseContext) &
                                                                 (T[8] extends FacadeModuleBase ? ExtractModuleContext<T[8]> : FacadeBaseContext) &
                                                                 (T[9] extends FacadeModuleBase ? ExtractModuleContext<T[9]> : FacadeBaseContext);


export type FacadeContext<T extends FacadeModuleBase[] | Facade<any> = []> =
  T extends FacadeModuleBase[] ? FacadeModulesContext<T> :
  T extends Facade<infer TFacadeModules> ? FacadeModulesContext<TFacadeModules> :
  FacadeBaseContext;


// DB Operation Success
() => {
    console.log('Successfully add new admin account');
    // eslint-disable-next-line no-process-exit
    process.exit();
  }


// When DB Operation failed
error => {
    console.error(error);
    // eslint-disable-next-line no-process-exit
    process.exit(1);
  }


async (relayer: Relayer, tokenAddress?: string) => {
  const name = 'name.mylogin.eth';
  const [wallet] = await getWallets(relayer.provider);
  const tokens = tokenAddress ? [tokenAddress, ETHER_NATIVE_TOKEN.address] : [ETHER_NATIVE_TOKEN.address];
  const services = await createPreconfiguredServices(relayer.provider, relayer, tokens);
  await services.sdk.tokensDetailsStore.fetchTokensDetails();
  const {contractAddress} = await createAndSetWallet(name, services.walletService, wallet, services.sdk);
  const appWrapper = mountWithContext(<App/>, services, ['/wallet']);
  const appPage = new AppPage(appWrapper);
  await appPage.login().waitForHomeView('$1.99');
  return {appPage, services, contractAddress, appWrapper};
}


(side) => {
        const panel = panels[side];
        return (
          <WidgetPanel
            key={side}
            panel={panel}
            spanBottom={panels.bottom.span}
            spanTop={panels.top.span}
          />


/** Properties of [[WidgetPanels]] component.
 * @internal
 */
export interface WidgetPanelsProps extends CommonProps {
  /** Content that is affected by pinned state of panels. */
  children?: React.ReactNode;
  /** Content that is always rendered as if panels are in a pinned state. */
  centerContent?: React.ReactNode;
}


export class StoreMap extends Array<unknown> {
  index = 0;

  currentScope: Scope | null = null;

  constructor() {
    super();
    if (typeof __RGH_DEVTOOLS__ !== 'undefined') {
      __RGH_DEVTOOLS__.registerStoreMap(this);
    }
  }
}


(charCode: number) => createInvertedIndexNode<number>(charCode)


() => {
  test("inverted index node should be created with correct char code", () => {
    const n = create(1);
    expect(n.charCode).toBe(1);
  });

  test("inverted index node should be created with null next value", () => {
    const n = create(1);
    expect(n.next).toBeNull();
  });

  test("inverted index node should be created with null firstChild", () => {
    const n = create(1);
    expect(n.firstChild).toBeNull();
  });

  test("inverted index node should be created with null firstPosting", () => {
    const n = create(1);
    expect(n.firstPosting).toBeNull();
  });
}


() => {
    const n = create(1);
    expect(n.charCode).toBe(1);
  }


() => {
    const n = create(1);
    expect(n.next).toBeNull();
  }


() => {
    const n = create(1);
    expect(n.firstChild).toBeNull();
  }


() => {
    const n = create(1);
    expect(n.firstPosting).toBeNull();
  }


() => {
  test("empty children list should return undefined", () => {
    const p = create(0);
    expect(findInvertedIndexChildNodeByCharCode(p, 0)).toBeUndefined();
  });

  test("searching for an unexisting node should return undefined", () => {
    const p = create(0);
    const c1 = create(1);
    const c2 = create(2);
    addInvertedIndexChildNode(p, c1);
    addInvertedIndexChildNode(p, c2);
    expect(findInvertedIndexChildNodeByCharCode(p, 0)).toBeUndefined();
  });

  test("searching for existing node should return node associated with provided charCode", () => {
    const p = create(0);
    const c1 = create(1);
    const c2 = create(2);
    addInvertedIndexChildNode(p, c1);
    addInvertedIndexChildNode(p, c2);
    expect(findInvertedIndexChildNodeByCharCode(p, 1)).toBe(c1);
    expect(findInvertedIndexChildNodeByCharCode(p, 2)).toBe(c2);
  });
}


() => {
    const p = create(0);
    expect(findInvertedIndexChildNodeByCharCode(p, 0)).toBeUndefined();
  }


() => {
    const p = create(0);
    const c1 = create(1);
    const c2 = create(2);
    addInvertedIndexChildNode(p, c1);
    addInvertedIndexChildNode(p, c2);
    expect(findInvertedIndexChildNodeByCharCode(p, 0)).toBeUndefined();
  }


() => {
    const p = create(0);
    const c1 = create(1);
    const c2 = create(2);
    addInvertedIndexChildNode(p, c1);
    addInvertedIndexChildNode(p, c2);
    expect(findInvertedIndexChildNodeByCharCode(p, 1)).toBe(c1);
    expect(findInvertedIndexChildNodeByCharCode(p, 2)).toBe(c2);
  }


() => {
  test("empty trie should return undefined", () => {
    const p = create(0);
    expect(findInvertedIndexNode(p, "abc")).toBeUndefined();
  });

  test("searching for an unexisting node should return undefined", () => {
    const p = create(0);
    const a = create(97);
    const b = create(98);
    const c = create(99);
    addInvertedIndexChildNode(p, a);
    addInvertedIndexChildNode(a, b);
    addInvertedIndexChildNode(b, c);
    expect(findInvertedIndexNode(p, "abc")).toBe(c);
  });
}


() => {
    const p = create(0);
    expect(findInvertedIndexNode(p, "abc")).toBeUndefined();
  }


() => {
    const p = create(0);
    const a = create(97);
    const b = create(98);
    const c = create(99);
    addInvertedIndexChildNode(p, a);
    addInvertedIndexChildNode(a, b);
    addInvertedIndexChildNode(b, c);
    expect(findInvertedIndexNode(p, "abc")).toBe(c);
  }


() => {
  test("should add one node", () => {
    const n = create(0);
    const p = {
      next: null,
      details: {
        id: 0,
        fieldLengths: [],
      },
      termFrequency: [],
    };
    addInvertedIndexPosting(n, p);
    expect(n.firstPosting).toBe(p);
  });

  test("should add two nodes", () => {
    const n = create(0);
    const p1 = {
      next: null,
      details: {
        id: 0,
        fieldLengths: [],
      },
      termFrequency: [],
    };
    const p2 = {
      next: null,
      details: {
        id: 0,
        fieldLengths: [],
      },
      termFrequency: [],
    };
    addInvertedIndexPosting(n, p1);
    addInvertedIndexPosting(n, p2);
    expect(n.firstPosting).toBe(p2);
    expect(p2.next).toBe(p1);
    expect(p1.next).toBe(null);
  });
}


() => {
    const n = create(0);
    const p = {
      next: null,
      details: {
        id: 0,
        fieldLengths: [],
      },
      termFrequency: [],
    };
    addInvertedIndexPosting(n, p);
    expect(n.firstPosting).toBe(p);
  }


() => {
    const n = create(0);
    const p1 = {
      next: null,
      details: {
        id: 0,
        fieldLengths: [],
      },
      termFrequency: [],
    };
    const p2 = {
      next: null,
      details: {
        id: 0,
        fieldLengths: [],
      },
      termFrequency: [],
    };
    addInvertedIndexPosting(n, p1);
    addInvertedIndexPosting(n, p2);
    expect(n.firstPosting).toBe(p2);
    expect(p2.next).toBe(p1);
    expect(p1.next).toBe(null);
  }


export default function siblings(elem: Element): any[] {
    const r = [];
    let n = elem.parentNode?.firstChild;
    for (; n; n = n.nextSibling) {
        if (n.nodeType === 1 && n !== elem) {
            r.push(n);
        }
    }
    return r;
}


(config: APIGatewayClientConfig) => {
  const browserDefaults = getBrowserRuntimeConfig(config);
  return {
    ...browserDefaults,
    ...config,
    runtime: "react-native",
    sha256: config?.sha256 ?? Sha256,
  };
}


/**
 * Incident Service payload for update requests.
 */
export class IncidentServiceUpdateData {
  "attributes"?: IncidentServiceUpdateAttributes;
  /**
   * The incident service's ID.
   */
  "id"?: string;
  "relationships"?: IncidentServiceRelationships;
  "type": IncidentServiceType;

  "unparsedObject"?: any;

  static readonly discriminator: string | undefined = undefined;

  static readonly attributeTypeMap: {
    [key: string]: { baseName: string; type: string; format: string };
  } = {
    attributes: {
      baseName: "attributes",
      type: "IncidentServiceUpdateAttributes",
      format: "",
    },
    id: {
      baseName: "id",
      type: "string",
      format: "",
    },
    relationships: {
      baseName: "relationships",
      type: "IncidentServiceRelationships",
      format: "",
    },
    type: {
      baseName: "type",
      type: "IncidentServiceType",
      format: "",
    },
  };

  static getAttributeTypeMap() {
    return IncidentServiceUpdateData.attributeTypeMap;
  }

  static deserialize(data: { [key: string]: any }): IncidentServiceUpdateData {
    const res = new IncidentServiceUpdateData();

    res.attributes = ObjectSerializer.deserialize(
      data.attributes,
      "IncidentServiceUpdateAttributes",
      ""
    );

    res.id = ObjectSerializer.deserialize(data.id, "string", "");

    res.relationships = ObjectSerializer.deserialize(
      data.relationships,
      "IncidentServiceRelationships",
      ""
    );

    if (data.type === undefined) {
      throw new TypeError(
        "missing required attribute 'type' on 'IncidentServiceUpdateData' object"
      );
    }
    if (["services", undefined].includes(data.type)) {
      res.type = data.type;
    } else {
      const raw = new IncidentServiceUpdateData();
      raw.unparsedObject = data;
      return raw;
    }

    return res;
  }

  static serialize(data: IncidentServiceUpdateData): { [key: string]: any } {
    const attributeTypes = IncidentServiceUpdateData.getAttributeTypeMap();
    const res: { [index: string]: any } = {};
    for (const [key, value] of Object.entries(data)) {
      if (!(key in attributeTypes)) {
        throw new TypeError(`${key} attribute not in schema`);
      }
    }
    if (data?.unparsedObject !== undefined) {
      return data.unparsedObject;
    }
    res.attributes = ObjectSerializer.serialize(
      data.attributes,
      "IncidentServiceUpdateAttributes",
      ""
    );

    res.id = ObjectSerializer.serialize(data.id, "string", "");

    res.relationships = ObjectSerializer.serialize(
      data.relationships,
      "IncidentServiceRelationships",
      ""
    );

    if (data.type === undefined) {
      throw new TypeError(
        "missing required attribute 'type' on 'IncidentServiceUpdateData' object"
      );
    }
    if (["services", undefined].includes(data.type)) {
      res.type = data.type;
    } else {
      throw TypeError(`invalid enum value ${data.type} for type`);
    }

    return res;
  }

  public constructor() {}
}


static getAttributeTypeMap() {
    return IncidentServiceUpdateData.attributeTypeMap;
  }


static deserialize(data: { [key: string]: any }): IncidentServiceUpdateData {
    const res = new IncidentServiceUpdateData();

    res.attributes = ObjectSerializer.deserialize(
      data.attributes,
      "IncidentServiceUpdateAttributes",
      ""
    );

    res.id = ObjectSerializer.deserialize(data.id, "string", "");

    res.relationships = ObjectSerializer.deserialize(
      data.relationships,
      "IncidentServiceRelationships",
      ""
    );

    if (data.type === undefined) {
      throw new TypeError(
        "missing required attribute 'type' on 'IncidentServiceUpdateData' object"
      );
    }
    if (["services", undefined].includes(data.type)) {
      res.type = data.type;
    } else {
      const raw = new IncidentServiceUpdateData();
      raw.unparsedObject = data;
      return raw;
    }

    return res;
  }


static serialize(data: IncidentServiceUpdateData): { [key: string]: any } {
    const attributeTypes = IncidentServiceUpdateData.getAttributeTypeMap();
    const res: { [index: string]: any } = {};
    for (const [key, value] of Object.entries(data)) {
      if (!(key in attributeTypes)) {
        throw new TypeError(`${key} attribute not in schema`);
      }
    }
    if (data?.unparsedObject !== undefined) {
      return data.unparsedObject;
    }
    res.attributes = ObjectSerializer.serialize(
      data.attributes,
      "IncidentServiceUpdateAttributes",
      ""
    );

    res.id = ObjectSerializer.serialize(data.id, "string", "");

    res.relationships = ObjectSerializer.serialize(
      data.relationships,
      "IncidentServiceRelationships",
      ""
    );

    if (data.type === undefined) {
      throw new TypeError(
        "missing required attribute 'type' on 'IncidentServiceUpdateData' object"
      );
    }
    if (["services", undefined].includes(data.type)) {
      res.type = data.type;
    } else {
      throw TypeError(`invalid enum value ${data.type} for type`);
    }

    return res;
  }


function pipeStdio(current: ExecProcess, other: Writable, stdout: boolean, stderr: boolean, extra1: boolean, extra2: boolean) {
  if(stdout && current.stdout)
    current.stdout.pipe(other);
  if(stderr && current.stderr)
    current.stderr.pipe(other);
  if(extra1 && current.stdio[3])
    current.stdio[3].pipe(other);
  if(extra2 && current.stdio[4])
    current.stdio[4].pipe(other);
  return other;
}


export function wrap(childProc: ChildProcess) {
  return Object.assign(childProc, execProcessExtensions) as ExecProcess;
}


export function extend(name: string, fn: (this: ExecProcess, ...args: any[]) => any) {
  (execProcessExtensions as any)[name] = fn;
}


(resolve, reject) =>
      this.once('close', resolve).once('error', reject)


export interface ExecProcess extends ChildProcess, PromiseLike<number> {
  pipe<T extends ChildProcess>(other: T, stdout?: boolean, stderr?: boolean, extra1?: boolean, extra2?: boolean): T;
  pipe<T extends Writable>(other: T, stdout?: boolean, stderr?: boolean, extra1?: boolean, extra2?: boolean): T;
}


pipe(this: ExecProcess, other: ChildProcess | Writable, stdout = true, stderr = false, extra1 = false, extra2 = false) {
    if(other instanceof Stream)
      return pipeStdio(this, other as Writable, stdout, stderr, extra1, extra2);
    if(other.stdin)
      pipeStdio(this, other.stdin, stdout, stderr, extra1, extra2)
    return other;
  }


then(this: ExecProcess, onFulfilled, onRejected) {
    return new Promise<number>((resolve, reject) =>
      this.once('close', resolve).once('error', reject))
      .then(onFulfilled, onRejected);
  }


export function App() {
  const [selectedGenreId, setSelectedGenreId] = useState(1);

  const [genres, setGenres] = useState<GenreResponseProps[]>([]);

  const [movies, setMovies] = useState<MovieProps[]>([]);
  const [selectedGenre, setSelectedGenre] = useState<GenreResponseProps>({} as GenreResponseProps);

  useEffect(() => {
    api.get<GenreResponseProps[]>('genres').then(response => {
      setGenres(response.data);
    });
  }, []);

  useEffect(() => {
    api.get<MovieProps[]>(`movies/?Genre_id=${selectedGenreId}`).then(response => {
      setMovies(response.data);
    });

    api.get<GenreResponseProps>(`genres/${selectedGenreId}`).then(response => {
      setSelectedGenre(response.data);
    })
  }, [selectedGenreId]);

  function handleClickButton(id: number) {
    setSelectedGenreId(id);
  }

  return (
    <div style={{ display: 'flex', flexDirection: 'row' }}


function handleClickButton(id: number) {
    setSelectedGenreId(id);
  }


() => {
    api.get<MovieProps[]>(`movies/?Genre_id=${selectedGenreId}`).then(response => {
      setMovies(response.data);
    });

    api.get<GenreResponseProps>(`genres/${selectedGenreId}`).then(response => {
      setSelectedGenre(response.data);
    })
  }


response => {
      setSelectedGenre(response.data);
    }


interface MovieProps {
  Title: string;
  Poster: string;
  Ratings: Array<{
    Source: string;
    Value: string;
  }>;
  Runtime: string;
}


() => {
      this.searchbar.setFocus();
      this.keyboard.show();
    }


@Component({
  selector: 'autocomplete',
  templateUrl: 'autocomplete.html'
})

export class Autocomplete {
  autocompleteItems: any;
  autocompleteData: any;
  autocompleteEntry: string;

  @ViewChild(Searchbar) searchbar:Searchbar;

  constructor (public viewCtrl: ViewController, public params: NavParams, public diacritics: Diacritics, private keyboard: Keyboard) {
    this.autocompleteItems = [];
    this.autocompleteData = this.params.get('dataAutocomplete');
    this.autocompleteEntry = this.params.get('entryAutocomplete');
  }

  ionViewDidEnter() {
    setTimeout(() => {
      this.searchbar.setFocus();
      this.keyboard.show();
    });
  }

  /**
   * Fonction qui supprime la page modale ouverte, en passant comme valeur à la page initiale la valeur entrée par l'utilisateur.
   * @method dismiss
   * @param {} - aucun paramètre n'est passé à la fonction.
   * @returns {} - aucune valeur n'est retournée par la fonction.
   */
  dismiss() {
    this.keyboard.close();
    this.viewCtrl.dismiss(this.autocompleteEntry);
  }

  /**
   * Fonction qui supprime la page modale ouverte, en passant comme valeur à la page initiale la valeur sélectionnée dans la liste proposée (autocompletion).
   * @method chooseItem
   * @param {any} - la valeur sélectionnée dans la liste proposée est passée à la fonction.
   * @returns {} - aucune valeur n'est retournée par la fonction.
   */
  chooseItem(item: any) {
    this.autocompleteEntry = item;
    this.keyboard.close();
    this.viewCtrl.dismiss(item);
  }

  /**
   * Fonction qui, à chaque saisie de l'utilisateur, compare le contenu saisi et la liste proposée pour limiter la liste aux valeurs qui correspondent à la saisie : autocompletion.
   * @method updateSearch
   * @param {} - aucun paramètre n'est passé à la fonction.
   * @returns {string} - une liste mise à jour suite à la nouvelle saisie de l'utilisateur est retournée par la fonction.
   */
  updateSearch() {
    if (this.autocompleteEntry == '') {
      this.autocompleteItems = [];
    } else {
      let arrayLength: number = this.autocompleteData.length;
      var i: number = 0;
      var nbItems: number = 0;
      var table = [];
      while (i < arrayLength && nbItems < 20) {
        let strVal = this.diacritics.replaceDiacritics(this.autocompleteData[i].toLowerCase());
        let strEntry = this.diacritics.replaceDiacritics(this.autocompleteEntry.toLowerCase());
        if (strVal.indexOf(strEntry) > -1) {
          table.push(strVal);
          nbItems++;
        }
        i++;
      }
      this.autocompleteItems = table;
    }
  }
}


ionViewDidEnter() {
    setTimeout(() => {
      this.searchbar.setFocus();
      this.keyboard.show();
    });
  }


/**
   * Fonction qui supprime la page modale ouverte, en passant comme valeur à la page initiale la valeur entrée par l'utilisateur.
   * @method dismiss
   * @param {} - aucun paramètre n'est passé à la fonction.
   * @returns {} - aucune valeur n'est retournée par la fonction.
   */
dismiss() {
    this.keyboard.close();
    this.viewCtrl.dismiss(this.autocompleteEntry);
  }


/**
   * Fonction qui supprime la page modale ouverte, en passant comme valeur à la page initiale la valeur sélectionnée dans la liste proposée (autocompletion).
   * @method chooseItem
   * @param {any} - la valeur sélectionnée dans la liste proposée est passée à la fonction.
   * @returns {} - aucune valeur n'est retournée par la fonction.
   */
chooseItem(item: any) {
    this.autocompleteEntry = item;
    this.keyboard.close();
    this.viewCtrl.dismiss(item);
  }


/**
   * Fonction qui, à chaque saisie de l'utilisateur, compare le contenu saisi et la liste proposée pour limiter la liste aux valeurs qui correspondent à la saisie : autocompletion.
   * @method updateSearch
   * @param {} - aucun paramètre n'est passé à la fonction.
   * @returns {string} - une liste mise à jour suite à la nouvelle saisie de l'utilisateur est retournée par la fonction.
   */
updateSearch() {
    if (this.autocompleteEntry == '') {
      this.autocompleteItems = [];
    } else {
      let arrayLength: number = this.autocompleteData.length;
      var i: number = 0;
      var nbItems: number = 0;
      var table = [];
      while (i < arrayLength && nbItems < 20) {
        let strVal = this.diacritics.replaceDiacritics(this.autocompleteData[i].toLowerCase());
        let strEntry = this.diacritics.replaceDiacritics(this.autocompleteEntry.toLowerCase());
        if (strVal.indexOf(strEntry) > -1) {
          table.push(strVal);
          nbItems++;
        }
        i++;
      }
      this.autocompleteItems = table;
    }
  }


function Demo() {
  return (
    <div style={{ maxWidth: 320, marginLeft: 'auto', marginRight: 'auto' }}


/* tslint:disable */
export interface Occupancy {

  /**
   * Number of datapoints used for the value calculation.
   */
  count: number;

  /**
   * Time of the latest report that was considered to calculate occupancy
   */
  latestReport?: null | string;

  /**
   * Occupancy in percent.
   */
  value: null | number;
}


export class PDFSinglePageViewer extends BaseViewer {
    constructor(options: any);
    _previousPageNumber: any;
    _shadowViewer: DocumentFragment | undefined;
    _updateScrollDown: any;
    _ensurePageViewVisible(): void;
}


_ensurePageViewVisible(): void;


(event: any) => { this._handleMousemove(event); }


() => { this._handleMouseup(); }


export type ClockView = 'hour' | 'minute';


ngAfterContentInit() {
    this.activeDate = this._activeDate || this._util.today();
    this._init();
  }


/** Handles mousedown events on the clock body. */
_handleMousedown(event: any) {
    this.setTime(event);
    document.addEventListener('mousemove', this.mouseMoveListener);
    document.addEventListener('touchmove', this.mouseMoveListener);
    document.addEventListener('mouseup', this.mouseUpListener);
    document.addEventListener('touchend', this.mouseUpListener);
  }


_handleMousemove(event: any) {
    event.preventDefault();
    this.setTime(event);
  }


_handleMouseup() {
    document.removeEventListener('mousemove', this.mouseMoveListener);
    document.removeEventListener('touchmove', this.mouseMoveListener);
    document.removeEventListener('mouseup', this.mouseUpListener);
    document.removeEventListener('touchend', this.mouseUpListener);
    this.selectedChange.emit(this.activeDate);
  }


/** Initializes this clock view. */
private _init() {
    this._hours.length = 0;
    this._minutes.length = 0;

    let hourNames = this._locale.getHourNames();
    let minuteNames = this._locale.getMinuteNames();

    if (this.twelvehour) {
      for (let i = 1; i < (hourNames.length / 2) + 1; i++) {
        let radian = i / 6 * Math.PI;
        let radius = CLOCK_OUTER_RADIUS;
        let date = new Date(this.activeDate.getTime());
        date.setHours(i + 1, 0, 0, 0);
        let enabled = this._util.isFullDateWithinRange(date, this.min, this.max);
        this._hours.push({
          value: i,
          displayValue: i === 0 ? '00' : hourNames[i],
          enabled: enabled,
          top: CLOCK_RADIUS - Math.cos(radian) * radius - CLOCK_TICK_RADIUS,
          left: CLOCK_RADIUS + Math.sin(radian) * radius - CLOCK_TICK_RADIUS,
        });
      }
    } else {
      for (let i = 0; i < hourNames.length; i++) {
        let radian = i / 6 * Math.PI;
        let outer = i > 0 && i < 13,
          radius = outer ? CLOCK_OUTER_RADIUS : CLOCK_INNER_RADIUS;
        let date = new Date(this.activeDate.getTime());
        date.setHours(i + 1, 0, 0, 0);
        let enabled = this._util.isFullDateWithinRange(date, this.min, this.max);
        this._hours.push({
          value: i,
          displayValue: i === 0 ? '00' : hourNames[i],
          enabled: enabled,
          top: CLOCK_RADIUS - Math.cos(radian) * radius - CLOCK_TICK_RADIUS,
          left: CLOCK_RADIUS + Math.sin(radian) * radius - CLOCK_TICK_RADIUS,
          fontSize: i > 0 && i < 13 ? '' : '80%'
        });
      }
    }

    for (let i = 0; i < minuteNames.length; i += 5) {
      let radian = i / 30 * Math.PI;
      let date = new Date(this.activeDate.getTime());
      date.setMinutes(i, 0, 0);
      let enabled = this._util.isFullDateWithinRange(date, this.min, this.max);
      this._minutes.push({
        value: i,
        displayValue: i === 0 ? '00' : minuteNames[i],
        enabled: enabled,
        top: CLOCK_RADIUS - Math.cos(radian) * CLOCK_OUTER_RADIUS - CLOCK_TICK_RADIUS,
        left: CLOCK_RADIUS + Math.sin(radian) * CLOCK_OUTER_RADIUS - CLOCK_TICK_RADIUS,
      });
    }
  }


/**
   * Set Time
   * @param event
   */
private setTime(event: any) {
    let trigger = this._element.nativeElement;
    let triggerRect = trigger.getBoundingClientRect();
    let width = trigger.offsetWidth;
    let height = trigger.offsetHeight;
    let pageX = event.pageX !== undefined ? event.pageX : event.touches[0].pageX;
    let pageY = event.pageY !== undefined ? event.pageY : event.touches[0].pageY;
    let x = (width / 2) - (pageX - triggerRect.left - window.pageXOffset);
    let y = (height / 2) - (pageY - triggerRect.top - window.pageYOffset);
    let radian = Math.atan2(-x, y);
    let unit = Math.PI / (this._hourView ? 6 : (this.interval ? (30 / this.interval) : 30));
    let z = Math.sqrt(x * x + y * y);
    let outer = this._hourView && z > ((width * (CLOCK_OUTER_RADIUS / 100)) +
      (width * (CLOCK_INNER_RADIUS / 100))) / 2;
    let value = 0;

    if (radian < 0) { radian = Math.PI * 2 + radian; }
    value = Math.round(radian / unit);
    radian = value * unit;

    let date = new Date(this.activeDate.getTime());
    if (this._hourView) {
      if (this.twelvehour) {
        value = value === 0 ? 12 : value;
      } else {
        if (value === 12) { value = 0; }
        value = outer ? (value === 0 ? 12 : value) : value === 0 ? 0 : value + 12;
      }
      date.setHours(value);
    } else {
      if (this.interval) { value *= this.interval; }
      if (value === 60) { value = 0; }
      date.setMinutes(value);
    }
    this.activeDate = this._util.clampDate(date, this.min, this.max);
    this.activeDateChange.emit(this.activeDate);
  }


(movie) => movie.id === id


(movie) => movie.id !== id


@Injectable()
export class MoviesService {
  private movies: Movie[] = [];

  getAll(): Movie[] {
    return this.movies;
  }

  getOne(id: number): Movie {
    const movie = this.movies.find((movie) => movie.id === id); //convert string into number}
    if (!movie) {
      throw new NotFoundException(`Movie with ID ${id} not found`);
    }
    return movie;
  }

  deleteOne(id: number) {
    this.getOne(id);
    this.movies = this.movies.filter((movie) => movie.id !== id);
  }

  create(movieData: CreateMovieDto) {
    this.movies.push({
      id: this.movies.length + 1,
      ...movieData,
    });
  }

  update(id: number, updateData: UpdateMovieDto) {
    const movie = this.getOne(id);
    this.deleteOne(id);
    this.movies.push({ ...movie, ...updateData });
  }
}


getAll(): Movie[] {
    return this.movies;
  }


getOne(id: number): Movie {
    const movie = this.movies.find((movie) => movie.id === id); //convert string into number}
    if (!movie) {
      throw new NotFoundException(`Movie with ID ${id} not found`);
    }
    return movie;
  }


deleteOne(id: number) {
    this.getOne(id);
    this.movies = this.movies.filter((movie) => movie.id !== id);
  }


create(movieData: CreateMovieDto) {
    this.movies.push({
      id: this.movies.length + 1,
      ...movieData,
    });
  }


update(id: number, updateData: UpdateMovieDto) {
    const movie = this.getOne(id);
    this.deleteOne(id);
    this.movies.push({ ...movie, ...updateData });
  }


() => {
  React.useEffect(() => {
    incModCount();
  }, []);

  return

    I'm component Comp_05_0698

;
}


/**
 * Script represents a single script.
 */
export interface Script {
  /** The content type */
  url: string;
  /** The content type */
  redirectedUrl: string;
  /** The content type */
  contentType: string;
  /** The source code of the script */
  source: string;
  /** The dependency import specifiers */
  imports: string[];
}


@Component({
  selector: 'app-factura-editar',
  templateUrl: './factura-editar.component.html',
  styleUrls: ['./factura-editar.component.css']
})
export class FacturaEditarComponent implements OnInit {

  constructor() { }

  ngOnInit(): void {
  }

}


export function checkPropClash(
	parser: JSParser,
	prop: AnyObjectMember | BindingObjectPatternProperty,
	props: Set<string>,
): void {
	if (prop.key.type === "ComputedPropertyKey" || prop.type === "ObjectMethod") {
		return undefined;
	}

	const key = prop.key.value;

	// We can only check these for collisions since they're statically known
	if (
		key.type !== "Identifier" &&
		key.type !== "StringLiteral" &&
		key.type !== "NumericLiteral"
	) {
		return;
	}

	// It is either an Identifier or a String/NumericLiteral
	const name = key.type === "Identifier" ? key.name : String(key.value);

	if (name === "__proto__") {
		if (props.has("proto")) {
			parser.addDiagnostic({
				description: descriptions.JS_PARSER.PROTO_PROP_REDEFINITION,
				loc: key.loc,
			});
		} else {
			props.add("proto");
		}
	}
}


export function parseExpression(
	parser: JSParser,
	context: ExpressionContext,
	noIn?: boolean,
	refShorthandDefaultPos?: IndexTracker,
): AnyExpression {
	const startPos = parser.state.startPos;
	const expr = parseMaybeAssign(parser, context, noIn, refShorthandDefaultPos);
	if (parser.match(tt.comma)) {
		let expressions: Array<AnyExpression> = [expr];
		while (parser.eat(tt.comma)) {
			expressions.push(
				parseMaybeAssign(parser, context, noIn, refShorthandDefaultPos),
			);
		}

		expressions = filterSpread(parser, toReferencedList(parser, expressions));

		return parser.finishNode(
			startPos,
			{
				type: "SequenceExpression",
				expressions,
			},
		);
	}
	return expr;
}


export function parseMaybeAssign<T extends AnyNode = AnyExpression>(
	parser: JSParser,
	context: ExpressionContext,
	noIn?: boolean,
	refShorthandDefaultPos?: IndexTracker,
	afterLeftParse?: MaybeAssignAfterParse<T>,
	refNeedsArrowPos?: IndexTracker,
): AnyExpression | T {
	const branches = parser.createBranch<AnyExpression | T>();

	// Try parsing as JSX
	if (
		(parser.isRelational("<") || parser.match(tt.jsxTagStart)) &&
		parser.shouldTokenizeJSX()
	) {
		branches.add(
			() => {
				return _parseMaybeAssign(
					parser,
					context,
					noIn,
					refShorthandDefaultPos,
					afterLeftParse,
					refNeedsArrowPos,
				);
			},
			{diagnosticsPriority: 1},
		);

		// Remove `tc.j_expr` and `tc.j_oTag` from 'context added

		// by parsing `jsxTagStart` to stop the JSX plugin from

		// messing with the tokens
		const cLength = parser.state.context.length;
		if (parser.state.context[cLength - 1] === tc.jsxOpenTag) {
			parser.state.context.length -= 2;
		}
		finishToken(parser, tt.relational, "<");
	}

	// Try parsing as an arrow function with type parameters
	if (parser.isRelational("<")) {
		branches.add(() => {
			const start = parser.getPosition();
			const typeParameters = parseTSTypeParameters(parser);
			const arrowExpression = forwardNoArrowParamsConversionAt(
				parser,
				start,
				() =>
					_parseMaybeAssign<T>(
						parser,
						context,
						noIn,
						refShorthandDefaultPos,
						afterLeftParse,
						refNeedsArrowPos,
					)
				,
			);
			parser.resetStartLocationFromNode(arrowExpression, typeParameters);

			if (arrowExpression.type === "ArrowFunctionExpression") {
				return {
					...arrowExpression,
					typeParameters,
				};
			} else {
				parser.addDiagnostic({
					loc: typeParameters.loc,
					description: descriptions.JS_PARSER.EXPECTED_ARROW_AFTER_TYPE_PARAMS,
				});
				return toReferenceIdentifier(
					parser,
					parser.createUnknownIdentifier("type params without arrow function"),
				);
			}
		});
	}

	branches.add(() => {
		return _parseMaybeAssign<T>(
			parser,
			context,
			noIn,
			refShorthandDefaultPos,
			afterLeftParse,
			refNeedsArrowPos,
		);
	});

	// Pick the branch with the least amount of errors
	return branches.pick();
}


function _parseMaybeAssign<T extends AnyNode>(
	parser: JSParser,
	context: ExpressionContext,
	noIn?: boolean,
	refShorthandDefaultPos?: IndexTracker,
	afterLeftParse?: MaybeAssignAfterParse<T>,
	refNeedsArrowPos?: IndexTracker,
): AnyExpression | T {
	const startPos = parser.state.startPos;

	if (parser.isContextual("yield")) {
		if (parser.inScope("GENERATOR")) {
			let left: T | AnyExpression = parseYield(parser, noIn);
			if (afterLeftParse) {
				left = afterLeftParse(parser, left, startPos);
			}
			return left;
		} else {
			// The tokenizer will assume an expression is allowed after
			// `yield`, but this isn't that kind of yield
			parser.state.exprAllowed = false;
		}
	}

	const oldCommaAfterSpreadAt = parser.state.commaAfterSpreadAt;
	parser.state.commaAfterSpreadAt = ob1Number0Neg1;

	let failOnShorthandAssign;
	if (refShorthandDefaultPos) {
		failOnShorthandAssign = false;
	} else {
		refShorthandDefaultPos = createIndexTracker();
		failOnShorthandAssign = true;
	}

	if (parser.match(tt.parenL) || parser.match(tt.name)) {
		parser.state.potentialArrowAt = parser.state.startPos.index;
	}

	let left: AnyExpression | T = parseMaybeConditional(
		parser,
		context,
		noIn,
		refShorthandDefaultPos,
		refNeedsArrowPos,
	);
	if (afterLeftParse) {
		left = afterLeftParse(parser, left, startPos);
	}

	if (parser.state.tokenType.isAssign) {
		const operator = (String(parser.state.tokenValue) as AssignmentOperator);
		const leftPatt = toAssignmentPattern(parser, left, "assignment expression");

		// reset because shorthand default was used correctly
		refShorthandDefaultPos.index = ob1Number0;

		checkLVal(parser, leftPatt, undefined, undefined, "assignment expression");

		// We should never get patterns here...?

		//if (left.type === 'BindingArrayPattern' || left.type === 'BindingObjectPattern') {
		//  checkCommaAfterRestFromSpread(parser);

		//}
		parser.state.commaAfterSpreadAt = oldCommaAfterSpreadAt;

		parser.next();
		const right = parseMaybeAssign(parser, "assignment right", noIn);
		return parser.finishNode(
			startPos,
			{
				type: "AssignmentExpression",
				operator,
				left: leftPatt,
				right,
			},
		);
	} else if (failOnShorthandAssign && ob1Get0(refShorthandDefaultPos.index) > 0) {
		parser.unexpectedToken(
			parser.getPositionFromIndex(refShorthandDefaultPos.index),
		);
	}

	parser.state.commaAfterSpreadAt = oldCommaAfterSpreadAt;

	return left;
}


export function parseMaybeConditional(
	parser: JSParser,
	context: ExpressionContext,
	noIn: undefined | boolean,
	refShorthandDefaultPos: IndexTracker,
	refNeedsArrowPos?: IndexTracker,
): AnyExpression {
	const startPos = parser.state.startPos;
	const potentialArrowAt = parser.state.potentialArrowAt;
	const expr = parseExpressionOps(parser, context, noIn, refShorthandDefaultPos);

	if (
		expr.type === "ArrowFunctionExpression" &&
		parser.getLoc(expr).start.index === potentialArrowAt
	) {
		return expr;
	}

	if (refShorthandDefaultPos && ob1Get0(refShorthandDefaultPos.index) > 0) {
		return expr;
	}

	return parseConditional(parser, expr, noIn, startPos, refNeedsArrowPos);
}


export function tryParseConditionalConsequent(
	parser: JSParser,
): {
	consequent: AnyExpression;
	failed: boolean;
} {
	const brancher = parser.createBranch<{
		consequent: AnyExpression;
		failed: boolean;
	}>();

	brancher.add(() => {
		parser.state.noArrowParamsConversionAt.push(parser.state.startPos.index);
		const consequent = parseMaybeAssign(parser, "conditional consequent");
		parser.state.noArrowParamsConversionAt.pop();
		return {
			consequent,
			failed: !parser.match(tt.colon),
		};
	});

	return brancher.pick();
}


export function parseConditional(
	parser: JSParser,
	expr: AnyExpression,
	noIn: undefined | boolean,
	startPos: Position,
	refNeedsArrowPos?: IndexTracker,
): AnyExpression {
	if (!parser.match(tt.question)) {
		return expr;
	}

	// This is to handle a case like this: const foo = (foo?: bar) => {};

	// We'll be called due to the `?`, and we should mark ourselves as an

	// expected arrow function if parsing as a regular conditional fails
	if (refNeedsArrowPos) {
		const branch = parser.createBranch<AnyExpression>();

		branch.add(
			() => _parseConditional(parser, expr, noIn, startPos),
			{
				maxNewDiagnostics: 0,
			},
		);

		if (branch.hasBranch()) {
			return branch.pick();
		} else {
			refNeedsArrowPos.index = parser.state.startPos.index;
			return expr;
		}
	}

	parser.expect(tt.question);
	const originalNoArrowAt = parser.state.noArrowAt;
	let {consequent} = tryParseConditionalConsequent(parser);
	parser.state.noArrowAt = originalNoArrowAt;

	if (!parser.eat(tt.colon)) {
		parser.addDiagnostic({
			description: descriptions.JS_PARSER.MISSING_CONDITIONAL_SEPARATOR,
		});
	}

	const alternate = forwardNoArrowParamsConversionAt(
		parser,
		startPos,
		() =>
			parseMaybeAssign(
				parser,
				"conditional alternate",
				noIn,
				undefined,
				undefined,
				undefined,
			)
		,
	);

	return parser.finishNode(
		startPos,
		{
			type: "ConditionalExpression",
			test: expr,
			consequent,
			alternate,
		},
	);
}


export function forwardNoArrowParamsConversionAt<T>(
	parser: JSParser,
	start: Position,
	parse: () => T,
): T {
	if (parser.state.noArrowParamsConversionAt.includes(start.index)) {
		let result: T;
		parser.state.noArrowParamsConversionAt.push(parser.state.startPos.index);
		result = parse();
		parser.state.noArrowParamsConversionAt.pop();
		return result;
	} else {
		return parse();
	}
}


function _parseConditional(
	parser: JSParser,
	expr: AnyExpression,
	noIn: undefined | boolean,
	startPos: Position,
): AnyExpression {
	if (parser.eat(tt.question)) {
		const test = expr;
		const consequent = parseMaybeAssign(parser, "conditional consequent");
		parser.expect(tt.colon);
		const alternate = parseMaybeAssign(parser, "conditional alternate", noIn);
		return parser.finishNode(
			startPos,
			{
				type: "ConditionalExpression",
				test,
				consequent,
				alternate,
			},
		);
	}
	return expr;
}


export function parseExpressionOps(
	parser: JSParser,
	context: ExpressionContext,
	noIn: undefined | boolean,
	refShorthandDefaultPos: IndexTracker,
): AnyExpression {
	const startPos = parser.state.startPos;
	const potentialArrowAt = parser.state.potentialArrowAt;
	const expr = parseMaybeUnary(parser, context, refShorthandDefaultPos);

	if (
		expr.type === "ArrowFunctionExpression" &&
		parser.getLoc(expr).start.index === potentialArrowAt
	) {
		return expr;
	}
	if (refShorthandDefaultPos && ob1Get0(refShorthandDefaultPos.index) > 0) {
		return expr;
	}

	return parseExpressionOp(parser, context, expr, startPos, -1, noIn);
}


export function parseExpressionOp(
	parser: JSParser,
	context: ExpressionContext,
	left: AnyExpression,
	leftStartPos: Position,
	minPrec: number,
	noIn: boolean = false,
): AnyExpression {
	if (
		tt._in.getBinop() > minPrec &&
		!parser.hasPrecedingLineBreak() &&
		parser.isContextual("as")
	) {
		const _const = tryTSNextParseConstantContext(parser);

		let typeAnnotation;
		if (_const) {
			tsCheckLiteralForConstantContext(parser, left);
			typeAnnotation = _const;
		} else {
			typeAnnotation = tsNextThenParseType(parser);
		}

		const node: TSAsExpression = parser.finishNode(
			leftStartPos,
			{
				type: "TSAsExpression",
				typeAnnotation,
				expression: left,
			},
		);

		return parseExpressionOp(parser, context, node, leftStartPos, minPrec, noIn);
	}

	const prec = parser.state.tokenType.binop;
	if (prec !== undefined && (!noIn || !parser.match(tt._in))) {
		if (prec > minPrec) {
			const operator = (String(parser.state.tokenValue) as
				 | BinaryOperator
				| LogicalOperator);

			if (
				operator === "**" &&
				left.type === "UnaryExpression" &&
				!parser.isParenthesized(left)
			) {
				parser.addDiagnostic({
					loc: left.argument.loc,
					description: descriptions.JS_PARSER.WRAP_EXPONENTIATION,
				});
			}

			const op = parser.state.tokenType;
			parser.next();

			const startPos = parser.state.startPos;

			const right = parseExpressionOp(
				parser,
				context,
				parseMaybeUnary(parser, context),
				startPos,
				op.rightAssociative ? prec - 1 : prec,
				noIn,
			);

			let node: LogicalExpression | BinaryExpression;
			if (operator === "||" || operator === "&&" || operator === "??") {
				node = parser.finishNode(
					leftStartPos,
					{
						type: "LogicalExpression",
						left,
						right,
						operator,
					},
				);
			} else {
				node = parser.finishNode(
					leftStartPos,
					{
						type: "BinaryExpression",
						left,
						right,
						operator,
					},
				);
			}

			return parseExpressionOp(parser, context, node, leftStartPos, minPrec, noIn);
		}
	}

	return left;
}


// Parse unary operators, both prefix and postfix.
export function parseMaybeUnary(
	parser: JSParser,
	context: ExpressionContext,
	refShorthandDefaultPos?: IndexTracker,
): AnyExpression {
	if (
		parser.isSyntaxEnabled("ts") &&
		!parser.isSyntaxEnabled("jsx") &&
		parser.isRelational("<")
	) {
		return parseTSTypeAssertion(parser);
	}

	if (parser.isContextual("await") && parser.inScope("ASYNC")) {
		return parseAwait(parser);
	}

	if (parser.state.tokenType.prefix) {
		const start = parser.getPosition();
		const update = parser.match(tt.incDec);
		const operator = (String(parser.state.tokenValue) as
			 | UnaryOperator
			| UpdateOperator);
		const prefix = true;

		parser.next();

		const argument = parseMaybeUnary(parser, context);

		if (refShorthandDefaultPos && ob1Get0(refShorthandDefaultPos.index) > 0) {
			parser.unexpectedToken(
				parser.getPositionFromIndex(refShorthandDefaultPos.index),
			);
		}

		if (update) {
			checkLVal(parser, argument, undefined, undefined, "prefix operation");
		} else if (parser.inScope("STRICT") && operator === "delete") {
			if (argument.type === "ReferenceIdentifier") {
				parser.addDiagnostic({
					loc: argument.loc,
					description: descriptions.JS_PARSER.DELETE_LOCAL_VARIABLE_IN_STRICT,
				});
			} else if (
				argument.type === "MemberExpression" &&
				argument.property.value.type === "PrivateName"
			) {
				parser.addDiagnostic({
					loc: argument.property.loc,
					description: descriptions.JS_PARSER.DELETE_PRIVATE_FIELD,
				});
			}
		}

		let node: UpdateExpression | UnaryExpression;
		if (update) {
			if (operator !== "++" && operator !== "--") {
				throw new Error("Expected ++/-- operator only for UpdateExpression");
			}

			node = parser.finishNode(
				start,
				{
					type: "UpdateExpression",
					argument,
					operator,
					prefix,
				},
			);
		} else {
			if (operator === "++" || operator === "--") {
				throw new Error("BinaryExpression cannot have ++/-- operator");
			}

			node = parser.finishNode(
				start,
				{
					type: "UnaryExpression",
					argument,
					operator,
					prefix,
				},
			);
		}

		return node;
	}

	const startPos = parser.state.startPos;

	let expr = parseExpressionWithPossibleSubscripts(
		parser,
		context,
		refShorthandDefaultPos,
	);
	if (refShorthandDefaultPos && ob1Get0(refShorthandDefaultPos.index) > 0) {
		return expr;
	}

	while (parser.state.tokenType.postfix && !parser.canInsertSemicolon()) {
		const operator = (String(parser.state.tokenValue) as UpdateOperator);
		checkLVal(parser, expr, undefined, undefined, "postfix operation");
		parser.next();

		const updateNode: UpdateExpression = parser.finishNode(
			startPos,
			{
				type: "UpdateExpression",
				operator,
				prefix: false,
				argument: expr,
			},
		);
		expr = updateNode;
	}

	return expr;
}


// Parse call, dot, and `[]`-subscript expressions.
export function parseExpressionWithPossibleSubscripts(
	parser: JSParser,
	context: ExpressionContext,
	refShorthandDefaultPos?: IndexTracker,
): AnyExpression {
	const startPos = parser.state.startPos;
	const potentialArrowAt = parser.state.potentialArrowAt;
	const expr = parseExpressionAtom(parser, context, refShorthandDefaultPos);

	if (
		expr.type === "ArrowFunctionExpression" &&
		parser.getLoc(expr).start.index === potentialArrowAt
	) {
		return expr;
	}

	if (refShorthandDefaultPos && ob1Get0(refShorthandDefaultPos.index) > 0) {
		return expr;
	}

	return parseSubscripts(parser, expr, startPos);
}


export function parseSubscripts(
	parser: JSParser,
	base: AnyExpression,
	startPos: Position,
	noCalls?: boolean,
): AnyExpression {
	const maybeAsyncArrow = atPossibleAsync(parser, base);

	if (
		base.type === "ReferenceIdentifier" &&
		base.name === "async" &&
		parser.state.noArrowAt.includes(startPos.index)
	) {
		const argsStart = parser.getPosition();
		const openContext = parser.expectOpening(
			tt.parenL,
			tt.parenR,
			"call arguments",
		);
		const callee = base;
		const {args} = parseCallExpressionArguments(parser, openContext, false);
		base = parser.finishNodeWithCommentStarts(
			[argsStart, startPos],
			{
				type: "CallExpression",
				callee,
				arguments: args,
			},
		);
	} else if (
		base.type === "ReferenceIdentifier" &&
		base.name === "async" &&
		parser.isRelational("<")
	) {
		const branch = parser.createBranch<AnyExpression>();
		branch.add(() => parseAsyncArrowWithTypeParameters(parser, startPos));
		branch.add(() =>
			parseExpressionSubscriptsRecursively(
				parser,
				base,
				startPos,
				noCalls,
				maybeAsyncArrow,
			)
		);
		return branch.pick();
	}

	return parseExpressionSubscriptsRecursively(
		parser,
		base,
		startPos,
		noCalls,
		maybeAsyncArrow,
	);
}


export function parseAsyncArrowWithTypeParameters(
	parser: JSParser,
	startPos: Position,
): undefined | ArrowFunctionExpression {
	const {params, rest, typeParameters} = parseFunctionParams(parser);

	const {returnType, valid} = parseArrowHead(parser);
	if (!valid) {
		parser.addDiagnostic({
			description: descriptions.JS_PARSER.INVALID_ASYNC_ARROW_WITH_TYPE_PARAMS,
		});
		return undefined;
	}

	const func = parseArrowExpression(
		parser,
		startPos,
		{
			bindingList: params,
			rest,
		},
		/* isAsync */ true,
	);

	return {
		...func,
		head: {
			...func.head,
			returnType,
			typeParameters,
		},
	};
}


function parseExpressionSubscriptsRecursively(
	parser: JSParser,
	base: AnyExpression,
	startPos: Position,
	noCalls: undefined | boolean,
	maybeAsyncArrow: boolean,
): AnyExpression {
	const state: ParseSubscriptState = {
		optionalChainMember: false,
		stop: false,
	};
	do {
		base = parseExpressionSubscript(
			parser,
			base,
			startPos,
			noCalls,
			state,
			maybeAsyncArrow,
		);
	} while (!state.stop);
	return base;
}


export function parseExpressionSubscript(
	parser: JSParser,
	base: AnyExpression,
	startPos: Position,
	noCalls: boolean = false,
	state: ParseSubscriptState,
	maybeAsyncArrow: boolean,
): AnyExpression {
	if (!parser.hasPrecedingLineBreak() && parser.match(tt.bang)) {
		parser.state.exprAllowed = false;
		parser.next();

		return parser.finishNode(
			startPos,
			{
				type: "TSNonNullExpression",
				expression: base,
			},
		);
	}

	if (parser.match(tt.questionDot)) {
		state.optionalChainMember = true;

		if (noCalls && parser.lookaheadState().tokenType === tt.parenL) {
			state.stop = true;
			return base;
		}

		parser.next();

		// eg: o.m?.<T>(e);
		if (parser.isRelational("<")) {
			if (noCalls) {
				state.stop = true;
				return base;
			}

			const callee = base;
			const typeArguments = parseTSTypeArguments(parser);
			const openContext = parser.expectOpening(
				tt.parenL,
				tt.parenR,
				"call arguments",
			);
			const {args} = parseCallExpressionArguments(parser, openContext, false);
			return parser.finishNode(
				startPos,
				{
					type: "OptionalCallExpression",
					arguments: args,
					callee,
					typeArguments,
				},
			);
		}

		if (parser.match(tt.bracketL)) {
			const propStart = parser.getPosition();
			const openContext = parser.expectOpening(
				tt.bracketL,
				tt.bracketR,
				"computed property",
			);
			const object = base;
			const property = parseExpression(
				parser,
				"optional member expression property",
			);
			parser.expectClosing(openContext);
			return parser.finishNode(
				startPos,
				{
					type: "MemberExpression",
					object,
					property: parser.finishNode(
						propStart,
						{
							type: "ComputedMemberProperty",
							optional: true,
							value: property,
						},
					),
				},
			);
		}

		if (parser.match(tt.parenL)) {
			const openContext = parser.expectOpening(
				tt.parenL,
				tt.parenR,
				"call arguments",
			);
			const callee = base;
			const {args} = parseCallExpressionArguments(parser, openContext, false);

			return parser.finishNode(
				startPos,
				{
					type: "OptionalCallExpression",
					callee,
					arguments: args,
				},
			);
		}

		const object = base;
		const property = parseIdentifier(parser, true);

		return parser.finishNode(
			startPos,
			{
				type: "MemberExpression",
				object,
				property: {
					type: "StaticMemberProperty",
					loc: property.loc,
					optional: true,
					value: property,
				},
			},
		);
	}

	if (parser.eat(tt.dot)) {
		const object = base;
		const property = parseMaybePrivateName(parser);

		return parser.finishNode(
			startPos,
			{
				type: "MemberExpression",
				object,
				property: {
					type: "StaticMemberProperty",
					loc: property.loc,
					value: property,
				},
			},
		);
	}

	if (parser.match(tt.bracketL)) {
		const propStart = parser.getPosition();
		const openContext = parser.expectOpening(
			tt.bracketL,
			tt.bracketR,
			"computed property",
		);
		const object = base;
		const property = parseExpression(
			parser,
			"member expression computed property",
		);
		parser.expectClosing(openContext);

		return parser.finishNode(
			startPos,
			{
				type: "MemberExpression",
				object,
				property: parser.finishNode(
					propStart,
					{
						type: "ComputedMemberProperty",
						value: property,
					},
				),
			},
		);
	}

	// Supports: foo<Foo>(); and foo<Foo>``;
	if (parser.isRelational("<") && parser.isSyntaxEnabled("ts")) {
		const possibleCallExpression = parser.tryBranch(() => {
			const typeArguments = parseTSTypeArguments(parser);

			if (!noCalls && parser.match(tt.parenL)) {
				const argsStart = parser.getPosition();
				const openContext = parser.expectOpening(
					tt.parenL,
					tt.parenR,
					"call arguments",
				);
				const {args} = parseCallExpressionArguments(parser, openContext, false);
				const node: CallExpression = parser.finishNodeWithCommentStarts(
					[argsStart, startPos],
					{
						type: "CallExpression",
						arguments: args,
						callee: base,
						typeArguments,
					},
				);
				return node;
			}

			if (parser.match(tt.backQuote)) {
				return parseTaggedTemplateExpression(
					parser,
					startPos,
					base,
					state,
					typeArguments,
				);
			}

			return undefined;
		});

		if (possibleCallExpression !== undefined) {
			return possibleCallExpression;
		}
	}

	if (!noCalls && parser.match(tt.parenL)) {
		const oldMaybeInArrowParameters = parser.state.maybeInArrowParameters;
		const oldYieldPos = parser.state.yieldPos;
		const oldAwaitPos = parser.state.awaitPos;
		parser.state.maybeInArrowParameters = true;
		parser.state.yieldPos = ob1Number0;
		parser.state.awaitPos = ob1Number0;

		const argsStart = parser.getPosition();
		const openContext = parser.expectOpening(
			tt.parenL,
			tt.parenR,
			"call arguments",
		);
		const callee = base;

		const oldCommaAfterSpreadAt = parser.state.commaAfterSpreadAt;
		parser.state.commaAfterSpreadAt = ob1Number0Neg1;

		let {args, params} = parseCallExpressionArguments(
			parser,
			openContext,
			maybeAsyncArrow,
		);

		if (maybeAsyncArrow && shouldParseAsyncArrow(parser)) {
			state.stop = true;

			checkCommaAfterRestFromSpread(parser);

			const node = parseAsyncArrowFromCallExpression(
				parser,
				startPos,
				params === undefined ? args : params,
			);
			checkYieldAwaitInDefaultParams(parser);
			parser.state.yieldPos = oldYieldPos;
			parser.state.awaitPos = oldAwaitPos;
			return node;
		} else {
			args = toReferencedListDeep(parser, args);

			// We keep the old value if it isn't null, for cases like

			//   (x = async(yield)) => {}
			parser.state.yieldPos = oldYieldPos || parser.state.yieldPos;
			parser.state.awaitPos = oldAwaitPos || parser.state.awaitPos;
		}

		parser.state.maybeInArrowParameters = oldMaybeInArrowParameters;
		parser.state.commaAfterSpreadAt = oldCommaAfterSpreadAt;

		return parser.finishNodeWithCommentStarts(
			[argsStart, startPos],
			{
				type: "CallExpression",
				callee,
				arguments: args,
			},
		);
	}

	if (parser.match(tt.backQuote)) {
		return parseTaggedTemplateExpression(parser, startPos, base, state);
	}

	state.stop = true;
	return base;
}


export function parseTaggedTemplateExpression(
	parser: JSParser,
	startPos: Position,
	tag: AnyExpression,
	state: ParseSubscriptState,
	typeArguments?: TSTypeParameterInstantiation,
): TaggedTemplateExpression {
	if (state.optionalChainMember) {
		parser.addDiagnostic({
			description: descriptions.JS_PARSER.TAGGED_TEMPLATE_IN_OPTIONAL_CHAIN,
		});
	}

	const quasi = parseTemplate(parser, true);
	return parser.finishNode(
		startPos,
		{
			type: "TaggedTemplateExpression",
			tag,
			quasi,
			typeArguments,
		},
	);
}


export function checkYieldAwaitInDefaultParams(parser: JSParser) {
	if (
		ob1Get0(parser.state.yieldPos) > 0 &&
		(parser.state.awaitPos === ob1Number0 ||
		parser.state.yieldPos < parser.state.awaitPos)
	) {
		parser.addDiagnostic({
			index: parser.state.yieldPos,
			description: descriptions.JS_PARSER.YIELD_IN_GENERATOR_PARAMS,
		});
	}

	if (ob1Get0(parser.state.awaitPos) > 0) {
		parser.addDiagnostic({
			index: parser.state.awaitPos,
			description: descriptions.JS_PARSER.AWAIT_IN_ASYNC_PARAMS,
		});
	}
}


export function atPossibleAsync(parser: JSParser, base: AnyExpression): boolean {
	const loc = parser.getLoc(base);
	return (
		base.type === "ReferenceIdentifier" &&
		base.name === "async" &&
		parser.state.lastEndPos.index === loc.end.index &&
		!parser.canInsertSemicolon() &&
		parser.getRawInput(loc.start.index, loc.end.index) === "async"
	);
}


export function parseCallExpressionArguments(
	parser: JSParser,
	openContext: OpeningContext,
	possibleAsyncArrow: boolean,
	refTrailingCommaPos?: IndexTracker,
): {
	args: CallExpression["arguments"];
	params:
		 | undefined
		| Array<AnyExpression | SpreadElement | AmbiguousFlowTypeCastExpression>;
} {
	let callArgs: CallExpression["arguments"] = [];
	let funcParams: Array<
		AnyExpression | SpreadElement | AmbiguousFlowTypeCastExpression
	> = [];

	let innerParenStart;
	let first = true;

	let forceAsyncArrow = false;

	while (true) {
		if (parser.match(openContext.close) || parser.match(tt.eof)) {
			parser.expectClosing(openContext);
			break;
		}

		if (first) {
			first = false;
		} else {
			if (!parser.expect(tt.comma)) {
				break;
			}

			if (parser.eat(openContext.close)) {
				break;
			}
		}

		// we need to make sure that if this is an async arrow functions, that we don't allow inner parens inside the params
		if (parser.match(tt.parenL) && !innerParenStart) {
			innerParenStart = parser.state.startPos;
		}

		const elt = parseCallArgument(
			parser,
			"call expression argument",
			false,
			possibleAsyncArrow ? createIndexTracker() : undefined,
			possibleAsyncArrow ? createIndexTracker() : undefined,
			possibleAsyncArrow ? refTrailingCommaPos : undefined,
		);
		if (elt.type === "ArrayHole") {
			throw new Error("Expected element");
		}

		if (elt.type === "AmbiguousFlowTypeCastExpression") {
			if (possibleAsyncArrow) {
				// Definitely needs to be an arrow
				forceAsyncArrow = true;

				if (callArgs.length > 0) {
					funcParams = callArgs.slice();
					callArgs = [];
				}

				funcParams.push(elt);
			} else {
				parser.addDiagnostic({
					description: descriptions.JS_PARSER.CONFUSING_CALL_ARGUMENT,
					loc: elt.loc,
				});
			}
			continue;
		}

		if (funcParams.length > 0) {
			funcParams.push(elt);
		} else {
			callArgs.push(elt);
		}
	}

	if (forceAsyncArrow && !shouldParseAsyncArrow(parser)) {
		parser.addDiagnostic({
			description: descriptions.JS_PARSER.EXPECTED_ARROW_AFTER_ASYNC_TYPE_PARAMS,
		});
	}

	// we found an async arrow function so let's not allow any inner parens
	if (
		possibleAsyncArrow &&
		innerParenStart !== undefined &&
		shouldParseAsyncArrow(parser)
	) {
		parser.addDiagnostic({
			start: innerParenStart,
			description: descriptions.JS_PARSER.PARENTHESIZED_FUNCTION_PARAMS,
		});
	}

	return {
		args: callArgs,
		params: funcParams.length === 0 ? undefined : funcParams,
	};
}


export function shouldParseAsyncArrow(parser: JSParser): boolean {
	return (
		parser.match(tt.colon) ||
		(parser.match(tt.arrow) && !parser.canInsertSemicolon())
	);
}


export function parseAsyncArrowFromCallExpression(
	parser: JSParser,
	start: Position,
	args: Array<AnyExpression | SpreadElement | AmbiguousFlowTypeCastExpression>,
): ArrowFunctionExpression {
	let returnType;

	if (parser.match(tt.colon)) {
		const oldNoAnonFunctionType = parser.state.noAnonFunctionType;
		parser.state.noAnonFunctionType = true;
		returnType = parseTSTypeAnnotation(parser, true);
		parser.state.noAnonFunctionType = oldNoAnonFunctionType;
	}

	const oldYield = parser.state.yieldInPossibleArrowParameters;
	parser.state.yieldInPossibleArrowParameters = undefined;
	parser.expect(tt.arrow);
	const node = parseArrowExpression(
		parser,
		start,
		{
			assignmentList: args,
		},
		true,
	);
	parser.state.yieldInPossibleArrowParameters = oldYield;
	return {
		...node,
		head: {
			...node.head,
			returnType,
		},
	};
}


// Parse a no-call expression (like argument of `new` or `::` operators).
export function parseNoCallExpr(
	parser: JSParser,
	context: ExpressionContext,
): AnyExpression {
	const startPos = parser.state.startPos;
	return parseSubscripts(
		parser,
		parseExpressionAtom(parser, context),
		startPos,
		true,
	);
}


export function parseExpressionAtom(
	parser: JSParser,
	context: ExpressionContext,
	refShorthandDefaultPos?: IndexTracker,
): AnyExpression {
	// If a division operator appears in an expression position, the
	// tokenizer got confused, and we force it to read a regexp instead.
	if (parser.state.tokenType === tt.slash) {
		readRegexp(parser);
	}

	const canBeArrow =
		parser.state.potentialArrowAt === parser.state.startPos.index;

	// We don't want to match <! as it's the start of a HTML comment
	if (
		parser.isRelational("<") &&
		parser.input.charCodeAt(ob1Get0(parser.state.index)) !==
		charCodes.exclamationMark
	) {
		// In case we encounter an lt token here it will always be the start of
		// jsx as the lt sign is not allowed in places that expect an expression
		finishToken(parser, tt.jsxTagStart);
		return parseJSXElement(parser);
	}

	switch (parser.state.tokenType) {
		case tt.jsxTagStart:
			return parseJSXElement(parser);

		case tt._super:
			return parseSuper(parser);

		case tt._import:
			return parseImportOrMetaProperty(parser);

		case tt._this: {
			const start = parser.getPosition();
			parser.next();
			return parser.finishNode(start, {type: "ThisExpression"});
		}

		case tt.name: {
			const start = parser.getPosition();
			const containsEsc = parser.state.escapePosition !== undefined;
			const id = parseIdentifier(parser);

			if (
				!containsEsc &&
				id.name === "async" &&
				parser.match(tt._function) &&
				!parser.canInsertSemicolon()
			) {
				parser.next();
				return parseFunctionExpression(parser, start, true);
			}

			if (
				canBeArrow &&
				!containsEsc &&
				id.name === "async" &&
				parser.match(tt.name)
			) {
				const oldYield = parser.state.yieldInPossibleArrowParameters;
				parser.state.yieldInPossibleArrowParameters = undefined;
				const params = [parseReferenceIdentifier(parser)];
				parser.expect(tt.arrow);
				// let foo = bar => {};
				const node = parseArrowExpression(
					parser,
					start,
					{
						assignmentList: params,
					},
					true,
				);
				parser.state.yieldInPossibleArrowParameters = oldYield;
				return node;
			}

			if (canBeArrow && !parser.canInsertSemicolon() && parser.eat(tt.arrow)) {
				const oldYield = parser.state.yieldInPossibleArrowParameters;
				parser.state.yieldInPossibleArrowParameters = undefined;
				const node = parseArrowExpression(
					parser,
					start,
					{
						assignmentList: [toReferenceIdentifier(parser, id)],
					},
				);
				parser.state.yieldInPossibleArrowParameters = oldYield;
				return node;
			}

			return toReferenceIdentifier(parser, id);
		}

		case tt._do:
			return parseDoExpression(parser);

		case tt.regexp:
			return parseRegExpLiteral(parser);

		case tt.num:
			return parseNumericLiteral(parser);

		case tt.bigint:
			return parseBigIntLiteral(parser);

		case tt.string:
			return parseStringLiteral(parser);

		case tt._null:
			return parseNullLiteral(parser);

		case tt._true:
		case tt._false:
			return parseBooleanLiteral(parser);

		case tt.parenL:
			return parseParenAndDistinguishExpression(parser, context, canBeArrow);

		case tt.bracketL:
			return parseArrayExpression(parser, refShorthandDefaultPos);

		case tt.braceL:
			return parseObjectExpression(parser, refShorthandDefaultPos);

		case tt._function:
			return parseFunctionExpressionOrMetaProperty(parser);

		case tt._class: {
			const start = parser.getPosition();
			return parseClassExpression(parser, start);
		}

		case tt._new:
			return parseNew(parser);

		case tt.backQuote:
			return parseTemplate(parser, false);

		default: {
			const start = parser.getPosition();
			parser.addDiagnostic({
				description: descriptions.JS_PARSER.UNKNOWN_EXPRESSION_ATOM_START(context),
			});
			parser.next();
			return toReferenceIdentifier(
				parser,
				parser.createUnknownIdentifier(context, start),
			);
		}
	}
}


export function parseBooleanLiteral(parser: JSParser): BooleanLiteral {
	const start = parser.getPosition();
	const value = parser.match(tt._true);
	parser.next();
	return parser.finishNode(
		start,
		{
			type: "BooleanLiteral",
			value,
		},
	);
}


export function parseMaybePrivateName(
	parser: JSParser,
): PrivateName | Identifier {
	const isPrivate = parser.match(tt.hash);

	if (isPrivate) {
		const start = parser.getPosition();
		parser.next();
		parser.assertNoSpace(descriptions.JS_PARSER.SPACE_BETWEEN_PRIVATE_HASH);
		const id = parseIdentifier(parser, true);
		return parser.finishNode(
			start,
			{
				type: "PrivateName",
				id,
			},
		);
	} else {
		return parseIdentifier(parser, true);
	}
}