import path from 'node:path'
import { describe, expect, test } from 'vitest'
import type { InternalModuleFormat } from 'rolldown'
import MagicString from 'magic-string'
import { resolveConfig } from '../../config'
import type { InlineConfig } from '../../config'
import {
  convertTargets,
  createCSSResolvers,
  cssPlugin,
  cssUrlRE,
  getEmptyChunkReplacer,
  hoistAtRules,
  injectInlinedCSS,
  preprocessCSS,
  resolveLibCssFilename,
} from '../../plugins/css'
import { PartialEnvironment } from '../../baseEnvironment'
import { normalizePath } from '../../utils'

const dirname = import.meta.dirname

describe('search css url function', () => {
  test('some spaces before it', () => {
    expect(
      cssUrlRE.test("list-style-image: url('../images/bullet.jpg');"),
    ).toBe(true)
  })

  test('no space after colon', () => {
    expect(cssUrlRE.test("list-style-image:url('../images/bullet.jpg');")).toBe(
      true,
    )
  })

  test('at the beginning of line', () => {
    expect(cssUrlRE.test("url('../images/bullet.jpg');")).toBe(true)
  })

  test('as suffix of a function name', () => {
    expect(
      cssUrlRE.test(`@function svg-url($string) {
      @return "";
    }`),
    ).toBe(false)
  })

  test('after parenthesis', () => {
    expect(
      cssUrlRE.test(
        'mask-image: image(url(mask.png), skyblue, linear-gradient(rgba(0, 0, 0, 1.0), transparent));',
      ),
    ).toBe(true)
  })

  test('after comma', () => {
    expect(
      cssUrlRE.test(
        'mask-image: image(skyblue,url(mask.png), linear-gradient(rgba(0, 0, 0, 1.0), transparent));',
      ),
    ).toBe(true)
  })

  test('should capture the full url with escaped parentheses', () => {
    const css = 'background-image: url(public/awkward-name\\)2.png);'
    const match = cssUrlRE.exec(css)
    expect(match?.[1].trim()).toBe('public/awkward-name\\)2.png')
  })
})

describe('css modules', () => {
  test('css module compose/from path resolutions', async () => {
    const { transform } = await createCssPluginTransform({
      configFile: false,
      resolve: {
        alias: [
          {
            find: '@',
            replacement: path.join(
              import.meta.dirname,
              './fixtures/css-module-compose',
            ),
          },
        ],
      },
    })

    const result = await transform(
      `\
.foo {
position: fixed;
composes: bar from '@/css/bar.module.css';
}`,
      '/css/foo.module.css',
    )

    expect(result.code).toMatchInlineSnapshot(
      `
      "._bar_1b4ow_1 {
        display: block;
        background: #f0f;
      }
      ._foo_86148_1 {
      position: fixed;
      }"
    `,
    )
  })

  test('custom generateScopedName', async () => {
    const { transform } = await createCssPluginTransform({
      configFile: false,
      css: {
        modules: {
          generateScopedName: 'custom__[hash:base64:5]',
        },
      },
    })
    const css = `\
.foo {
  color: red;
}`
    const result1 = await transform(css, '/foo.module.css') // server
    const result2 = await transform(css, '/foo.module.css?direct') // client
    expect(result1.code).toBe(result2.code)
  })

  test('custom generateScopedName with lightningcss', async () => {
    const { transform } = await createCssPluginTransform({
      configFile: false,
      css: {
        modules: {
          generateScopedName: 'custom__[hash:base64:5]',
        },
        transformer: 'lightningcss',
      },
    })
    const css = `\
.foo {
  color: red;
}`
    const result1 = await transform(css, '/foo.module.css') // server
    const result2 = await transform(css, '/foo.module.css?direct') // client
    expect(result1.code).toBe(result2.code)
  })
})

describe('hoist @ rules', () => {
  test('hoist @import', async () => {
    const css = `.foo{color:red;}@import "bla";`
    const result = await hoistAtRules(css)
    expect(result).toBe(`@import "bla";.foo{color:red;}`)
  })

  test('hoist @import url with semicolon', async () => {
    const css = `.foo{color:red;}@import url("bla;bla");`
    const result = await hoistAtRules(css)
    expect(result).toBe(`@import url("bla;bla");.foo{color:red;}`)
  })

  test('hoist @import url data with semicolon', async () => {
    const css = `.foo{color:red;}@import url(data:image/png;base64,iRxVB0);`
    const result = await hoistAtRules(css)
    expect(result).toBe(
      `@import url(data:image/png;base64,iRxVB0);.foo{color:red;}`,
    )
  })

  test('hoist @import with semicolon in quotes', async () => {
    const css = `.foo{color:red;}@import "bla;bar";`
    const result = await hoistAtRules(css)
    expect(result).toBe(`@import "bla;bar";.foo{color:red;}`)
  })

  test('hoist @charset', async () => {
    const css = `.foo{color:red;}@charset "utf-8";`
    const result = await hoistAtRules(css)
    expect(result).toBe(`@charset "utf-8";.foo{color:red;}`)
  })

  test('hoist one @charset only', async () => {
    const css = `.foo{color:red;}@charset "utf-8";@charset "utf-8";`
    const result = await hoistAtRules(css)
    expect(result).toBe(`@charset "utf-8";.foo{color:red;}`)
  })

  test('hoist @import and @charset', async () => {
    const css = `.foo{color:red;}@import "bla";@charset "utf-8";.bar{color:green;}@import "baz";`
    const result = await hoistAtRules(css)
    expect(result).toBe(
      `@charset "utf-8";@import "bla";@import "baz";.foo{color:red;}.bar{color:green;}`,
    )
  })

  test('dont hoist @import in comments', async () => {
    const css = `.foo{color:red;}/* @import "bla"; */@import "bar";`
    const result = await hoistAtRules(css)
    expect(result).toBe(`@import "bar";.foo{color:red;}/* @import "bla"; */`)
  })

  test('dont hoist @charset in comments', async () => {
    const css = `.foo{color:red;}/* @charset "utf-8"; */@charset "utf-8";`
    const result = await hoistAtRules(css)
    expect(result).toBe(
      `@charset "utf-8";.foo{color:red;}/* @charset "utf-8"; */`,
    )
  })

  test('dont hoist @import and @charset in comments', async () => {
    const css = `
.foo{color:red;}
/*
  @import "bla";
*/
@charset "utf-8";
/*
  @charset "utf-8";
  @import "bar";
*/
@import "baz";`
    const result = await hoistAtRules(css)
    expect(result).toMatchInlineSnapshot(`
      "@charset "utf-8";@import "baz";
      .foo{color:red;}
      /*
        @import "bla";
      */

      /*
        @charset "utf-8";
        @import "bar";
      */
      "
    `)
  })
})

async function createCssPluginTransform(inlineConfig: InlineConfig = {}) {
  const config = await resolveConfig(inlineConfig, 'serve')
  const environment = new PartialEnvironment('client', config)

  const { transform, buildStart } = cssPlugin(config)

  // @ts-expect-error buildStart is function
  await buildStart.call({})

  return {
    async transform(code: string, id: string) {
      // @ts-expect-error transform.handler is function
      return await transform.handler.call(
        {
          addWatchFile() {
            return
          },
          environment,
        },
        code,
        id,
      )
    },
  }
}

describe('convertTargets', () => {
  test('basic cases', () => {
    expect(convertTargets('es2018')).toStrictEqual({
      chrome: 4128768,
      edge: 5177344,
      firefox: 3801088,
      safari: 786432,
      ios_saf: 786432,
      opera: 3276800,
    })
    expect(convertTargets(['safari13.1', 'ios13', 'node14'])).toStrictEqual({
      ios_saf: 851968,
      safari: 852224,
    })
  })

  test('supports es6 as an alias of es2015', () => {
    expect(convertTargets('es6')).toStrictEqual(convertTargets('es2015'))
  })
})

describe('getEmptyChunkReplacer', () => {
  test('replaces import call', () => {
    const code = `\
import "some-module";
import "pure_css_chunk.js";
import "other-module";`

    const replacer = getEmptyChunkReplacer(['pure_css_chunk.js'], 'es')
    const replaced = replacer(code)
    expect(replaced.length).toBe(code.length)
    expect(replaced).toMatchInlineSnapshot(`
      "import "some-module";
      /* empty css             */
      import "other-module";"
    `)
  })

  test('replaces import call without new lines', () => {
    const code = `import "some-module";import "pure_css_chunk.js";import "other-module";`

    const replacer = getEmptyChunkReplacer(['pure_css_chunk.js'], 'es')
    const replaced = replacer(code)
    expect(replaced.length).toBe(code.length)
    expect(replaced).toMatchInlineSnapshot(
      `"import "some-module";/* empty css             */import "other-module";"`,
    )
  })

  test('replaces require call', () => {
    const code = `\
require("some-module");
require("pure_css_chunk.js");
require("other-module");`

    const replacer = getEmptyChunkReplacer(['pure_css_chunk.js'], 'cjs')
    const replaced = replacer(code)
    expect(replaced.length).toBe(code.length)
    expect(replaced).toMatchInlineSnapshot(`
      "require("some-module");
      ;/* empty css              */
      require("other-module");"
    `)
  })

  test('replaces require call in minified code without new lines', () => {
    const code = `require("some-module");require("pure_css_chunk.js");require("other-module");`

    const replacer = getEmptyChunkReplacer(['pure_css_chunk.js'], 'cjs')
    const replaced = replacer(code)
    expect(replaced.length).toBe(code.length)
    expect(replaced).toMatchInlineSnapshot(
      `"require("some-module");;/* empty css              */require("other-module");"`,
    )
  })

  test('replaces require call in minified code that uses comma operator', () => {
    const code =
      'require("some-module"),require("pure_css_chunk.js"),require("other-module");'

    const replacer = getEmptyChunkReplacer(['pure_css_chunk.js'], 'cjs')
    const newCode = replacer(code)
    expect(newCode.length).toBe(code.length)
    expect(newCode).toMatchInlineSnapshot(
      `"require("some-module"),/* empty css               */require("other-module");"`,
    )
    // So there should be no pure css chunk anymore
    expect(newCode).not.toContain('pure_css_chunk.js')
  })

  test('replaces require call in minified code that uses comma operator 2', () => {
    const code = 'require("pure_css_chunk.js"),console.log();'
    const replacer = getEmptyChunkReplacer(['pure_css_chunk.js'], 'cjs')
    const newCode = replacer(code)
    expect(newCode.length).toBe(code.length)
    expect(newCode).toMatchInlineSnapshot(
      `"/* empty css               */console.log();"`,
    )
    expect(newCode).not.toContain('pure_css_chunk.js')
  })

  test('replaces require call in minified code that uses comma operator followed by assignment', () => {
    const code =
      'require("some-module"),require("pure_css_chunk.js");const v=require("other-module");'

    const replacer = getEmptyChunkReplacer(['pure_css_chunk.js'], 'cjs')
    const newCode = replacer(code)
    expect(newCode.length).toBe(code.length)
    expect(newCode).toMatchInlineSnapshot(
      `"require("some-module");/* empty css               */const v=require("other-module");"`,
    )
    expect(newCode).not.toContain('pure_css_chunk.js')
  })
})

describe('preprocessCSS', () => {
  test('works', async () => {
    const resolvedConfig = await resolveConfig({ configFile: false }, 'serve')
    const result = await preprocessCSS(
      `\
.foo {
  color:red;
  background: url(./foo.png);
}`,
      'foo.css',
      resolvedConfig,
    )
    expect(result.code).toMatchInlineSnapshot(`
      ".foo {
        color:red;
        background: url(./foo.png);
      }"
    `)
  })

  test('works with lightningcss', async () => {
    const resolvedConfig = await resolveConfig(
      {
        configFile: false,
        css: { transformer: 'lightningcss' },
      },
      'serve',
    )
    const result = await preprocessCSS(
      `\
.foo {
  color: red;
  background: url(./foo.png);
}`,
      'foo.css',
      resolvedConfig,
    )
    expect(result.code).toMatchInlineSnapshot(`
      ".foo {
        color: red;
        background: url("./foo.png");
      }
      "
    `)
  })

  test('lightningcss preserves $ in external @import url', async () => {
    const resolvedConfig = await resolveConfig(
      {
        configFile: false,
        css: { transformer: 'lightningcss' },
      },
      'serve',
    )
    const result = await preprocessCSS(
      `@import 'http://example.com/a.css?x=$&y';`,
      'foo.css',
      resolvedConfig,
    )
    expect(result.code).toContain('http://example.com/a.css?x=$&y')
  })
})

// Sass does not consult the `main` field; see
// https://sass-lang.com/documentation/js-api/classes/nodepackageimporter/
describe('sass package resolution', () => {
  const fixtureRoot = path.resolve(dirname, 'fixtures/sass-package-resolution')
  const importer = path.resolve(fixtureRoot, 'entry.scss')

  async function getSassResolver() {
    const config = await resolveConfig(
      { configFile: false, root: fixtureRoot },
      'serve',
    )
    const environment = new PartialEnvironment('client', config)
    const resolvers = createCSSResolvers(config)
    return (id: string) => resolvers.sass(environment, id, importer)
  }

  test('resolves to index.scss at package root, ignoring main field', async () => {
    const resolve = await getSassResolver()
    const resolved = await resolve('sass-pkg-with-index')
    expect(resolved).toBe(
      normalizePath(
        path.resolve(
          fixtureRoot,
          'node_modules/sass-pkg-with-index/index.scss',
        ),
      ),
    )
  })
})

describe('resolveLibCssFilename', () => {
  test('use name from package.json', () => {
    const filename = resolveLibCssFilename(
      {
        entry: 'mylib.js',
      },
      path.resolve(dirname, '../packages/name'),
    )
    expect(filename).toBe('mylib.css')
  })

  test('set cssFileName', () => {
    const filename = resolveLibCssFilename(
      {
        entry: 'mylib.js',
        cssFileName: 'style',
      },
      path.resolve(dirname, '../packages/noname'),
    )
    expect(filename).toBe('style.css')
  })

  test('use fileName if set', () => {
    const filename = resolveLibCssFilename(
      {
        entry: 'mylib.js',
        fileName: 'custom-name',
      },
      path.resolve(dirname, '../packages/name'),
    )
    expect(filename).toBe('custom-name.css')
  })

  test('use fileName if set and has array entry', () => {
    const filename = resolveLibCssFilename(
      {
        entry: ['mylib.js', 'mylib2.js'],
        fileName: 'custom-name',
      },
      path.resolve(dirname, '../packages/name'),
    )
    expect(filename).toBe('custom-name.css')
  })
})

describe('injectInlinedCSS', () => {
  function getInlinedCSSInjectedCode(
    code: string,
    format: InternalModuleFormat,
  ) {
    const s = new MagicString(code)
    injectInlinedCSS(
      s,
      {
        error(e) {
          throw e
        },
      },
      code,
      format,
      'injectCSS();',
    )
    return s.toString()
  }

  test('should inject CSS for iife without exports from esm', async () => {
    const result = getInlinedCSSInjectedCode(
      `(function() {

"use strict";

//#region src/index.js
(async () => {
	await new Promise((resolve) => setTimeout(resolve, 1e3));
	console.log("foo");
})();

//#endregion
})();`,
      'iife',
    )
    expect(result).toMatchInlineSnapshot(`
      "(function() {

      "use strict";injectCSS();

      //#region src/index.js
      (async () => {
      	await new Promise((resolve) => setTimeout(resolve, 1e3));
      	console.log("foo");
      })();

      //#endregion
      })();"
    `)
  })

  test('should inject helper for iife without exports from cjs', async () => {
    const result = getInlinedCSSInjectedCode(
      `(function() {

//#region src/index.js
(async () => {
	await new Promise((resolve) => setTimeout(resolve, 1e3));
	console.log("foo");
})();

//#endregion
})();`,
      'iife',
    )
    expect(result).toMatchInlineSnapshot(`
      "(function() {injectCSS();

      //#region src/index.js
      (async () => {
      	await new Promise((resolve) => setTimeout(resolve, 1e3));
      	console.log("foo");
      })();

      //#endregion
      })();"
    `)
  })

  test('should inject helper for iife with exports', async () => {
    const result = getInlinedCSSInjectedCode(
      `var lib = (function(exports) {

//#region entry.js
(async () => {
	await new Promise((resolve) => setTimeout(resolve, 1e3));
	console.log("foo");
})();
const foo = "foo";

//#endregion
exports.foo = foo;
return exports;
})({});`,
      'iife',
    )
    expect(result).toMatchInlineSnapshot(`
      "var lib = (function(exports) {injectCSS();

      //#region entry.js
      (async () => {
      	await new Promise((resolve) => setTimeout(resolve, 1e3));
      	console.log("foo");
      })();
      const foo = "foo";

      //#endregion
      exports.foo = foo;
      return exports;
      })({});"
    `)
  })

  test('should inject helper for iife with nested name', async () => {
    const result = getInlinedCSSInjectedCode(
      `this.nested = this.nested || {};
this.nested.lib = (function(exports) {

Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });

//#region a.ts
	const foo = "foo";

//#endregion
exports.foo = foo;
return exports;
})({});`,
      'iife',
    )
    expect(result).toMatchInlineSnapshot(`
      "this.nested = this.nested || {};
      this.nested.lib = (function(exports) {injectCSS();

      Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });

      //#region a.ts
      	const foo = "foo";

      //#endregion
      exports.foo = foo;
      return exports;
      })({});"
    `)
  })

  test('should inject helper for umd without exports', async () => {
    const result = getInlinedCSSInjectedCode(
      `(function(factory) {

  typeof define === 'function' && define.amd ? define([], factory) :
  factory();
})(function() {

//#region entry.js
(async () => {
	await new Promise((resolve) => setTimeout(resolve, 1e3));
	console.log("foo");
})();

//#endregion
});`,
      'umd',
    )
    expect(result).toMatchInlineSnapshot(`
      "(function(factory) {

        typeof define === 'function' && define.amd ? define([], factory) :
        factory();
      })(function() {injectCSS();

      //#region entry.js
      (async () => {
      	await new Promise((resolve) => setTimeout(resolve, 1e3));
      	console.log("foo");
      })();

      //#endregion
      });"
    `)
  })

  test('should inject helper for umd with exports', async () => {
    const result = getInlinedCSSInjectedCode(
      `(function(global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ?  factory(exports) :
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.lib = {})));
})(this, function(exports) {

//#region entry.js
(async () => {
	await new Promise((resolve) => setTimeout(resolve, 1e3));
	console.log("foo");
})();
const foo = "foo";

//#endregion
exports.foo = foo;
});`,
      'umd',
    )
    expect(result).toMatchInlineSnapshot(`
      "(function(global, factory) {
        typeof exports === 'object' && typeof module !== 'undefined' ?  factory(exports) :
        typeof define === 'function' && define.amd ? define(['exports'], factory) :
        (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.lib = {})));
      })(this, function(exports) {injectCSS();

      //#region entry.js
      (async () => {
      	await new Promise((resolve) => setTimeout(resolve, 1e3));
      	console.log("foo");
      })();
      const foo = "foo";

      //#endregion
      exports.foo = foo;
      });"
    `)
  })

  test('should inject helper for umd with only default export', async () => {
    const result = getInlinedCSSInjectedCode(
      `(function(global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports =  factory() :
  typeof define === 'function' && define.amd ? define([], factory) :
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, (global.lib = factory()));
})(this, function() {

//#region entry.js
(async () => {
	await new Promise((resolve) => setTimeout(resolve, 1e3));
	console.log("foo");
})();
var index_default = "foo";

//#endregion
return index_default;
});`,
      'umd',
    )
    expect(result).toMatchInlineSnapshot(`
      "(function(global, factory) {
        typeof exports === 'object' && typeof module !== 'undefined' ? module.exports =  factory() :
        typeof define === 'function' && define.amd ? define([], factory) :
        (global = typeof globalThis !== 'undefined' ? globalThis : global || self, (global.lib = factory()));
      })(this, function() {injectCSS();

      //#region entry.js
      (async () => {
      	await new Promise((resolve) => setTimeout(resolve, 1e3));
      	console.log("foo");
      })();
      var index_default = "foo";

      //#endregion
      return index_default;
      });"
    `)
  })

  test('should inject helper for umd with nested name', async () => {
    const result = getInlinedCSSInjectedCode(
      `(function(global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ?  factory(exports) :
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.nested = global.nested || {},global.nested.lib = {})));
})(this, function(exports) {
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });

//#region a.ts
	const foo = "foo";

//#endregion
exports.foo = foo;
});`,
      'umd',
    )
    expect(result).toMatchInlineSnapshot(`
      "(function(global, factory) {
        typeof exports === 'object' && typeof module !== 'undefined' ?  factory(exports) :
        typeof define === 'function' && define.amd ? define(['exports'], factory) :
        (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.nested = global.nested || {},global.nested.lib = {})));
      })(this, function(exports) {injectCSS();
      Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });

      //#region a.ts
      	const foo = "foo";

      //#endregion
      exports.foo = foo;
      });"
    `)
  })

  test('should inject multiple helpers', async () => {
    const result = getInlinedCSSInjectedCode(
      `(function() {

"use strict";

//#region src/index.js
(async () => {
	await new Promise((resolve) => setTimeout(resolve, 1e3));
	console.log("foo", { ..."foo" });
})();

//#endregion
})();`,
      'iife',
    )
    expect(result).toMatchInlineSnapshot(`
      "(function() {

      "use strict";injectCSS();

      //#region src/index.js
      (async () => {
      	await new Promise((resolve) => setTimeout(resolve, 1e3));
      	console.log("foo", { ..."foo" });
      })();

      //#endregion
      })();"
    `)
  })

  test('should inject CSS after the shebang line for es', async () => {
    const result = getInlinedCSSInjectedCode(
      `#!/usr/bin/env node
console.log("foo");`,
      'es',
    )
    expect(result).toMatchInlineSnapshot(`
      "#!/usr/bin/env node
      injectCSS();console.log("foo");"
    `)
  })

  test('should inject CSS at the start for es without shebang', async () => {
    const result = getInlinedCSSInjectedCode(`console.log("foo");`, 'es')
    expect(result).toMatchInlineSnapshot(`"injectCSS();console.log("foo");"`)
  })

  test('should inject CSS for es shebang without trailing newline', async () => {
    const result = getInlinedCSSInjectedCode(`#!/usr/bin/env node`, 'es')
    expect(result).toMatchInlineSnapshot(`
      "#!/usr/bin/env node
      injectCSS();"
    `)
  })
})


import requireExternalCjs from '@vitejs/test-require-external-cjs'

export async function render(url) {
  let html = ''

  html += `\n<p class="require-external-cjs">message from require-external-cjs: ${requireExternalCjs}</p>`

  return html + '\n'
}


# <small>nlohmann::basic_json::</small>parse_event_t

```cpp
enum class parse_event_t : std::uint8_t {
    object_start,
    object_end,
    array_start,
    array_end,
    key,
    value
};
```

The parser callback distinguishes the following events:

- `object_start`: the parser read `{` and started to process a JSON object
- `key`: the parser read a key of a value in an object
- `object_end`: the parser read `}` and finished processing a JSON object
- `array_start`: the parser read `[` and started to process a JSON array
- `array_end`: the parser read `]` and finished processing a JSON array
- `value`: the parser finished reading a JSON value

## Examples

![Example when certain parse events are triggered](../../images/callback_events.png)

## See also

- [parser_callback_t](parser_callback_t.md) callback function type for the parser
- [parse](parse.md) deserialize from a compatible input

## Version history

- Added in version 1.0.0.


import { defineConfig } from 'vite'
import baseConfig from './vite.config.js'

export default defineConfig({
  ...baseConfig,
  build: {
    ...baseConfig.build,
    minify: false,
    outDir: 'dist/nominify',
  },
  plugins: [],
  cacheDir: 'node_modules/.vite-nominify',
})


import fs from 'node:fs'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import { describe, expect, test } from 'vitest'
import {
  isBuild,
  isBundled,
  isBundledDev,
  isServe,
  isWindows,
  page,
  testDir,
  viteTestUrl,
} from '~utils'

test('bom import', async () => {
  expect(await page.textContent('.utf8-bom')).toMatch('[success]')
})

test('deep import', async () => {
  expect(await page.textContent('.deep-import')).toMatch('[2,4]')
})

test('exports and a nested package scope with a different type', async () => {
  expect(await page.textContent('.exports-and-nested-scope')).toMatch(
    '[success]',
  )
})

test('entry with exports field', async () => {
  expect(await page.textContent('.exports-entry')).toMatch('[success]')
})

test('deep import with exports field', async () => {
  expect(await page.textContent('.exports-deep')).toMatch('[success]')
})

test('deep import with query with exports field', async () => {
  // since it is imported with `?url` it should return a URL
  expect(await page.textContent('.exports-deep-query')).toMatch(
    isBundled ? /base64/ : '/exports-path/deep.json',
  )
})

test('deep import with exports field + exposed dir', async () => {
  expect(await page.textContent('.exports-deep-exposed-dir')).toMatch(
    '[success]',
  )
})

test('deep import with exports field + mapped dir', async () => {
  expect(await page.textContent('.exports-deep-mapped-dir')).toMatch(
    '[success]',
  )
})

test('exports read from the root package.json', async () => {
  expect(await page.textContent('.exports-from-root')).toMatch('[success]')
})

// this is how Svelte 3 is packaged
test('deep import with exports and legacy fallback', async () => {
  expect(await page.textContent('.exports-legacy-fallback')).toMatch(
    '[success]',
  )
})

test('Respect exports field env key priority', async () => {
  expect(await page.textContent('.exports-env')).toMatch('[success]')
})

test('Respect production/development conditionals', async () => {
  expect(await page.textContent('.exports-env')).toMatch(
    isBuild ? `browser.prod.mjs` : `browser.mjs`,
  )
})

test('Respect exports to take precedence over mainFields', async () => {
  expect(await page.textContent('.exports-with-module')).toMatch('[success]')
})

test('import and require resolve using module condition', async () => {
  expect(await page.textContent('.exports-with-module-condition')).toMatch(
    '[success]',
  )
  expect(
    await page.textContent('.exports-with-module-condition-required'),
  ).toMatch('[success]')
})

test('implicit dir/index.js', async () => {
  expect(await page.textContent('.index')).toMatch('[success]')
})

test('implicit dir/index.js vs explicit file', async () => {
  expect(await page.textContent('.dir-vs-file')).toMatch('[success]')
})

test('nested extension', async () => {
  expect(await page.textContent('.nested-extension')).toMatch(
    '[success] file.json.js',
  )
})

test('exact extension vs. duplicated (.js.js)', async () => {
  expect(await page.textContent('.exact-extension')).toMatch('[success]')
})

test("don't add extension to directory name (./dir-with-ext.js/index.js)", async () => {
  expect(await page.textContent('.dir-with-ext')).toMatch('[success]')
})

test('a ts module can import another ts module using its corresponding js file name', async () => {
  expect(await page.textContent('.ts-extension')).toMatch('[success]')
})

test('a js module can import another ts module using its corresponding js file name', async () => {
  expect(await page.textContent('.js-ts-extension')).toMatch('[success]')
})

test('filename with dot', async () => {
  expect(await page.textContent('.dot')).toMatch('[success]')
})

test.runIf(isWindows)('drive-relative path', async () => {
  expect(await page.textContent('.drive-relative')).toMatch('[success]')
})

test('absolute path', async () => {
  expect(await page.textContent('.absolute')).toMatch('[success]')
})

test('file url', async () => {
  expect(await page.textContent('.file-url')).toMatch('[success]')
})

test('browser field', async () => {
  expect(await page.textContent('.browser')).toMatch('[success]')
})

// accessing a property of a `browser: false` module must not throw (#22022)
test('access property of browser:false module', async () => {
  expect(await page.textContent('.browser-field-false-access')).toMatch(
    '[success]',
  )
})

test('Resolve browser field even if module field exists', async () => {
  expect(await page.textContent('.browser-module1')).toMatch('[success]')
})

test('css entry', async () => {
  expect(await page.textContent('.css')).toMatch('[success]')
})

test('monorepo linked dep', async () => {
  expect(await page.textContent('.monorepo')).toMatch('[success]')
})

test('plugin resolved virtual file', async () => {
  expect(await page.textContent('.virtual')).toMatch('[success]')
})

test('plugin resolved virtual file that has import', async () => {
  expect(await page.textContent('.virtual-has-import')).toMatch('[success]')
})

test('plugin resolved custom virtual file', async () => {
  expect(await page.textContent('.custom-virtual')).toMatch('[success]')
})

test('virtual file with URL scheme should not be rewritten (#20803)', async () => {
  expect(await page.textContent('.virtual-url-scheme')).toMatch('[success]')
})

test('resolve inline package', async () => {
  expect(await page.textContent('.inline-pkg')).toMatch('[success]')
})

test('resolve.extensions', async () => {
  expect(await page.textContent('.custom-ext')).toMatch('[success]')
})

test('resolve.mainFields', async () => {
  expect(await page.textContent('.custom-main-fields')).toMatch('[success]')
})

test('resolve.mainFields.browser-first', async () => {
  expect(await page.textContent('.custom-browser-main-field')).toBe(
    'resolved browser field',
  )
})

test('resolve.conditions', async () => {
  expect(await page.textContent('.custom-condition')).toMatch('[success]')
})

test('resolve package that contains # in path', async () => {
  expect(await page.textContent('.path-contains-sharp-symbol')).toMatch(
    '[success] ok ok ok',
  )
})

test('Resolving top level with imports field', async () => {
  expect(await page.textContent('.imports-top-level')).toMatch('[success]')
})

test('Resolving same level with imports field', async () => {
  expect(await page.textContent('.imports-same-level')).toMatch(
    await page.textContent('.imports-top-level'),
  )
})

test('Resolving nested path with imports field', async () => {
  expect(await page.textContent('.imports-nested')).toMatch('[success]')
})

test('Resolving star with imports filed', async () => {
  expect(await page.textContent('.imports-star')).toMatch('[success]')
})

test('Resolving slash with imports filed', async () => {
  expect(await page.textContent('.imports-slash')).toMatch('[success]')
})

test('Resolving from other package with imports field', async () => {
  expect(await page.textContent('.imports-pkg-slash')).toMatch('[success]')
})

test('Resolving with query with imports field', async () => {
  // since it is imported with `?url` it should return a URL
  expect(await page.textContent('.imports-query')).toMatch(
    isBundled ? /base64/ : '/imports-path/query.json',
  )
})

test('Resolving dot-prefixed directory with imports field', async () => {
  expect(await page.textContent('.imports-dot-prefixed')).toMatch('[success]')
})

test('Resolving #/ root alias pattern with imports field', async () => {
  // This tests the new Node.js behavior from https://github.com/nodejs/node/pull/60864
  // which allows "#/*" patterns (slash immediately after #) in package.json imports
  expect(await page.textContent('.imports-root-slash')).toMatch('[success]')
})

test("Resolve doesn't interrupt page request with trailing query and .css", async () => {
  await page.goto(viteTestUrl + '/?test.css')
  expect(await page.locator('vite-error-overlay').count()).toBe(0)
  expect(await page.textContent('h1')).toBe('Resolve')
})

test('resolve non-normalized absolute path', async () => {
  expect(await page.textContent('.non-normalized')).toMatch('[success]')
})

test.runIf(!isWindows)(
  "Resolve doesn't interrupt page request that clashes with local project package.json",
  async () => {
    // Sometimes request path may point to a different project's package.json, but for testing
    // we point to Vite's own monorepo which always exists, and the package.json is not a library
    const pathToViteMonorepoRoot = new URL('../../../', import.meta.url)
    const urlPath = fileURLToPath(pathToViteMonorepoRoot).replace(/\/$/, '')
    await page.goto(viteTestUrl + urlPath)
    expect(await page.locator('vite-error-overlay').count()).toBe(0)
    expect(await page.textContent('h1')).toBe('Resolve')
  },
)

test.runIf(isBuild)('public dir is not copied', async () => {
  expect(
    fs.existsSync(path.resolve(testDir, 'dist/should-not-be-copied')),
  ).toBe(false)
})

test('import utf8-bom package', async () => {
  expect(await page.textContent('.utf8-bom-package')).toMatch('[success]')
})

test.runIf(isBuild)('sideEffects field glob pattern is respected', async () => {
  const sideEffectValues = await page.evaluate(
    () => (window as any).__SIDE_EFFECT,
  )
  expect(sideEffectValues).toStrictEqual(['success'])
})

// bundled dev: these HEAD requests ask for source files (/absolute.js,
// /style.css). Those files are not in the bundle, and bundled dev serves
// only the bundle.
describe.runIf(isServe && !isBundledDev)('HEAD request handling', () => {
  test('HEAD request to JS file returns correct Content-Type', async () => {
    const response = await fetch(new URL('/absolute.js', viteTestUrl), {
      method: 'HEAD',
    })
    expect(response.headers.get('content-type')).toBe('text/javascript')
    expect(response.status).toBe(200)
    const text = await response.text()
    expect(text).toBe('')
  })

  test('HEAD request to CSS file returns correct Content-Type', async () => {
    const response = await fetch(new URL('/style.css', viteTestUrl), {
      method: 'HEAD',
      headers: {
        Accept: 'text/css',
      },
    })
    expect(response.headers.get('content-type')).toBe('text/css')
    expect(response.status).toBe(200)
  })
})


import { describe, expect, test } from 'vitest'
import { rolldown } from 'rolldown'
import { definePlugin } from '../../plugins/define'
import { resolveConfig } from '../../config'
import { PartialEnvironment } from '../../baseEnvironment'

async function createDefinePluginTransform(
  define: Record<string, any> = {},
  isSsrDev = false,
) {
  const ssr = isSsrDev
  const build = !isSsrDev
  const config = await resolveConfig(
    { configFile: false, define, environments: { ssr: {} } },
    build ? 'build' : 'serve',
  )
  const instance = definePlugin(config)
  const environment = new PartialEnvironment(ssr ? 'ssr' : 'client', config)

  return async (code: string) => {
    if (isSsrDev) {
      // @ts-expect-error transform.handler should exist
      const result = await instance.transform.handler.call(
        { environment },
        code,
        'foo.ts',
      )
      return result?.code || result
    } else {
      const nativeDefinePlugin = await (
        definePlugin(config) as any
      ).applyToEnvironment(environment)
      const bundler = await rolldown({
        input: 'entry.js',
        plugins: [
          {
            name: 'test',
            resolveId(id) {
              if (id === 'entry.js') {
                return '\0' + id
              }
            },
            load(id) {
              if (id === '\0entry.js') {
                return code
              }
            },
          },
          {
            name: 'native:define',
            options: nativeDefinePlugin.options.bind({ environment }),
          },
        ],
        experimental: {
          attachDebugInfo: 'none',
        },
      })
      return (await bundler.generate()).output[0].code
    }
  }
}

describe('definePlugin (SSR dev)', () => {
  const createJsDefinePluginTransform = (define: Record<string, any> = {}) =>
    createDefinePluginTransform(define, true)

  test('replaces custom define', async () => {
    const transform = await createJsDefinePluginTransform({
      __APP_VERSION__: JSON.stringify('1.0'),
    })
    expect(await transform('export const version = __APP_VERSION__ ;')).toBe(
      'export const version = "1.0";\n',
    )
    expect(await transform('export const version = __APP_VERSION__;')).toBe(
      'export const version = "1.0";\n',
    )
  })

  test('should not replace if not defined', async () => {
    const transform = await createJsDefinePluginTransform({
      __APP_VERSION__: JSON.stringify('1.0'),
    })
    expect(await transform('export const version = "1.0";')).toBe(undefined)
    expect(
      await transform('export const version = import.meta.SOMETHING'),
    ).toBe(undefined)
  })

  test('replace import.meta.env when it is a invalid json', async () => {
    const transform = await createJsDefinePluginTransform({
      'import.meta.env.LEGACY': '__VITE_IS_LEGACY__',
    })

    expect(
      await transform(
        'export const isLegacy = import.meta.env.LEGACY;\nimport.meta.env.UNDEFINED && console.log(import.meta.env.UNDEFINED);',
      ),
    ).toMatchInlineSnapshot(`
      "export const isLegacy = __VITE_IS_LEGACY__;
      import.meta.env.UNDEFINED && console.log(import.meta.env.UNDEFINED);
      "
    `)
  })
})

describe('native definePlugin', () => {
  test('replaces custom define', async () => {
    const transform = await createDefinePluginTransform({
      __APP_VERSION__: JSON.stringify('1.0'),
    })
    expect(await transform('export const version = __APP_VERSION__;')).toBe(
      'const version = "1.0";\nexport { version };\n',
    )
    expect(await transform('export const version = __APP_VERSION__ ;')).toBe(
      'const version = "1.0";\nexport { version };\n',
    )
  })

  test('should not replace if not defined', async () => {
    const transform = await createDefinePluginTransform({
      __APP_VERSION__: JSON.stringify('1.0'),
    })
    expect(await transform('export const version = "1.0";')).toBe(
      'const version = "1.0";\nexport { version };\n',
    )
    expect(
      await transform('export const version = import.meta.SOMETHING'),
    ).toBe('const version = import.meta.SOMETHING;\nexport { version };\n')
  })

  test('replaces import.meta.env.SSR with false', async () => {
    const transform = await createDefinePluginTransform()
    expect(await transform('export const isSSR = import.meta.env.SSR;')).toBe(
      'const isSSR = false;\nexport { isSSR };\n',
    )
  })

  test('preserve import.meta.hot with override', async () => {
    // assert that the default behavior is to replace import.meta.hot with undefined
    const transform = await createDefinePluginTransform()
    expect(await transform('export const hot = import.meta.hot;')).toBe(
      'const hot = void 0;\nexport { hot };\n',
    )
    // assert that we can specify a user define to preserve import.meta.hot
    const overrideTransform = await createDefinePluginTransform({
      'import.meta.hot': 'import.meta.hot',
    })
    expect(await overrideTransform('export const hot = import.meta.hot;')).toBe(
      'const hot = import.meta.hot;\nexport { hot };\n',
    )
  })

  test('replace import.meta.env.UNKNOWN with undefined', async () => {
    const transform = await createDefinePluginTransform()
    expect(await transform('export const foo = import.meta.env.UNKNOWN;')).toBe(
      'const foo = void 0;\nexport { foo };\n',
    )
  })

  test('leave import.meta.env["UNKNOWN"] to runtime', async () => {
    const transform = await createDefinePluginTransform()
    expect(
      await transform('export const foo = import.meta.env["UNKNOWN"];'),
    ).toMatch(/const foo = .*\["UNKNOWN"\];\nexport \{ foo \};\n/s)
  })

  test('preserve import.meta.env.UNKNOWN with override', async () => {
    const transform = await createDefinePluginTransform({
      'import.meta.env.UNKNOWN': 'import.meta.env.UNKNOWN',
    })
    expect(await transform('export const foo = import.meta.env.UNKNOWN;')).toBe(
      'const foo = import.meta.env.UNKNOWN;\nexport { foo };\n',
    )
  })

  test('replace import.meta.env when it is a invalid json', async () => {
    const transform = await createDefinePluginTransform({
      'import.meta.env.LEGACY': '__VITE_IS_LEGACY__',
    })

    expect(
      await transform(
        'export const isLegacy = import.meta.env.LEGACY;\nimport.meta.env.UNDEFINED && console.log(import.meta.env.UNDEFINED);',
      ),
    ).toMatchInlineSnapshot(
      `"const isLegacy = __VITE_IS_LEGACY__;\nexport { isLegacy };\n"`,
    )
  })

  test('replace bare import.meta.env', async () => {
    const transform = await createDefinePluginTransform()
    expect(await transform('export const env = import.meta.env;')).toMatch(
      /const env = .*;\nexport \{ env \};\n/s,
    )
  })
})


# Fuzz Testing

## Introduction

Fuzz testing produces pseudo-random / arbitrary data that is used to find
stability issues within a code base. While Rust provides a strong type system,
this does not guarantee that an object will convert properly from one struct
to another. It is the responsibility of the developer to ensure that a struct
is converted properly. Fuzz testing will generate input within the domain of
each property. This arbitrary data can then be used to convert from ObjectA
to ObjectB and then back. This type of testing will help catch bugs that the
type system is not able to see.

## Installation

This crate relies on the `cargo-fuzz` component. To install this component,
run the following from the `fuzz` directory:

```bash
cargo install cargo-fuzz
```

## Listing Targets

Once installed, fuzz targets can be listed by running the following command:

```bash
cargo fuzz list
```

This command will print out a list of all targets that can be tested.

## Running Fuzz Tests

To run a fuzz test, the target must be specified:

```bash
cargo fuzz run <target>
```

Note that the above will run the fuzz test indefinitely. Use the
`-max_total_time=<num seconds>` flag to specify how many seconds the test
should run for:

```bash
cargo fuzz run <target> -- -max_total_time=5
```

The above command will run the fuzz test for five seconds. If the test
completes without error it will show how many tests were run successfully.
The test will abort and return a non-zero error code if it is able to produce
an error. The arbitrary input will be displayed in the event of a failure.


import type { Config } from 'tailwindcss'

export default {
  content: [
    // Before editing this section, make sure no paths are matching with `/src/main.js`
    // See https://github.com/vitejs/vite/pull/6959 for more details
    import.meta.dirname + '/src/{components,views}/**/*.js',
    import.meta.dirname + '/src/main.js',
    import.meta.dirname + '/index.html',
  ],
  theme: {
    extend: {},
  },
  plugins: [],
} satisfies Config


#include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp>

using json = nlohmann::json;

int main()
{
    // create JSON value
    json j_flattened =
    {
        {"/answer/everything", 42},
        {"/happy", true},
        {"/list/0", 1},
        {"/list/1", 0},
        {"/list/2", 2},
        {"/name", "Niels"},
        {"/nothing", nullptr},
        {"/object/currency", "USD"},
        {"/object/value", 42.99},
        {"/pi", 3.141}
    };

    // call unflatten()
    std::cout << std::setw(4) << j_flattened.unflatten() << '\n';
}


# Iterators

## Overview

A `basic_json` value is a container and allows access via iterators. Depending on the value type, `basic_json` stores zero or more values.

As for other containers, `begin()` returns an iterator to the first value and `end()` returns an iterator to the value following the last value. The latter iterator is a placeholder and cannot be dereferenced. In case of null values, empty arrays, or empty objects, `begin()` will return `end()`.

![Illustration from cppreference.com](../images/range-begin-end.svg)

### Iteration order for objects

When iterating over objects, values are ordered with respect to the `object_comparator_t` type which defaults to `std::less`. See the [types documentation](types/index.md#key-order) for more information.

??? example

    ```cpp
    // create JSON object {"one": 1, "two": 2, "three": 3}
    json j;
    j["one"] = 1;
    j["two"] = 2;
    j["three"] = 3;

    for (auto it = j.begin(); it != j.end(); ++it)
    {
        std::cout << *it << std::endl;
    }
    ```

    Output:

    ```json
    1
    3
    2
    ```

    The reason for the order is the lexicographic ordering of the object keys "one", "three", "two".

### Access object keys during iteration

The JSON iterators have two member functions, `key()` and `value()` to access the object key and stored value, respectively. When calling `key()` on a non-object iterator, an [invalid_iterator.207](../home/exceptions.md#jsonexceptioninvalid_iterator207) exception is thrown.

??? example

    ```cpp
    // create JSON object {"one": 1, "two": 2, "three": 3}
    json j;
    j["one"] = 1;
    j["two"] = 2;
    j["three"] = 3;

    for (auto it = j.begin(); it != j.end(); ++it)
    {
        std::cout << it.key() << " : " << it.value() << std::endl;
    }
    ```

    Output:

    ```json
    one : 1
    three : 3
    two : 2
    ```

### Range-based for loops

C++11 allows using range-based for loops to iterate over a container.

```cpp
for (auto it : j_object)
{
    // "it" is of type json::reference and has no key() member
    std::cout << "value: " << it << '\n';
}
```

For this reason, the `items()` function allows accessing `iterator::key()` and `iterator::value()` during range-based for loops. In these loops, a reference to the JSON values is returned, so there is no access to the underlying iterator.

```cpp
for (auto& el : j_object.items())
{
    std::cout << "key: " << el.key() << ", value:" << el.value() << '\n';
}
```

The items() function also allows using structured bindings (C++17):

```cpp
for (auto& [key, val] : j_object.items())
{
    std::cout << "key: " << key << ", value:" << val << '\n';
}
```

!!! note

    When iterating over an array, `key()` will return the index of the element as string. For primitive types (e.g., numbers), `key()` returns an empty string.

!!! warning

    Using `items()` on temporary objects is dangerous. Make sure the object's lifetime exceeds the iteration. See [#2040](https://github.com/nlohmann/json/issues/2040) for more information.

### Reverse iteration order

`rbegin()` and `rend()` return iterators in the reverse sequence.

![Illustration from cppreference.com](../images/range-rbegin-rend.svg)

??? example

    ```cpp
    json j = {1, 2, 3, 4};

    for (auto it = j.rbegin(); it != j.rend(); ++it)
    {
        std::cout << *it << std::endl;
    }
    ```

    Output:

    ```json
    4
    3
    2
    1
    ```

### Iterating strings and binary values

Note that "value" means a JSON value in this setting, not values stored in the underlying containers. That is, `*begin()` returns the complete string or binary array and is also safe if the underlying string or binary array is empty.

??? example

    ```cpp
    json j = "Hello, world";
    for (auto it = j.begin(); it != j.end(); ++it)
    {
        std::cout << *it << std::endl;
    }
    ```

    Output:

    ```json
    "Hello, world"
    ```

## Iterator invalidation

| Operations | invalidated iterators |
|------------|-----------------------|
| `clear`    | all                   |


#include <iostream>
#include <nlohmann/json.hpp>

using json = nlohmann::json;

int main()
{
    try
    {
        // calling push_back() on a string value
        json j = "string";
        j.push_back("another string");
    }
    catch (const json::type_error& e)
    {
        // output exception information
        std::cout << "message: " << e.what() << '\n'
                  << "exception id: " << e.id << std::endl;
    }
}


// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.

// Simple test for a fuzzer. The fuzzer must find a particular string.
#include <cstring>
#include <cstdint>
#include <cstdio>
#include <cstdlib>

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
  char *S = (char*)Data;
  if (Size >= 7 && !strcmp(S, "qwerty")) {
    fprintf(stderr, "BINGO\n");
    exit(1);
  }
  return 0;
}


<link rel="icon" href="/src/favicon.ico" />

FS Serve Normal Tests

Normal Import


//     __ _____ _____ _____
//  __|  |   __|     |   | |  JSON for Modern C++
// |  |  |__   |  |  | | | |  version 3.12.0
// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT

#pragma once

#include <cstddef> // ptrdiff_t
#include <iterator> // reverse_iterator
#include <utility> // declval

#include <nlohmann/detail/abi_macros.hpp>

NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{

//////////////////////
// reverse_iterator //
//////////////////////

/*!
@brief a template for a reverse iterator class

@tparam Base the base iterator type to reverse. Valid types are @ref
iterator (to create @ref reverse_iterator) and @ref const_iterator (to
create @ref const_reverse_iterator).

@requirement REQ-JSON-02 The class satisfies the following concept requirements:
-
[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
  The iterator that can be moved can be moved in both directions (i.e.
  incremented and decremented).
- [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator):
  It is possible to write to the pointed-to element (only if @a Base is
  @ref iterator).

@since version 1.0.0
*/
template<typename Base>
class json_reverse_iterator : public std::reverse_iterator<Base>
{
  public:
    using difference_type = std::ptrdiff_t;
    /// shortcut to the reverse iterator adapter
    using base_iterator = std::reverse_iterator<Base>;
    /// the reference type for the pointed-to element
    using reference = typename Base::reference;

    /// create reverse iterator from iterator
    explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
        : base_iterator(it) {}

    /// create reverse iterator from base class
    explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}

    /// post-increment (it++)
    json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp)
    {
        return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
    }

    /// pre-increment (++it)
    json_reverse_iterator& operator++()
    {
        return static_cast<json_reverse_iterator&>(base_iterator::operator++());
    }

    /// post-decrement (it--)
    json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp)
    {
        return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
    }

    /// pre-decrement (--it)
    json_reverse_iterator& operator--()
    {
        return static_cast<json_reverse_iterator&>(base_iterator::operator--());
    }

    /// add to iterator
    json_reverse_iterator& operator+=(difference_type i)
    {
        return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
    }

    /// add to iterator
    json_reverse_iterator operator+(difference_type i) const
    {
        return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
    }

    /// subtract from iterator
    json_reverse_iterator operator-(difference_type i) const
    {
        return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
    }

    /// return difference
    difference_type operator-(const json_reverse_iterator& other) const
    {
        return base_iterator(*this) - base_iterator(other);
    }

    /// access to successor
    reference operator[](difference_type n) const
    {
        return *(this->operator+(n));
    }

    /// return the key of an object iterator
    auto key() const -> decltype(std::declval<Base>().key())
    {
        auto it = --this->base();
        return it.key();
    }

    /// return the value of an iterator
    reference value() const
    {
        auto it = --this->base();
        return it.operator * ();
    }
};

}  // namespace detail
NLOHMANN_JSON_NAMESPACE_END


import { describe, expect, onTestFinished } from 'vitest'
import { createModuleRunnerTester } from './utils'

describe(
  'module runner hmr works as expected',
  async () => {
    const it = await createModuleRunnerTester({
      server: {
        // override watch options because it's disabled by default
        watch: {},
      },
    })

    it('hmr options are defined', async ({ runner }) => {
      expect(runner.hmrClient).toBeDefined()

      const mod = await runner.import('/fixtures/hmr.js')
      expect(mod).toHaveProperty('hmr')
      expect(mod.hmr).toHaveProperty('accept')
    })

    it('correctly populates hmr client', async ({ runner }) => {
      const mod = await runner.import('/fixtures/d')
      expect(mod.d).toBe('a')

      const fixtureC = '/fixtures/c.ts'
      const fixtureD = '/fixtures/d.ts'

      expect(runner.hmrClient!.hotModulesMap.size).toBe(2)
      expect(runner.hmrClient!.dataMap.size).toBe(2)
      expect(runner.hmrClient!.ctxToListenersMap.size).toBe(2)

      for (const fixture of [fixtureC, fixtureD]) {
        expect(runner.hmrClient!.hotModulesMap.has(fixture)).toBe(true)
        expect(runner.hmrClient!.dataMap.has(fixture)).toBe(true)
        expect(runner.hmrClient!.ctxToListenersMap.has(fixture)).toBe(true)
      }
    })

    it('does not expose partial exports during concurrent updates', async ({
      runner,
    }) => {
      const testGlobal = globalThis as any

      testGlobal.__vite_ssr_hmr_reexport_race__ = {
        wait: () => Promise.resolve(),
      }
      onTestFinished(() => {
        delete testGlobal.__vite_ssr_hmr_reexport_race__
      })

      await runner.import('/fixtures/hmr-reexport-race/entry-a.js')
      await runner.import('/fixtures/hmr-reexport-race/entry-b.js')

      const sharedModule = runner.evaluatedModules.getModuleByUrl(
        '/fixtures/hmr-reexport-race/shared.js',
      )
      const coreModule = runner.evaluatedModules.getModuleByUrl(
        '/fixtures/hmr-reexport-race/core.js',
      )
      const entryAModule = runner.evaluatedModules.getModuleByUrl(
        '/fixtures/hmr-reexport-race/entry-a.js',
      )
      const entryBModule = runner.evaluatedModules.getModuleByUrl(
        '/fixtures/hmr-reexport-race/entry-b.js',
      )
      expect(sharedModule).toBeDefined()
      expect(coreModule).toBeDefined()
      expect(entryAModule).toBeDefined()
      expect(entryBModule).toBeDefined()

      let waitStarted!: () => void
      const waitStartedPromise = new Promise<void>((resolve) => {
        waitStarted = resolve
      })
      let releaseWait!: () => void
      const waitPromise = new Promise<void>((resolve) => {
        releaseWait = resolve
      })

      testGlobal.__vite_ssr_hmr_reexport_race__ = {
        wait: () => {
          waitStarted()
          return waitPromise
        },
      }

      for (const module of [
        entryAModule!,
        entryBModule!,
        sharedModule!,
        coreModule!,
      ]) {
        runner.evaluatedModules.invalidateModule(module)
      }

      const importA = runner.import('/fixtures/hmr-reexport-race/entry-a.js')
      await waitStartedPromise

      const importB = runner.import('/fixtures/hmr-reexport-race/entry-b.js')
      // Wait deterministically until entry-b has reached the point where it
      // observes shared as in-flight. The `mod.imports.add(depMod.id)` line
      // in `request()` runs synchronously immediately before `cachedRequest`
      // executes its cycle-detection prefix, so observing this edge means
      // the buggy/fixed branch has either just run or is about to run on
      // the same microtask. `imports` is cleared by invalidateModule, so
      // this is a fresh signal (unlike `importers`, which is preserved).
      const entryBNode = runner.evaluatedModules.getModuleByUrl(
        '/fixtures/hmr-reexport-race/entry-b.js',
      )!
      while (!entryBNode.imports.has(sharedModule!.id)) {
        await new Promise((resolve) => setImmediate(resolve))
      }
      releaseWait()
      const results = await Promise.allSettled([importA, importB] as const)

      expect(results).toEqual([
        {
          status: 'fulfilled',
          value: expect.objectContaining({ result: 'a' }),
        },
        {
          status: 'fulfilled',
          value: expect.objectContaining({ result: 'b' }),
        },
      ])

      const hmrListeners = runner.hmrClient!.hotModulesMap
      expect(hmrListeners.has('/fixtures/hmr-reexport-race/entry-a.js')).toBe(
        true,
      )
      expect(hmrListeners.has('/fixtures/hmr-reexport-race/entry-b.js')).toBe(
        true,
      )
    })
  },
  process.env.CI ? 50_00 : 5_000,
)


/*!
Provides routines for generating ripgrep's man page in `roff` format.
*/

use std::{collections::BTreeMap, fmt::Write};

use crate::flags::{Flag, defs::FLAGS, doc::version};

const TEMPLATE: &'static str = include_str!("template.rg.1");

/// Wraps `std::write!` and asserts there is no failure.
///
/// We only write to `String` in this module.
macro_rules! write {
    ($($tt:tt)*) => { std::write!($($tt)*).unwrap(); }
}

/// Wraps `std::writeln!` and asserts there is no failure.
///
/// We only write to `String` in this module.
macro_rules! writeln {
    ($($tt:tt)*) => { std::writeln!($($tt)*).unwrap(); }
}

/// Returns a `roff` formatted string corresponding to ripgrep's entire man
/// page.
pub(crate) fn generate() -> String {
    let mut cats = BTreeMap::new();
    for flag in FLAGS.iter().copied() {
        let mut cat = cats.entry(flag.doc_category()).or_insert(String::new());
        if !cat.is_empty() {
            writeln!(cat, ".sp");
        }
        generate_flag(flag, &mut cat);
    }

    let mut out = TEMPLATE.replace("!!VERSION!!", &version::generate_digits());
    for (cat, value) in cats.iter() {
        let var = format!("!!{name}!!", name = cat.as_str());
        if !cfg!(feature = "unstable-index")
            && matches!(cat, crate::flags::Category::Indexing)
        {
            out = out.replace(&var, crate::flags::INDEXING_NOT_SUPPORTED);
        } else {
            out = out.replace(&var, value);
        }
    }
    out
}

/// Writes `roff` formatted documentation for `flag` to `out`.
fn generate_flag(flag: &'static dyn Flag, out: &mut String) {
    if let Some(byte) = flag.name_short() {
        let name = char::from(byte);
        write!(out, r"\fB\-{name}\fP");
        if let Some(var) = flag.doc_variable() {
            write!(out, r" \fI{var}\fP");
        }
        write!(out, r", ");
    }

    let name = flag.name_long().replace("-", r"\-");
    write!(out, r"\fB\-\-{name}\fP");
    if let Some(var) = flag.doc_variable() {
        write!(out, r"=\fI{var}\fP");
    }
    write!(out, "\n");

    writeln!(out, ".RS 4");
    let doc = flag.doc_long().trim();
    // Convert \flag{foo} into something nicer.
    let doc = super::render_custom_markup(doc, "flag", |name, out| {
        let Some(flag) = crate::flags::parse::lookup(name) else {
            unreachable!(r"found unrecognized \flag{{{name}}} in roff docs")
        };
        out.push_str(r"\fB");
        if let Some(name) = flag.name_short() {
            write!(out, r"\-{}/", char::from(name));
        }
        write!(out, r"\-\-{}", flag.name_long().replace("-", r"\-"));
        out.push_str(r"\fP");
    });
    // Convert \flag-negate{foo} into something nicer.
    let doc = super::render_custom_markup(&doc, "flag-negate", |name, out| {
        let Some(flag) = crate::flags::parse::lookup(name) else {
            unreachable!(
                r"found unrecognized \flag-negate{{{name}}} in roff docs"
            )
        };
        let Some(name) = flag.name_negated() else {
            let long = flag.name_long();
            unreachable!(
                "found \\flag-negate{{{long}}} in roff docs but \
                 {long} does not have a negation"
            );
        };
        out.push_str(r"\fB");
        write!(out, r"\-\-{name}");
        out.push_str(r"\fP");
    });
    writeln!(out, "{doc}");
    if let Some(negated) = flag.name_negated() {
        // Flags that can be negated that aren't switches, like
        // --context-separator, are somewhat weird. Because of that, the docs
        // for those flags should discuss the semantics of negation explicitly.
        // But for switches, the behavior is always the same.
        if flag.is_switch() {
            writeln!(out, ".sp");
            writeln!(
                out,
                r"This flag can be disabled with \fB\-\-{negated}\fP."
            );
        }
    }
    writeln!(out, ".RE");
}


use regex_syntax::ast::{self, Ast};

/// The results of analyzing AST of a regular expression (e.g., for supporting
/// smart case).
#[derive(Clone, Debug)]
pub(crate) struct AstAnalysis {
    /// True if and only if a literal uppercase character occurs in the regex.
    any_uppercase: bool,
    /// True if and only if the regex contains any literal at all.
    any_literal: bool,
}

impl AstAnalysis {
    /// Returns a `AstAnalysis` value by doing analysis on the AST of `pattern`.
    ///
    /// If `pattern` is not a valid regular expression, then `None` is
    /// returned.
    #[cfg(test)]
    pub(crate) fn from_pattern(pattern: &str) -> Option<AstAnalysis> {
        regex_syntax::ast::parse::Parser::new()
            .parse(pattern)
            .map(|ast| AstAnalysis::from_ast(&ast))
            .ok()
    }

    /// Perform an AST analysis given the AST.
    pub(crate) fn from_ast(ast: &Ast) -> AstAnalysis {
        let mut analysis = AstAnalysis::new();
        analysis.from_ast_impl(ast);
        analysis
    }

    /// Returns true if and only if a literal uppercase character occurs in
    /// the pattern.
    ///
    /// For example, a pattern like `\pL` contains no uppercase literals,
    /// even though `L` is uppercase and the `\pL` class contains uppercase
    /// characters.
    pub(crate) fn any_uppercase(&self) -> bool {
        self.any_uppercase
    }

    /// Returns true if and only if the regex contains any literal at all.
    ///
    /// For example, a pattern like `\pL` reports `false`, but a pattern like
    /// `\pLfoo` reports `true`.
    pub(crate) fn any_literal(&self) -> bool {
        self.any_literal
    }

    /// Creates a new `AstAnalysis` value with an initial configuration.
    fn new() -> AstAnalysis {
        AstAnalysis { any_uppercase: false, any_literal: false }
    }

    fn from_ast_impl(&mut self, ast: &Ast) {
        if self.done() {
            return;
        }
        match *ast {
            Ast::Empty(_) => {}
            Ast::Flags(_)
            | Ast::Dot(_)
            | Ast::Assertion(_)
            | Ast::ClassUnicode(_)
            | Ast::ClassPerl(_) => {}
            Ast::Literal(ref x) => {
                self.from_ast_literal(x);
            }
            Ast::ClassBracketed(ref x) => {
                self.from_ast_class_set(&x.kind);
            }
            Ast::Repetition(ref x) => {
                self.from_ast_impl(&x.ast);
            }
            Ast::Group(ref x) => {
                self.from_ast_impl(&x.ast);
            }
            Ast::Alternation(ref alt) => {
                for x in &alt.asts {
                    self.from_ast_impl(x);
                }
            }
            Ast::Concat(ref alt) => {
                for x in &alt.asts {
                    self.from_ast_impl(x);
                }
            }
        }
    }

    fn from_ast_class_set(&mut self, ast: &ast::ClassSet) {
        if self.done() {
            return;
        }
        match *ast {
            ast::ClassSet::Item(ref item) => {
                self.from_ast_class_set_item(item);
            }
            ast::ClassSet::BinaryOp(ref x) => {
                self.from_ast_class_set(&x.lhs);
                self.from_ast_class_set(&x.rhs);
            }
        }
    }

    fn from_ast_class_set_item(&mut self, ast: &ast::ClassSetItem) {
        if self.done() {
            return;
        }
        match *ast {
            ast::ClassSetItem::Empty(_)
            | ast::ClassSetItem::Ascii(_)
            | ast::ClassSetItem::Unicode(_)
            | ast::ClassSetItem::Perl(_) => {}
            ast::ClassSetItem::Literal(ref x) => {
                self.from_ast_literal(x);
            }
            ast::ClassSetItem::Range(ref x) => {
                self.from_ast_literal(&x.start);
                self.from_ast_literal(&x.end);
            }
            ast::ClassSetItem::Bracketed(ref x) => {
                self.from_ast_class_set(&x.kind);
            }
            ast::ClassSetItem::Union(ref union) => {
                for x in &union.items {
                    self.from_ast_class_set_item(x);
                }
            }
        }
    }

    fn from_ast_literal(&mut self, ast: &ast::Literal) {
        self.any_literal = true;
        self.any_uppercase = self.any_uppercase || ast.c.is_uppercase();
    }

    /// Returns true if and only if the attributes can never change no matter
    /// what other AST it might see.
    fn done(&self) -> bool {
        self.any_uppercase && self.any_literal
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    fn analysis(pattern: &str) -> AstAnalysis {
        AstAnalysis::from_pattern(pattern).unwrap()
    }

    #[test]
    fn various() {
        let x = analysis("");
        assert!(!x.any_uppercase);
        assert!(!x.any_literal);

        let x = analysis("foo");
        assert!(!x.any_uppercase);
        assert!(x.any_literal);

        let x = analysis("Foo");
        assert!(x.any_uppercase);
        assert!(x.any_literal);

        let x = analysis("foO");
        assert!(x.any_uppercase);
        assert!(x.any_literal);

        let x = analysis(r"foo\\");
        assert!(!x.any_uppercase);
        assert!(x.any_literal);

        let x = analysis(r"foo\w");
        assert!(!x.any_uppercase);
        assert!(x.any_literal);

        let x = analysis(r"foo\S");
        assert!(!x.any_uppercase);
        assert!(x.any_literal);

        let x = analysis(r"foo\p{Ll}");
        assert!(!x.any_uppercase);
        assert!(x.any_literal);

        let x = analysis(r"foo[a-z]");
        assert!(!x.any_uppercase);
        assert!(x.any_literal);

        let x = analysis(r"foo[A-Z]");
        assert!(x.any_uppercase);
        assert!(x.any_literal);

        let x = analysis(r"foo[\S\t]");
        assert!(!x.any_uppercase);
        assert!(x.any_literal);

        let x = analysis(r"foo\\S");
        assert!(x.any_uppercase);
        assert!(x.any_literal);

        let x = analysis(r"\p{Ll}");
        assert!(!x.any_uppercase);
        assert!(!x.any_literal);

        let x = analysis(r"aBc\w");
        assert!(x.any_uppercase);
        assert!(x.any_literal);

        let x = analysis(r"a\u0061");
        assert!(!x.any_uppercase);
        assert!(x.any_literal);
    }
}


//===- FuzzerIOWindows.cpp - IO utils for Windows. ------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// IO functions implementation for Windows.
//===----------------------------------------------------------------------===//
#include "FuzzerDefs.h"
#if LIBFUZZER_WINDOWS

#include "FuzzerExtFunctions.h"
#include "FuzzerIO.h"
#include <cstdarg>
#include <cstdio>
#include <fstream>
#include <io.h>
#include <iterator>
#include <sys/stat.h>
#include <sys/types.h>
#include <windows.h>

namespace fuzzer {

static bool IsFile(const std::string &Path, const DWORD &FileAttributes) {

  if (FileAttributes & FILE_ATTRIBUTE_NORMAL)
    return true;

  if (FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
    return false;

  HANDLE FileHandle(
      CreateFileA(Path.c_str(), 0, FILE_SHARE_READ, NULL, OPEN_EXISTING,
                  FILE_FLAG_BACKUP_SEMANTICS, 0));

  if (FileHandle == INVALID_HANDLE_VALUE) {
    Printf("CreateFileA() failed for \"%s\" (Error code: %lu).\n", Path.c_str(),
        GetLastError());
    return false;
  }

  DWORD FileType = GetFileType(FileHandle);

  if (FileType == FILE_TYPE_UNKNOWN) {
    Printf("GetFileType() failed for \"%s\" (Error code: %lu).\n", Path.c_str(),
        GetLastError());
    CloseHandle(FileHandle);
    return false;
  }

  if (FileType != FILE_TYPE_DISK) {
    CloseHandle(FileHandle);
    return false;
  }

  CloseHandle(FileHandle);
  return true;
}

bool IsFile(const std::string &Path) {
  DWORD Att = GetFileAttributesA(Path.c_str());

  if (Att == INVALID_FILE_ATTRIBUTES) {
    Printf("GetFileAttributesA() failed for \"%s\" (Error code: %lu).\n",
        Path.c_str(), GetLastError());
    return false;
  }

  return IsFile(Path, Att);
}

void ListFilesInDirRecursive(const std::string &Dir, long *Epoch,
                             std::vector<std::string> *V, bool TopDir) {
  auto E = GetEpoch(Dir);
  if (Epoch)
    if (E && *Epoch >= E) return;

  std::string Path(Dir);
  assert(!Path.empty());
  if (Path.back() != '\\')
      Path.push_back('\\');
  Path.push_back('*');

  // Get the first directory entry.
  WIN32_FIND_DATAA FindInfo;
  HANDLE FindHandle(FindFirstFileA(Path.c_str(), &FindInfo));
  if (FindHandle == INVALID_HANDLE_VALUE)
  {
    Printf("No file found in: %s.\n", Dir.c_str());
    return;
  }

  do {
    std::string FileName = DirPlusFile(Dir, FindInfo.cFileName);

    if (FindInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
      size_t FilenameLen = strlen(FindInfo.cFileName);
      if ((FilenameLen == 1 && FindInfo.cFileName[0] == '.') ||
          (FilenameLen == 2 && FindInfo.cFileName[0] == '.' &&
                               FindInfo.cFileName[1] == '.'))
        continue;

      ListFilesInDirRecursive(FileName, Epoch, V, false);
    }
    else if (IsFile(FileName, FindInfo.dwFileAttributes))
      V->push_back(FileName);
  } while (FindNextFileA(FindHandle, &FindInfo));

  DWORD LastError = GetLastError();
  if (LastError != ERROR_NO_MORE_FILES)
    Printf("FindNextFileA failed (Error code: %lu).\n", LastError);

  FindClose(FindHandle);

  if (Epoch && TopDir)
    *Epoch = E;
}

char GetSeparator() {
  return '\\';
}

FILE* OpenFile(int Fd, const char* Mode) {
  return _fdopen(Fd, Mode);
}

int CloseFile(int Fd) {
  return _close(Fd);
}

int DuplicateFile(int Fd) {
  return _dup(Fd);
}

void RemoveFile(const std::string &Path) {
  _unlink(Path.c_str());
}

static bool IsSeparator(char C) {
  return C == '\\' || C == '/';
}

// Parse disk designators, like "C:\". If Relative == true, also accepts: "C:".
// Returns number of characters considered if successful.
static size_t ParseDrive(const std::string &FileName, const size_t Offset,
                         bool Relative = true) {
  if (Offset + 1 >= FileName.size() || FileName[Offset + 1] != ':')
    return 0;
  if (Offset + 2 >= FileName.size() || !IsSeparator(FileName[Offset + 2])) {
    if (!Relative) // Accept relative path?
      return 0;
    else
      return 2;
  }
  return 3;
}

// Parse a file name, like: SomeFile.txt
// Returns number of characters considered if successful.
static size_t ParseFileName(const std::string &FileName, const size_t Offset) {
  size_t Pos = Offset;
  const size_t End = FileName.size();
  for(; Pos < End && !IsSeparator(FileName[Pos]); ++Pos)
    ;
  return Pos - Offset;
}

// Parse a directory ending in separator, like: SomeDir\
// Returns number of characters considered if successful.
static size_t ParseDir(const std::string &FileName, const size_t Offset) {
  size_t Pos = Offset;
  const size_t End = FileName.size();
  if (Pos >= End || IsSeparator(FileName[Pos]))
    return 0;
  for(; Pos < End && !IsSeparator(FileName[Pos]); ++Pos)
    ;
  if (Pos >= End)
    return 0;
  ++Pos; // Include separator.
  return Pos - Offset;
}

// Parse a servername and share, like: SomeServer\SomeShare\
// Returns number of characters considered if successful.
static size_t ParseServerAndShare(const std::string &FileName,
                                  const size_t Offset) {
  size_t Pos = Offset, Res;
  if (!(Res = ParseDir(FileName, Pos)))
    return 0;
  Pos += Res;
  if (!(Res = ParseDir(FileName, Pos)))
    return 0;
  Pos += Res;
  return Pos - Offset;
}

// Parse the given Ref string from the position Offset, to exactly match the given
// string Patt.
// Returns number of characters considered if successful.
static size_t ParseCustomString(const std::string &Ref, size_t Offset,
                                const char *Patt) {
  size_t Len = strlen(Patt);
  if (Offset + Len > Ref.size())
    return 0;
  return Ref.compare(Offset, Len, Patt) == 0 ? Len : 0;
}

// Parse a location, like:
// \\?\UNC\Server\Share\  \\?\C:\  \\Server\Share\  \  C:\  C:
// Returns number of characters considered if successful.
static size_t ParseLocation(const std::string &FileName) {
  size_t Pos = 0, Res;

  if ((Res = ParseCustomString(FileName, Pos, R"(\\?\)"))) {
    Pos += Res;
    if ((Res = ParseCustomString(FileName, Pos, R"(UNC\)"))) {
      Pos += Res;
      if ((Res = ParseServerAndShare(FileName, Pos)))
        return Pos + Res;
      return 0;
    }
    if ((Res = ParseDrive(FileName, Pos, false)))
      return Pos + Res;
    return 0;
  }

  if (Pos < FileName.size() && IsSeparator(FileName[Pos])) {
    ++Pos;
    if (Pos < FileName.size() && IsSeparator(FileName[Pos])) {
      ++Pos;
      if ((Res = ParseServerAndShare(FileName, Pos)))
        return Pos + Res;
      return 0;
    }
    return Pos;
  }

  if ((Res = ParseDrive(FileName, Pos)))
    return Pos + Res;

  return Pos;
}

std::string DirName(const std::string &FileName) {
  size_t LocationLen = ParseLocation(FileName);
  size_t DirLen = 0, Res;
  while ((Res = ParseDir(FileName, LocationLen + DirLen)))
    DirLen += Res;
  size_t FileLen = ParseFileName(FileName, LocationLen + DirLen);

  if (LocationLen + DirLen + FileLen != FileName.size()) {
    Printf("DirName() failed for \"%s\", invalid path.\n", FileName.c_str());
    exit(1);
  }

  if (DirLen) {
    --DirLen; // Remove trailing separator.
    if (!FileLen) { // Path ended in separator.
      assert(DirLen);
      // Remove file name from Dir.
      while (DirLen && !IsSeparator(FileName[LocationLen + DirLen - 1]))
        --DirLen;
      if (DirLen) // Remove trailing separator.
        --DirLen;
    }
  }

  if (!LocationLen) { // Relative path.
    if (!DirLen)
      return ".";
    return std::string(".\\").append(FileName, 0, DirLen);
  }

  return FileName.substr(0, LocationLen + DirLen);
}

}  // namespace fuzzer

#endif // LIBFUZZER_WINDOWS


import { nanoid } from 'nanoid/non-secure'
import { DevRuntime } from 'rolldown/experimental/runtime'
import {
  BundledDevHMRClient,
  BundledDevHMRContext,
} from './bundledDevHmrClient'
import {
  base,
  clearOverlayOrReloadOnFirstUpdate,
  registerBundledDevClient,
  removeStyle,
  transport,
  updateStyle,
} from './client'

// keep the same public exports as `client.ts`, which this entry replaces when inlined
export {
  createHotContext,
  injectQuery,
  removeStyle,
  updateStyle,
  ErrorOverlay,
} from './client'

if (typeof DevRuntime !== 'undefined') {
  class ViteDevRuntime extends DevRuntime {
    override createModuleHotContext(moduleId: string) {
      const ctx = new BundledDevHMRContext(bundledDevHmrClient, moduleId)
      // @ts-expect-error TODO: support CSS properly
      ctx._internal = { updateStyle, removeStyle }
      return ctx
    }
  }

  const clientId = nanoid()

  transport.send({
    type: 'custom',
    event: 'vite:client-connected',
    data: { clientId },
  })

  const runtime = ((globalThis as any).__rolldown_runtime__ ??=
    new ViteDevRuntime(clientId))

  const bundledDevHmrClient = new BundledDevHMRClient(
    {
      error: (err) => console.error('[vite]', err),
      debug: (...msg) => console.debug('[vite]', ...msg),
    },
    transport,
    runtime,
    {
      base,
      beforeApply: clearOverlayOrReloadOnFirstUpdate,
    },
  )
  registerBundledDevClient(bundledDevHmrClient)

  runtime.hooks = {
    createModuleHotContext: (id: string) => runtime.createModuleHotContext(id),
    onModuleCacheRemoval: (id: string) =>
      bundledDevHmrClient.handleModuleCacheRemoval(id),
  }
}


#include <iostream>
#include <nlohmann/json.hpp>

using json = nlohmann::json;

int main()
{
    // create a JSON object
    const json object =
    {
        {"one", 1}, {"two", 2}, {"three", 2.9}
    };

    // output element with key "two"
    std::cout << object["two"] << '\n';
}


# <small>nlohmann::basic_json::</small>array

```cpp
static basic_json array(initializer_list_t init = {});
```

Creates a JSON array value from a given initializer list. That is, given a list of values `a, b, c`, creates the JSON
value `#!json [a, b, c]`. If the initializer list is empty, the empty array `#!json []` is created.

## Parameters

`init` (in)
:   initializer list with JSON values to create an array from (optional)

## Return value

JSON array value

## Exception safety

Strong guarantee: if an exception is thrown, there are no changes in the JSON value.

## Complexity

Linear in the size of `init`.

## Notes

This function is only needed to express two edge cases that cannot be realized with the initializer list constructor
([`basic_json(initializer_list_t, bool, value_t)`](basic_json.md)). These cases are:

1. creating an array whose elements are all pairs whose first element is a string -- in this case, the initializer list
   constructor would create an object, taking the first elements as keys
2. creating an empty array -- passing the empty initializer list to the initializer list constructor yields an empty
   object

## Examples

??? example

    The following code shows an example for the `array` function.

    ```cpp
    --8<-- "examples/array.cpp"
    ```

    Output:

    ```json
    --8<-- "examples/array.output"
    ```

## See also

- [`basic_json(initializer_list_t)`](basic_json.md) - create a JSON value from an initializer list
- [`object`](object.md) - create a JSON object value from an initializer list
- [Creating JSON values](../../features/creating_values.md) - the article on creating JSON values

## Version history

- Added in version 1.0.0.


/*!
The ignore crate provides a fast recursive directory iterator that respects
various filters such as globs, file types and `.gitignore` files. The precise
matching rules and precedence is explained in the documentation for
`WalkBuilder`.

Secondarily, this crate exposes gitignore and file type matchers for use cases
that demand more fine-grained control.

# Example

This example shows the most basic usage of this crate. This code will
recursively traverse the current directory while automatically filtering out
files and directories according to ignore globs found in files like
`.ignore` and `.gitignore`:

```rust,no_run
use ignore::Walk;

for result in Walk::new("./") {
    // Each item yielded by the iterator is either a directory entry or an
    // error, so either print the path or the error.
    match result {
        Ok(entry) => println!("{}", entry.path().display()),
        Err(err) => println!("ERROR: {}", err),
    }
}
```

# Example: advanced

By default, the recursive directory iterator will ignore hidden files and
directories. This can be disabled by building the iterator with `WalkBuilder`:

```rust,no_run
use ignore::WalkBuilder;

for result in WalkBuilder::new("./").hidden(false).build() {
    println!("{:?}", result);
}
```

See the documentation for `WalkBuilder` for many other options.
*/

#![deny(missing_docs)]

use std::path::{Path, PathBuf};

pub use crate::incremental::{IncrementalIgnore, IncrementalMatch};
pub use crate::walk::{
    DirEntry, ParallelVisitor, ParallelVisitorBuilder, Walk, WalkBuilder,
    WalkParallel, WalkState,
};

mod default_types;
mod dir;
pub mod gitignore;
mod incremental;
pub mod overrides;
mod pathutil;
pub mod types;
mod walk;

/// Represents an error that can occur when parsing a gitignore file.
#[derive(Debug)]
pub enum Error {
    /// A collection of "soft" errors. These occur when adding an ignore
    /// file partially succeeded.
    Partial(Vec<Error>),
    /// An error associated with a specific line number.
    WithLineNumber {
        /// The line number.
        line: u64,
        /// The underlying error.
        err: Box<Error>,
    },
    /// An error associated with a particular file path.
    WithPath {
        /// The file path.
        path: PathBuf,
        /// The underlying error.
        err: Box<Error>,
    },
    /// An error associated with a particular directory depth when recursively
    /// walking a directory.
    WithDepth {
        /// The directory depth.
        depth: usize,
        /// The underlying error.
        err: Box<Error>,
    },
    /// An error that occurs when a file loop is detected when traversing
    /// symbolic links.
    Loop {
        /// The ancestor file path in the loop.
        ancestor: PathBuf,
        /// The child file path in the loop.
        child: PathBuf,
    },
    /// An error that occurs when doing I/O, such as reading an ignore file.
    Io(std::io::Error),
    /// An error that occurs when trying to parse a glob.
    Glob {
        /// The original glob that caused this error. This glob, when
        /// available, always corresponds to the glob provided by an end user.
        /// e.g., It is the glob as written in a `.gitignore` file.
        ///
        /// (This glob may be distinct from the glob that is actually
        /// compiled, after accounting for `gitignore` semantics.)
        glob: Option<String>,
        /// The underlying glob error as a string.
        err: String,
    },
    /// A type selection for a file type that is not defined.
    UnrecognizedFileType(String),
    /// A user specified file type definition could not be parsed.
    InvalidDefinition,
}

impl Clone for Error {
    fn clone(&self) -> Error {
        match *self {
            Error::Partial(ref errs) => Error::Partial(errs.clone()),
            Error::WithLineNumber { line, ref err } => {
                Error::WithLineNumber { line, err: err.clone() }
            }
            Error::WithPath { ref path, ref err } => {
                Error::WithPath { path: path.clone(), err: err.clone() }
            }
            Error::WithDepth { depth, ref err } => {
                Error::WithDepth { depth, err: err.clone() }
            }
            Error::Loop { ref ancestor, ref child } => Error::Loop {
                ancestor: ancestor.clone(),
                child: child.clone(),
            },
            Error::Io(ref err) => match err.raw_os_error() {
                Some(e) => Error::Io(std::io::Error::from_raw_os_error(e)),
                None => {
                    Error::Io(std::io::Error::new(err.kind(), err.to_string()))
                }
            },
            Error::Glob { ref glob, ref err } => {
                Error::Glob { glob: glob.clone(), err: err.clone() }
            }
            Error::UnrecognizedFileType(ref err) => {
                Error::UnrecognizedFileType(err.clone())
            }
            Error::InvalidDefinition => Error::InvalidDefinition,
        }
    }
}

impl Error {
    /// Returns true if this is a partial error.
    ///
    /// A partial error occurs when only some operations failed while others
    /// may have succeeded. For example, an ignore file may contain an invalid
    /// glob among otherwise valid globs.
    pub fn is_partial(&self) -> bool {
        match *self {
            Error::Partial(_) => true,
            Error::WithLineNumber { ref err, .. } => err.is_partial(),
            Error::WithPath { ref err, .. } => err.is_partial(),
            Error::WithDepth { ref err, .. } => err.is_partial(),
            _ => false,
        }
    }

    /// Returns true if this error is exclusively an I/O error.
    pub fn is_io(&self) -> bool {
        match *self {
            Error::Partial(ref errs) => errs.len() == 1 && errs[0].is_io(),
            Error::WithLineNumber { ref err, .. } => err.is_io(),
            Error::WithPath { ref err, .. } => err.is_io(),
            Error::WithDepth { ref err, .. } => err.is_io(),
            Error::Loop { .. } => false,
            Error::Io(_) => true,
            Error::Glob { .. } => false,
            Error::UnrecognizedFileType(_) => false,
            Error::InvalidDefinition => false,
        }
    }

    /// Inspect the original [`std::io::Error`] if there is one.
    ///
    /// [`None`] is returned if the [`Error`] doesn't correspond to an
    /// [`std::io::Error`]. This might happen, for example, when the error was
    /// produced because a cycle was found in the directory tree while
    /// following symbolic links.
    ///
    /// This method returns a borrowed value that is bound to the lifetime of the [`Error`]. To
    /// obtain an owned value, the [`into_io_error`] can be used instead.
    ///
    /// > This is the original [`std::io::Error`] and is _not_ the same as
    /// > [`impl From<Error> for std::io::Error`][impl] which contains
    /// > additional context about the error.
    ///
    /// [`None`]: https://doc.rust-lang.org/stable/std/option/enum.Option.html#variant.None
    /// [`std::io::Error`]: https://doc.rust-lang.org/stable/std/io/struct.Error.html
    /// [`From`]: https://doc.rust-lang.org/stable/std/convert/trait.From.html
    /// [`Error`]: struct.Error.html
    /// [`into_io_error`]: struct.Error.html#method.into_io_error
    /// [impl]: struct.Error.html#impl-From%3CError%3E
    pub fn io_error(&self) -> Option<&std::io::Error> {
        match *self {
            Error::Partial(ref errs) => {
                if errs.len() == 1 {
                    errs[0].io_error()
                } else {
                    None
                }
            }
            Error::WithLineNumber { ref err, .. } => err.io_error(),
            Error::WithPath { ref err, .. } => err.io_error(),
            Error::WithDepth { ref err, .. } => err.io_error(),
            Error::Loop { .. } => None,
            Error::Io(ref err) => Some(err),
            Error::Glob { .. } => None,
            Error::UnrecognizedFileType(_) => None,
            Error::InvalidDefinition => None,
        }
    }

    /// Similar to [`io_error`] except consumes self to convert to the original
    /// [`std::io::Error`] if one exists.
    ///
    /// [`io_error`]: struct.Error.html#method.io_error
    /// [`std::io::Error`]: https://doc.rust-lang.org/stable/std/io/struct.Error.html
    pub fn into_io_error(self) -> Option<std::io::Error> {
        match self {
            Error::Partial(mut errs) => {
                if errs.len() == 1 {
                    errs.remove(0).into_io_error()
                } else {
                    None
                }
            }
            Error::WithLineNumber { err, .. } => err.into_io_error(),
            Error::WithPath { err, .. } => err.into_io_error(),
            Error::WithDepth { err, .. } => err.into_io_error(),
            Error::Loop { .. } => None,
            Error::Io(err) => Some(err),
            Error::Glob { .. } => None,
            Error::UnrecognizedFileType(_) => None,
            Error::InvalidDefinition => None,
        }
    }

    /// Returns a depth associated with recursively walking a directory (if
    /// this error was generated from a recursive directory iterator).
    pub fn depth(&self) -> Option<usize> {
        match *self {
            Error::WithPath { ref err, .. } => err.depth(),
            Error::WithDepth { depth, .. } => Some(depth),
            _ => None,
        }
    }

    /// Turn an error into a tagged error with the given file path.
    fn with_path<P: AsRef<Path>>(self, path: P) -> Error {
        Error::WithPath {
            path: path.as_ref().to_path_buf(),
            err: Box::new(self),
        }
    }

    /// Turn an error into a tagged error with the given depth.
    fn with_depth(self, depth: usize) -> Error {
        Error::WithDepth { depth, err: Box::new(self) }
    }

    /// Turn an error into a tagged error with the given file path and line
    /// number. If path is empty, then it is omitted from the error.
    fn tagged<P: AsRef<Path>>(self, path: P, lineno: u64) -> Error {
        let errline =
            Error::WithLineNumber { line: lineno, err: Box::new(self) };
        if path.as_ref().as_os_str().is_empty() {
            return errline;
        }
        errline.with_path(path)
    }

    /// Build an error from a walkdir error.
    fn from_walkdir(err: walkdir::Error) -> Error {
        let depth = err.depth();
        if let (Some(anc), Some(child)) = (err.loop_ancestor(), err.path()) {
            return Error::WithDepth {
                depth,
                err: Box::new(Error::Loop {
                    ancestor: anc.to_path_buf(),
                    child: child.to_path_buf(),
                }),
            };
        }
        let path = err.path().map(|p| p.to_path_buf());
        let mut ig_err = Error::WithDepth {
            depth,
            err: Box::new(Error::Io(std::io::Error::from(err))),
        };
        if let Some(path) = path {
            ig_err = Error::WithPath { path, err: Box::new(ig_err) };
        }
        ig_err
    }
}

impl std::error::Error for Error {
    #[allow(deprecated)]
    fn description(&self) -> &str {
        match *self {
            Error::Partial(_) => "partial error",
            Error::WithLineNumber { ref err, .. } => err.description(),
            Error::WithPath { ref err, .. } => err.description(),
            Error::WithDepth { ref err, .. } => err.description(),
            Error::Loop { .. } => "file system loop found",
            Error::Io(ref err) => err.description(),
            Error::Glob { ref err, .. } => err,
            Error::UnrecognizedFileType(_) => "unrecognized file type",
            Error::InvalidDefinition => "invalid definition",
        }
    }
}

impl std::fmt::Display for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match *self {
            Error::Partial(ref errs) => {
                let msgs: Vec<String> =
                    errs.iter().map(|err| err.to_string()).collect();
                write!(f, "{}", msgs.join("\n"))
            }
            Error::WithLineNumber { line, ref err } => {
                write!(f, "line {}: {}", line, err)
            }
            Error::WithPath { ref path, ref err } => {
                write!(f, "{}: {}", path.display(), err)
            }
            Error::WithDepth { ref err, .. } => err.fmt(f),
            Error::Loop { ref ancestor, ref child } => write!(
                f,
                "File system loop found: \
                           {} points to an ancestor {}",
                child.display(),
                ancestor.display()
            ),
            Error::Io(ref err) => err.fmt(f),
            Error::Glob { glob: None, ref err } => write!(f, "{}", err),
            Error::Glob { glob: Some(ref glob), ref err } => {
                write!(f, "error parsing glob '{}': {}", glob, err)
            }
            Error::UnrecognizedFileType(ref ty) => {
                write!(f, "unrecognized file type: {}", ty)
            }
            Error::InvalidDefinition => write!(
                f,
                "invalid definition (format is type:glob, e.g., \
                           html:*.html)"
            ),
        }
    }
}

impl From<std::io::Error> for Error {
    fn from(err: std::io::Error) -> Error {
        Error::Io(err)
    }
}

#[derive(Debug, Default)]
struct PartialErrorBuilder(Vec<Error>);

impl PartialErrorBuilder {
    fn push(&mut self, err: Error) {
        self.0.push(err);
    }

    fn push_ignore_io(&mut self, err: Error) {
        if !err.is_io() {
            self.push(err);
        }
    }

    fn maybe_push(&mut self, err: Option<Error>) {
        if let Some(err) = err {
            self.push(err);
        }
    }

    fn maybe_push_ignore_io(&mut self, err: Option<Error>) {
        if let Some(err) = err {
            self.push_ignore_io(err);
        }
    }

    fn into_error_option(mut self) -> Option<Error> {
        if self.0.is_empty() {
            None
        } else if self.0.len() == 1 {
            Some(self.0.pop().unwrap())
        } else {
            Some(Error::Partial(self.0))
        }
    }
}

/// The result of a glob match.
///
/// The type parameter `T` typically refers to a type that provides more
/// information about a particular match. For example, it might identify
/// the specific gitignore file and the specific glob pattern that caused
/// the match.
#[derive(Clone, Debug)]
pub enum Match<T> {
    /// The path didn't match any glob.
    None,
    /// The highest precedent glob matched indicates the path should be
    /// ignored.
    Ignore(T),
    /// The highest precedent glob matched indicates the path should be
    /// whitelisted.
    Whitelist(T),
}

impl<T> Match<T> {
    /// Returns true if the match result didn't match any globs.
    pub fn is_none(&self) -> bool {
        match *self {
            Match::None => true,
            Match::Ignore(_) | Match::Whitelist(_) => false,
        }
    }

    /// Returns true if the match result implies the path should be ignored.
    pub fn is_ignore(&self) -> bool {
        match *self {
            Match::Ignore(_) => true,
            Match::None | Match::Whitelist(_) => false,
        }
    }

    /// Returns true if the match result implies the path should be
    /// whitelisted.
    pub fn is_whitelist(&self) -> bool {
        match *self {
            Match::Whitelist(_) => true,
            Match::None | Match::Ignore(_) => false,
        }
    }

    /// Inverts the match so that `Ignore` becomes `Whitelist` and
    /// `Whitelist` becomes `Ignore`. A non-match remains the same.
    pub fn invert(self) -> Match<T> {
        match self {
            Match::None => Match::None,
            Match::Ignore(t) => Match::Whitelist(t),
            Match::Whitelist(t) => Match::Ignore(t),
        }
    }

    /// Return the value inside this match if it exists.
    pub fn inner(&self) -> Option<&T> {
        match *self {
            Match::None => None,
            Match::Ignore(ref t) => Some(t),
            Match::Whitelist(ref t) => Some(t),
        }
    }

    /// Apply the given function to the value inside this match.
    ///
    /// If the match has no value, then return the match unchanged.
    pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Match<U> {
        match self {
            Match::None => Match::None,
            Match::Ignore(t) => Match::Ignore(f(t)),
            Match::Whitelist(t) => Match::Whitelist(f(t)),
        }
    }

    /// Return the match if it is not none. Otherwise, return other.
    pub fn or(self, other: Self) -> Self {
        if self.is_none() { other } else { self }
    }
}

#[cfg(test)]
mod tests {
    use std::{
        env, fs,
        path::{Path, PathBuf},
    };

    /// A convenient result type alias.
    pub(crate) type Result<T> =
        std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;

    macro_rules! err {
        ($($tt:tt)*) => {
            Box::<dyn std::error::Error + Send + Sync>::from(format!($($tt)*))
        }
    }

    /// A simple wrapper for creating a temporary directory that is
    /// automatically deleted when it's dropped.
    ///
    /// We use this in lieu of tempfile because tempfile brings in too many
    /// dependencies.
    #[derive(Debug)]
    pub struct TempDir(PathBuf);

    impl Drop for TempDir {
        fn drop(&mut self) {
            fs::remove_dir_all(&self.0).unwrap();
        }
    }

    impl TempDir {
        /// Create a new empty temporary directory under the system's configured
        /// temporary directory.
        pub fn new() -> Result<TempDir> {
            use std::sync::atomic::{AtomicUsize, Ordering};

            static TRIES: usize = 100;
            static COUNTER: AtomicUsize = AtomicUsize::new(0);

            let tmpdir = env::temp_dir();
            for _ in 0..TRIES {
                let count = COUNTER.fetch_add(1, Ordering::Relaxed);
                let path = tmpdir.join("rust-ignore").join(count.to_string());
                if path.is_dir() {
                    continue;
                }
                fs::create_dir_all(&path).map_err(|e| {
                    err!("failed to create {}: {}", path.display(), e)
                })?;
                return Ok(TempDir(path));
            }
            Err(err!("failed to create temp dir after {} tries", TRIES))
        }

        /// Return the underlying path to this temporary directory.
        pub fn path(&self) -> &Path {
            &self.0
        }
    }
}


// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.

// Simple test for a fuzzer. The fuzzer must find repeated bytes.
#include <assert.h>
#include <cstdint>
#include <cstdlib>
#include <cstddef>
#include <iostream>

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
  assert(Data);
  // Looking for AAAAAAAAAAAAAAAAAAAAAA or some such.
  size_t CurA = 0, MaxA = 0;
  for (size_t i = 0; i < Size; i++) {
    // Make sure there are no conditionals in the loop so that
    // coverage can't help the fuzzer.
    int EQ = Data[i] == 'A';
    CurA = EQ * (CurA + 1);
    int GT = CurA > MaxA;
    MaxA = GT * CurA + (!GT) * MaxA;
  }
  if (MaxA >= 20) {
    std::cout << "BINGO; Found the target (Max: " << MaxA << "), exiting\n";
    exit(0);
  }
  return 0;
}