diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 69ba432050fa7e..cde7dfb03825ed 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,6 +11,8 @@ on: - main - release/* - feat/* + - fix/* + - perf/* pull_request: workflow_dispatch: @@ -36,7 +38,7 @@ jobs: name: "Build&Test: node-${{ matrix.node_version }}, ${{ matrix.os }}" steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install pnpm uses: pnpm/action-setup@v2 @@ -72,7 +74,7 @@ jobs: runs-on: ubuntu-latest name: "Lint: node-16, ubuntu-latest" steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: fetch-depth: 0 diff --git a/.github/workflows/lock-closed-issues.yml b/.github/workflows/lock-closed-issues.yml index e20c3e3c8e8138..1f24f316952ea0 100644 --- a/.github/workflows/lock-closed-issues.yml +++ b/.github/workflows/lock-closed-issues.yml @@ -11,11 +11,11 @@ jobs: action: runs-on: ubuntu-latest steps: - - uses: dessant/lock-threads@v2 + - uses: dessant/lock-threads@v3 with: github-token: ${{ secrets.GITHUB_TOKEN }} - issue-lock-inactive-days: "14" - #issue-lock-comment: | + issue-inactive-days: "14" + #issue-comment: | # This issue has been locked since it has been closed for more than 14 days. # # If you have found a concrete bug or regression related to it, please open a new [bug report](https://github.com/vitejs/vite/issues/new/choose) with a reproduction against the latest Vite version. If you have any other comments you should join the chat at [Vite Land](https://chat.vitejs.dev) or create a new [discussion](https://github.com/vitejs/vite/discussions). diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 9e22af5aed6ee8..c58c28adac7b40 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -15,7 +15,7 @@ jobs: environment: Release steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install pnpm uses: pnpm/action-setup@v2 diff --git a/.github/workflows/release-tag.yml b/.github/workflows/release-tag.yml index f9d5b8de30bec9..21af4792d4741a 100644 --- a/.github/workflows/release-tag.yml +++ b/.github/workflows/release-tag.yml @@ -13,7 +13,7 @@ jobs: release: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Get pkgName for tag id: tag diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 31c1f34f3a4815..a87561a8e4146c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,7 +10,9 @@ To develop and test the core `vite` package: 1. Run `pnpm i` in Vite's root folder -2. Go to `packages/vite` and run `pnpm run dev`. This starts `rollup` in watch mode. +2. Run `pnpm run build` in Vite's root folder. + +3. If you are developing Vite itself, you can go to `packages/vite` and run `pnpm run dev` to automatically rebuild Vite whenever you change its code. You can alternatively use [Vite.js Docker Dev](https://github.com/nystudio107/vitejs-docker-dev) for a containerized Docker setup for Vite.js development. @@ -67,6 +69,8 @@ And re-run `pnpm install` to link the package. Each package under `packages/playground/` contains a `__tests__` directory. The tests are run using [Jest](https://jestjs.io/) + [Playwright](https://playwright.dev/) with custom integrations to make writing tests simple. The detailed setup is inside `jest.config.js` and `scripts/jest*` files. +Before running the tests, make sure that [Vite has been built](#repo-setup). On Windows, you may want to [activate Developer Mode](https://docs.microsoft.com/en-us/windows/apps/get-started/enable-your-device-for-development) to solve [issues with symlink creation for non-admins](https://github.com/vitejs/vite/issues/7390). + Each test can be run under either dev server mode or build mode. - `pnpm test` by default runs every test in both serve and build mode. diff --git a/docs/config/index.md b/docs/config/index.md index 1e824b7e431350..a8d8cb36079f0a 100644 --- a/docs/config/index.md +++ b/docs/config/index.md @@ -27,7 +27,8 @@ You can also explicitly specify a config file to use with the `--config` CLI opt vite --config my-config.js ``` -Note that Vite will replace `__filename`, `__dirname`, and `import.meta.url`. Using these as variable names will result in an error: +::: tip NOTE +Vite will replace `__filename`, `__dirname`, and `import.meta.url` in **CommonJS** and **TypeScript** config files. Using these as variable names will result in an error: ```js const __filename = "value" @@ -35,6 +36,8 @@ const __filename = "value" const "path/vite.config.js" = "value" ``` +::: + ### Config Intellisense Since Vite ships with TypeScript typings, you can leverage your IDE's intellisense with jsdoc type hints: @@ -324,6 +327,14 @@ export default defineConfig(({ command, mode }) => { }) ``` +### css.devSourcemap + +- **Experimental** +- **Type:** `boolean` +- **Default:** `false` + + Whether to enable sourcemaps during dev. + ### json.namedExports - **Type:** `boolean` @@ -355,7 +366,7 @@ export default defineConfig(({ command, mode }) => { }) ``` - By default, ESBuild is applied to `ts`, `jsx` and `tsx` files. You can customize this with `esbuild.include` and `esbuild.exclude`, both of which expect type of `string | RegExp | (string | RegExp)[]`. + By default, ESBuild is applied to `ts`, `jsx` and `tsx` files. You can customize this with `esbuild.include` and `esbuild.exclude`, which can be a regex, a [picomatch](https://github.com/micromatch/picomatch#globbing-features) pattern, or an array of either. In addition, you can also use `esbuild.jsxInject` to automatically inject JSX helper imports for every file transformed by ESBuild: @@ -374,7 +385,7 @@ export default defineConfig(({ command, mode }) => { - **Type:** `string | RegExp | (string | RegExp)[]` - **Related:** [Static Asset Handling](/guide/assets) - Specify additional [picomatch patterns](https://github.com/micromatch/picomatch) to be treated as static assets so that: + Specify additional [picomatch patterns](https://github.com/micromatch/picomatch#globbing-features) to be treated as static assets so that: - They will be excluded from the plugin transform pipeline when referenced from HTML or directly requested over `fetch` or XHR. @@ -549,7 +560,7 @@ export default defineConfig(({ command, mode }) => { `clientPort` is an advanced option that overrides the port only on the client side, allowing you to serve the websocket on a different port than the client code looks for it on. Useful if you're using an SSL proxy in front of your dev server. - When using `server.middlewareMode` or `server.https`, assigning `server.hmr.server` to your HTTP(S) server will process HMR connection requests through your server. This can be helpful when using self-signed certificates or when you want to expose Vite over a network on a single port. + If specifying `server.hmr.server`, Vite will process HMR connection requests through the provided server. If not in middleware mode, Vite will attempt to process HMR connection requests through the existing server. This can be helpful when using self-signed certificates or when you want to expose Vite over a network on a single port. ### server.watch @@ -962,9 +973,9 @@ export default defineConfig({ - **Type:** `string | string[]` - By default, Vite will crawl your `index.html` to detect dependencies that need to be pre-bundled. If `build.rollupOptions.input` is specified, Vite will crawl those entry points instead. + By default, Vite will crawl all your `.html` files to detect dependencies that need to be pre-bundled (ignoring `node_modules`, `build.outDir`, `__tests__` and `coverage`). If `build.rollupOptions.input` is specified, Vite will crawl those entry points instead. - If neither of these fit your needs, you can specify custom entries using this option - the value should be a [fast-glob pattern](https://github.com/mrmlnc/fast-glob#basic-syntax) or array of patterns that are relative from Vite project root. This will overwrite default entries inference. + If neither of these fit your needs, you can specify custom entries using this option - the value should be a [fast-glob pattern](https://github.com/mrmlnc/fast-glob#basic-syntax) or array of patterns that are relative from Vite project root. This will overwrite default entries inference. Only `node_modules` and `build.outDir` folders will be ignored by default when `optimizeDeps.entries` is explicitily defined. If other folders needs to be ignored, you can use an ignore pattern as part of the entries list, marked with an initial `!`. ### optimizeDeps.exclude diff --git a/docs/guide/api-hmr.md b/docs/guide/api-hmr.md index f4ddf59d8abcd1..46eabab04e8868 100644 --- a/docs/guide/api-hmr.md +++ b/docs/guide/api-hmr.md @@ -123,3 +123,11 @@ The following HMR events are dispatched by Vite automatically: - `'vite:error'` when an error occurs (e.g. syntax error) Custom HMR events can also be sent from plugins. See [handleHotUpdate](./api-plugin#handlehotupdate) for more details. + +## `hot.send(event, data)` + +Send custom events back to Vite's dev server. + +If called before connected, the data will be buffered and sent once the connection is established. + +See [Client-server Communication](/guide/api-plugin.html#client-server-communication) for more details. diff --git a/docs/guide/api-plugin.md b/docs/guide/api-plugin.md index b3888b0fd7009b..228755dd6f85c2 100644 --- a/docs/guide/api-plugin.md +++ b/docs/guide/api-plugin.md @@ -480,7 +480,7 @@ export default defineConfig({ Check out [Vite Rollup Plugins](https://vite-rollup-plugins.patak.dev) for a list of compatible official Rollup plugins with usage instructions. -## Path normalization +## Path Normalization Vite normalizes paths while resolving ids to use POSIX separators ( / ) while preserving the volume in Windows. On the other hand, Rollup keeps resolved paths untouched by default, so resolved ids have win32 separators ( \\ ) in Windows. However, Rollup plugins use a [`normalizePath` utility function](https://github.com/rollup/plugins/tree/master/packages/pluginutils#normalizepath) from `@rollup/pluginutils` internally, which converts separators to POSIX before performing comparisons. This means that when these plugins are used in Vite, the `include` and `exclude` config pattern and other similar paths against resolved ids comparisons work correctly. @@ -492,3 +492,87 @@ import { normalizePath } from 'vite' normalizePath('foo\\bar') // 'foo/bar' normalizePath('foo/bar') // 'foo/bar' ``` + +## Client-server Communication + +Since Vite 2.9, we provide some utilities for plugins to help handle the communication with clients. + +### Server to Client + +On the plugin side, we could use `server.ws.send` to boardcast events to all the clients: + +```js +// vite.config.js +export default defineConfig({ + plugins: [ + { + // ... + configureServer(server) { + server.ws.send('my:greetings', { msg: 'hello' }) + } + } + ] +}) +``` + +::: tip NOTE +We recommend **alway prefixing** your event names to avoid collisions with other plugins. +::: + +On the client side, use [`hot.on`](/guide/api-hmr.html#hot-on-event-cb) to listen to the events: + +```ts +// client side +if (import.meta.hot) { + import.meta.hot.on('my:greetings', (data) => { + console.log(data.msg) // hello + }) +} +``` + +### Client to Server + +To send events from the client to the server, we can use [`hot.send`](/guide/api-hmr.html#hot-send-event-payload): + +```ts +// client side +if (import.meta.hot) { + import.meta.hot.send('my:from-client', { msg: 'Hey!' }) +} +``` + +Then use `server.ws.on` and listen to the events on the server side: + +```js +// vite.config.js +export default defineConfig({ + plugins: [ + { + // ... + configureServer(server) { + server.ws.on('my:from-client', (data, client) => { + console.log('Message from client:', data.msg) // Hey! + // reply only to the client (if needed) + client.send('my:ack', { msg: 'Hi! I got your message!' }) + }) + } + } + ] +}) +``` + +### TypeScript for Custom Events + +It is possible to type custom events by extending the `CustomEventMap` interface: + +```ts +// events.d.ts +import 'vite/types/customEvent' + +declare module 'vite/types/customEvent' { + interface CustomEventMap { + 'custom:foo': { msg: string } + // 'event-key': payload + } +} +``` diff --git a/docs/guide/features.md b/docs/guide/features.md index 7bf870646da909..ebed85cd2d529d 100644 --- a/docs/guide/features.md +++ b/docs/guide/features.md @@ -352,6 +352,24 @@ In the production build, `.wasm` files smaller than `assetInlineLimit` will be i ## Web Workers +### Import with Constructors + +A web worker script can be imported using [`new Worker()`](https://developer.mozilla.org/en-US/docs/Web/API/Worker/Worker) and [`new SharedWorker()`](https://developer.mozilla.org/en-US/docs/Web/API/SharedWorker/SharedWorker). Compared to the worker suffixes, this syntax leans closer to the standards and is the **recommended** way to create workers. + +```ts +const worker = new Worker(new URL('./worker.js', import.meta.url)) +``` + +The worker constructor also accepts options, which can be used to create "module" workers: + +```ts +const worker = new Worker(new URL('./worker.js', import.meta.url), { + type: 'module' +}) +``` + +### Import with Query Suffixes + A web worker script can be directly imported by appending `?worker` or `?sharedworker` to the import request. The default export will be a custom worker constructor: ```js @@ -368,6 +386,8 @@ By default, the worker script will be emitted as a separate chunk in the product import MyWorker from './worker?worker&inline' ``` +See [Worker Options](/config/#worker-options) for details on configuring the bundling of all workers. + ## Build Optimizations > Features listed below are automatically applied as part of the build process and there is no need for explicit configuration unless you want to disable them. diff --git a/jest.config.ts b/jest.config.ts index 7d4831524d01c3..11663af4e08107 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -6,7 +6,7 @@ const config: Config.InitialOptions = { testMatch: process.env.VITE_TEST_BUILD ? ['**/playground/**/*.spec.[jt]s?(x)'] : ['**/*.spec.[jt]s?(x)'], - testTimeout: process.env.CI ? 30000 : 10000, + testTimeout: process.env.CI ? 50000 : 20000, globalSetup: './scripts/jestGlobalSetup.cjs', globalTeardown: './scripts/jestGlobalTeardown.cjs', testEnvironment: './scripts/jestEnv.cjs', diff --git a/package.json b/package.json index 72b7076ee65d01..878fd5c7de506f 100644 --- a/package.json +++ b/package.json @@ -34,41 +34,41 @@ "ci-docs": "run-s build-vite build-plugin-vue build-docs" }, "devDependencies": { - "@microsoft/api-extractor": "^7.19.4", + "@microsoft/api-extractor": "^7.19.5", "@types/fs-extra": "^9.0.13", - "@types/jest": "^27.4.0", - "@types/node": "^16.11.22", + "@types/jest": "^27.4.1", + "@types/node": "^16.11.26", "@types/prompts": "^2.0.14", "@types/semver": "^7.3.9", - "@typescript-eslint/eslint-plugin": "^5.11.0", - "@typescript-eslint/parser": "^5.11.0", + "@typescript-eslint/eslint-plugin": "^5.16.0", + "@typescript-eslint/parser": "^5.16.0", "conventional-changelog-cli": "^2.2.2", "cross-env": "^7.0.3", - "esbuild": "^0.14.14", - "eslint": "^8.8.0", - "eslint-define-config": "^1.2.4", + "esbuild": "^0.14.27", + "eslint": "^8.12.0", + "eslint-define-config": "^1.3.0", "eslint-plugin-node": "^11.1.0", "execa": "^5.1.1", - "fs-extra": "^10.0.0", + "fs-extra": "^10.0.1", "jest": "^27.5.1", - "lint-staged": "^12.3.3", - "minimist": "^1.2.5", + "lint-staged": "^12.3.7", + "minimist": "^1.2.6", "node-fetch": "^2.6.6", "npm-run-all": "^4.1.5", "picocolors": "^1.0.0", - "playwright-chromium": "^1.18.1", - "prettier": "2.5.1", + "playwright-chromium": "^1.20.1", + "prettier": "2.6.1", "prompts": "^2.4.2", "rimraf": "^3.0.2", "rollup": "^2.59.0", "semver": "^7.3.5", "simple-git-hooks": "^2.7.0", "sirv": "^2.0.2", - "ts-jest": "^27.1.3", + "ts-jest": "^27.1.4", "ts-node": "^10.4.0", "typescript": "~4.5.4", "vite": "workspace:*", - "vitepress": "^0.21.6" + "vitepress": "^0.22.3" }, "simple-git-hooks": { "pre-commit": "pnpm exec lint-staged --concurrent false", @@ -85,7 +85,7 @@ "eslint --ext .ts" ] }, - "packageManager": "pnpm@6.30.0", + "packageManager": "pnpm@6.32.3", "pnpm": { "overrides": { "vite": "workspace:*", diff --git a/packages/create-vite/package.json b/packages/create-vite/package.json index 5d873b83fe515b..ec8199455ef86f 100644 --- a/packages/create-vite/package.json +++ b/packages/create-vite/package.json @@ -26,7 +26,7 @@ "homepage": "https://github.com/vitejs/vite/tree/main/packages/create-vite#readme", "dependencies": { "kolorist": "^1.5.1", - "minimist": "^1.2.5", + "minimist": "^1.2.6", "prompts": "^2.4.2" } } diff --git a/packages/playground/assets/__tests__/assets.spec.ts b/packages/playground/assets/__tests__/assets.spec.ts index 0635236bd7369e..f53c783c52b606 100644 --- a/packages/playground/assets/__tests__/assets.spec.ts +++ b/packages/playground/assets/__tests__/assets.spec.ts @@ -194,6 +194,16 @@ test('?url import', async () => { ) }) +test('?url import on css', async () => { + const src = readFile('css/icons.css') + const txt = await page.textContent('.url-css') + expect(txt).toEqual( + isBuild + ? `data:text/css;base64,${Buffer.from(src).toString('base64')}` + : '/foo/css/icons.css' + ) +}) + describe('unicode url', () => { test('from js import', async () => { const src = readFile('テスト-測試-white space.js') diff --git a/packages/playground/assets/index.html b/packages/playground/assets/index.html index 25c889a445b771..7534ecbe1677bf 100644 --- a/packages/playground/assets/index.html +++ b/packages/playground/assets/index.html @@ -134,6 +134,9 @@

?raw import

?url import

+

?url import with css

+ +

new URL('...', import.meta.url)

@@ -242,6 +245,9 @@

import unicodeUrl from './テスト-測試-white space.js?url' text('.unicode-url', unicodeUrl) + import cssUrl from './css/icons.css?url' + text('.url-css', cssUrl) + // const url = new URL('non_existent_file.png', import.meta.url) const metaUrl = new URL('./nested/asset.png', import.meta.url) text('.import-meta-url', metaUrl) diff --git a/packages/playground/cli-module/__tests__/serve.js b/packages/playground/cli-module/__tests__/serve.js index 1cda05f0adc21a..2b354f566524bf 100644 --- a/packages/playground/cli-module/__tests__/serve.js +++ b/packages/playground/cli-module/__tests__/serve.js @@ -78,7 +78,7 @@ exports.serve = async function serve(root, isProd) { const timeoutError = `server process still alive after 3s` try { killProcess(serverProcess) - await resolvedOrTimeout(serverProcess, 3000, timeoutError) + await resolvedOrTimeout(serverProcess, 10000, timeoutError) } catch (e) { if (e === timeoutError || (!serverProcess.killed && !isWindows)) { collectErrorStreams('server', e) diff --git a/packages/playground/css-sourcemap/__tests__/build.spec.ts b/packages/playground/css-sourcemap/__tests__/build.spec.ts new file mode 100644 index 00000000000000..e36c1f52d2c1f8 --- /dev/null +++ b/packages/playground/css-sourcemap/__tests__/build.spec.ts @@ -0,0 +1,13 @@ +import { isBuild } from 'testUtils' + +if (isBuild) { + test('should not output sourcemap warning (#4939)', () => { + serverLogs.forEach((log) => { + expect(log).not.toMatch('Sourcemap is likely to be incorrect') + }) + }) +} else { + test('this file only includes test for build', () => { + expect(true).toBe(true) + }) +} diff --git a/packages/playground/css-sourcemap/__tests__/serve.spec.ts b/packages/playground/css-sourcemap/__tests__/serve.spec.ts new file mode 100644 index 00000000000000..0c6696b0dff7a2 --- /dev/null +++ b/packages/playground/css-sourcemap/__tests__/serve.spec.ts @@ -0,0 +1,282 @@ +import { fromComment } from 'convert-source-map' +import { URL } from 'url' +import { normalizePath } from 'vite' +import { isBuild, testDir } from 'testUtils' + +if (!isBuild) { + const root = normalizePath(testDir) + + const getStyleTagContentIncluding = async (content: string) => { + const styles = await page.$$('style') + for (const style of styles) { + const text = await style.textContent() + if (text.includes(content)) { + return text + } + } + throw new Error('Not found') + } + + const extractSourcemap = (content: string) => { + const lines = content.trim().split('\n') + return fromComment(lines[lines.length - 1]).toObject() + } + + const formatSourcemapForSnapshot = (map: any) => { + const m = { ...map } + delete m.file + delete m.names + m.sources = m.sources.map((source) => source.replace(root, '/root')) + return m + } + + test('inline css', async () => { + const css = await getStyleTagContentIncluding('.inline ') + const map = extractSourcemap(css) + expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(` + Object { + "mappings": "AAGO;AACP,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACX,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACf,CAAC,CAAC,CAAC;", + "sources": Array [ + "/root/index.html", + ], + "sourcesContent": Array [ + " + + + + +
+

CSS Sourcemap

+ +

<inline>

+ +

<linked>: no import

+

<linked>: with import

+ +

<imported>: no import

+

<imported>: with import

+ +

<imported sass>

+

<imported sass> with module

+ +

<imported less> with string additionalData

+ +

<imported stylus>

+
+ + + + + ", + ], + "version": 3, + } + `) + }) + + test('linked css', async () => { + const res = await page.request.get( + new URL('./linked.css', page.url()).href, + { + headers: { + accept: 'text/css' + } + } + ) + const css = await res.text() + const lines = css.split('\n') + expect(lines[lines.length - 1].includes('/*')).toBe(false) // expect no sourcemap + }) + + test('linked css with import', async () => { + const res = await page.request.get( + new URL('./linked-with-import.css', page.url()).href, + { + headers: { + accept: 'text/css' + } + } + ) + const css = await res.text() + const map = extractSourcemap(css) + expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(` + Object { + "mappings": "AAAA;EACE,UAAU;AACZ;;ACAA;EACE,UAAU;AACZ", + "sources": Array [ + "/root/be-imported.css", + "/root/linked-with-import.css", + ], + "sourcesContent": Array [ + ".be-imported { + color: red; + } + ", + "@import '@/be-imported.css'; + + .linked-with-import { + color: red; + } + ", + ], + "version": 3, + } + `) + }) + + test('imported css', async () => { + const css = await getStyleTagContentIncluding('.imported ') + const map = extractSourcemap(css) + expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(` + Object { + "mappings": "AAAA,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACX,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACb,CAAC;", + "sources": Array [ + "/root/imported.css", + ], + "sourcesContent": Array [ + ".imported { + color: red; + } + ", + ], + "version": 3, + } + `) + }) + + test('imported css with import', async () => { + const css = await getStyleTagContentIncluding('.imported-with-import ') + const map = extractSourcemap(css) + expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(` + Object { + "mappings": "AAAA;EACE,UAAU;AACZ;;ACAA;EACE,UAAU;AACZ", + "sources": Array [ + "/root/be-imported.css", + "/root/imported-with-import.css", + ], + "sourcesContent": Array [ + ".be-imported { + color: red; + } + ", + "@import '@/be-imported.css'; + + .imported-with-import { + color: red; + } + ", + ], + "version": 3, + } + `) + }) + + test('imported sass', async () => { + const css = await getStyleTagContentIncluding('.imported-sass ') + const map = extractSourcemap(css) + expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(` + Object { + "mappings": "AACE;EACE", + "sources": Array [ + "/root/imported.sass", + ], + "sourcesContent": Array [ + ".imported + &-sass + color: red + ", + ], + "version": 3, + } + `) + }) + + test('imported sass module', async () => { + const css = await getStyleTagContentIncluding('._imported-sass-module_') + const map = extractSourcemap(css) + expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(` + Object { + "mappings": "AACE;EACE", + "sources": Array [ + "/root/imported.module.sass", + ], + "sourcesContent": Array [ + ".imported + &-sass-module + color: red + ", + ], + "version": 3, + } + `) + }) + + test('imported less', async () => { + const css = await getStyleTagContentIncluding('.imported-less ') + const map = extractSourcemap(css) + expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(` + Object { + "mappings": "AACE;EACE", + "sources": Array [ + "/root/imported.less", + ], + "sourcesContent": Array [ + ".imported { + &-less { + color: @color; + } + } + ", + ], + "version": 3, + } + `) + }) + + test('imported stylus', async () => { + const css = await getStyleTagContentIncluding('.imported-stylus ') + const map = extractSourcemap(css) + expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(` + Object { + "mappings": "AACE;EACE,cAAM", + "sources": Array [ + "/root/imported.styl", + ], + "sourcesContent": Array [ + ".imported + &-stylus + color blue-red-mixed + ", + ], + "version": 3, + } + `) + }) + + test('should not output missing source file warning', () => { + serverLogs.forEach((log) => { + expect(log).not.toMatch(/Sourcemap for .+ points to missing source files/) + }) + }) +} else { + test('this file only includes test for serve', () => { + expect(true).toBe(true) + }) +} diff --git a/packages/playground/css-sourcemap/be-imported.css b/packages/playground/css-sourcemap/be-imported.css new file mode 100644 index 00000000000000..a29e5f77e3cb5d --- /dev/null +++ b/packages/playground/css-sourcemap/be-imported.css @@ -0,0 +1,3 @@ +.be-imported { + color: red; +} diff --git a/packages/playground/css-sourcemap/imported-with-import.css b/packages/playground/css-sourcemap/imported-with-import.css new file mode 100644 index 00000000000000..6a1ed3c3772698 --- /dev/null +++ b/packages/playground/css-sourcemap/imported-with-import.css @@ -0,0 +1,5 @@ +@import '@/be-imported.css'; + +.imported-with-import { + color: red; +} diff --git a/packages/playground/css-sourcemap/imported.css b/packages/playground/css-sourcemap/imported.css new file mode 100644 index 00000000000000..9c9b32924962dc --- /dev/null +++ b/packages/playground/css-sourcemap/imported.css @@ -0,0 +1,3 @@ +.imported { + color: red; +} diff --git a/packages/playground/css-sourcemap/imported.less b/packages/playground/css-sourcemap/imported.less new file mode 100644 index 00000000000000..e71b15eb102441 --- /dev/null +++ b/packages/playground/css-sourcemap/imported.less @@ -0,0 +1,5 @@ +.imported { + &-less { + color: @color; + } +} diff --git a/packages/playground/css-sourcemap/imported.module.sass b/packages/playground/css-sourcemap/imported.module.sass new file mode 100644 index 00000000000000..448a5e7e31f75a --- /dev/null +++ b/packages/playground/css-sourcemap/imported.module.sass @@ -0,0 +1,3 @@ +.imported + &-sass-module + color: red diff --git a/packages/playground/css-sourcemap/imported.sass b/packages/playground/css-sourcemap/imported.sass new file mode 100644 index 00000000000000..06fa634d5dd4e9 --- /dev/null +++ b/packages/playground/css-sourcemap/imported.sass @@ -0,0 +1,3 @@ +.imported + &-sass + color: red diff --git a/packages/playground/css-sourcemap/imported.styl b/packages/playground/css-sourcemap/imported.styl new file mode 100644 index 00000000000000..83c7cf517acf4d --- /dev/null +++ b/packages/playground/css-sourcemap/imported.styl @@ -0,0 +1,3 @@ +.imported + &-stylus + color blue-red-mixed diff --git a/packages/playground/css-sourcemap/index.html b/packages/playground/css-sourcemap/index.html new file mode 100644 index 00000000000000..a943c1d113a9b4 --- /dev/null +++ b/packages/playground/css-sourcemap/index.html @@ -0,0 +1,45 @@ + + + + + +
+

CSS Sourcemap

+ +

<inline>

+ +

<linked>: no import

+

<linked>: with import

+ +

<imported>: no import

+

<imported>: with import

+ +

<imported sass>

+

<imported sass> with module

+ +

<imported less> with string additionalData

+ +

<imported stylus>

+
+ + + + diff --git a/packages/playground/css-sourcemap/linked-with-import.css b/packages/playground/css-sourcemap/linked-with-import.css new file mode 100644 index 00000000000000..6f65d92441fa49 --- /dev/null +++ b/packages/playground/css-sourcemap/linked-with-import.css @@ -0,0 +1,5 @@ +@import '@/be-imported.css'; + +.linked-with-import { + color: red; +} diff --git a/packages/playground/css-sourcemap/linked.css b/packages/playground/css-sourcemap/linked.css new file mode 100644 index 00000000000000..e3b67c83872ac0 --- /dev/null +++ b/packages/playground/css-sourcemap/linked.css @@ -0,0 +1,3 @@ +.linked { + color: red; +} diff --git a/packages/playground/css-sourcemap/package.json b/packages/playground/css-sourcemap/package.json new file mode 100644 index 00000000000000..c29f18d4dee0d7 --- /dev/null +++ b/packages/playground/css-sourcemap/package.json @@ -0,0 +1,18 @@ +{ + "name": "test-css-sourcemap", + "private": true, + "version": "0.0.0", + "scripts": { + "dev": "vite", + "build": "vite build", + "debug": "node --inspect-brk ../../vite/bin/vite", + "preview": "vite preview" + }, + "devDependencies": { + "convert-source-map": "^1.8.0", + "less": "^4.1.2", + "magic-string": "^0.25.7", + "sass": "^1.43.4", + "stylus": "^0.55.0" + } +} diff --git a/packages/playground/css-sourcemap/vite.config.js b/packages/playground/css-sourcemap/vite.config.js new file mode 100644 index 00000000000000..4fbeaa9a13aeb0 --- /dev/null +++ b/packages/playground/css-sourcemap/vite.config.js @@ -0,0 +1,61 @@ +const MagicString = require('magic-string') + +/** + * @type {import('vite').UserConfig} + */ +module.exports = { + resolve: { + alias: { + '@': __dirname + } + }, + css: { + devSourcemap: true, + preprocessorOptions: { + less: { + additionalData: '@color: red;' + }, + styl: { + additionalData: (content, filename) => { + const ms = new MagicString(content, { filename }) + + const willBeReplaced = 'blue-red-mixed' + const start = content.indexOf(willBeReplaced) + ms.overwrite(start, start + willBeReplaced.length, 'purple') + + const map = ms.generateMap({ hires: true }) + map.file = filename + map.sources = [filename] + + return { + content: ms.toString(), + map + } + } + } + } + }, + build: { + sourcemap: true + }, + plugins: [ + { + name: 'virtual-html', + configureServer(server) { + server.middlewares.use(async (req, res, next) => { + if (req.url === '/virtual.html') { + const t = await server.transformIndexHtml( + '/virtual.html', + '

virtual html

' + ) + res.setHeader('Content-Type', 'text/html') + res.statusCode = 200 + res.end(t) + return + } + next() + }) + } + } + ] +} diff --git a/packages/playground/css/__tests__/css.spec.ts b/packages/playground/css/__tests__/css.spec.ts index 360e46dbbba150..3fe4a09bcc94c8 100644 --- a/packages/playground/css/__tests__/css.spec.ts +++ b/packages/playground/css/__tests__/css.spec.ts @@ -54,6 +54,12 @@ test('css import from js', async () => { await untilUpdated(() => getColor(atImport), 'blue') }) +test('css import asset with space', async () => { + const importedWithSpace = await page.$('.import-with-space') + + expect(await getBg(importedWithSpace)).toMatch(/.*ok\..*png/) +}) + test('postcss config', async () => { const imported = await page.$('.postcss .nesting') expect(await getColor(imported)).toBe('pink') @@ -365,6 +371,14 @@ test('minify css', async () => { expect(cssFile).not.toMatch('#ffff00b3') }) +test('?raw', async () => { + const rawImportCss = await page.$('.raw-imported-css') + + expect(await rawImportCss.textContent()).toBe( + require('fs').readFileSync(require.resolve('../raw-imported.css'), 'utf-8') + ) +}) + test('import css in less', async () => { expect(await getColor('.css-in-less')).toBe('yellow') expect(await getColor('.css-in-less-2')).toBe('blue') diff --git a/packages/playground/css/folder with space/ok.png b/packages/playground/css/folder with space/ok.png new file mode 100644 index 00000000000000..a8d1e52510c41c Binary files /dev/null and b/packages/playground/css/folder with space/ok.png differ diff --git a/packages/playground/css/folder with space/space.css b/packages/playground/css/folder with space/space.css new file mode 100644 index 00000000000000..55a8532da32a94 --- /dev/null +++ b/packages/playground/css/folder with space/space.css @@ -0,0 +1,5 @@ +.import-with-space { + color: green; + background: url(spacefolder/ok.png); + background-position: center; +} diff --git a/packages/playground/css/imported.css b/packages/playground/css/imported.css index 65743d08b932a7..7d582995fab9fd 100644 --- a/packages/playground/css/imported.css +++ b/packages/playground/css/imported.css @@ -1,4 +1,5 @@ @import './imported-at-import.css'; +@import 'spacefolder/space.css'; .imported { color: green; diff --git a/packages/playground/css/index.html b/packages/playground/css/index.html index acbbe44a7f8a60..060aed7fb1b27f 100644 --- a/packages/playground/css/index.html +++ b/packages/playground/css/index.html @@ -10,6 +10,10 @@

CSS

@import in import from js: This should be purple

+

+ @import from file with space: This should be green and have a background + image +

Imported css string:


   

@@ -118,6 +122,9 @@ 

CSS


+
+  

Raw Support

+

 
 
 
diff --git a/packages/playground/css/main.js b/packages/playground/css/main.js
index 3599ed0d60562c..6edd840a87c5e7 100644
--- a/packages/playground/css/main.js
+++ b/packages/playground/css/main.js
@@ -12,6 +12,9 @@ text('.imported-less', less)
 import stylus from './stylus.styl'
 text('.imported-stylus', stylus)
 
+import rawCss from './raw-imported.css?raw'
+text('.raw-imported-css', rawCss)
+
 import mod from './mod.module.css'
 document.querySelector('.modules').classList.add(mod['apply-color'])
 text('.modules-code', JSON.stringify(mod, null, 2))
diff --git a/packages/playground/css/raw-imported.css b/packages/playground/css/raw-imported.css
new file mode 100644
index 00000000000000..ac0aee96390c33
--- /dev/null
+++ b/packages/playground/css/raw-imported.css
@@ -0,0 +1,3 @@
+.raw-imported {
+  color: yellow;
+}
diff --git a/packages/playground/css/vite.config.js b/packages/playground/css/vite.config.js
index 53d001d8387989..639a1302debb88 100644
--- a/packages/playground/css/vite.config.js
+++ b/packages/playground/css/vite.config.js
@@ -9,7 +9,8 @@ module.exports = {
   },
   resolve: {
     alias: {
-      '@': __dirname
+      '@': __dirname,
+      spacefolder: __dirname + '/folder with space'
     }
   },
   css: {
diff --git a/packages/playground/glob-import/__tests__/glob-import.spec.ts b/packages/playground/glob-import/__tests__/glob-import.spec.ts
index fff8d9fe202ebc..ebdf6c0ab29193 100644
--- a/packages/playground/glob-import/__tests__/glob-import.spec.ts
+++ b/packages/playground/glob-import/__tests__/glob-import.spec.ts
@@ -66,6 +66,12 @@ const rawResult = {
   }
 }
 
+const relativeRawResult = {
+  '../glob-import/dir/baz.json': {
+    msg: 'baz'
+  }
+}
+
 test('should work', async () => {
   expect(await page.textContent('.result')).toBe(
     JSON.stringify(allResult, null, 2)
@@ -81,6 +87,12 @@ test('import glob raw', async () => {
   )
 })
 
+test('import relative glob raw', async () => {
+  expect(await page.textContent('.relative-glob-raw')).toBe(
+    JSON.stringify(relativeRawResult, null, 2)
+  )
+})
+
 if (!isBuild) {
   test('hmr for adding/removing files', async () => {
     addFile('dir/a.js', '')
diff --git a/packages/playground/glob-import/index.html b/packages/playground/glob-import/index.html
index 52d41b817a169c..64f456aeb4d6a2 100644
--- a/packages/playground/glob-import/index.html
+++ b/packages/playground/glob-import/index.html
@@ -1,6 +1,7 @@
 

 

 

+

 
 
 
+
+
diff --git a/packages/playground/hmr/__tests__/hmr.spec.ts b/packages/playground/hmr/__tests__/hmr.spec.ts
index 1f28763a90df94..6ddc2345ae4fb4 100644
--- a/packages/playground/hmr/__tests__/hmr.spec.ts
+++ b/packages/playground/hmr/__tests__/hmr.spec.ts
@@ -16,7 +16,7 @@ if (!isBuild) {
   test('self accept', async () => {
     const el = await page.$('.app')
 
-    editFile('hmr.js', (code) => code.replace('const foo = 1', 'const foo = 2'))
+    editFile('hmr.ts', (code) => code.replace('const foo = 1', 'const foo = 2'))
     await untilUpdated(() => el.textContent(), '2')
 
     expect(browserLogs).toMatchObject([
@@ -24,11 +24,11 @@ if (!isBuild) {
       'foo was: 1',
       '(self-accepting 1) foo is now: 2',
       '(self-accepting 2) foo is now: 2',
-      '[vite] hot updated: /hmr.js'
+      '[vite] hot updated: /hmr.ts'
     ])
     browserLogs.length = 0
 
-    editFile('hmr.js', (code) => code.replace('const foo = 2', 'const foo = 3'))
+    editFile('hmr.ts', (code) => code.replace('const foo = 2', 'const foo = 3'))
     await untilUpdated(() => el.textContent(), '3')
 
     expect(browserLogs).toMatchObject([
@@ -36,7 +36,7 @@ if (!isBuild) {
       'foo was: 2',
       '(self-accepting 1) foo is now: 3',
       '(self-accepting 2) foo is now: 3',
-      '[vite] hot updated: /hmr.js'
+      '[vite] hot updated: /hmr.ts'
     ])
     browserLogs.length = 0
   })
@@ -57,7 +57,7 @@ if (!isBuild) {
       '(single dep) nested foo is now: 1',
       '(multi deps) foo is now: 2',
       '(multi deps) nested foo is now: 1',
-      '[vite] hot updated: /hmrDep.js via /hmr.js'
+      '[vite] hot updated: /hmrDep.js via /hmr.ts'
     ])
     browserLogs.length = 0
 
@@ -74,7 +74,7 @@ if (!isBuild) {
       '(single dep) nested foo is now: 1',
       '(multi deps) foo is now: 3',
       '(multi deps) nested foo is now: 1',
-      '[vite] hot updated: /hmrDep.js via /hmr.js'
+      '[vite] hot updated: /hmrDep.js via /hmr.ts'
     ])
     browserLogs.length = 0
   })
@@ -95,7 +95,7 @@ if (!isBuild) {
       '(single dep) nested foo is now: 2',
       '(multi deps) foo is now: 3',
       '(multi deps) nested foo is now: 2',
-      '[vite] hot updated: /hmrDep.js via /hmr.js'
+      '[vite] hot updated: /hmrDep.js via /hmr.ts'
     ])
     browserLogs.length = 0
 
@@ -112,7 +112,7 @@ if (!isBuild) {
       '(single dep) nested foo is now: 3',
       '(multi deps) foo is now: 3',
       '(multi deps) nested foo is now: 3',
-      '[vite] hot updated: /hmrDep.js via /hmr.js'
+      '[vite] hot updated: /hmrDep.js via /hmr.ts'
     ])
     browserLogs.length = 0
   })
@@ -123,11 +123,16 @@ if (!isBuild) {
     await untilUpdated(() => el.textContent(), 'edited')
   })
 
+  test('plugin client-server communication', async () => {
+    const el = await page.$('.custom-communication')
+    await untilUpdated(() => el.textContent(), '3')
+  })
+
   test('full-reload encodeURI path', async () => {
     await page.goto(
       viteTestUrl + '/unicode-path/中文-にほんご-한글-🌕🌖🌗/index.html'
     )
-    let el = await page.$('#app')
+    const el = await page.$('#app')
     expect(await el.textContent()).toBe('title')
     await editFile(
       'unicode-path/中文-にほんご-한글-🌕🌖🌗/index.html',
diff --git a/packages/playground/hmr/event.d.ts b/packages/playground/hmr/event.d.ts
new file mode 100644
index 00000000000000..151a9cc3b861cd
--- /dev/null
+++ b/packages/playground/hmr/event.d.ts
@@ -0,0 +1,9 @@
+import 'vite/types/customEvent'
+
+declare module 'vite/types/customEvent' {
+  interface CustomEventMap {
+    'custom:foo': { msg: string }
+    'custom:remote-add': { a: number; b: number }
+    'custom:remote-add-result': { result: string }
+  }
+}
diff --git a/packages/playground/hmr/hmr.js b/packages/playground/hmr/hmr.ts
similarity index 81%
rename from packages/playground/hmr/hmr.js
rename to packages/playground/hmr/hmr.ts
index 01dca20f5dd71c..113b87bc5865d4 100644
--- a/packages/playground/hmr/hmr.js
+++ b/packages/playground/hmr/hmr.ts
@@ -41,7 +41,7 @@ if (import.meta.hot) {
         update.type === 'css-update' && update.path.match('global.css')
     )
     if (cssUpdate) {
-      const el = document.querySelector('#global-css')
+      const el = document.querySelector('#global-css') as HTMLLinkElement
       text('.css-prev', el.href)
       // We don't have a vite:afterUpdate event, but updates are currently sync
       setTimeout(() => {
@@ -54,9 +54,15 @@ if (import.meta.hot) {
     console.log(`>>> vite:error -- ${event.type}`)
   })
 
-  import.meta.hot.on('foo', ({ msg }) => {
+  import.meta.hot.on('custom:foo', ({ msg }) => {
     text('.custom', msg)
   })
+
+  // send custom event to server to calculate 1 + 2
+  import.meta.hot.send('custom:remote-add', { a: 1, b: 2 })
+  import.meta.hot.on('custom:remote-add-result', ({ result }) => {
+    text('.custom-communication', result)
+  })
 }
 
 function text(el, text) {
diff --git a/packages/playground/hmr/index.html b/packages/playground/hmr/index.html
index 766338598e51ad..0add7c26011a01 100644
--- a/packages/playground/hmr/index.html
+++ b/packages/playground/hmr/index.html
@@ -1,9 +1,10 @@
 
-
+
 
 
+
diff --git a/packages/playground/hmr/tsconfig.json b/packages/playground/hmr/tsconfig.json new file mode 100644 index 00000000000000..41b16fdc65ec8c --- /dev/null +++ b/packages/playground/hmr/tsconfig.json @@ -0,0 +1,15 @@ +{ + "include": ["."], + "exclude": ["**/dist/**"], + "compilerOptions": { + "target": "es2019", + "module": "esnext", + "outDir": "dist", + "allowJs": true, + "esModuleInterop": true, + "moduleResolution": "node", + "baseUrl": ".", + "jsx": "preserve", + "types": ["vite/client", "jest", "node"] + } +} diff --git a/packages/playground/hmr/vite.config.js b/packages/playground/hmr/vite.config.js deleted file mode 100644 index c34637844e2170..00000000000000 --- a/packages/playground/hmr/vite.config.js +++ /dev/null @@ -1,23 +0,0 @@ -/** - * @type {import('vite').UserConfig} - */ -module.exports = { - plugins: [ - { - name: 'mock-custom', - async handleHotUpdate({ file, read, server }) { - if (file.endsWith('customFile.js')) { - const content = await read() - const msg = content.match(/export const msg = '(\w+)'/)[1] - server.ws.send({ - type: 'custom', - event: 'foo', - data: { - msg - } - }) - } - } - } - ] -} diff --git a/packages/playground/hmr/vite.config.ts b/packages/playground/hmr/vite.config.ts new file mode 100644 index 00000000000000..ef5d3cf36a2fcb --- /dev/null +++ b/packages/playground/hmr/vite.config.ts @@ -0,0 +1,21 @@ +import { defineConfig } from 'vite' + +export default defineConfig({ + plugins: [ + { + name: 'mock-custom', + async handleHotUpdate({ file, read, server }) { + if (file.endsWith('customFile.js')) { + const content = await read() + const msg = content.match(/export const msg = '(\w+)'/)[1] + server.ws.send('custom:foo', { msg }) + } + }, + configureServer(server) { + server.ws.on('custom:remote-add', ({ a, b }, client) => { + client.send('custom:remote-add-result', { result: a + b }) + }) + } + } + ] +}) diff --git a/packages/playground/optimize-deps/__tests__/optimize-deps.spec.ts b/packages/playground/optimize-deps/__tests__/optimize-deps.spec.ts index 3c45287017fb44..d95a6d984cd9aa 100644 --- a/packages/playground/optimize-deps/__tests__/optimize-deps.spec.ts +++ b/packages/playground/optimize-deps/__tests__/optimize-deps.spec.ts @@ -66,6 +66,12 @@ test('import from dep with .notjs files', async () => { expect(await page.textContent('.not-js')).toMatch(`[success]`) }) +test('dep with dynamic import', async () => { + expect(await page.textContent('.dep-with-dynamic-import')).toMatch( + `[success]` + ) +}) + test('dep with css import', async () => { expect(await getColor('h1')).toBe('red') }) diff --git a/packages/playground/optimize-deps/dep-with-dynamic-import/dynamic.js b/packages/playground/optimize-deps/dep-with-dynamic-import/dynamic.js new file mode 100644 index 00000000000000..ea435dc36b7d48 --- /dev/null +++ b/packages/playground/optimize-deps/dep-with-dynamic-import/dynamic.js @@ -0,0 +1 @@ +export const foo = '[success] dependency with dynamic import' diff --git a/packages/playground/optimize-deps/dep-with-dynamic-import/index.js b/packages/playground/optimize-deps/dep-with-dynamic-import/index.js new file mode 100644 index 00000000000000..68a78d10d6e2d2 --- /dev/null +++ b/packages/playground/optimize-deps/dep-with-dynamic-import/index.js @@ -0,0 +1,4 @@ +export const lazyFoo = async function () { + const { foo } = await import('./dynamic.js') + return foo +} diff --git a/packages/playground/optimize-deps/dep-with-dynamic-import/package.json b/packages/playground/optimize-deps/dep-with-dynamic-import/package.json new file mode 100644 index 00000000000000..81c5d2dda6a62a --- /dev/null +++ b/packages/playground/optimize-deps/dep-with-dynamic-import/package.json @@ -0,0 +1,6 @@ +{ + "name": "dep-with-dynamic-import", + "private": true, + "version": "0.0.0", + "main": "index.js" +} diff --git a/packages/playground/optimize-deps/index.html b/packages/playground/optimize-deps/index.html index fc1b83a6b50c65..2be896d00acba9 100644 --- a/packages/playground/optimize-deps/index.html +++ b/packages/playground/optimize-deps/index.html @@ -41,6 +41,9 @@

import * as ...

Import from dependency with .notjs files

+

Import from dependency with dynamic import

+
+

Dep w/ special file format supported via plugins

@@ -88,6 +91,11 @@

Reused variable names

import { notjsValue } from 'dep-not-js' text('.not-js', notjsValue) + import { lazyFoo } from 'dep-with-dynamic-import' + lazyFoo().then((foo) => { + text('.dep-with-dynamic-import', foo) + }) + import { createApp } from 'vue' import { createStore } from 'vuex' if (typeof createApp === 'function' && typeof createStore === 'function') { diff --git a/packages/playground/optimize-deps/package.json b/packages/playground/optimize-deps/package.json index 09c578d684ffe7..2752e691da6fb2 100644 --- a/packages/playground/optimize-deps/package.json +++ b/packages/playground/optimize-deps/package.json @@ -18,6 +18,7 @@ "dep-linked": "link:./dep-linked", "dep-linked-include": "link:./dep-linked-include", "dep-not-js": "file:./dep-not-js", + "dep-with-dynamic-import": "file:./dep-with-dynamic-import", "lodash-es": "^4.17.21", "nested-exclude": "file:./nested-exclude", "phoenix": "^1.6.2", diff --git a/packages/playground/resolve/__tests__/resolve.spec.ts b/packages/playground/resolve/__tests__/resolve.spec.ts index b64da138033fc0..c8c85d8df9b806 100644 --- a/packages/playground/resolve/__tests__/resolve.spec.ts +++ b/packages/playground/resolve/__tests__/resolve.spec.ts @@ -58,6 +58,12 @@ test('dont add extension to directory name (./dir-with-ext.js/index.js)', async expect(await page.textContent('.dir-with-ext')).toMatch('[success]') }) +test('do not resolve to the `module` field if the importer is a `require` call', async () => { + expect(await page.textContent('.require-pkg-with-module-field')).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]') }) diff --git a/packages/playground/resolve/index.html b/packages/playground/resolve/index.html index c0569345d86837..2c4ed7b9aa760c 100644 --- a/packages/playground/resolve/index.html +++ b/packages/playground/resolve/index.html @@ -58,6 +58,9 @@

Resolve file name containing dot

Browser Field

fail

+

Don't resolve to the `module` field if the importer is a `require` call

+

fail

+

CSS Entry

@@ -181,6 +184,9 @@

resolve package that contains # in path

text('.browser', main) } + import { msg as requireButWithModuleFieldMsg } from 'require-pkg-with-module-field' + text('.require-pkg-with-module-field', requireButWithModuleFieldMsg) + import { msg as customExtMsg } from './custom-ext' text('.custom-ext', customExtMsg) diff --git a/packages/playground/resolve/package.json b/packages/playground/resolve/package.json index 5e0f53b4c8468a..dda4476bc6ae82 100644 --- a/packages/playground/resolve/package.json +++ b/packages/playground/resolve/package.json @@ -12,6 +12,7 @@ "@babel/runtime": "^7.16.0", "es5-ext": "0.10.53", "normalize.css": "^8.0.1", + "require-pkg-with-module-field": "link:./require-pkg-with-module-field", "resolve-browser-field": "link:./browser-field", "resolve-custom-condition": "link:./custom-condition", "resolve-custom-main-field": "link:./custom-main-field", diff --git a/packages/playground/resolve/require-pkg-with-module-field/dep.cjs b/packages/playground/resolve/require-pkg-with-module-field/dep.cjs new file mode 100644 index 00000000000000..3fb20b76d48b79 --- /dev/null +++ b/packages/playground/resolve/require-pkg-with-module-field/dep.cjs @@ -0,0 +1,5 @@ +const BigNumber = require('bignumber.js') + +const x = new BigNumber('1111222233334444555566') + +module.exports = x.toString() diff --git a/packages/playground/resolve/require-pkg-with-module-field/index.cjs b/packages/playground/resolve/require-pkg-with-module-field/index.cjs new file mode 100644 index 00000000000000..da215f306d1ac1 --- /dev/null +++ b/packages/playground/resolve/require-pkg-with-module-field/index.cjs @@ -0,0 +1,8 @@ +const dep = require('./dep.cjs') + +const msg = + dep === '1.111222233334444555566e+21' + ? '[success] require-pkg-with-module-field' + : '[failed] require-pkg-with-module-field' + +exports.msg = msg diff --git a/packages/playground/resolve/require-pkg-with-module-field/package.json b/packages/playground/resolve/require-pkg-with-module-field/package.json new file mode 100644 index 00000000000000..e409343a7567d5 --- /dev/null +++ b/packages/playground/resolve/require-pkg-with-module-field/package.json @@ -0,0 +1,9 @@ +{ + "name": "require-pkg-with-module-field", + "private": true, + "version": "1.0.0", + "main": "./index.cjs", + "dependencies": { + "bignumber.js": "9.0.2" + } +} diff --git a/packages/playground/resolve/vite.config.js b/packages/playground/resolve/vite.config.js index be1b75e431383a..0550d1ecf6f044 100644 --- a/packages/playground/resolve/vite.config.js +++ b/packages/playground/resolve/vite.config.js @@ -40,5 +40,8 @@ module.exports = { } } } - ] + ], + optimizeDeps: { + include: ['require-pkg-with-module-field'] + } } diff --git a/packages/playground/vue-sourcemap/Css.vue b/packages/playground/vue-sourcemap/Css.vue new file mode 100644 index 00000000000000..19668de8d33965 --- /dev/null +++ b/packages/playground/vue-sourcemap/Css.vue @@ -0,0 +1,23 @@ + + + + + + + diff --git a/packages/playground/vue-sourcemap/Less.vue b/packages/playground/vue-sourcemap/Less.vue new file mode 100644 index 00000000000000..f12a3e55f2111c --- /dev/null +++ b/packages/playground/vue-sourcemap/Less.vue @@ -0,0 +1,9 @@ + + + diff --git a/packages/playground/vue-sourcemap/Main.vue b/packages/playground/vue-sourcemap/Main.vue new file mode 100644 index 00000000000000..04ddf50071ccb3 --- /dev/null +++ b/packages/playground/vue-sourcemap/Main.vue @@ -0,0 +1,16 @@ + + + diff --git a/packages/playground/vue-sourcemap/Sass.vue b/packages/playground/vue-sourcemap/Sass.vue new file mode 100644 index 00000000000000..0fded031a52c72 --- /dev/null +++ b/packages/playground/vue-sourcemap/Sass.vue @@ -0,0 +1,8 @@ + + + diff --git a/packages/playground/vue-sourcemap/SassWithImport.vue b/packages/playground/vue-sourcemap/SassWithImport.vue new file mode 100644 index 00000000000000..7a00420a00bb3a --- /dev/null +++ b/packages/playground/vue-sourcemap/SassWithImport.vue @@ -0,0 +1,11 @@ + + + diff --git a/packages/playground/vue-sourcemap/__tests__/build.spec.ts b/packages/playground/vue-sourcemap/__tests__/build.spec.ts new file mode 100644 index 00000000000000..e36c1f52d2c1f8 --- /dev/null +++ b/packages/playground/vue-sourcemap/__tests__/build.spec.ts @@ -0,0 +1,13 @@ +import { isBuild } from 'testUtils' + +if (isBuild) { + test('should not output sourcemap warning (#4939)', () => { + serverLogs.forEach((log) => { + expect(log).not.toMatch('Sourcemap is likely to be incorrect') + }) + }) +} else { + test('this file only includes test for build', () => { + expect(true).toBe(true) + }) +} diff --git a/packages/playground/vue-sourcemap/__tests__/serve.spec.ts b/packages/playground/vue-sourcemap/__tests__/serve.spec.ts new file mode 100644 index 00000000000000..193b0afb9ba73f --- /dev/null +++ b/packages/playground/vue-sourcemap/__tests__/serve.spec.ts @@ -0,0 +1,283 @@ +import { fromComment } from 'convert-source-map' +import { normalizePath } from 'vite' +import { isBuild, testDir } from 'testUtils' + +if (!isBuild) { + const root = normalizePath(testDir) + + const getStyleTagContentIncluding = async (content: string) => { + const styles = await page.$$('style') + for (const style of styles) { + const text = await style.textContent() + if (text.includes(content)) { + return text + } + } + throw new Error('Not found') + } + + const extractSourcemap = (content: string) => { + const lines = content.trim().split('\n') + return fromComment(lines[lines.length - 1]).toObject() + } + + const formatSourcemapForSnapshot = (map: any) => { + const m = { ...map } + delete m.file + delete m.names + m.sources = m.sources.map((source) => source.replace(root, '/root')) + return m + } + + test('css', async () => { + const css = await getStyleTagContentIncluding('.css ') + const map = extractSourcemap(css) + expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(` + Object { + "mappings": ";AAOA;EACE,UAAU;AACZ", + "sources": Array [ + "/root/Css.vue", + ], + "sourcesContent": Array [ + " + + + + + + + ", + ], + "version": 3, + } + `) + }) + + test('css module', async () => { + const css = await getStyleTagContentIncluding('._css-module_') + const map = extractSourcemap(css) + expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(` + Object { + "mappings": ";AAaA;EACE,UAAU;AACZ", + "sources": Array [ + "/root/Css.vue", + ], + "sourcesContent": Array [ + " + + + + + + + ", + ], + "version": 3, + } + `) + }) + + test('css scoped', async () => { + const css = await getStyleTagContentIncluding('.css-scoped[data-v-') + const map = extractSourcemap(css) + expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(` + Object { + "mappings": ";AAmBA;EACE,UAAU;AACZ", + "sources": Array [ + "/root/Css.vue", + ], + "sourcesContent": Array [ + " + + + + + + + ", + ], + "version": 3, + } + `) + }) + + test('sass', async () => { + const css = await getStyleTagContentIncluding('.sass ') + const map = extractSourcemap(css) + expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(` + Object { + "mappings": "AAKA;EACE", + "sources": Array [ + "/root/Sass.vue", + ], + "sourcesContent": Array [ + " + + + ", + ], + "version": 3, + } + `) + }) + + test('sass with import', async () => { + const css = await getStyleTagContentIncluding('.sass-with-import ') + const map = extractSourcemap(css) + expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(` + Object { + "mappings": "AAAA;EACE;;ACOF;EACE", + "sources": Array [ + "/root/sassWithImportImported.sass", + "/root/SassWithImport.vue", + ], + "sourcesContent": Array [ + ".sass-with-import-imported + color: red + ", + " + + + ", + ], + "version": 3, + } + `) + }) + + test('less with additionalData', async () => { + const css = await getStyleTagContentIncluding('.less ') + const map = extractSourcemap(css) + expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(` + Object { + "mappings": "AAKA;EACE", + "sources": Array [ + "/root/Less.vue", + ], + "sourcesContent": Array [ + " + + + ", + ], + "version": 3, + } + `) + }) + + test('src imported', async () => { + const css = await getStyleTagContentIncluding('.src-import[data-v-') + const map = extractSourcemap(css) + expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(` + Object { + "mappings": "AAAA;EACE,UAAU;AACZ", + "sources": Array [ + "/root/src-import/src-import.css", + ], + "sourcesContent": Array [ + ".src-import { + color: red; + } + ", + ], + "version": 3, + } + `) + }) + + test('src imported sass', async () => { + const css = await getStyleTagContentIncluding('.src-import-sass[data-v-') + const map = extractSourcemap(css) + expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(` + Object { + "mappings": "AAAA;EACE;;ACCF;EACE", + "sources": Array [ + "/root/src-import/src-import-imported.sass", + "/root/src-import/src-import.sass", + ], + "sourcesContent": Array [ + ".src-import-sass-imported + color: red + ", + "@import './src-import-imported' + + .src-import-sass + color: red + ", + ], + "version": 3, + } + `) + }) +} else { + test('this file only includes test for serve', () => { + expect(true).toBe(true) + }) +} diff --git a/packages/playground/vue-sourcemap/index.html b/packages/playground/vue-sourcemap/index.html new file mode 100644 index 00000000000000..57f325518a2c25 --- /dev/null +++ b/packages/playground/vue-sourcemap/index.html @@ -0,0 +1,7 @@ +
+ diff --git a/packages/playground/vue-sourcemap/package.json b/packages/playground/vue-sourcemap/package.json new file mode 100644 index 00000000000000..5672b5e3d9d57d --- /dev/null +++ b/packages/playground/vue-sourcemap/package.json @@ -0,0 +1,20 @@ +{ + "name": "test-vue-sourcemap", + "private": true, + "version": "0.0.0", + "scripts": { + "dev": "vite", + "build": "vite build", + "debug": "node --inspect-brk ../../vite/bin/vite", + "preview": "vite preview" + }, + "devDependencies": { + "@vitejs/plugin-vue": "workspace:*", + "convert-source-map": "^1.8.0", + "less": "^4.1.2", + "sass": "^1.43.4" + }, + "dependencies": { + "vue": "^3.2.31" + } +} diff --git a/packages/playground/vue-sourcemap/sassWithImportImported.sass b/packages/playground/vue-sourcemap/sassWithImportImported.sass new file mode 100644 index 00000000000000..8092b37048cbdd --- /dev/null +++ b/packages/playground/vue-sourcemap/sassWithImportImported.sass @@ -0,0 +1,2 @@ +.sass-with-import-imported + color: red diff --git a/packages/playground/vue-sourcemap/src-import/SrcImport.vue b/packages/playground/vue-sourcemap/src-import/SrcImport.vue new file mode 100644 index 00000000000000..406c6a6b45382d --- /dev/null +++ b/packages/playground/vue-sourcemap/src-import/SrcImport.vue @@ -0,0 +1,8 @@ + + + + diff --git a/packages/playground/vue-sourcemap/src-import/src-import-imported.sass b/packages/playground/vue-sourcemap/src-import/src-import-imported.sass new file mode 100644 index 00000000000000..2ed87d933e58a6 --- /dev/null +++ b/packages/playground/vue-sourcemap/src-import/src-import-imported.sass @@ -0,0 +1,2 @@ +.src-import-sass-imported + color: red diff --git a/packages/playground/vue-sourcemap/src-import/src-import.css b/packages/playground/vue-sourcemap/src-import/src-import.css new file mode 100644 index 00000000000000..da61ff0fb6cb27 --- /dev/null +++ b/packages/playground/vue-sourcemap/src-import/src-import.css @@ -0,0 +1,3 @@ +.src-import { + color: red; +} diff --git a/packages/playground/vue-sourcemap/src-import/src-import.sass b/packages/playground/vue-sourcemap/src-import/src-import.sass new file mode 100644 index 00000000000000..c7e0314fda541c --- /dev/null +++ b/packages/playground/vue-sourcemap/src-import/src-import.sass @@ -0,0 +1,4 @@ +@import './src-import-imported' + +.src-import-sass + color: red diff --git a/packages/playground/vue-sourcemap/vite.config.js b/packages/playground/vue-sourcemap/vite.config.js new file mode 100644 index 00000000000000..2a48cad3cb00d4 --- /dev/null +++ b/packages/playground/vue-sourcemap/vite.config.js @@ -0,0 +1,19 @@ +const vuePlugin = require('@vitejs/plugin-vue') + +/** + * @type {import('vite').UserConfig} + */ +module.exports = { + css: { + devSourcemap: true, + preprocessorOptions: { + less: { + additionalData: '@color: red;' + } + } + }, + plugins: [vuePlugin()], + build: { + sourcemap: true + } +} diff --git a/packages/playground/worker/__tests__/es/es-worker.spec.ts b/packages/playground/worker/__tests__/es/es-worker.spec.ts new file mode 100644 index 00000000000000..51497a0f5ebadd --- /dev/null +++ b/packages/playground/worker/__tests__/es/es-worker.spec.ts @@ -0,0 +1,102 @@ +import fs from 'fs' +import path from 'path' +import { untilUpdated, isBuild, testDir } from '../../../testUtils' +import type { Page } from 'playwright-chromium' + +test('normal', async () => { + await page.click('.ping') + await untilUpdated(() => page.textContent('.pong'), 'pong') + await untilUpdated( + () => page.textContent('.mode'), + isBuild ? 'production' : 'development' + ) + await untilUpdated( + () => page.textContent('.bundle-with-plugin'), + 'worker bundle with plugin success!' + ) +}) + +test('TS output', async () => { + await page.click('.ping-ts-output') + await untilUpdated(() => page.textContent('.pong-ts-output'), 'pong') +}) + +test('inlined', async () => { + await page.click('.ping-inline') + await untilUpdated(() => page.textContent('.pong-inline'), 'pong') +}) + +const waitSharedWorkerTick = ( + (resolvedSharedWorkerCount: number) => async (page: Page) => { + await untilUpdated(async () => { + const count = await page.textContent('.tick-count') + // ignore the initial 0 + return count === '1' ? 'page loaded' : '' + }, 'page loaded') + // test.concurrent sequential is not guaranteed + // force page to wait to ensure two pages overlap in time + resolvedSharedWorkerCount++ + if (resolvedSharedWorkerCount < 2) return + + await untilUpdated(() => { + return resolvedSharedWorkerCount === 2 ? 'all pages loaded' : '' + }, 'all pages loaded') + } +)(0) + +test.concurrent.each([[true], [false]])('shared worker', async (doTick) => { + if (doTick) { + await page.click('.tick-shared') + } + await waitSharedWorkerTick(page) +}) + +test('worker emitted', async () => { + await untilUpdated(() => page.textContent('.nested-worker'), 'pong') +}) + +if (isBuild) { + const assetsDir = path.resolve(testDir, 'dist/es/assets') + // assert correct files + test('inlined code generation', async () => { + const files = fs.readdirSync(assetsDir) + expect(files.length).toBe(20) + const index = files.find((f) => f.includes('main-module')) + const content = fs.readFileSync(path.resolve(assetsDir, index), 'utf-8') + const worker = files.find((f) => f.includes('my-worker')) + const workerContent = fs.readFileSync( + path.resolve(assetsDir, worker), + 'utf-8' + ) + + // worker should have all imports resolved and no exports + expect(workerContent).not.toMatch(`import`) + expect(workerContent).not.toMatch(`export`) + // chunk + expect(content).toMatch(`new Worker("/es/assets`) + expect(content).toMatch(`new SharedWorker("/es/assets`) + // inlined + expect(content).toMatch(`(window.URL||window.webkitURL).createObjectURL`) + expect(content).toMatch(`window.Blob`) + }) +} + +test('module worker', async () => { + expect(await page.textContent('.shared-worker-import-meta-url')).toMatch( + 'A string' + ) +}) + +test('classic worker', async () => { + expect(await page.textContent('.classic-worker')).toMatch('A classic') + expect(await page.textContent('.classic-shared-worker')).toMatch('A classic') +}) + +test('emit chunk', async () => { + expect(await page.textContent('.emti-chunk-worker')).toMatch( + '{"msg1":"module1","msg2":"module2","msg3":"module3"}' + ) + expect(await page.textContent('.emti-chunk-dynamic-import-worker')).toMatch( + '"A string/es/"' + ) +}) diff --git a/packages/playground/worker/__tests__/es/vite.config.js b/packages/playground/worker/__tests__/es/vite.config.js new file mode 100644 index 00000000000000..931d457792c4f9 --- /dev/null +++ b/packages/playground/worker/__tests__/es/vite.config.js @@ -0,0 +1 @@ +module.exports = require('../../vite.config-es') diff --git a/packages/playground/worker/__tests__/worker.spec.ts b/packages/playground/worker/__tests__/worker.spec.ts index 6d93e810c0c510..263c49cff52fb9 100644 --- a/packages/playground/worker/__tests__/worker.spec.ts +++ b/packages/playground/worker/__tests__/worker.spec.ts @@ -51,21 +51,20 @@ test.concurrent.each([[true], [false]])('shared worker', async (doTick) => { await waitSharedWorkerTick(page) }) -test('worker emitted', async () => { - await untilUpdated(() => page.textContent('.nested-worker'), 'pong') +test('worker emitted and import.meta.url in nested worker', async () => { await untilUpdated( - () => page.textContent('.nested-worker-dynamic-import'), - '"msg":"pong"' + () => page.textContent('.nested-worker'), + 'pong http://localhost:3000/iife/sub-worker.js?worker_file' ) }) if (isBuild) { - const assetsDir = path.resolve(testDir, 'dist/assets') + const assetsDir = path.resolve(testDir, 'dist/iife/assets') // assert correct files test('inlined code generation', async () => { const files = fs.readdirSync(assetsDir) - expect(files.length).toBe(11) - const index = files.find((f) => f.includes('index')) + expect(files.length).toBe(13) + const index = files.find((f) => f.includes('main-module')) const content = fs.readFileSync(path.resolve(assetsDir, index), 'utf-8') const worker = files.find((f) => f.includes('my-worker')) const workerContent = fs.readFileSync( @@ -77,15 +76,21 @@ if (isBuild) { expect(workerContent).not.toMatch(`import`) expect(workerContent).not.toMatch(`export`) // chunk - expect(content).toMatch(`new Worker("/assets`) - expect(content).toMatch(`new SharedWorker("/assets`) + expect(content).toMatch(`new Worker("/iife/assets`) + expect(content).toMatch(`new SharedWorker("/iife/assets`) // inlined expect(content).toMatch(`(window.URL||window.webkitURL).createObjectURL`) expect(content).toMatch(`window.Blob`) }) } -test('classic worker is run', async () => { +test('module worker', async () => { + expect(await page.textContent('.shared-worker-import-meta-url')).toMatch( + 'A string' + ) +}) + +test('classic worker', async () => { expect(await page.textContent('.classic-worker')).toMatch('A classic') expect(await page.textContent('.classic-shared-worker')).toMatch('A classic') }) diff --git a/packages/playground/worker/newUrl/classic-shared-worker.js b/packages/playground/worker/classic-shared-worker.js similarity index 58% rename from packages/playground/worker/newUrl/classic-shared-worker.js rename to packages/playground/worker/classic-shared-worker.js index 462e49dfa8847f..8bd39e194f0618 100644 --- a/packages/playground/worker/newUrl/classic-shared-worker.js +++ b/packages/playground/worker/classic-shared-worker.js @@ -1,4 +1,4 @@ -importScripts('/classic.js') +importScripts(`/${self.location.pathname.split('/')[1]}/classic.js`) self.onconnect = (event) => { const port = event.ports[0] diff --git a/packages/playground/worker/classic-worker.js b/packages/playground/worker/classic-worker.js index bb6f9c3f49fc84..0700428ee0c80b 100644 --- a/packages/playground/worker/classic-worker.js +++ b/packages/playground/worker/classic-worker.js @@ -1,29 +1,5 @@ -// prettier-ignore -function text(el, text) { - document.querySelector(el).textContent = text -} +importScripts(`/${self.location.pathname.split("/")[1]}/classic.js`) -const classicWorker = new Worker( - new URL('./newUrl/classic-worker.js', import.meta.url) /* , */ , - // test comment - -) - -classicWorker.addEventListener('message', ({ data }) => { - text('.classic-worker', data) -}) -classicWorker.postMessage('ping') - -const classicSharedWorker = new SharedWorker( - new URL('./newUrl/classic-shared-worker.js', import.meta.url), - { - type: 'classic' - } -) -classicSharedWorker.port.addEventListener('message', (ev) => { - text( - '.classic-shared-worker', - ev.data - ) +self.addEventListener('message', () => { + self.postMessage(self.constant) }) -classicSharedWorker.port.start() diff --git a/packages/playground/worker/emit-chunk-dynamic-import-worker.js b/packages/playground/worker/emit-chunk-dynamic-import-worker.js new file mode 100644 index 00000000000000..f96e0b15d26497 --- /dev/null +++ b/packages/playground/worker/emit-chunk-dynamic-import-worker.js @@ -0,0 +1,3 @@ +import('./modules/module').then((module) => { + self.postMessage(module.default + import.meta.env.BASE_URL) +}) diff --git a/packages/playground/worker/emit-chunk-nested-worker.js b/packages/playground/worker/emit-chunk-nested-worker.js new file mode 100644 index 00000000000000..dff0f5bc64c5ad --- /dev/null +++ b/packages/playground/worker/emit-chunk-nested-worker.js @@ -0,0 +1,7 @@ +import SubWorker from './emit-chunk-sub-worker?worker' + +const subWorker = new SubWorker() + +subWorker.onmessage = (event) => { + self.postMessage(event.data) +} diff --git a/packages/playground/worker/emit-chunk-sub-worker.js b/packages/playground/worker/emit-chunk-sub-worker.js new file mode 100644 index 00000000000000..bd6b1f6e4f7419 --- /dev/null +++ b/packages/playground/worker/emit-chunk-sub-worker.js @@ -0,0 +1,6 @@ +Promise.all([import('./modules/module2'), import('./modules/module3')]).then( + (data) => { + const _data = { ...data[0], ...data[1] } + self.postMessage(_data) + } +) diff --git a/packages/playground/worker/index.html b/packages/playground/worker/index.html index b3525da299ff5a..60289ff84d6a06 100644 --- a/packages/playground/worker/index.html +++ b/packages/playground/worker/index.html @@ -1,3 +1,4 @@ +

format iife:

Expected values:
@@ -20,113 +21,59 @@ 0
-

new Worker(new Url('path', import.meta.url), { type: 'module' })

-
- -

new SharedWorker(new Url('path', import.meta.url), { type: 'module' })

-
- -

nested worker

-
-
-

new Worker(new Url('path', import.meta.url))

-
- -

new Worker(new Url('path', import.meta.url), { type: 'classic' })

-
- - + .classname { + color: green; + } + + diff --git a/packages/playground/worker/newUrl/module.js b/packages/playground/worker/modules/module.js similarity index 100% rename from packages/playground/worker/newUrl/module.js rename to packages/playground/worker/modules/module.js diff --git a/packages/playground/worker/modules/module1.js b/packages/playground/worker/modules/module1.js new file mode 100644 index 00000000000000..191db09d29c44f --- /dev/null +++ b/packages/playground/worker/modules/module1.js @@ -0,0 +1 @@ +export const msg1 = 'module1' diff --git a/packages/playground/worker/modules/module2.js b/packages/playground/worker/modules/module2.js new file mode 100644 index 00000000000000..60447933b8b16e --- /dev/null +++ b/packages/playground/worker/modules/module2.js @@ -0,0 +1,3 @@ +export * from './module' +export * from './module1' +export const msg2 = 'module2' diff --git a/packages/playground/worker/modules/module3.js b/packages/playground/worker/modules/module3.js new file mode 100644 index 00000000000000..33355423bc030e --- /dev/null +++ b/packages/playground/worker/modules/module3.js @@ -0,0 +1,2 @@ +export * from './module' +export const msg3 = 'module3' diff --git a/packages/playground/worker/test-plugin.tsx b/packages/playground/worker/modules/test-plugin.tsx similarity index 100% rename from packages/playground/worker/test-plugin.tsx rename to packages/playground/worker/modules/test-plugin.tsx diff --git a/packages/playground/worker/workerImport.js b/packages/playground/worker/modules/workerImport.js similarity index 100% rename from packages/playground/worker/workerImport.js rename to packages/playground/worker/modules/workerImport.js diff --git a/packages/playground/worker/my-worker.ts b/packages/playground/worker/my-worker.ts index 550382be72c331..dd6061885128c7 100644 --- a/packages/playground/worker/my-worker.ts +++ b/packages/playground/worker/my-worker.ts @@ -1,5 +1,5 @@ -import { msg, mode } from './workerImport' -import { bundleWithPlugin } from './test-plugin' +import { msg, mode } from './modules/workerImport' +import { bundleWithPlugin } from './modules/test-plugin' self.onmessage = (e) => { if (e.data === 'ping') { diff --git a/packages/playground/worker/newUrl/classic-worker.js b/packages/playground/worker/newUrl/classic-worker.js deleted file mode 100644 index 865810c76fbf85..00000000000000 --- a/packages/playground/worker/newUrl/classic-worker.js +++ /dev/null @@ -1,5 +0,0 @@ -importScripts('/classic.js') - -self.addEventListener('message', () => { - self.postMessage(self.constant) -}) diff --git a/packages/playground/worker/newUrl/url-worker.js b/packages/playground/worker/newUrl/url-worker.js deleted file mode 100644 index afd91bfe613dc2..00000000000000 --- a/packages/playground/worker/newUrl/url-worker.js +++ /dev/null @@ -1,3 +0,0 @@ -import constant from './module' - -self.postMessage(constant) diff --git a/packages/playground/worker/package.json b/packages/playground/worker/package.json index 131df8c4cbf336..54b737ca2d9cc4 100644 --- a/packages/playground/worker/package.json +++ b/packages/playground/worker/package.json @@ -5,8 +5,11 @@ "scripts": { "dev": "vite", "build": "vite build", - "debug": "node --inspect-brk ../../vite/bin/vite", - "preview": "vite preview" + "preview": "vite preview", + "dev:es": "vite --config ./vite.config-es.js dev", + "build:es": "vite --config ./vite.config-es.js build", + "preview:es": "vite --config ./vite.config-es.js preview", + "debug": "node --inspect-brk ../../vite/bin/vite" }, "devDependencies": { "@vitejs/plugin-vue-jsx": "workspace:*" diff --git a/packages/playground/worker/possible-ts-output-worker.mjs b/packages/playground/worker/possible-ts-output-worker.mjs index 2bcce3faa8a50e..25f1a447617cd9 100644 --- a/packages/playground/worker/possible-ts-output-worker.mjs +++ b/packages/playground/worker/possible-ts-output-worker.mjs @@ -1,4 +1,4 @@ -import { msg, mode } from './workerImport' +import { msg, mode } from './modules/workerImport' self.onmessage = (e) => { if (e.data === 'ping') { diff --git a/packages/playground/worker/sub-worker.js b/packages/playground/worker/sub-worker.js index ab64b3667099bb..eff49dfbb46ba6 100644 --- a/packages/playground/worker/sub-worker.js +++ b/packages/playground/worker/sub-worker.js @@ -1,13 +1,5 @@ self.onmessage = (event) => { if (event.data === 'ping') { - self.postMessage('pong') + self.postMessage(`pong ${import.meta.url}`) } } -const data = import('./workerImport') -data.then((data) => { - const { mode, msg } = data - self.postMessage({ - mode, - msg - }) -}) diff --git a/packages/playground/worker/newUrl/url-shared-worker.js b/packages/playground/worker/url-shared-worker.js similarity index 69% rename from packages/playground/worker/newUrl/url-shared-worker.js rename to packages/playground/worker/url-shared-worker.js index f52de169243056..3535d5c277ec84 100644 --- a/packages/playground/worker/newUrl/url-shared-worker.js +++ b/packages/playground/worker/url-shared-worker.js @@ -1,4 +1,4 @@ -import constant from './module' +import constant from './modules/module' self.onconnect = (event) => { const port = event.ports[0] diff --git a/packages/playground/worker/url-worker.js b/packages/playground/worker/url-worker.js new file mode 100644 index 00000000000000..c25cbefdff89ec --- /dev/null +++ b/packages/playground/worker/url-worker.js @@ -0,0 +1 @@ +self.postMessage('A string' + import.meta.env.BASE_URL + import.meta.url) diff --git a/packages/playground/worker/vite.config-es.js b/packages/playground/worker/vite.config-es.js new file mode 100644 index 00000000000000..a65dece2d0db21 --- /dev/null +++ b/packages/playground/worker/vite.config-es.js @@ -0,0 +1,29 @@ +const vueJsx = require('@vitejs/plugin-vue-jsx') +const vite = require('vite') +const path = require('path') + +module.exports = vite.defineConfig({ + base: '/es/', + enforce: 'pre', + worker: { + format: 'es', + plugins: [vueJsx()] + }, + build: { + outDir: 'dist/es' + }, + plugins: [ + { + name: 'resolve-format-es', + + transform(code, id) { + if (id.includes('main.js')) { + return code.replace( + `/* flag: will replace in vite config import("./format-es.js") */`, + `import("./main-format-es")` + ) + } + } + } + ] +}) diff --git a/packages/playground/worker/vite.config.js b/packages/playground/worker/vite.config.js new file mode 100644 index 00000000000000..b7760bc4d7a240 --- /dev/null +++ b/packages/playground/worker/vite.config.js @@ -0,0 +1,13 @@ +const vueJsx = require('@vitejs/plugin-vue-jsx') +const vite = require('vite') + +module.exports = vite.defineConfig({ + base: '/iife/', + worker: { + format: 'iife', + plugins: [vueJsx()] + }, + build: { + outDir: 'dist/iife' + } +}) diff --git a/packages/playground/worker/vite.config.ts b/packages/playground/worker/vite.config.ts deleted file mode 100644 index 6cef7d9cea0bed..00000000000000 --- a/packages/playground/worker/vite.config.ts +++ /dev/null @@ -1,9 +0,0 @@ -import vueJsx from '@vitejs/plugin-vue-jsx' -import { defineConfig } from 'vite' - -export default defineConfig({ - worker: { - format: 'es', - plugins: [vueJsx()] - } -}) diff --git a/packages/playground/worker/worker/main-classic.js b/packages/playground/worker/worker/main-classic.js new file mode 100644 index 00000000000000..4ef7776a56876e --- /dev/null +++ b/packages/playground/worker/worker/main-classic.js @@ -0,0 +1,28 @@ +// prettier-ignore +function text(el, text) { + document.querySelector(el).textContent = text +} + +let classicWorker = new Worker( + new URL('../classic-worker.js', import.meta.url) /* , */ + // test comment +) + +// just test for case: ') ... ,' mean no worker options parmas +classicWorker = new Worker(new URL('../classic-worker.js', import.meta.url)) + +classicWorker.addEventListener('message', ({ data }) => { + text('.classic-worker', JSON.stringify(data)) +}) +classicWorker.postMessage('ping') + +const classicSharedWorker = new SharedWorker( + new URL('../classic-shared-worker.js', import.meta.url), + { + type: 'classic' + } +) +classicSharedWorker.port.addEventListener('message', (ev) => { + text('.classic-shared-worker', JSON.stringify(ev.data)) +}) +classicSharedWorker.port.start() diff --git a/packages/playground/worker/worker/main-format-es.js b/packages/playground/worker/worker/main-format-es.js new file mode 100644 index 00000000000000..aa16636c34c73a --- /dev/null +++ b/packages/playground/worker/worker/main-format-es.js @@ -0,0 +1,23 @@ +// run when format es +import NestedWorker from '../emit-chunk-nested-worker?worker' + +function text(el, text) { + document.querySelector(el).textContent = text +} + +text('.format-es', 'format es:') + +const nestedWorker = new NestedWorker() +nestedWorker.addEventListener('message', (ev) => { + text('.emti-chunk-worker', JSON.stringify(ev.data)) +}) + +const dynamicImportWorker = new Worker( + new URL('../emit-chunk-dynamic-import-worker.js', import.meta.url), + { + type: 'module' + } +) +dynamicImportWorker.addEventListener('message', (ev) => { + text('.emti-chunk-dynamic-import-worker', JSON.stringify(ev.data)) +}) diff --git a/packages/playground/worker/worker/main-module.js b/packages/playground/worker/worker/main-module.js new file mode 100644 index 00000000000000..b66c7299cdf690 --- /dev/null +++ b/packages/playground/worker/worker/main-module.js @@ -0,0 +1,84 @@ +import myWorker from '../my-worker?worker' +import InlineWorker from '../my-worker?worker&inline' +import mySharedWorker from '../my-shared-worker?sharedworker&name=shared' +import TSOutputWorker from '../possible-ts-output-worker?worker' +import NestedWorker from '../worker-nested-worker?worker' +import { mode } from '../modules/workerImport' + +function text(el, text) { + document.querySelector(el).textContent = text +} + +document.querySelector('.mode-true').textContent = mode + +const worker = new myWorker() +worker.addEventListener('message', (e) => { + text('.pong', e.data.msg) + text('.mode', e.data.mode) + text('.bundle-with-plugin', e.data.bundleWithPlugin) +}) + +document.querySelector('.ping').addEventListener('click', () => { + worker.postMessage('ping') +}) + +const inlineWorker = new InlineWorker() +inlineWorker.addEventListener('message', (e) => { + text('.pong-inline', e.data.msg) +}) + +document.querySelector('.ping-inline').addEventListener('click', () => { + inlineWorker.postMessage('ping') +}) + +const sharedWorker = new mySharedWorker() +document.querySelector('.tick-shared').addEventListener('click', () => { + sharedWorker.port.postMessage('tick') +}) + +sharedWorker.port.addEventListener('message', (event) => { + text('.tick-count', event.data) +}) + +sharedWorker.port.start() + +const tsOutputWorker = new TSOutputWorker() +tsOutputWorker.addEventListener('message', (e) => { + text('.pong-ts-output', e.data.msg) +}) + +document.querySelector('.ping-ts-output').addEventListener('click', () => { + tsOutputWorker.postMessage('ping') +}) + +const nestedWorker = new NestedWorker() +nestedWorker.addEventListener('message', (ev) => { + if (typeof ev.data === 'string') { + text('.nested-worker', JSON.stringify(ev.data)) + } +}) +nestedWorker.postMessage('ping') + +const workerOptions = { type: 'module' } +// url import worker +const w = new Worker( + new URL('../url-worker.js', import.meta.url), + /* @vite-ignore */ workerOptions +) +w.addEventListener('message', (ev) => + text('.worker-import-meta-url', JSON.stringify(ev.data)) +) + +const genWorkerName = () => 'module' +const w2 = new SharedWorker( + new URL('../url-shared-worker.js', import.meta.url), + { + /* @vite-ignore */ + name: genWorkerName(), + type: 'module' + } +) +w2.port.addEventListener('message', (ev) => { + text('.shared-worker-import-meta-url', JSON.stringify(ev.data)) +}) +w2.port.start() diff --git a/packages/playground/worker/worker/main.js b/packages/playground/worker/worker/main.js new file mode 100644 index 00000000000000..953b5ef1bf3b53 --- /dev/null +++ b/packages/playground/worker/worker/main.js @@ -0,0 +1,3 @@ +/* flag: will replace in vite config import("./format-es.js") */ +import('./main-module') +import('./main-classic') diff --git a/packages/plugin-legacy/README.md b/packages/plugin-legacy/README.md index b5bf572e53fa2c..ec7e630c87755a 100644 --- a/packages/plugin-legacy/README.md +++ b/packages/plugin-legacy/README.md @@ -165,7 +165,9 @@ The legacy plugin requires inline scripts for [Safari 10.1 `nomodule` fix](https - `sha256-MS6/3FCg4WjP9gwgaBGwLpRCY6fZBgwmhVCdrPrNf3E=` - `sha256-tQjf8gvb2ROOMapIxFvFAYBeUJ0v1HCbOcSmDNXGtDo=` -- `sha256-T9h4ixy0FtNsCwAyTfBtIY6uV5ZhMeNQIlL42GAKEME=` +- `sha256-xYj09txJ9OsgySe5ommpqul6FiaJZRrwe3KTD7wbV6w=` +- `sha256-4m6wOIrq/wFDmi9Xh3mFM2mwI4ik9n3TMgHk6xDtLxk=` +- `sha256-uS7/g9fhQwNZS1f/MqYqqKv8y9hCu36IfX9XZB5L7YY=` These values (without the `sha256-` prefix) can also be retrieved via diff --git a/packages/plugin-legacy/index.js b/packages/plugin-legacy/index.js index b66c4714e19c09..626b48f85ea955 100644 --- a/packages/plugin-legacy/index.js +++ b/packages/plugin-legacy/index.js @@ -18,7 +18,11 @@ const safari10NoModuleFix = `!function(){var e=document,t=e.createElement("scrip const legacyPolyfillId = 'vite-legacy-polyfill' const legacyEntryId = 'vite-legacy-entry' const systemJSInlineCode = `System.import(document.getElementById('${legacyEntryId}').getAttribute('data-src'))` -const dynamicFallbackInlineCode = `!function(){try{new Function("m","return import(m)")}catch(o){console.warn("vite: loading legacy build because dynamic import is unsupported, syntax error above should be ignored");var e=document.getElementById("${legacyPolyfillId}"),n=document.createElement("script");n.src=e.src,n.onload=function(){${systemJSInlineCode}},document.body.appendChild(n)}}();` + +const detectDynamicImportVarName = '__vite_is_dynamic_import_support' +const detectDynamicImportVarInitCode = `var ${detectDynamicImportVarName}=false;` +const detectDynamicImportCode = `try{import("_").catch(()=>1);}catch(e){}window.${detectDynamicImportVarName}=true;` +const dynamicFallbackInlineCode = `!function(){if(window.${detectDynamicImportVarName})return;console.warn("vite: loading legacy build because dynamic import is unsupported, syntax error above should be ignored");var e=document.getElementById("${legacyPolyfillId}"),n=document.createElement("script");n.src=e.src,n.onload=function(){${systemJSInlineCode}},document.body.appendChild(n)}();` const forceDynamicImportUsage = `export function __vite_legacy_guard(){import('data:text/javascript,')};` @@ -430,6 +434,18 @@ function viteLegacyPlugin(options = {}) { // 5. inject dynamic import fallback entry if (genDynamicFallback && legacyPolyfillFilename && legacyEntryFilename) { + tags.push({ + tag: 'script', + attrs: { type: 'module' }, + children: detectDynamicImportVarInitCode, + injectTo: 'head' + }) + tags.push({ + tag: 'script', + attrs: { type: 'module' }, + children: detectDynamicImportCode, + injectTo: 'head' + }) tags.push({ tag: 'script', attrs: { type: 'module' }, @@ -695,5 +711,7 @@ viteLegacyPlugin.default = viteLegacyPlugin viteLegacyPlugin.cspHashes = [ createHash('sha256').update(safari10NoModuleFix).digest('base64'), createHash('sha256').update(systemJSInlineCode).digest('base64'), + createHash('sha256').update(detectDynamicImportVarInitCode).digest('base64'), + createHash('sha256').update(detectDynamicImportCode).digest('base64'), createHash('sha256').update(dynamicFallbackInlineCode).digest('base64') ] diff --git a/packages/plugin-legacy/package.json b/packages/plugin-legacy/package.json index e464c18b4dca1d..6f3e44cc3e9fdd 100644 --- a/packages/plugin-legacy/package.json +++ b/packages/plugin-legacy/package.json @@ -22,9 +22,9 @@ }, "homepage": "https://github.com/vitejs/vite/tree/main/packages/plugin-legacy#readme", "dependencies": { - "@babel/standalone": "^7.17.2", - "core-js": "^3.21.0", - "magic-string": "^0.25.7", + "@babel/standalone": "^7.17.8", + "core-js": "^3.21.1", + "magic-string": "^0.26.1", "regenerator-runtime": "^0.13.9", "systemjs": "^6.12.1" }, diff --git a/packages/plugin-react/package.json b/packages/plugin-react/package.json index 5c4ba1077a1933..f182a7f5a2fb10 100644 --- a/packages/plugin-react/package.json +++ b/packages/plugin-react/package.json @@ -33,12 +33,12 @@ }, "homepage": "https://github.com/vitejs/vite/tree/main/packages/plugin-react#readme", "dependencies": { - "@babel/core": "^7.17.2", - "@babel/plugin-transform-react-jsx": "^7.16.7", + "@babel/core": "^7.17.8", + "@babel/plugin-transform-react-jsx": "^7.17.3", "@babel/plugin-transform-react-jsx-development": "^7.16.7", "@babel/plugin-transform-react-jsx-self": "^7.16.7", "@babel/plugin-transform-react-jsx-source": "^7.16.7", - "@rollup/pluginutils": "^4.1.2", + "@rollup/pluginutils": "^4.2.0", "react-refresh": "^0.11.0", "resolve": "^1.22.0" } diff --git a/packages/plugin-react/src/index.ts b/packages/plugin-react/src/index.ts index afa1e2c5422da2..76f6c6c2a799f3 100644 --- a/packages/plugin-react/src/index.ts +++ b/packages/plugin-react/src/index.ts @@ -32,6 +32,12 @@ export interface Options { * @default "react" */ jsxImportSource?: string + /** + * Set this to `true` to annotate the JSX factory with `\/* @__PURE__ *\/`. + * This option is ignored when `jsxRuntime` is not `"automatic"`. + * @default true + */ + jsxPure?: boolean /** * Babel configuration applied in both dev and prod. @@ -195,7 +201,8 @@ export default function viteReact(opts: Options = {}): PluginOption[] { ), { runtime: 'automatic', - importSource: opts.jsxImportSource + importSource: opts.jsxImportSource, + pure: opts.jsxPure !== false } ]) diff --git a/packages/plugin-vue-jsx/package.json b/packages/plugin-vue-jsx/package.json index 8cf4d45792db58..ed807955ed0c87 100644 --- a/packages/plugin-vue-jsx/package.json +++ b/packages/plugin-vue-jsx/package.json @@ -22,10 +22,10 @@ }, "homepage": "https://github.com/vitejs/vite/tree/main/packages/plugin-vue-jsx#readme", "dependencies": { - "@babel/core": "^7.17.2", + "@babel/core": "^7.17.8", "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-transform-typescript": "^7.16.8", - "@rollup/pluginutils": "^4.1.2", + "@rollup/pluginutils": "^4.2.0", "@vue/babel-plugin-jsx": "^1.1.1", "hash-sum": "^2.0.0" } diff --git a/packages/plugin-vue/CHANGELOG.md b/packages/plugin-vue/CHANGELOG.md index 6fb47f160b1689..c4b3f8e1a1ddb0 100644 --- a/packages/plugin-vue/CHANGELOG.md +++ b/packages/plugin-vue/CHANGELOG.md @@ -1,3 +1,12 @@ +## 2.3.0-beta.0 (2022-03-22) + +* fix(deps): update all non-major dependencies (#7392) ([b63fc3b](https://github.com/vitejs/vite/commit/b63fc3b)), closes [#7392](https://github.com/vitejs/vite/issues/7392) +* feat: css sourcemap support during dev (#7173) ([38a655f](https://github.com/vitejs/vite/commit/38a655f)), closes [#7173](https://github.com/vitejs/vite/issues/7173) +* chore(deps): update all non-major dependencies (#6905) ([839665c](https://github.com/vitejs/vite/commit/839665c)), closes [#6905](https://github.com/vitejs/vite/issues/6905) +* docs(vue): add transformAssetUrls example (#7232) ([08e928c](https://github.com/vitejs/vite/commit/08e928c)), closes [#7232](https://github.com/vitejs/vite/issues/7232) + + + ## [2.2.4](https://github.com/vitejs/vite/compare/plugin-vue@2.2.3...plugin-vue@2.2.4) (2022-02-28) diff --git a/packages/plugin-vue/package.json b/packages/plugin-vue/package.json index 20e28f4e928afe..bf4749ac8ee428 100644 --- a/packages/plugin-vue/package.json +++ b/packages/plugin-vue/package.json @@ -1,6 +1,6 @@ { "name": "@vitejs/plugin-vue", - "version": "2.2.4", + "version": "2.3.0-beta.0", "license": "MIT", "author": "Evan You", "files": [ @@ -35,13 +35,13 @@ "vue": "^3.2.25" }, "devDependencies": { - "@rollup/pluginutils": "^4.1.2", + "@rollup/pluginutils": "^4.2.0", "@types/hash-sum": "^1.0.0", - "debug": "^4.3.3", + "debug": "^4.3.4", "hash-sum": "^2.0.0", "rollup": "^2.59.0", "slash": "^4.0.0", "source-map": "^0.6.1", - "vue": "^3.2.30" + "vue": "^3.2.31" } } diff --git a/packages/plugin-vue/src/index.ts b/packages/plugin-vue/src/index.ts index fb1bce3cd61132..7bdf63b700fa15 100644 --- a/packages/plugin-vue/src/index.ts +++ b/packages/plugin-vue/src/index.ts @@ -63,7 +63,9 @@ export interface ResolvedOptions extends Options { compiler: typeof _compiler root: string sourceMap: boolean + cssDevSourcemap: boolean devServer?: ViteDevServer + devToolsEnabled?: boolean } export default function vuePlugin(rawOptions: Options = {}): Plugin { @@ -97,7 +99,9 @@ export default function vuePlugin(rawOptions: Options = {}): Plugin { customElement, reactivityTransform, root: process.cwd(), - sourceMap: true + sourceMap: true, + cssDevSourcemap: false, + devToolsEnabled: process.env.NODE_ENV !== 'production' } // Temporal handling for 2.7 breaking change @@ -135,7 +139,10 @@ export default function vuePlugin(rawOptions: Options = {}): Plugin { ...options, root: config.root, sourceMap: config.command === 'build' ? !!config.build.sourcemap : true, - isProduction: config.isProduction + cssDevSourcemap: config.css?.devSourcemap ?? false, + isProduction: config.isProduction, + devToolsEnabled: + !!config.define!.__VUE_PROD_DEVTOOLS__ || !config.isProduction } }, @@ -235,7 +242,8 @@ export default function vuePlugin(rawOptions: Options = {}): Plugin { descriptor, Number(query.index), options, - this + this, + filename ) } } diff --git a/packages/plugin-vue/src/main.ts b/packages/plugin-vue/src/main.ts index 7fb26fd39c6c03..44b1de74721efd 100644 --- a/packages/plugin-vue/src/main.ts +++ b/packages/plugin-vue/src/main.ts @@ -27,7 +27,7 @@ export async function transformMain( ssr: boolean, asCustomElement: boolean ) { - const { devServer, isProduction } = options + const { devServer, isProduction, devToolsEnabled } = options // prev descriptor is only set and used for hmr const prevDescriptor = getPrevDescriptor(filename) @@ -102,9 +102,12 @@ export async function transformMain( if (hasScoped) { attachedProps.push([`__scopeId`, JSON.stringify(`data-v-${descriptor.id}`)]) } - if (devServer && !isProduction) { + if (devToolsEnabled || (devServer && !isProduction)) { // expose filename during serve for devtools to pickup - attachedProps.push([`__file`, JSON.stringify(filename)]) + attachedProps.push([ + `__file`, + JSON.stringify(isProduction ? path.basename(filename) : filename) + ]) } // HMR diff --git a/packages/plugin-vue/src/style.ts b/packages/plugin-vue/src/style.ts index ad9d981412f52d..cab75791bd54ec 100644 --- a/packages/plugin-vue/src/style.ts +++ b/packages/plugin-vue/src/style.ts @@ -1,6 +1,8 @@ import type { SFCDescriptor } from 'vue/compiler-sfc' -import type { TransformPluginContext } from 'rollup' +import type { ExistingRawSourceMap, TransformPluginContext } from 'rollup' import type { ResolvedOptions } from '.' +import type { RawSourceMap } from 'source-map' +import { formatPostcssSourceMap } from 'vite' // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types export async function transformStyle( @@ -8,7 +10,8 @@ export async function transformStyle( descriptor: SFCDescriptor, index: number, options: ResolvedOptions, - pluginContext: TransformPluginContext + pluginContext: TransformPluginContext, + filename: string ) { const block = descriptor.styles[index] // vite already handles pre-processors and CSS module so this is only @@ -19,7 +22,18 @@ export async function transformStyle( id: `data-v-${descriptor.id}`, isProd: options.isProduction, source: code, - scoped: block.scoped + scoped: block.scoped, + ...(options.cssDevSourcemap + ? { + postcssOptions: { + map: { + from: filename, + inline: false, + annotation: false + } + } + } + : {}) }) if (result.errors.length) { @@ -36,8 +50,17 @@ export async function transformStyle( return null } + const map = result.map + ? formatPostcssSourceMap( + // version property of result.map is declared as string + // but actually it is a number + result.map as Omit as ExistingRawSourceMap, + filename + ) + : ({ mappings: '' } as any) + return { code: result.code, - map: result.map || ({ mappings: '' } as any) + map: map } } diff --git a/packages/vite/CHANGELOG.md b/packages/vite/CHANGELOG.md index d1381d2ba4ce32..b79c75db3260f0 100644 --- a/packages/vite/CHANGELOG.md +++ b/packages/vite/CHANGELOG.md @@ -1,3 +1,93 @@ +## 2.9.0-beta.9 (2022-03-26) + +* feat: support importing css with ?raw (#5796) ([fedb106](https://github.com/vitejs/vite/commit/fedb106)), closes [#5796](https://github.com/vitejs/vite/issues/5796) +* feat(css): css.devSourcemap option (#7471) ([57f14cb](https://github.com/vitejs/vite/commit/57f14cb)), closes [#7471](https://github.com/vitejs/vite/issues/7471) +* feat(dev): expose APIs for client-server communication (#7437) ([e29ea8e](https://github.com/vitejs/vite/commit/e29ea8e)), closes [#7437](https://github.com/vitejs/vite/issues/7437) +* fix: errors in worker handling (#7236) ([77dc1a1](https://github.com/vitejs/vite/commit/77dc1a1)), closes [#7236](https://github.com/vitejs/vite/issues/7236) + + + +## 2.9.0-beta.8 (2022-03-24) + +* fix: consider undefined port when checking port (#7318) ([c7fc7c3](https://github.com/vitejs/vite/commit/c7fc7c3)), closes [#7318](https://github.com/vitejs/vite/issues/7318) +* fix: inline style css sourcemap (#7434) ([47668b5](https://github.com/vitejs/vite/commit/47668b5)), closes [#7434](https://github.com/vitejs/vite/issues/7434) +* fix: sourcemap missing source files warning with cached vue (#7442) ([a2ce20d](https://github.com/vitejs/vite/commit/a2ce20d)), closes [#7442](https://github.com/vitejs/vite/issues/7442) +* fix: update tsconfck to 1.2.1 (#7424) ([a90b03b](https://github.com/vitejs/vite/commit/a90b03b)), closes [#7424](https://github.com/vitejs/vite/issues/7424) +* fix: virtual html sourcemap warning (#7440) ([476786b](https://github.com/vitejs/vite/commit/476786b)), closes [#7440](https://github.com/vitejs/vite/issues/7440) +* fix(less): empty less file error (#7412) ([0535c70](https://github.com/vitejs/vite/commit/0535c70)), closes [#7412](https://github.com/vitejs/vite/issues/7412) +* fix(resolve): skip `module` field when the importer is a `require` call (#7438) ([fe4c1ed](https://github.com/vitejs/vite/commit/fe4c1ed)), closes [#7438](https://github.com/vitejs/vite/issues/7438) +* feat: hide optimized deps found during scan phase logs (#7419) ([f4934e8](https://github.com/vitejs/vite/commit/f4934e8)), closes [#7419](https://github.com/vitejs/vite/issues/7419) + + + +## 2.9.0-beta.7 (2022-03-23) + +* feat: non-blocking scanning of dependencies (#7379) ([676f545](https://github.com/vitejs/vite/commit/676f545)), closes [#7379](https://github.com/vitejs/vite/issues/7379) + + + +## 2.9.0-beta.6 (2022-03-22) + + + + +## 2.9.0-beta.5 (2022-03-22) + +* fix: avoid mangling code from incorrect magic-string usage (#7397) ([68d76c9](https://github.com/vitejs/vite/commit/68d76c9)), closes [#7397](https://github.com/vitejs/vite/issues/7397) +* fix(config): server restart on config dependencies changed on windows (#7366) ([c43467a](https://github.com/vitejs/vite/commit/c43467a)), closes [#7366](https://github.com/vitejs/vite/issues/7366) +* fix(deps): update all non-major dependencies (#7392) ([b63fc3b](https://github.com/vitejs/vite/commit/b63fc3b)), closes [#7392](https://github.com/vitejs/vite/issues/7392) +* feat: css sourcemap support during dev (#7173) ([38a655f](https://github.com/vitejs/vite/commit/38a655f)), closes [#7173](https://github.com/vitejs/vite/issues/7173) + + + +## 2.9.0-beta.4 (2022-03-19) + +* fix: add version to optimized chunks, fix #7323 (#7350) ([1be1db6](https://github.com/vitejs/vite/commit/1be1db6)), closes [#7323](https://github.com/vitejs/vite/issues/7323) [#7350](https://github.com/vitejs/vite/issues/7350) +* fix: browser cache of newly discovered deps (#7378) ([392a0de](https://github.com/vitejs/vite/commit/392a0de)), closes [#7378](https://github.com/vitejs/vite/issues/7378) +* fix: do not warn (about not being able to bundle non module scripts) when src is an external url (#7 ([0646fe8](https://github.com/vitejs/vite/commit/0646fe8)), closes [#7380](https://github.com/vitejs/vite/issues/7380) +* fix: overwrite deps info browserHash only on commit (#7359) ([1e9615d](https://github.com/vitejs/vite/commit/1e9615d)), closes [#7359](https://github.com/vitejs/vite/issues/7359) +* chore: fix typo in comment (#7370) ([e682863](https://github.com/vitejs/vite/commit/e682863)), closes [#7370](https://github.com/vitejs/vite/issues/7370) +* chore: update es-module-lexer (#7357) ([fde0f3c](https://github.com/vitejs/vite/commit/fde0f3c)), closes [#7357](https://github.com/vitejs/vite/issues/7357) +* chore(deps): update all non-major dependencies (#6905) ([839665c](https://github.com/vitejs/vite/commit/839665c)), closes [#6905](https://github.com/vitejs/vite/issues/6905) + + + +## 2.9.0-beta.3 (2022-03-16) + +* fix: delayed full page reload (#7347) ([fa0820a](https://github.com/vitejs/vite/commit/fa0820a)), closes [#7347](https://github.com/vitejs/vite/issues/7347) +* fix: early discovery of missing deps, fix #7333 (#7346) ([7d2f37c](https://github.com/vitejs/vite/commit/7d2f37c)), closes [#7333](https://github.com/vitejs/vite/issues/7333) [#7346](https://github.com/vitejs/vite/issues/7346) +* fix: unhandled exception on eager transformRequest (#7345) ([c3260a4](https://github.com/vitejs/vite/commit/c3260a4)), closes [#7345](https://github.com/vitejs/vite/issues/7345) +* fix: update to esbuild 0.14.27, fix #6994 (#7320) ([65aaeee](https://github.com/vitejs/vite/commit/65aaeee)), closes [#6994](https://github.com/vitejs/vite/issues/6994) [#7320](https://github.com/vitejs/vite/issues/7320) +* chore: comment typo (#7344) ([61df324](https://github.com/vitejs/vite/commit/61df324)), closes [#7344](https://github.com/vitejs/vite/issues/7344) + + + +## 2.9.0-beta.2 (2022-03-14) + +* fix: `ssrExternal` should not skip nested dependencies (#7154) ([f8f934a](https://github.com/vitejs/vite/commit/f8f934a)), closes [#7154](https://github.com/vitejs/vite/issues/7154) +* fix: dep with dynamic import wrong error log (#7313) ([769f535](https://github.com/vitejs/vite/commit/769f535)), closes [#7313](https://github.com/vitejs/vite/issues/7313) + + + +## 2.9.0-beta.1 (2022-03-14) + +* fix: avoid caching transform result of invalidated module (#7254) ([2d7ba72](https://github.com/vitejs/vite/commit/2d7ba72)), closes [#7254](https://github.com/vitejs/vite/issues/7254) +* fix: dont replace define in json (#7294) ([fc5c937](https://github.com/vitejs/vite/commit/fc5c937)), closes [#7294](https://github.com/vitejs/vite/issues/7294) +* fix: main browserHash after stable optimization rerun (#7284) ([98eefa8](https://github.com/vitejs/vite/commit/98eefa8)), closes [#7284](https://github.com/vitejs/vite/issues/7284) +* fix: needs es interop check for newly discovered deps (#7243) ([ba3047d](https://github.com/vitejs/vite/commit/ba3047d)), closes [#7243](https://github.com/vitejs/vite/issues/7243) +* fix: pending requests after module invalidation (#7283) ([a1044d7](https://github.com/vitejs/vite/commit/a1044d7)), closes [#7283](https://github.com/vitejs/vite/issues/7283) +* fix: use browserHash for imports from node_modules (#7278) ([161f8ea](https://github.com/vitejs/vite/commit/161f8ea)), closes [#7278](https://github.com/vitejs/vite/issues/7278) +* fix: use hmr port if specified (#7282) ([3ee04c0](https://github.com/vitejs/vite/commit/3ee04c0)), closes [#7282](https://github.com/vitejs/vite/issues/7282) +* fix: use relative paths in _metadata.json (#7299) ([8b945f5](https://github.com/vitejs/vite/commit/8b945f5)), closes [#7299](https://github.com/vitejs/vite/issues/7299) +* fix(asset): allow non-existent url (#7306) ([6bc45a2](https://github.com/vitejs/vite/commit/6bc45a2)), closes [#7306](https://github.com/vitejs/vite/issues/7306) +* fix(hmr): hmr style tag no support in html (#7262) ([fae120a](https://github.com/vitejs/vite/commit/fae120a)), closes [#7262](https://github.com/vitejs/vite/issues/7262) +* chore: clarify writableEnded guard comment (#7256) ([dddda1e](https://github.com/vitejs/vite/commit/dddda1e)), closes [#7256](https://github.com/vitejs/vite/issues/7256) +* chore: new line for non-existent url (#7308) ([522faf8](https://github.com/vitejs/vite/commit/522faf8)), closes [#7308](https://github.com/vitejs/vite/issues/7308) +* chore: remove unused code (#7303) ([467512b](https://github.com/vitejs/vite/commit/467512b)), closes [#7303](https://github.com/vitejs/vite/issues/7303) +* feat: expose ssrRewriteStacktrace (#7091) ([d4ae45d](https://github.com/vitejs/vite/commit/d4ae45d)), closes [#7091](https://github.com/vitejs/vite/issues/7091) + + + ## 2.9.0-beta.0 (2022-03-09) * fix: `import.meta.url` should not throw (#7219) ([5de3a98](https://github.com/vitejs/vite/commit/5de3a98)), closes [#7219](https://github.com/vitejs/vite/issues/7219) diff --git a/packages/vite/LICENSE.md b/packages/vite/LICENSE.md index 1ff0b8dae73e1e..ccff3f1508a73b 100644 --- a/packages/vite/LICENSE.md +++ b/packages/vite/LICENSE.md @@ -1210,7 +1210,7 @@ Repository: git+https://github.com/guybedford/es-module-lexer.git > MIT License > ----------- > -> Copyright (C) 2018-2021 Guy Bedford +> Copyright (C) 2018-2022 Guy Bedford > > Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: > diff --git a/packages/vite/package.json b/packages/vite/package.json index 7b6f8357a84bce..f6c177b248289f 100644 --- a/packages/vite/package.json +++ b/packages/vite/package.json @@ -1,6 +1,6 @@ { "name": "vite", - "version": "2.9.0-beta.0", + "version": "2.9.0-beta.9", "license": "MIT", "author": "Evan You", "description": "Native-ESM powered web dev build tool", @@ -43,8 +43,8 @@ }, "//": "READ CONTRIBUTING.md to understand what to put under deps vs. devDeps!", "dependencies": { - "esbuild": "^0.14.14", - "postcss": "^8.4.6", + "esbuild": "^0.14.27", + "postcss": "^8.4.12", "resolve": "^1.22.0", "rollup": "^2.59.0" }, @@ -52,17 +52,17 @@ "fsevents": "~2.3.2" }, "devDependencies": { - "@ampproject/remapping": "^2.1.0", - "@babel/parser": "^7.17.0", + "@ampproject/remapping": "^2.1.2", + "@babel/parser": "^7.17.8", "@babel/types": "^7.17.0", - "@jridgewell/trace-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.4", "@rollup/plugin-alias": "^3.1.9", - "@rollup/plugin-commonjs": "^21.0.1", + "@rollup/plugin-commonjs": "^21.0.3", "@rollup/plugin-dynamic-import-vars": "^1.4.2", "@rollup/plugin-json": "^4.1.0", "@rollup/plugin-node-resolve": "13.1.3", - "@rollup/plugin-typescript": "^8.3.0", - "@rollup/pluginutils": "^4.1.2", + "@rollup/plugin-typescript": "^8.3.1", + "@rollup/pluginutils": "^4.2.0", "@types/convert-source-map": "^1.5.2", "@types/cross-spawn": "^6.0.2", "@types/debug": "^4.1.7", @@ -71,12 +71,12 @@ "@types/less": "^3.0.3", "@types/micromatch": "^4.0.2", "@types/mime": "^2.0.3", - "@types/node": "^16.11.22", + "@types/node": "^16.11.26", "@types/resolve": "^1.20.1", "@types/sass": "~1.43.1", "@types/stylus": "^0.48.36", - "@types/ws": "^8.2.2", - "@vue/compiler-dom": "^3.2.30", + "@types/ws": "^8.5.3", + "@vue/compiler-dom": "^3.2.31", "acorn": "^8.7.0", "cac": "6.7.9", "chokidar": "^3.5.3", @@ -85,34 +85,35 @@ "convert-source-map": "^1.8.0", "cors": "^2.8.5", "cross-spawn": "^7.0.3", - "debug": "^4.3.3", + "debug": "^4.3.4", "dotenv": "^14.3.2", "dotenv-expand": "^5.1.0", - "es-module-lexer": "^0.9.3", + "es-module-lexer": "^0.10.4", "estree-walker": "^2.0.2", "etag": "^1.8.1", "fast-glob": "^3.2.11", "http-proxy": "^1.18.1", - "json5": "^2.2.0", + "json5": "^2.2.1", "launch-editor-middleware": "^2.3.0", - "magic-string": "^0.25.7", - "micromatch": "^4.0.4", + "magic-string": "^0.26.1", + "micromatch": "^4.0.5", "mrmime": "^1.0.0", - "node-forge": "^1.2.1", + "node-forge": "^1.3.0", "okie": "^1.0.1", "open": "^8.4.0", "periscopic": "^2.0.3", "picocolors": "^1.0.0", - "postcss-import": "^14.0.2", + "postcss-import": "^14.1.0", "postcss-load-config": "^3.1.3", - "postcss-modules": "^4.3.0", + "postcss-modules": "^4.3.1", "resolve.exports": "^1.1.0", "rollup-plugin-license": "^2.6.1", "sirv": "^2.0.2", + "source-map-js": "^1.0.2", "source-map-support": "^0.5.21", "strip-ansi": "^6.0.1", - "terser": "^5.10.0", - "tsconfck": "^1.2.0", + "terser": "^5.12.1", + "tsconfck": "^1.2.1", "tslib": "^2.3.1", "types": "link:./types", "ws": "^8.5.0" diff --git a/packages/vite/src/client/client.ts b/packages/vite/src/client/client.ts index a9e8fb639de958..c180714f5a69bf 100644 --- a/packages/vite/src/client/client.ts +++ b/packages/vite/src/client/client.ts @@ -1,12 +1,6 @@ -import type { - ErrorPayload, - FullReloadPayload, - HMRPayload, - PrunePayload, - Update, - UpdatePayload -} from 'types/hmrPayload' -import type { CustomEventName } from 'types/customEvent' +import type { ErrorPayload, HMRPayload, Update } from 'types/hmrPayload' +import type { ViteHotContext } from 'types/hot' +import type { InferCustomEventPayload } from 'types/customEvent' import { ErrorOverlay, overlayId } from './overlay' // eslint-disable-next-line node/no-missing-import import '@vite/env' @@ -30,6 +24,7 @@ const socketHost = __HMR_PORT__ const socket = new WebSocket(`${socketProtocol}://${socketHost}`, 'vite-hmr') const base = __BASE__ || '/' +const messageBuffer: string[] = [] function warnFailedFetch(err: Error, path: string | string[]) { if (!err.message.match('fetch')) { @@ -59,9 +54,10 @@ async function handleMessage(payload: HMRPayload) { switch (payload.type) { case 'connected': console.log(`[vite] connected.`) + sendMessageBuffer() // proxy(nginx, docker) hmr ws maybe caused timeout, // so send ping package let ws keep alive. - setInterval(() => socket.send('ping'), __HMR_TIMEOUT__) + setInterval(() => socket.send('{"type":"ping"}'), __HMR_TIMEOUT__) break case 'update': notifyListeners('vite:beforeUpdate', payload) @@ -101,7 +97,7 @@ async function handleMessage(payload: HMRPayload) { }) break case 'custom': { - notifyListeners(payload.event as CustomEventName, payload.data) + notifyListeners(payload.event, payload.data) break } case 'full-reload': @@ -154,19 +150,9 @@ async function handleMessage(payload: HMRPayload) { } } -function notifyListeners( - event: 'vite:beforeUpdate', - payload: UpdatePayload -): void -function notifyListeners(event: 'vite:beforePrune', payload: PrunePayload): void -function notifyListeners( - event: 'vite:beforeFullReload', - payload: FullReloadPayload -): void -function notifyListeners(event: 'vite:error', payload: ErrorPayload): void function notifyListeners( - event: CustomEventName, - data: any + event: T, + data: InferCustomEventPayload ): void function notifyListeners(event: string, data: any): void { const cbs = customListenersMap.get(event) @@ -361,6 +347,13 @@ async function fetchUpdate({ path, acceptedPath, timestamp }: Update) { } } +function sendMessageBuffer() { + if (socket.readyState === 1) { + messageBuffer.forEach((msg) => socket.send(msg)) + messageBuffer.length = 0 + } +} + interface HotModule { id: string callbacks: HotCallback[] @@ -382,9 +375,7 @@ const ctxToListenersMap = new Map< Map void)[]> >() -// Just infer the return type for now -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types -export const createHotContext = (ownerPath: string) => { +export function createHotContext(ownerPath: string): ViteHotContext { if (!dataMap.has(ownerPath)) { dataMap.set(ownerPath, {}) } @@ -425,12 +416,12 @@ export const createHotContext = (ownerPath: string) => { hotModulesMap.set(ownerPath, mod) } - const hot = { + const hot: ViteHotContext = { get data() { return dataMap.get(ownerPath) }, - accept(deps: any, callback?: any) { + accept(deps?: any, callback?: any) { if (typeof deps === 'function' || !deps) { // self-accept: hot.accept(() => {}) acceptDeps([ownerPath], ([mod]) => deps && deps(mod)) @@ -451,10 +442,11 @@ export const createHotContext = (ownerPath: string) => { ) }, - dispose(cb: (data: any) => void) { + dispose(cb) { disposeMap.set(ownerPath, cb) }, + // @ts-expect-error untyped prune(cb: (data: any) => void) { pruneMap.set(ownerPath, cb) }, @@ -470,7 +462,7 @@ export const createHotContext = (ownerPath: string) => { }, // custom events - on: (event: string, cb: (data: any) => void) => { + on(event, cb) { const addToMap = (map: Map) => { const existing = map.get(event) || [] existing.push(cb) @@ -478,6 +470,11 @@ export const createHotContext = (ownerPath: string) => { } addToMap(customListenersMap) addToMap(newListeners) + }, + + send(event, data) { + messageBuffer.push(JSON.stringify({ type: 'custom', event, data })) + sendMessageBuffer() } } diff --git a/packages/vite/src/node/build.ts b/packages/vite/src/node/build.ts index 7f0b014659b221..6b4d38836b6c51 100644 --- a/packages/vite/src/node/build.ts +++ b/packages/vite/src/node/build.ts @@ -306,6 +306,7 @@ export function resolveBuildPlugins(config: ResolvedConfig): { post: Plugin[] } { const options = config.build + return { pre: [ watchPackageDataPlugin(config), diff --git a/packages/vite/src/node/config.ts b/packages/vite/src/node/config.ts index e5f72e6ac65957..9910cbb3a8b004 100644 --- a/packages/vite/src/node/config.ts +++ b/packages/vite/src/node/config.ts @@ -248,6 +248,7 @@ export type ResolvedConfig = Readonly< cacheDir: string command: 'build' | 'serve' mode: string + isWorker: boolean isProduction: boolean env: Record resolve: ResolveOptions & { @@ -465,7 +466,9 @@ export async function resolveConfig( const resolved: ResolvedConfig = { ...config, configFile: configFile ? normalizePath(configFile) : undefined, - configFileDependencies, + configFileDependencies: configFileDependencies.map((name) => + normalizePath(path.resolve(name)) + ), inlineConfig, root: resolvedRoot, base: BASE_URL, @@ -474,6 +477,7 @@ export async function resolveConfig( cacheDir, command, mode, + isWorker: false, isProduction, plugins: userPlugins, server, @@ -506,7 +510,7 @@ export async function resolveConfig( // flat config.worker.plugin const [workerPrePlugins, workerNormalPlugins, workerPostPlugins] = sortUserPlugins(config.worker?.plugins as Plugin[]) - const workerResolved = { ...resolved } + const workerResolved: ResolvedConfig = { ...resolved, isWorker: true } resolved.worker.plugins = await resolvePlugins( workerResolved, workerPrePlugins, diff --git a/packages/vite/src/node/importGlob.ts b/packages/vite/src/node/importGlob.ts index 8ed3ba66d09744..a759bee2b5fa59 100644 --- a/packages/vite/src/node/importGlob.ts +++ b/packages/vite/src/node/importGlob.ts @@ -147,7 +147,7 @@ export async function transformImportGlob( ) } entries += ` ${JSON.stringify(file)}: ${JSON.stringify( - await fsp.readFile(path.join(base, file), 'utf-8') + await fsp.readFile(path.join(base, files[i]), 'utf-8') )},` } else { const importeeUrl = isCSSRequest(importee) ? `${importee}?used` : importee diff --git a/packages/vite/src/node/index.ts b/packages/vite/src/node/index.ts index 99567735b21757..2e849d846527ca 100644 --- a/packages/vite/src/node/index.ts +++ b/packages/vite/src/node/index.ts @@ -5,6 +5,7 @@ export { build } from './build' export { optimizeDeps } from './optimizer' export { send } from './server/send' export { createLogger, printHttpServerUrls } from './logger' +export { formatPostcssSourceMap } from './plugins/css' export { transformWithEsbuild } from './plugins/esbuild' export { resolvePackageEntry } from './plugins/resolve' export { @@ -39,7 +40,8 @@ export type { DepOptimizationOptions, DepOptimizationResult, DepOptimizationProcessing, - OptimizedDepInfo + OptimizedDepInfo, + OptimizedDeps } from './optimizer' export type { Plugin } from './plugin' export type { PackageCache, PackageData } from './packages' @@ -71,7 +73,11 @@ export type { TransformOptions as EsbuildTransformOptions } from 'esbuild' export type { ESBuildOptions, ESBuildTransformResult } from './plugins/esbuild' export type { Manifest, ManifestChunk } from './plugins/manifest' export type { ResolveOptions, InternalResolveOptions } from './plugins/resolve' -export type { WebSocketServer } from './server/ws' +export type { + WebSocketServer, + WebSocketClient, + WebSocketCustomListener +} from './server/ws' export type { PluginContainer } from './server/pluginContainer' export type { ModuleGraph, ModuleNode, ResolvedUrl } from './server/moduleGraph' export type { SendOptions } from './server/send' @@ -102,6 +108,7 @@ export type { export type { Terser } from 'types/terser' export type { RollupCommonJSOptions } from 'types/commonjs' export type { RollupDynamicImportVarsOptions } from 'types/dynamicImportVars' +export type { CustomEventMap, InferCustomEventPayload } from 'types/customEvent' export type { Matcher, AnymatchPattern, AnymatchFn } from 'types/anymatch' export type { SplitVendorChunkCache } from './plugins/splitVendorChunk' diff --git a/packages/vite/src/node/optimizer/esbuildDepPlugin.ts b/packages/vite/src/node/optimizer/esbuildDepPlugin.ts index 3ff86c213a54a2..4303be0ec876e7 100644 --- a/packages/vite/src/node/optimizer/esbuildDepPlugin.ts +++ b/packages/vite/src/node/optimizer/esbuildDepPlugin.ts @@ -37,8 +37,7 @@ const externalTypes = [ export function esbuildDepPlugin( qualified: Record, exportsData: Record, - config: ResolvedConfig, - ssr?: boolean + config: ResolvedConfig ): Plugin { // remove optimizable extensions from `externalTypes` list const allExternalTypes = config.optimizeDeps.extensions @@ -48,12 +47,13 @@ export function esbuildDepPlugin( : externalTypes // default resolver which prefers ESM - const _resolve = config.createResolver({ asSrc: false }) + const _resolve = config.createResolver({ asSrc: false, scan: true }) // cjs resolver that prefers Node const _resolveRequire = config.createResolver({ asSrc: false, - isRequire: true + isRequire: true, + scan: true }) const resolve = ( @@ -72,7 +72,7 @@ export function esbuildDepPlugin( _importer = importer in qualified ? qualified[importer] : importer } const resolver = kind.startsWith('require') ? _resolveRequire : _resolve - return resolver(id, _importer, undefined, ssr) + return resolver(id, _importer, undefined) } return { diff --git a/packages/vite/src/node/optimizer/index.ts b/packages/vite/src/node/optimizer/index.ts index 59141d12ef7fd2..37294aea459c15 100644 --- a/packages/vite/src/node/optimizer/index.ts +++ b/packages/vite/src/node/optimizer/index.ts @@ -21,15 +21,25 @@ import { scanImports } from './scan' import { transformWithEsbuild } from '../plugins/esbuild' import { performance } from 'perf_hooks' -const debug = createDebugger('vite:deps') +export const debuggerViteDeps = createDebugger('vite:deps') +const debug = debuggerViteDeps const isDebugEnabled = _debug('vite:deps').enabled +const jsExtensionRE = /\.js$/i +const jsMapExtensionRE = /\.js\.map$/i + export type ExportsData = ReturnType & { // es-module-lexer has a facade detection but isn't always accurate for our // use case when the module has default export hasReExports?: true } +export interface OptimizedDeps { + metadata: DepOptimizationMetadata + scanProcessing?: Promise + registerMissingImport: (id: string, resolved: string) => OptimizedDepInfo +} + export interface DepOptimizationOptions { /** * By default, Vite will crawl your `index.html` to detect dependencies that @@ -94,23 +104,25 @@ export interface DepOptimizationOptions { } export interface DepOptimizationResult { + metadata: DepOptimizationMetadata /** - * After a re-optimization, the internal bundled chunks may change - * and a full page reload is required if that is the case - * If the files are stable, we can avoid the reload that is expensive - * for large applications + * When doing a re-run, if there are newly discovered dependendencies + * the page reload will be delayed until the next rerun so we need + * to be able to discard the result */ - alteredFiles: boolean + commit: () => void + cancel: () => void } export interface DepOptimizationProcessing { - promise: Promise - resolve: (result?: DepOptimizationResult) => void + promise: Promise + resolve: () => void } export interface OptimizedDepInfo { + id: string file: string - src: string + src?: string needsInterop?: boolean browserHash?: string fileHash?: string @@ -118,7 +130,7 @@ export interface OptimizedDepInfo { * During optimization, ids can still be resolved to their final location * but the bundles may not yet be saved to disk */ - processing: Promise + processing?: Promise } export interface DepOptimizationMetadata { @@ -137,15 +149,18 @@ export interface DepOptimizationMetadata { * Metadata for each already optimized dependency */ optimized: Record + /** + * Metadata for non-entry optimized chunks and dynamic imports + */ + chunks: Record /** * Metadata for each newly discovered dependency after processing */ discovered: Record /** - * During optimization, ids can still be resolved to their final location - * but the bundles may not yet be saved to disk + * OptimizedDepInfo list */ - processing: Promise + depInfoList: OptimizedDepInfo[] } /** @@ -154,44 +169,65 @@ export interface DepOptimizationMetadata { export async function optimizeDeps( config: ResolvedConfig, force = config.server.force, - asCommand = false, - newDeps?: Record, // missing imports encountered after server has started - ssr?: boolean + asCommand = false ): Promise { - const { metadata, run } = await createOptimizeDepsRun( + const log = asCommand ? config.logger.info : debug + + const cachedMetadata = loadCachedDepOptimizationMetadata( config, force, - asCommand, - null, - newDeps, - ssr + asCommand ) - await run() - return metadata + if (cachedMetadata) { + return cachedMetadata + } + const depsInfo = await discoverProjectDependencies(config) + + const depsString = depsLogString(Object.keys(depsInfo)) + log(colors.green(`Optimizing dependencies:\n ${depsString}`)) + + const result = await runOptimizeDeps(config, depsInfo) + + result.commit() + + return result.metadata +} + +export function createOptimizedDepsMetadata( + config: ResolvedConfig, + timestamp?: string +): DepOptimizationMetadata { + const hash = getDepHash(config) + return { + hash, + browserHash: getOptimizedBrowserHash(hash, {}, timestamp), + optimized: {}, + chunks: {}, + discovered: {}, + depInfoList: [] + } +} + +export function addOptimizedDepInfo( + metadata: DepOptimizationMetadata, + type: 'optimized' | 'discovered' | 'chunks', + depInfo: OptimizedDepInfo +): OptimizedDepInfo { + metadata[type][depInfo.id] = depInfo + metadata.depInfoList.push(depInfo) + return depInfo } /** - * Internally, Vite uses this function to prepare a optimizeDeps run. When Vite starts, we can get - * the metadata and start the server without waiting for the optimizeDeps processing to be completed + * Creates the initial dep optimization metadata, loading it from the deps cache + * if it exists and pre-bundling isn't forced */ -export async function createOptimizeDepsRun( +export function loadCachedDepOptimizationMetadata( config: ResolvedConfig, force = config.server.force, - asCommand = false, - currentData: DepOptimizationMetadata | null = null, - newDeps?: Record, // missing imports encountered after server has started - ssr?: boolean -): Promise<{ - metadata: DepOptimizationMetadata - run: () => Promise -}> { - config = { - ...config, - command: 'build' - } - - const { root, logger } = config - const log = asCommand ? logger.info : debug + asCommand = false +): DepOptimizationMetadata | undefined { + const log = asCommand ? config.logger.info : debug // Before Vite 2.9, dependencies were cached in the root of the cacheDir // For compat, we remove the cache if we find the old structure @@ -200,40 +236,106 @@ export async function createOptimizeDepsRun( } const depsCacheDir = getDepsCacheDir(config) - const processingCacheDir = getProcessingDepsCacheDir(config) - - const mainHash = getDepHash(root, config) - - const processing = newDepOptimizationProcessing() - - const metadata: DepOptimizationMetadata = { - hash: mainHash, - browserHash: mainHash, - optimized: {}, - discovered: {}, - processing: processing.promise - } if (!force) { - let prevData: DepOptimizationMetadata | undefined + let cachedMetadata: DepOptimizationMetadata | undefined try { - const prevDataPath = path.join(depsCacheDir, '_metadata.json') - prevData = parseOptimizedDepsMetadata( - fs.readFileSync(prevDataPath, 'utf-8'), - depsCacheDir, - processing.promise + const cachedMetadataPath = path.join(depsCacheDir, '_metadata.json') + cachedMetadata = parseOptimizedDepsMetadata( + fs.readFileSync(cachedMetadataPath, 'utf-8'), + depsCacheDir ) } catch (e) {} // hash is consistent, no need to re-bundle - if (prevData && prevData.hash === metadata.hash) { + if (cachedMetadata && cachedMetadata.hash === getDepHash(config)) { log('Hash is consistent. Skipping. Use --force to override.') - return { - metadata: prevData, - run: () => (processing.resolve(), processing.promise) - } + // Nothing to commit or cancel as we are using the cache, we only + // need to resolve the processing promise so requests can move on + return cachedMetadata } + } else { + config.logger.info('Forced re-optimization of dependencies') } + // Start with a fresh cache + removeDirSync(depsCacheDir) +} + +/** + * Initial optimizeDeps at server start. Perform a fast scan using esbuild to + * find deps to pre-bundle and include user hard-coded dependencies + */ +export async function discoverProjectDependencies( + config: ResolvedConfig, + timestamp?: string +): Promise> { + const { deps, missing } = await scanImports(config) + + const missingIds = Object.keys(missing) + if (missingIds.length) { + throw new Error( + `The following dependencies are imported but could not be resolved:\n\n ${missingIds + .map( + (id) => + `${colors.cyan(id)} ${colors.white( + colors.dim(`(imported by ${missing[id]})`) + )}` + ) + .join(`\n `)}\n\nAre they installed?` + ) + } + + await addManuallyIncludedOptimizeDeps(deps, config) + + const browserHash = getOptimizedBrowserHash( + getDepHash(config), + deps, + timestamp + ) + const discovered: Record = {} + for (const id in deps) { + const entry = deps[id] + discovered[id] = { + id, + file: getOptimizedDepPath(id, config), + src: entry, + browserHash: browserHash + } + } + return discovered +} + +export function depsLogString(qualifiedIds: string[]): string { + if (isDebugEnabled) { + return colors.yellow(qualifiedIds.join(`\n `)) + } else { + const total = qualifiedIds.length + const maxListed = 5 + const listed = Math.min(total, maxListed) + const extra = Math.max(0, total - maxListed) + return colors.yellow( + qualifiedIds.slice(0, listed).join(`, `) + + (extra > 0 ? `, ...and ${extra} more` : ``) + ) + } +} + +/** + * Internally, Vite uses this function to prepare a optimizeDeps run. When Vite starts, we can get + * the metadata and start the server without waiting for the optimizeDeps processing to be completed + */ +export async function runOptimizeDeps( + config: ResolvedConfig, + depsInfo: Record +): Promise { + config = { + ...config, + command: 'build' + } + + const depsCacheDir = getDepsCacheDir(config) + const processingCacheDir = getProcessingDepsCacheDir(config) + // Create a temporal directory so we don't need to delete optimized deps // until they have been processed. This also avoids leaving the deps cache // directory in a corrupted state if there is an error @@ -250,289 +352,199 @@ export async function createOptimizeDepsRun( JSON.stringify({ type: 'module' }) ) - let newBrowserHash: string - - let deps: Record - if (!newDeps) { - // Initial optimizeDeps at server start. Perform a fast scan using esbuild to - // find deps to pre-bundle and include user hard-coded dependencies - - let missing: Record - ;({ deps, missing } = await scanImports(config)) - - const missingIds = Object.keys(missing) - if (missingIds.length) { - processing.resolve() - throw new Error( - `The following dependencies are imported but could not be resolved:\n\n ${missingIds - .map( - (id) => - `${colors.cyan(id)} ${colors.white( - colors.dim(`(imported by ${missing[id]})`) - )}` - ) - .join(`\n `)}\n\nAre they installed?` - ) - } + const metadata = createOptimizedDepsMetadata(config) - try { - await addManuallyIncludedOptimizeDeps(deps, config) - } catch (e) { - processing.resolve() - throw e - } - - // update browser hash - newBrowserHash = metadata.browserHash = getOptimizedBrowserHash( - metadata.hash, - deps - ) + metadata.browserHash = getOptimizedBrowserHash( + metadata.hash, + depsFromOptimizedDepInfo(depsInfo) + ) - // We generate the mapping of dependency ids to their cache file location - // before processing the dependencies with esbuild. This allow us to continue - // processing files in the importAnalysis and resolve plugins - for (const id in deps) { - const entry = deps[id] - metadata.optimized[id] = { - file: getOptimizedDepPath(id, config), - src: entry, - browserHash: newBrowserHash, - processing: processing.promise - } + // We prebundle dependencies with esbuild and cache them, but there is no need + // to wait here. Code that needs to access the cached deps needs to await + // the optimizedDepInfo.processing promise for each dep + + const qualifiedIds = Object.keys(depsInfo) + + if (!qualifiedIds.length) { + return { + metadata, + commit() { + // Write metadata file, delete `deps` folder and rename the `processing` folder to `deps` + commitProcessingDepsCacheSync() + config.logger.info(`No dependencies to bundle. Skipping.\n\n\n`) + }, + cancel } - } else { - // Missing dependencies were found at run-time, optimizeDeps called while the - // server is running - deps = depsFromOptimizedDepInfo(newDeps) - - metadata.optimized = newDeps - - // For reruns keep current global browser hash and newDeps individual hashes until we know - // if files are stable so we can avoid a full page reload - metadata.browserHash = currentData!.browserHash - newBrowserHash = getOptimizedBrowserHash(metadata.hash, deps) } - return { metadata, run: prebundleDeps } - - async function prebundleDeps(): Promise { - // We prebundle dependencies with esbuild and cache them, but there is no need - // to wait here. Code that needs to access the cached deps needs to await - // the optimizeDepsMetadata.processing promise - - const qualifiedIds = Object.keys(deps) - - if (!qualifiedIds.length) { - // Write metadata file, delete `deps` folder and rename the `processing` folder to `deps` - commitProcessingDepsCacheSync() - log(`No dependencies to bundle. Skipping.\n\n\n`) - processing.resolve() - return - } - - let depsString: string - if (isDebugEnabled) { - depsString = colors.yellow(qualifiedIds.join(`\n `)) + // esbuild generates nested directory output with lowest common ancestor base + // this is unpredictable and makes it difficult to analyze entry / output + // mapping. So what we do here is: + // 1. flatten all ids to eliminate slash + // 2. in the plugin, read the entry ourselves as virtual files to retain the + // path. + const flatIdDeps: Record = {} + const idToExports: Record = {} + const flatIdToExports: Record = {} + + const { plugins = [], ...esbuildOptions } = + config.optimizeDeps?.esbuildOptions ?? {} + + await init + for (const id in depsInfo) { + const flatId = flattenId(id) + const filePath = (flatIdDeps[flatId] = depsInfo[id].src!) + let exportsData: ExportsData + if (config.optimizeDeps.extensions?.some((ext) => filePath.endsWith(ext))) { + // For custom supported extensions, build the entry file to transform it into JS, + // and then parse with es-module-lexer. Note that the `bundle` option is not `true`, + // so only the entry file is being transformed. + const result = await build({ + ...esbuildOptions, + plugins, + entryPoints: [filePath], + write: false, + format: 'esm' + }) + exportsData = parse(result.outputFiles[0].text) as ExportsData } else { - const total = qualifiedIds.length - const maxListed = 5 - const listed = Math.min(total, maxListed) - const extra = Math.max(0, total - maxListed) - depsString = colors.yellow( - qualifiedIds.slice(0, listed).join(`\n `) + - (extra > 0 ? `\n (...and ${extra} more)` : ``) - ) - } - - if (!asCommand) { - if (!newDeps) { - // This is auto run on server start - let the user know that we are - // pre-optimizing deps - logger.info(colors.green(`Pre-bundling dependencies:\n ${depsString}`)) - logger.info( - `(this will be run only when your dependencies or config have changed)` + const entryContent = fs.readFileSync(filePath, 'utf-8') + try { + exportsData = parse(entryContent) as ExportsData + } catch { + debug( + `Unable to parse dependency: ${id}. Trying again with a JSX transform.` ) - } - } else { - logger.info(colors.green(`Optimizing dependencies:\n ${depsString}`)) - } - - // esbuild generates nested directory output with lowest common ancestor base - // this is unpredictable and makes it difficult to analyze entry / output - // mapping. So what we do here is: - // 1. flatten all ids to eliminate slash - // 2. in the plugin, read the entry ourselves as virtual files to retain the - // path. - const flatIdDeps: Record = {} - const idToExports: Record = {} - const flatIdToExports: Record = {} - - const { plugins = [], ...esbuildOptions } = - config.optimizeDeps?.esbuildOptions ?? {} - - await init - for (const id in deps) { - const flatId = flattenId(id) - const filePath = (flatIdDeps[flatId] = deps[id]) - let exportsData: ExportsData - if ( - config.optimizeDeps.extensions?.some((ext) => filePath.endsWith(ext)) - ) { - // For custom supported extensions, build the entry file to transform it into JS, - // and then parse with es-module-lexer. Note that the `bundle` option is not `true`, - // so only the entry file is being transformed. - const result = await build({ - ...esbuildOptions, - plugins, - entryPoints: [filePath], - write: false, - format: 'esm' + const transformed = await transformWithEsbuild(entryContent, filePath, { + loader: 'jsx' }) - exportsData = parse(result.outputFiles[0].text) as ExportsData - } else { - const entryContent = fs.readFileSync(filePath, 'utf-8') - try { - exportsData = parse(entryContent) as ExportsData - } catch { - debug( - `Unable to parse dependency: ${id}. Trying again with a JSX transform.` - ) - const transformed = await transformWithEsbuild( - entryContent, - filePath, - { - loader: - (esbuildOptions.loader && - esbuildOptions.loader[path.extname(filePath)]) || - 'jsx' - } - ) - - // Ensure that optimization won't fail by defaulting '.js' to the JSX parser. - // This is useful for packages such as Gatsby. - esbuildOptions.loader = { - '.js': 'jsx', - ...esbuildOptions.loader - } - exportsData = parse(transformed.code) as ExportsData + // Ensure that optimization won't fail by defaulting '.js' to the JSX parser. + // This is useful for packages such as Gatsby. + esbuildOptions.loader = { + '.js': 'jsx', + ...esbuildOptions.loader } - for (const { ss, se } of exportsData[0]) { - const exp = entryContent.slice(ss, se) - if (/export\s+\*\s+from/.test(exp)) { - exportsData.hasReExports = true - } + exportsData = parse(transformed.code) as ExportsData + } + for (const { ss, se } of exportsData[0]) { + const exp = entryContent.slice(ss, se) + if (/export\s+\*\s+from/.test(exp)) { + exportsData.hasReExports = true } } - - idToExports[id] = exportsData - flatIdToExports[flatId] = exportsData } - const define: Record = { - 'process.env.NODE_ENV': JSON.stringify(config.mode) - } - for (const key in config.define) { - const value = config.define[key] - define[key] = typeof value === 'string' ? value : JSON.stringify(value) - } + idToExports[id] = exportsData + flatIdToExports[flatId] = exportsData + } - const start = performance.now() - - const result = await build({ - absWorkingDir: process.cwd(), - entryPoints: Object.keys(flatIdDeps), - bundle: true, - format: 'esm', - target: config.build.target || undefined, - external: config.optimizeDeps?.exclude, - logLevel: 'error', - splitting: true, - sourcemap: true, - outdir: processingCacheDir, - ignoreAnnotations: true, - metafile: true, - define, - plugins: [ - ...plugins, - esbuildDepPlugin(flatIdDeps, flatIdToExports, config, ssr) - ], - ...esbuildOptions - }) + const define: Record = { + 'process.env.NODE_ENV': JSON.stringify(config.mode) + } + for (const key in config.define) { + const value = config.define[key] + define[key] = typeof value === 'string' ? value : JSON.stringify(value) + } - const meta = result.metafile! + const start = performance.now() + + const result = await build({ + absWorkingDir: process.cwd(), + entryPoints: Object.keys(flatIdDeps), + bundle: true, + format: 'esm', + target: config.build.target || undefined, + external: config.optimizeDeps?.exclude, + logLevel: 'error', + splitting: true, + sourcemap: true, + outdir: processingCacheDir, + ignoreAnnotations: true, + metafile: true, + define, + plugins: [ + ...plugins, + esbuildDepPlugin(flatIdDeps, flatIdToExports, config) + ], + ...esbuildOptions + }) - // the paths in `meta.outputs` are relative to `process.cwd()` - const processingCacheDirOutputPath = path.relative( - process.cwd(), - processingCacheDir - ) + const meta = result.metafile! - for (const id in deps) { - const optimizedInfo = metadata.optimized[id] - optimizedInfo.needsInterop = needsInterop( - id, - idToExports[id], - meta.outputs, - processingCacheDirOutputPath - ) - const output = - meta.outputs[path.relative(process.cwd(), optimizedInfo.file)] - if (output) { - // We only need to hash the output.imports in to check for stability, but adding the hash - // and file path gives us a unique hash that may be useful for other things in the future - optimizedInfo.fileHash = getHash( - metadata.hash + optimizedInfo.file + JSON.stringify(output.imports) - ) - } - } + // the paths in `meta.outputs` are relative to `process.cwd()` + const processingCacheDirOutputPath = path.relative( + process.cwd(), + processingCacheDir + ) - // This only runs when missing deps are processed. Previous optimized deps are stable if - // the newly discovered deps don't have common chunks with them. Comparing their fileHash we - // can find out if it is safe to keep the current browser state. If one of the file hashes - // changed, a full page reload is needed - let alteredFiles = false - if (currentData) { - alteredFiles = Object.keys(currentData.optimized).some((dep) => { - const currentInfo = currentData.optimized[dep] - const info = metadata.optimized[dep] - return ( - !info?.fileHash || - !currentInfo?.fileHash || - info?.fileHash !== currentInfo?.fileHash - ) - }) - debug(`optimized deps have altered files: ${alteredFiles}`) - } + for (const id in depsInfo) { + const output = esbuildOutputFromId(meta.outputs, id, processingCacheDir) + + addOptimizedDepInfo(metadata, 'optimized', { + ...depsInfo[id], + needsInterop: needsInterop(id, idToExports[id], output), + // We only need to hash the output.imports in to check for stability, but adding the hash + // and file path gives us a unique hash that may be useful for other things in the future + fileHash: getHash( + metadata.hash + depsInfo[id].file + JSON.stringify(output.imports) + ), + browserHash: metadata.browserHash + }) + } - if (alteredFiles) { - // Overrite individual hashes with the new global browserHash, a full page reload is required - // New deps that ended up with a different hash replaced while doing analysis import are going to - // return a not found so the browser doesn't cache them. And will properly get loaded after the reload - for (const id in deps) { - metadata.optimized[id].browserHash = newBrowserHash + for (const o of Object.keys(meta.outputs)) { + if (!o.match(jsMapExtensionRE)) { + const id = path + .relative(processingCacheDirOutputPath, o) + .replace(jsExtensionRE, '') + const file = getOptimizedDepPath(id, config) + if ( + !findOptimizedDepInfoInRecord( + metadata.optimized, + (depInfo) => depInfo.file === file + ) + ) { + addOptimizedDepInfo(metadata, 'chunks', { + id, + file, + needsInterop: false, + browserHash: metadata.browserHash + }) } - metadata.browserHash = newBrowserHash } + } + + const dataPath = path.join(processingCacheDir, '_metadata.json') + writeFile(dataPath, stringifyOptimizedDepsMetadata(metadata, depsCacheDir)) - // Write metadata file, delete `deps` folder and rename the new `processing` folder to `deps` in sync - commitProcessingDepsCacheSync() + debug(`deps bundled in ${(performance.now() - start).toFixed(2)}ms`) - debug(`deps bundled in ${(performance.now() - start).toFixed(2)}ms`) - processing.resolve({ alteredFiles }) - return processing.promise + return { + metadata, + commit() { + // Write metadata file, delete `deps` folder and rename the new `processing` folder to `deps` in sync + commitProcessingDepsCacheSync() + }, + cancel } function commitProcessingDepsCacheSync() { - // Rewire the file paths from the temporal processing dir to the final deps cache dir - const dataPath = path.join(processingCacheDir, '_metadata.json') - writeFile(dataPath, stringifyOptimizedDepsMetadata(metadata, depsCacheDir)) // Processing is done, we can now replace the depsCacheDir with processingCacheDir - if (fs.existsSync(depsCacheDir)) { - const rmSync = fs.rmSync ?? fs.rmdirSync // TODO: Remove after support for Node 12 is dropped - rmSync(depsCacheDir, { recursive: true }) - } + // Rewire the file paths from the temporal processing dir to the final deps cache dir + removeDirSync(depsCacheDir) fs.renameSync(processingCacheDir, depsCacheDir) } + + function cancel() { + removeDirSync(processingCacheDir) + } +} + +function removeDirSync(dir: string) { + if (fs.existsSync(dir)) { + const rmSync = fs.rmSync ?? fs.rmdirSync // TODO: Remove after support for Node 12 is dropped + rmSync(dir, { recursive: true }) + } } export async function findKnownImports( @@ -569,10 +581,10 @@ async function addManuallyIncludedOptimizeDeps( } export function newDepOptimizationProcessing(): DepOptimizationProcessing { - let resolve: (result?: DepOptimizationResult) => void + let resolve: () => void const promise = new Promise((_resolve) => { resolve = _resolve - }) as Promise + }) as Promise return { promise, resolve: resolve! } } @@ -581,38 +593,21 @@ export function depsFromOptimizedDepInfo( depsInfo: Record ) { return Object.fromEntries( - Object.entries(depsInfo).map((d) => [d[0], d[1].src]) + Object.entries(depsInfo).map((d) => [d[0], d[1].src!]) ) } -function getHash(text: string) { - return createHash('sha256').update(text).digest('hex').substring(0, 8) -} - -export function getOptimizedBrowserHash( - hash: string, - deps: Record, - missing?: Record -) { - // update browser hash - return getHash( - hash + JSON.stringify(deps) + (missing ? JSON.stringify(missing) : '') - ) -} - -function getCachedDepFilePath(id: string, depsCacheDir: string) { - return normalizePath(path.resolve(depsCacheDir, flattenId(id) + '.js')) -} - export function getOptimizedDepPath(id: string, config: ResolvedConfig) { - return getCachedDepFilePath(id, getDepsCacheDir(config)) + return normalizePath( + path.resolve(getDepsCacheDir(config), flattenId(id) + '.js') + ) } export function getDepsCacheDir(config: ResolvedConfig) { return normalizePath(path.resolve(config.cacheDir, 'deps')) } -export function getProcessingDepsCacheDir(config: ResolvedConfig) { +function getProcessingDepsCacheDir(config: ResolvedConfig) { return normalizePath(path.resolve(config.cacheDir, 'processing')) } @@ -641,33 +636,87 @@ export function createIsOptimizedDepUrl(config: ResolvedConfig) { function parseOptimizedDepsMetadata( jsonMetadata: string, - depsCacheDir: string, - processing: Promise -) { - const metadata = JSON.parse(jsonMetadata, (key: string, value: string) => { - // Paths can be absolute or relative to the deps cache dir where - // the _metadata.json is located - if (key === 'file' || key === 'src') { - return normalizePath(path.resolve(depsCacheDir, value)) + depsCacheDir: string +): DepOptimizationMetadata | undefined { + const { hash, browserHash, optimized, chunks } = JSON.parse( + jsonMetadata, + (key: string, value: string) => { + // Paths can be absolute or relative to the deps cache dir where + // the _metadata.json is located + if (key === 'file' || key === 'src') { + return normalizePath(path.resolve(depsCacheDir, value)) + } + return value } - return value - }) - for (const o of Object.keys(metadata.optimized)) { - metadata.optimized[o].processing = processing + ) + if ( + !chunks || + Object.values(optimized).some((depInfo: any) => !depInfo.fileHash) + ) { + // outdated _metadata.json version, ignore + return + } + const metadata = { + hash, + browserHash, + optimized: {}, + discovered: {}, + chunks: {}, + depInfoList: [] } - return { ...metadata, discovered: {}, processing } + for (const id of Object.keys(optimized)) { + addOptimizedDepInfo(metadata, 'optimized', { + ...optimized[id], + id, + browserHash + }) + } + for (const id of Object.keys(chunks)) { + addOptimizedDepInfo(metadata, 'chunks', { + ...chunks[id], + id, + browserHash, + needsInterop: false + }) + } + return metadata } +/** + * Stringify metadata for deps cache. Remove processing promises + * and individual dep info browserHash. Once the cache is reload + * the next time the server start we need to use the global + * browserHash to allow long term caching + */ function stringifyOptimizedDepsMetadata( metadata: DepOptimizationMetadata, depsCacheDir: string ) { + const { hash, browserHash, optimized, chunks } = metadata return JSON.stringify( - metadata, - (key: string, value: any) => { - if (key === 'processing' || key === 'discovered') { - return - } + { + hash, + browserHash, + optimized: Object.fromEntries( + Object.values(optimized).map( + ({ id, src, file, fileHash, needsInterop }) => [ + id, + { + src, + file, + fileHash, + needsInterop + } + ] + ) + ), + chunks: Object.fromEntries( + Object.values(chunks).map(({ id, file }) => [id, { file }]) + ) + }, + (key: string, value: string) => { + // Paths can be absolute or relative to the deps cache dir where + // the _metadata.json is located if (key === 'file' || key === 'src') { return normalizePath(path.relative(depsCacheDir, value)) } @@ -677,6 +726,19 @@ function stringifyOptimizedDepsMetadata( ) } +function esbuildOutputFromId( + outputs: Record, + id: string, + cacheDirOutputPath: string +): any { + const flatId = flattenId(id) + '.js' + return outputs[ + normalizePath( + path.relative(process.cwd(), path.join(cacheDirOutputPath, flatId)) + ) + ] +} + // https://github.com/vitejs/vite/issues/1724#issuecomment-767619642 // a list of modules that pretends to be ESM but still uses `require`. // this causes esbuild to wrap them as CJS even when its entry appears to be ESM. @@ -685,8 +747,7 @@ const KNOWN_INTEROP_IDS = new Set(['moment']) function needsInterop( id: string, exportsData: ExportsData, - outputs: Record, - cacheDirOutputPath: string + output: { exports: string[] } ): boolean { if (KNOWN_INTEROP_IDS.has(id)) { return true @@ -700,17 +761,7 @@ function needsInterop( // if a peer dependency used require() on a ESM dependency, esbuild turns the // ESM dependency's entry chunk into a single default export... detect // such cases by checking exports mismatch, and force interop. - const flatId = flattenId(id) + '.js' - let generatedExports: string[] | undefined - for (const output in outputs) { - if ( - normalizePath(output) === - normalizePath(path.join(cacheDirOutputPath, flatId)) - ) { - generatedExports = outputs[output].exports - break - } - } + const generatedExports: string[] = output.exports if ( !generatedExports || @@ -727,8 +778,8 @@ function isSingleDefaultExport(exports: readonly string[]) { const lockfileFormats = ['package-lock.json', 'yarn.lock', 'pnpm-lock.yaml'] -function getDepHash(root: string, config: ResolvedConfig): string { - let content = lookupFile(root, lockfileFormats) || '' +export function getDepHash(config: ResolvedConfig): string { + let content = lookupFile(config.root, lockfileFormats) || '' // also take config into account // only a subset of config options that can affect dep optimization content += JSON.stringify( @@ -758,26 +809,44 @@ function getDepHash(root: string, config: ResolvedConfig): string { return value } ) - return createHash('sha256').update(content).digest('hex').substring(0, 8) + return getHash(content) +} + +function getOptimizedBrowserHash( + hash: string, + deps: Record, + timestamp = '' +) { + return getHash(hash + JSON.stringify(deps) + timestamp) } -export function optimizeDepInfoFromFile( +export function getHash(text: string): string { + return createHash('sha256').update(text).digest('hex').substring(0, 8) +} + +export function optimizedDepInfoFromId( metadata: DepOptimizationMetadata, - file: string + id: string ): OptimizedDepInfo | undefined { return ( - findFileInfo(metadata.optimized, file) || - findFileInfo(metadata.discovered, file) + metadata.optimized[id] || metadata.discovered[id] || metadata.chunks[id] ) } -function findFileInfo( - dependenciesInfo: Record, +export function optimizedDepInfoFromFile( + metadata: DepOptimizationMetadata, file: string +): OptimizedDepInfo | undefined { + return metadata.depInfoList.find((depInfo) => depInfo.file === file) +} + +function findOptimizedDepInfoInRecord( + dependenciesInfo: Record, + callbackFn: (depInfo: OptimizedDepInfo, id: string) => any ): OptimizedDepInfo | undefined { for (const o of Object.keys(dependenciesInfo)) { const info = dependenciesInfo[o] - if (info.file === file) { + if (callbackFn(info, o)) { return info } } @@ -787,7 +856,7 @@ export async function optimizedDepNeedsInterop( metadata: DepOptimizationMetadata, file: string ): Promise { - const depInfo = optimizeDepInfoFromFile(metadata, file) + const depInfo = optimizedDepInfoFromFile(metadata, file) if (!depInfo) return undefined diff --git a/packages/vite/src/node/optimizer/registerMissing.ts b/packages/vite/src/node/optimizer/registerMissing.ts index 2b7fe0bb8c629c..ee4824389c202b 100644 --- a/packages/vite/src/node/optimizer/registerMissing.ts +++ b/packages/vite/src/node/optimizer/registerMissing.ts @@ -1,18 +1,26 @@ import colors from 'picocolors' +import _debug from 'debug' import { - createOptimizeDepsRun, + runOptimizeDeps, getOptimizedDepPath, - getOptimizedBrowserHash, + getHash, depsFromOptimizedDepInfo, - newDepOptimizationProcessing + newDepOptimizationProcessing, + loadCachedDepOptimizationMetadata, + createOptimizedDepsMetadata, + addOptimizedDepInfo, + discoverProjectDependencies, + depsLogString, + debuggerViteDeps as debug } from '.' import type { - DepOptimizationMetadata, - DepOptimizationResult, - OptimizedDepInfo + DepOptimizationProcessing, + OptimizedDepInfo, + OptimizedDeps } from '.' import type { ViteDevServer } from '..' -import { resolveSSRExternal } from '../ssr/ssrExternal' + +const isDebugEnabled = _debug('vite:deps').enabled /** * The amount to wait for requests to register newly found dependencies before triggering @@ -20,139 +28,258 @@ import { resolveSSRExternal } from '../ssr/ssrExternal' */ const debounceMs = 100 -export function createMissingImporterRegisterFn( - server: ViteDevServer -): (id: string, resolved: string, ssr?: boolean) => OptimizedDepInfo { - const { logger } = server.config - let metadata = server._optimizeDepsMetadata! +export function createOptimizedDeps(server: ViteDevServer): OptimizedDeps { + const { config } = server + const { logger } = config + + const sessionTimestamp = Date.now().toString() + + const cachedMetadata = loadCachedDepOptimizationMetadata(config) + + const optimizedDeps: OptimizedDeps = { + metadata: + cachedMetadata || createOptimizedDepsMetadata(config, sessionTimestamp), + registerMissingImport + } let handle: NodeJS.Timeout | undefined - let needFullReload: boolean = false + let newDepsDiscovered = false + + let newDepsToLog: string[] = [] + let newDepsToLogHandle: NodeJS.Timeout | undefined + const logNewlyDiscoveredDeps = () => { + if (newDepsToLog.length) { + config.logger.info( + colors.green( + `✨ new dependencies optimized: ${depsLogString(newDepsToLog)}` + ), + { + timestamp: true + } + ) + newDepsToLog = [] + } + } let depOptimizationProcessing = newDepOptimizationProcessing() + let depOptimizationProcessingQueue: DepOptimizationProcessing[] = [] + const resolveEnqueuedProcessingPromises = () => { + // Resolve all the processings (including the ones which were delayed) + for (const processing of depOptimizationProcessingQueue) { + processing.resolve() + } + depOptimizationProcessingQueue = [] + } - let lastDepOptimizationPromise = metadata.processing + let enqueuedRerun: (() => void) | undefined + let currentlyProcessing = false - async function rerun(ssr: boolean | undefined) { - // debounce time to wait for new missing deps finished, issue a new - // optimization of deps (both old and newly found) once the previous - // optimizeDeps processing is finished + // If there wasn't a cache or it is outdated, perform a fast scan with esbuild + // to quickly find project dependencies and do a first optimize run + if (!cachedMetadata) { + currentlyProcessing = true - // a succesful completion of the optimizeDeps rerun will end up - // creating new bundled version of all current and discovered deps - // in the cache dir and a new metadata info object assigned - // to server._optimizeDepsMetadata. A fullReload is only issued if - // the previous bundled dependencies have changed. + const scanPhaseProcessing = newDepOptimizationProcessing() + optimizedDeps.scanProcessing = scanPhaseProcessing.promise - // if the rerun fails, server._optimizeDepsMetadata remains untouched, - // current discovered deps are cleaned, and a fullReload is issued + const warmUp = async () => { + try { + debug(colors.green(`scanning for dependencies...`), { + timestamp: true + }) - // optimizeDeps needs to be run in serie. Await until the previous - // rerun is finished here. It could happen that two reruns are queued - // in that case, we only need to run one of them - const awaitedOptimizeDepsPromise = lastDepOptimizationPromise + const { metadata } = optimizedDeps - await lastDepOptimizationPromise + const discovered = await discoverProjectDependencies( + config, + sessionTimestamp + ) - if (awaitedOptimizeDepsPromise !== lastDepOptimizationPromise) { - // There were two or more rerun queued and one of them already - // started. Only let through the first one, and discard the others - return - } + // Respect the scan phase discover order to improve reproducibility + for (const depInfo of Object.values(discovered)) { + addOptimizedDepInfo(metadata, 'discovered', { + ...depInfo, + processing: depOptimizationProcessing.promise + }) + } - if (handle) { - // New deps could have been found here, skip this rerun. Once the - // debounce time is over, a new rerun will be issued - return - } + debug( + colors.green( + `dependencies found: ${depsLogString(Object.keys(discovered))}` + ), + { + timestamp: true + } + ) - logger.info( - colors.yellow( - `new dependencies found: ${Object.keys(metadata.discovered).join( - ', ' - )}, updating...` - ), - { - timestamp: true + scanPhaseProcessing.resolve() + optimizedDeps.scanProcessing = undefined + + runOptimizer() + } catch (e) { + logger.error(e.message) + if (optimizedDeps.scanProcessing) { + scanPhaseProcessing.resolve() + optimizedDeps.scanProcessing = undefined + } } - ) + } + + setTimeout(warmUp, 0) + } + + async function runOptimizer(isRerun = false) { + // Ensure that rerun is called sequentially + enqueuedRerun = undefined + currentlyProcessing = true + + // Ensure that a rerun will not be issued for current discovered deps + if (handle) clearTimeout(handle) + + // a succesful completion of the optimizeDeps rerun will end up + // creating new bundled version of all current and discovered deps + // in the cache dir and a new metadata info object assigned + // to optimizeDeps.metadata. A fullReload is only issued if + // the previous bundled dependencies have changed. + + // if the rerun fails, optimizeDeps.metadata remains untouched, + // current discovered deps are cleaned, and a fullReload is issued + + let { metadata } = optimizedDeps // All deps, previous known and newly discovered are rebundled, // respect insertion order to keep the metadata file stable + const newDeps: Record = {} + // Clone optimized info objects, fileHash, browserHash may be changed for them - const clonedOptimizedDeps: Record = {} - for (const o of Object.keys(metadata.optimized)) { - clonedOptimizedDeps[o] = { ...metadata.optimized[o] } + for (const dep of Object.keys(metadata.optimized)) { + newDeps[dep] = { ...metadata.optimized[dep] } + } + for (const dep of Object.keys(metadata.discovered)) { + // Clone the discovered info discarding its processing promise + const { processing, ...info } = metadata.discovered[dep] + newDeps[dep] = info } - const newDeps = { ...clonedOptimizedDeps, ...metadata.discovered } - const thisDepOptimizationProcessing = depOptimizationProcessing - - // Other rerun will await until this run is finished - lastDepOptimizationPromise = thisDepOptimizationProcessing.promise + newDepsDiscovered = false - let processingResult: DepOptimizationResult | undefined + // Add the current depOptimizationProcessing to the queue, these + // promises are going to be resolved once a rerun is committed + depOptimizationProcessingQueue.push(depOptimizationProcessing) // Create a new promise for the next rerun, discovered missing // dependencies will be asigned this promise from this point depOptimizationProcessing = newDepOptimizationProcessing() - let newData: DepOptimizationMetadata | null = null - try { - const optimizeDeps = await createOptimizeDepsRun( - server.config, - true, - false, - metadata, - newDeps, - ssr - ) + const processingResult = await runOptimizeDeps(config, newDeps) + + const newData = processingResult.metadata + + // After a re-optimization, if the internal bundled chunks change a full page reload + // is required. If the files are stable, we can avoid the reload that is expensive + // for large applications. Comparing their fileHash we can find out if it is safe to + // keep the current browser state. + const needsReload = + metadata.hash !== newData.hash || + Object.keys(metadata.optimized).some((dep) => { + return ( + metadata.optimized[dep].fileHash !== newData.optimized[dep].fileHash + ) + }) - // We await the optimizeDeps run here, we are only going to use - // the newData if there wasn't an error - newData = optimizeDeps.metadata - processingResult = await optimizeDeps.run() + const commitProcessing = () => { + processingResult.commit() - // update ssr externals - if (ssr) { - server._ssrExternals = resolveSSRExternal( - server.config, - Object.keys(newData.optimized) - ) - } + // While optimizeDeps is running, new missing deps may be discovered, + // in which case they will keep being added to metadata.discovered + for (const id in metadata.discovered) { + if (!newData.optimized[id]) { + addOptimizedDepInfo(newData, 'discovered', metadata.discovered[id]) + } + } + + // If we don't reload the page, we need to keep browserHash stable + if (!needsReload) { + newData.browserHash = metadata.browserHash + for (const dep in newData.chunks) { + newData.chunks[dep].browserHash = metadata.browserHash + } + for (const dep in newData.optimized) { + newData.optimized[dep].browserHash = ( + metadata.optimized[dep] || metadata.discovered[dep] + ).browserHash + } + } - // While optimizeDeps is running, new missing deps may be discovered, - // in which case they will keep being added to metadata.discovered - for (const o of Object.keys(metadata.discovered)) { - if (!newData.optimized[o]) { - newData.discovered[o] = metadata.discovered[o] + // Commit hash and needsInterop changes to the discovered deps info + // object. Allow for code to await for the discovered processing promise + // and use the information in the same object + for (const o in newData.optimized) { + const discovered = metadata.discovered[o] + if (discovered) { + const optimized = newData.optimized[o] + discovered.browserHash = optimized.browserHash + discovered.fileHash = optimized.fileHash + discovered.needsInterop = optimized.needsInterop + discovered.processing = undefined + } + } + + if (isRerun) { + newDepsToLog.push( + ...Object.keys(newData.optimized).filter( + (dep) => !metadata.optimized[dep] + ) + ) } + + metadata = optimizedDeps.metadata = newData + resolveEnqueuedProcessingPromises() } - newData.processing = thisDepOptimizationProcessing.promise - metadata = server._optimizeDepsMetadata = newData - if (!needFullReload && !processingResult?.alteredFiles) { - logger.info(colors.green(`✨ new dependencies pre-bundled...`), { - timestamp: true - }) + if (!needsReload) { + commitProcessing() + + if (!isDebugEnabled) { + if (newDepsToLogHandle) clearTimeout(newDepsToLogHandle) + newDepsToLogHandle = setTimeout(() => { + newDepsToLogHandle = undefined + logNewlyDiscoveredDeps() + }, 2 * debounceMs) + } else { + debug(colors.green(`✨ optimized dependencies unchanged`), { + timestamp: true + }) + } } else { - if (Object.keys(metadata.discovered).length > 0) { + if (newDepsDiscovered) { // There are newly discovered deps, and another rerun is about to be - // excecuted. Avoid the current full reload, but queue it for the next one - needFullReload = true - logger.info( + // excecuted. Avoid the current full reload discarding this rerun result + // We don't resolve the processing promise, as they will be resolved + // once a rerun is committed + processingResult.cancel() + + debug( colors.green( - `✨ dependencies updated, delaying reload as new dependencies have been found...` + `✨ delaying reload as new dependencies have been found...` ), { timestamp: true } ) } else { + commitProcessing() + + if (!isDebugEnabled) { + if (newDepsToLogHandle) clearTimeout(newDepsToLogHandle) + newDepsToLogHandle = undefined + logNewlyDiscoveredDeps() + } + logger.info( - colors.green(`✨ dependencies updated, reloading page...`), + colors.green(`✨ optimized dependencies changed. reloading`), { timestamp: true } @@ -165,15 +292,16 @@ export function createMissingImporterRegisterFn( colors.red(`error while updating dependencies:\n${e.stack}`), { timestamp: true, error: e } ) + resolveEnqueuedProcessingPromises() // Reset missing deps, let the server rediscover the dependencies metadata.discovered = {} fullReload() - } finally { - // Rerun finished, resolve the promise to let awaiting requests or - // other rerun queued be processed - thisDepOptimizationProcessing.resolve() } + + currentlyProcessing = false + // @ts-ignore + enqueuedRerun?.() } function fullReload() { @@ -186,33 +314,65 @@ export function createMissingImporterRegisterFn( type: 'full-reload', path: '*' }) + } - needFullReload = false + async function rerun() { + // debounce time to wait for new missing deps finished, issue a new + // optimization of deps (both old and newly found) once the previous + // optimizeDeps processing is finished + const deps = Object.keys(optimizedDeps.metadata.discovered) + const depsString = depsLogString(deps) + debug(colors.green(`new dependencies found: ${depsString}`), { + timestamp: true + }) + runOptimizer(true) } - return function registerMissingImport( + function getDiscoveredBrowserHash( + hash: string, + deps: Record, + missing: Record + ) { + return getHash( + hash + JSON.stringify(deps) + JSON.stringify(missing) + sessionTimestamp + ) + } + + function registerMissingImport( id: string, resolved: string, ssr?: boolean ): OptimizedDepInfo { + if (optimizedDeps.scanProcessing) { + config.logger.error( + 'Vite internal error: registering missing import before initial scanning is over' + ) + } + const { metadata } = optimizedDeps const optimized = metadata.optimized[id] if (optimized) { return optimized } + const chunk = metadata.chunks[id] + if (chunk) { + return chunk + } let missing = metadata.discovered[id] if (missing) { // We are already discover this dependency // It will be processed in the next rerun call return missing } - missing = metadata.discovered[id] = { + newDepsDiscovered = true + missing = addOptimizedDepInfo(metadata, 'discovered', { + id, file: getOptimizedDepPath(id, server.config), src: resolved, // Assing a browserHash to this missing dependency that is unique to // the current state of known + missing deps. If its optimizeDeps run // doesn't alter the bundled files of previous known dependendencies, // we don't need a full reload and this browserHash will be kept - browserHash: getOptimizedBrowserHash( + browserHash: getDiscoveredBrowserHash( metadata.hash, depsFromOptimizedDepInfo(metadata.optimized), depsFromOptimizedDepInfo(metadata.discovered) @@ -220,18 +380,26 @@ export function createMissingImporterRegisterFn( // loading of this pre-bundled dep needs to await for its processing // promise to be resolved processing: depOptimizationProcessing.promise - } + }) // Debounced rerun, let other missing dependencies be discovered before // the running next optimizeDeps + enqueuedRerun = undefined if (handle) clearTimeout(handle) + if (newDepsToLogHandle) clearTimeout(newDepsToLogHandle) + newDepsToLogHandle = undefined handle = setTimeout(() => { handle = undefined - rerun(ssr) + enqueuedRerun = rerun + if (!currentlyProcessing) { + enqueuedRerun() + } }, debounceMs) // Return the path for the optimized bundle, this path is known before // esbuild is run to generate the pre-bundle return missing } + + return optimizedDeps } diff --git a/packages/vite/src/node/optimizer/scan.ts b/packages/vite/src/node/optimizer/scan.ts index 4f7cf7b0e3f483..cf566fe5ad6420 100644 --- a/packages/vite/src/node/optimizer/scan.ts +++ b/packages/vite/src/node/optimizer/scan.ts @@ -123,18 +123,29 @@ export async function scanImports(config: ResolvedConfig): Promise<{ debug(`Scan completed in ${(performance.now() - start).toFixed(2)}ms:`, deps) return { - deps, + // Ensure a fixed order so hashes are stable and improve logs + deps: orderedDependencies(deps), missing } } +function orderedDependencies(deps: Record) { + const depsList = Object.entries(deps) + // Ensure the same browserHash for the same set of dependencies + depsList.sort((a, b) => a[0].localeCompare(b[0])) + return Object.fromEntries(depsList) +} + function globEntries(pattern: string | string[], config: ResolvedConfig) { return glob(pattern, { cwd: config.root, ignore: [ '**/node_modules/**', `**/${config.build.outDir}/**`, - `**/__tests__/**` + // if there aren't explicit entries, also ignore other common folders + ...(config.optimizeDeps.entries + ? [] + : [`**/__tests__/**`, `**/coverage/**`]) ], absolute: true }) @@ -165,7 +176,10 @@ function esbuildScanPlugin( } const resolved = await container.resolveId( id, - importer && normalizePath(importer) + importer && normalizePath(importer), + { + scan: true + } ) const res = resolved?.id seen.set(key, res) @@ -504,7 +518,7 @@ async function transformGlob( resolve ) s.prepend(importsString) - s.overwrite(expStart, endIndex, exp) + s.overwrite(expStart, endIndex, exp, { contentOnly: true }) } return s.toString() } diff --git a/packages/vite/src/node/plugin.ts b/packages/vite/src/node/plugin.ts index 36674e242bd33e..354b246dd9f182 100644 --- a/packages/vite/src/node/plugin.ts +++ b/packages/vite/src/node/plugin.ts @@ -121,7 +121,14 @@ export interface Plugin extends RollupPlugin { this: PluginContext, source: string, importer: string | undefined, - options: { custom?: CustomPluginOptions; ssr?: boolean } + options: { + custom?: CustomPluginOptions + ssr?: boolean + /** + * @internal + */ + scan?: boolean + } ): Promise | ResolveIdResult load?( this: PluginContext, diff --git a/packages/vite/src/node/plugins/asset.ts b/packages/vite/src/node/plugins/asset.ts index 4df0de80300e24..633438cf3cb0d4 100644 --- a/packages/vite/src/node/plugins/asset.ts +++ b/packages/vite/src/node/plugins/asset.ts @@ -100,7 +100,9 @@ export function assetPlugin(config: ResolvedConfig): Plugin { const file = getAssetFilename(hash, config) || this.getFileName(hash) chunk.viteMetadata.importedAssets.add(cleanUrl(file)) const outputFilepath = config.base + file + postfix - s.overwrite(match.index, match.index + full.length, outputFilepath) + s.overwrite(match.index, match.index + full.length, outputFilepath, { + contentOnly: true + }) } if (s) { diff --git a/packages/vite/src/node/plugins/assetImportMetaUrl.ts b/packages/vite/src/node/plugins/assetImportMetaUrl.ts index 421c18182ae0a9..b0c59bed808604 100644 --- a/packages/vite/src/node/plugins/assetImportMetaUrl.ts +++ b/packages/vite/src/node/plugins/assetImportMetaUrl.ts @@ -51,7 +51,8 @@ export function assetImportMetaUrlPlugin(config: ResolvedConfig): Plugin { index + exp.length, `new URL(import.meta.globEagerDefault(${JSON.stringify( pattern - )})[${rawUrl}], self.location)` + )})[${rawUrl}], self.location)`, + { contentOnly: true } ) continue } @@ -70,7 +71,8 @@ export function assetImportMetaUrlPlugin(config: ResolvedConfig): Plugin { s.overwrite( index, index + exp.length, - `new URL(${JSON.stringify(builtUrl)}, self.location)` + `new URL(${JSON.stringify(builtUrl)}, self.location)`, + { contentOnly: true } ) } if (s) { diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts index d513c88420b6ff..4933f8455931c1 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -11,21 +11,23 @@ import { isObject, normalizePath, processSrcSet, - parseRequest + parseRequest, + combineSourcemaps } from '../utils' import type { Plugin } from '../plugin' import type { ResolvedConfig } from '../config' import postcssrc from 'postcss-load-config' import type { + ExistingRawSourceMap, NormalizedOutputOptions, OutputChunk, RenderedChunk, RollupError, - SourceMap + SourceMapInput } from 'rollup' import { dataToEsm } from '@rollup/pluginutils' import colors from 'picocolors' -import { CLIENT_PUBLIC_PATH } from '../constants' +import { CLIENT_PUBLIC_PATH, SPECIAL_QUERY_RE } from '../constants' import type { ResolveFn, ViteDevServer } from '../' import { getAssetFilename, @@ -44,6 +46,8 @@ import type { Alias } from 'types/alias' import type { ModuleNode } from '../server/moduleGraph' import { transform, formatMessages } from 'esbuild' import { addToHTMLProxyTransformResult } from './html' +import { injectSourcesContent, getCodeWithSourcemap } from '../server/sourcemap' +import type { RawSourceMap } from '@ampproject/remapping' // const debug = createDebugger('vite:css') @@ -58,6 +62,12 @@ export interface CSSOptions { | (Postcss.ProcessOptions & { plugins?: Postcss.Plugin[] }) + /** + * Enables css sourcemaps during dev + * @default false + * @experimental + */ + devSourcemap?: boolean } export interface CSSModulesOptions { @@ -159,7 +169,11 @@ export function cssPlugin(config: ResolvedConfig): Plugin { }, async transform(raw, id, options) { - if (!isCSSRequest(id) || commonjsProxyRE.test(id)) { + if ( + !isCSSRequest(id) || + commonjsProxyRE.test(id) || + SPECIAL_QUERY_RE.test(id) + ) { return } const ssr = options?.ssr === true @@ -178,7 +192,8 @@ export function cssPlugin(config: ResolvedConfig): Plugin { const { code: css, modules, - deps + deps, + map } = await compileCSS( id, raw, @@ -245,8 +260,7 @@ export function cssPlugin(config: ResolvedConfig): Plugin { return { code: css, - // TODO CSS source map - map: { mappings: '' } + map } } } @@ -276,7 +290,11 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin { }, async transform(css, id, options) { - if (!isCSSRequest(id) || commonjsProxyRE.test(id)) { + if ( + !isCSSRequest(id) || + commonjsProxyRE.test(id) || + SPECIAL_QUERY_RE.test(id) + ) { return } @@ -296,12 +314,20 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin { if (inlined) { return `export default ${JSON.stringify(css)}` } + + let cssContent = css + if (config.css?.devSourcemap) { + const sourcemap = this.getCombinedSourcemap() + await injectSourcesContent(sourcemap, cleanUrl(id), config.logger) + cssContent = getCodeWithSourcemap('css', css, sourcemap) + } + return [ `import { updateStyle as __vite__updateStyle, removeStyle as __vite__removeStyle } from ${JSON.stringify( path.posix.join(config.base, CLIENT_PUBLIC_PATH) )}`, `const __vite__id = ${JSON.stringify(id)}`, - `const __vite__css = ${JSON.stringify(css)}`, + `const __vite__css = ${JSON.stringify(cssContent)}`, `__vite__updateStyle(__vite__id, __vite__css)`, // css modules exports change on edit so it can't self accept `${ @@ -590,12 +616,16 @@ async function compileCSS( server?: ViteDevServer ): Promise<{ code: string - map?: SourceMap + map?: SourceMapInput ast?: Postcss.Result modules?: Record deps?: Set }> { - const { modules: modulesOptions, preprocessorOptions } = config.css || {} + const { + modules: modulesOptions, + preprocessorOptions, + devSourcemap + } = config.css || {} const isModule = modulesOptions !== false && cssModuleRE.test(id) // although at serve time it can work without processing, we do need to // crawl them in order to register watch dependencies. @@ -612,10 +642,10 @@ async function compileCSS( !needInlineImport && !hasUrl ) { - return { code } + return { code, map: null } } - let map: SourceMap | undefined + let preprocessorMap: ExistingRawSourceMap | undefined let modules: Record | undefined const deps = new Set() @@ -644,6 +674,7 @@ async function compileCSS( } // important: set this for relative import resolving opts.filename = cleanUrl(id) + opts.enableSourcemap = devSourcemap ?? false const preprocessResult = await preProcessor( code, @@ -657,7 +688,12 @@ async function compileCSS( } code = preprocessResult.code - map = preprocessResult.map as SourceMap + preprocessorMap = combineSourcemapsIfExists( + opts.filename, + preprocessResult.map, + preprocessResult.additionalMap + ) + if (preprocessResult.deps) { preprocessResult.deps.forEach((dep) => { // sometimes sass registers the file itself as a dep @@ -733,7 +769,7 @@ async function compileCSS( if (!postcssPlugins.length) { return { code, - map + map: preprocessorMap } } @@ -742,12 +778,14 @@ async function compileCSS( .default(postcssPlugins) .process(code, { ...postcssOptions, - to: id, - from: id, + to: cleanUrl(id), + from: cleanUrl(id), map: { inline: false, annotation: false, - prev: map + sourcesContent: false + // when "prev: preprocessorMap", the result map may include duplicate filename in `postcssResult.map.sources` + // prev: preprocessorMap, } }) @@ -791,15 +829,71 @@ async function compileCSS( } } + if (!devSourcemap) { + return { + ast: postcssResult, + code: postcssResult.css, + map: { mappings: '' }, + modules, + deps + } + } + + const rawPostcssMap = postcssResult.map.toJSON() + + const postcssMap = formatPostcssSourceMap( + // version property of rawPostcssMap is declared as string + // but actually it is a number + rawPostcssMap as Omit as ExistingRawSourceMap, + cleanUrl(id) + ) + return { ast: postcssResult, code: postcssResult.css, - map: postcssResult.map as any, + map: combineSourcemapsIfExists(cleanUrl(id), postcssMap, preprocessorMap), modules, deps } } +export function formatPostcssSourceMap( + rawMap: ExistingRawSourceMap, + file: string +): ExistingRawSourceMap { + const inputFileDir = path.dirname(file) + const sources = rawMap.sources + // remove from sources, to prevent source map to be combined incorrectly + .filter((source) => source !== '') + .map((source) => { + const cleanSource = cleanUrl(decodeURIComponent(source)) + return normalizePath(path.resolve(inputFileDir, cleanSource)) + }) + + return { + file, + mappings: rawMap.mappings, + names: rawMap.names, + sources, + version: rawMap.version + } +} + +function combineSourcemapsIfExists( + filename: string, + map1: ExistingRawSourceMap | undefined, + map2: ExistingRawSourceMap | undefined +): ExistingRawSourceMap | undefined { + return map1 && map2 + ? (combineSourcemaps(filename, [ + // type of version property of ExistingRawSourceMap is number + // but it is always 3 + map1 as RawSourceMap, + map2 as RawSourceMap + ]) as ExistingRawSourceMap) + : map1 +} + interface PostCSSConfigResult { options: Postcss.ProcessOptions plugins: Postcss.Plugin[] @@ -935,7 +1029,12 @@ async function doUrlReplace( return matched } - return `url(${wrap}${await replacer(rawUrl)}${wrap})` + const newUrl = await replacer(rawUrl) + if (wrap === '' && newUrl !== encodeURI(newUrl)) { + // The new url might need wrapping even if the original did not have it, e.g. if a space was added during replacement + wrap = "'" + } + return `url(${wrap}${newUrl}${wrap})` } async function doImportCSSReplace( @@ -998,15 +1097,25 @@ AtImportHoistPlugin.postcss = true // Preprocessor support. This logic is largely replicated from @vue/compiler-sfc +type PreprocessorAdditionalDataResult = + | string + | { content: string; map?: ExistingRawSourceMap } + type PreprocessorAdditionalData = | string - | ((source: string, filename: string) => string | Promise) + | (( + source: string, + filename: string + ) => + | PreprocessorAdditionalDataResult + | Promise) type StylePreprocessorOptions = { [key: string]: any additionalData?: PreprocessorAdditionalData filename: string alias: Alias[] + enableSourcemap: boolean } type SassStylePreprocessorOptions = StylePreprocessorOptions & Sass.Options @@ -1027,7 +1136,8 @@ type SassStylePreprocessor = ( export interface StylePreprocessorResults { code: string - map?: object + map?: ExistingRawSourceMap | undefined + additionalMap?: ExistingRawSourceMap | undefined errors: RollupError[] deps: string[] } @@ -1092,12 +1202,25 @@ const scss: SassStylePreprocessor = async ( : importer.push(options.importer) } + const { content: data, map: additionalMap } = await getSource( + source, + options.filename, + options.additionalData, + options.enableSourcemap + ) const finalOptions: Sass.Options = { ...options, - data: await getSource(source, options.filename, options.additionalData), + data, file: options.filename, outFile: options.filename, - importer + importer, + ...(options.enableSourcemap + ? { + sourceMap: true, + omitSourceMapUrl: true, + sourceMapRoot: path.dirname(options.filename) + } + : {}) } try { @@ -1111,9 +1234,14 @@ const scss: SassStylePreprocessor = async ( }) }) const deps = result.stats.includedFiles + const map: ExistingRawSourceMap | undefined = result.map + ? JSON.parse(result.map.toString()) + : undefined return { code: result.css.toString(), + map, + additionalMap, errors: [], deps } @@ -1203,13 +1331,26 @@ const less: StylePreprocessor = async (source, root, options, resolvers) => { options.alias, resolvers ) - source = await getSource(source, options.filename, options.additionalData) + const { content, map: additionalMap } = await getSource( + source, + options.filename, + options.additionalData, + options.enableSourcemap + ) let result: Less.RenderOutput | undefined try { - result = await nodeLess.render(source, { + result = await nodeLess.render(content, { ...options, - plugins: [viteResolverPlugin, ...(options.plugins || [])] + plugins: [viteResolverPlugin, ...(options.plugins || [])], + ...(options.enableSourcemap + ? { + sourceMap: { + outputSourceFiles: true, + sourceMapFileInline: false + } + } + : {}) }) } catch (e) { const error = e as Less.RenderError @@ -1222,8 +1363,16 @@ const less: StylePreprocessor = async (source, root, options, resolvers) => { } return { code: '', errors: [normalizedError], deps: [] } } + + const map: ExistingRawSourceMap = result.map && JSON.parse(result.map) + if (map) { + delete map.sourcesContent + } + return { code: result.css.toString(), + map, + additionalMap, deps: result.imports, errors: [] } @@ -1305,10 +1454,11 @@ const styl: StylePreprocessor = async (source, root, options) => { const nodeStylus = loadPreprocessor(PreprocessLang.stylus, root) // Get source with preprocessor options.additionalData. Make sure a new line separator // is added to avoid any render error, as added stylus content may not have semi-colon separators - source = await getSource( + const { content, map: additionalMap } = await getSource( source, options.filename, options.additionalData, + options.enableSourcemap, '\n' ) // Get preprocessor options.imports dependencies as stylus @@ -1317,32 +1467,85 @@ const styl: StylePreprocessor = async (source, root, options) => { path.resolve(dep) ) try { - const ref = nodeStylus(source, options) - - // if (map) ref.set('sourcemap', { inline: false, comment: false }) + const ref = nodeStylus(content, options) + if (options.enableSourcemap) { + ref.set('sourcemap', { + comment: false, + inline: false, + basePath: root + }) + } const result = ref.render() // Concat imports deps with computed deps const deps = [...ref.deps(), ...importsDeps] - return { code: result, errors: [], deps } + // @ts-expect-error sourcemap exists + const map: ExistingRawSourceMap | undefined = ref.sourcemap + + return { + code: result, + map: formatStylusSourceMap(map, root), + additionalMap, + errors: [], + deps + } } catch (e) { return { code: '', errors: [e], deps: [] } } } -function getSource( +function formatStylusSourceMap( + mapBefore: ExistingRawSourceMap | undefined, + root: string +): ExistingRawSourceMap | undefined { + if (!mapBefore) return undefined + const map = { ...mapBefore } + + const resolveFromRoot = (p: string) => normalizePath(path.resolve(root, p)) + + if (map.file) { + map.file = resolveFromRoot(map.file) + } + map.sources = map.sources.map(resolveFromRoot) + + return map +} + +async function getSource( source: string, filename: string, - additionalData?: PreprocessorAdditionalData, + additionalData: PreprocessorAdditionalData | undefined, + enableSourcemap: boolean, sep: string = '' -): string | Promise { - if (!additionalData) return source +): Promise<{ content: string; map?: ExistingRawSourceMap }> { + if (!additionalData) return { content: source } + if (typeof additionalData === 'function') { - return additionalData(source, filename) + const newContent = await additionalData(source, filename) + if (typeof newContent === 'string') { + return { content: newContent } + } + return newContent + } + + if (!enableSourcemap) { + return { content: additionalData + sep + source } + } + + const ms = new MagicString(source) + ms.appendLeft(0, sep) + ms.appendLeft(0, additionalData) + + const map = ms.generateMap({ hires: true }) + map.file = filename + map.sources = [filename] + + return { + content: ms.toString(), + map } - return additionalData + sep + source } const preProcessors = Object.freeze({ diff --git a/packages/vite/src/node/plugins/define.ts b/packages/vite/src/node/plugins/define.ts index c987e0f80fd46e..024cf32d41f72a 100644 --- a/packages/vite/src/node/plugins/define.ts +++ b/packages/vite/src/node/plugins/define.ts @@ -10,6 +10,7 @@ const isNonJsRequest = (request: string): boolean => nonJsRe.test(request) export function definePlugin(config: ResolvedConfig): Plugin { const isBuild = config.command === 'build' + const isWorker = config.isWorker const processNodeEnv: Record = { 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || config.mode), @@ -40,7 +41,12 @@ export function definePlugin(config: ResolvedConfig): Plugin { Object.assign(importMetaKeys, { 'import.meta.env.': `({}).`, 'import.meta.env': JSON.stringify(config.env), - 'import.meta.hot': `false` + 'import.meta.hot': `false`, + ...(isWorker + ? { + 'import.meta.url': 'self.location.href' + } + : {}) }) } @@ -130,7 +136,7 @@ export function definePlugin(config: ResolvedConfig): Plugin { const start = match.index const end = start + match[0].length const replacement = '' + replacements[match[1]] - s.overwrite(start, end, replacement) + s.overwrite(start, end, replacement, { contentOnly: true }) } if (!hasReplaced) { diff --git a/packages/vite/src/node/plugins/html.ts b/packages/vite/src/node/plugins/html.ts index b1509ac2cdecdd..30e65a36f83bbe 100644 --- a/packages/vite/src/node/plugins/html.ts +++ b/packages/vite/src/node/plugins/html.ts @@ -5,7 +5,8 @@ import type { OutputAsset, OutputBundle, OutputChunk, - RollupError + RollupError, + SourceMapInput } from 'rollup' import { cleanUrl, @@ -54,7 +55,7 @@ export const isHTMLRequest = (request: string): boolean => // HTML Proxy Caches are stored by config -> filePath -> index export const htmlProxyMap = new WeakMap< ResolvedConfig, - Map> + Map> >() // HTML Proxy Transform result are stored by config @@ -83,7 +84,7 @@ export function htmlInlineProxyPlugin(config: ResolvedConfig): Plugin { const file = cleanUrl(id) const url = file.replace(normalizePath(config.root), '') const result = htmlProxyMap.get(config)!.get(url)![index] - if (typeof result === 'string') { + if (result) { return result } else { throw new Error(`No matching HTML proxy module found from ${id}`) @@ -97,7 +98,7 @@ export function addToHTMLProxyCache( config: ResolvedConfig, filePath: string, index: number, - code: string + result: { code: string; map?: SourceMapInput } ): void { if (!htmlProxyMap.get(config)) { htmlProxyMap.set(config, new Map()) @@ -105,7 +106,7 @@ export function addToHTMLProxyCache( if (!htmlProxyMap.get(config)!.get(filePath)) { htmlProxyMap.get(config)!.set(filePath, []) } - htmlProxyMap.get(config)!.get(filePath)![index] = code + htmlProxyMap.get(config)!.get(filePath)![index] = result } export function addToHTMLProxyTransformResult( @@ -266,7 +267,8 @@ export function buildHtmlPlugin(config: ResolvedConfig): Plugin { s.overwrite( src!.value!.loc.start.offset, src!.value!.loc.end.offset, - `"${config.base + url.slice(1)}"` + `"${config.base + url.slice(1)}"`, + { contentOnly: true } ) } @@ -283,12 +285,9 @@ export function buildHtmlPlugin(config: ResolvedConfig): Plugin { .join('') // const filePath = id.replace(normalizePath(config.root), '') - addToHTMLProxyCache( - config, - filePath, - inlineModuleIndex, - contents - ) + addToHTMLProxyCache(config, filePath, inlineModuleIndex, { + code: contents + }) js += `\nimport "${id}?html-proxy&index=${inlineModuleIndex}.js"` shouldRemove = true } @@ -297,9 +296,11 @@ export function buildHtmlPlugin(config: ResolvedConfig): Plugin { someScriptsAreAsync ||= isAsync someScriptsAreDefer ||= !isAsync } else if (url && !isPublicFile) { - config.logger.warn( - ` asset for (const { start, end, url } of scriptUrls) { if (!isExcludedUrl(url)) { - s.overwrite(start, end, await urlToBuiltUrl(url, id, config, this)) + s.overwrite( + start, + end, + await urlToBuiltUrl(url, id, config, this), + { contentOnly: true } + ) } else if (checkPublicFile(url, config)) { - s.overwrite(start, end, config.base + url.slice(1)) + s.overwrite(start, end, config.base + url.slice(1), { + contentOnly: true + }) } } @@ -597,7 +605,8 @@ export function buildHtmlPlugin(config: ResolvedConfig): Plugin { s.overwrite( match.index, match.index + full.length, - cssTransformedCode + cssTransformedCode, + { contentOnly: true } ) } if (s) { @@ -696,6 +705,8 @@ export function resolveHtmlTransforms( return [preHooks, postHooks] } +export const maybeVirtualHtmlSet = new Set() + export async function applyHtmlTransforms( html: string, hooks: IndexHtmlTransformHook[], @@ -706,6 +717,8 @@ export async function applyHtmlTransforms( const bodyTags: HtmlTagDescriptor[] = [] const bodyPrependTags: HtmlTagDescriptor[] = [] + maybeVirtualHtmlSet.add(ctx.filename) + for (const hook of hooks) { const res = await hook(html, ctx) if (!res) { diff --git a/packages/vite/src/node/plugins/importAnalysis.ts b/packages/vite/src/node/plugins/importAnalysis.ts index f9d50b13e1885e..e7336ae4947677 100644 --- a/packages/vite/src/node/plugins/importAnalysis.ts +++ b/packages/vite/src/node/plugins/importAnalysis.ts @@ -37,6 +37,7 @@ import { VALID_ID_PREFIX, NULL_BYTE_PLACEHOLDER } from '../constants' +import { ERR_OUTDATED_OPTIMIZED_DEP } from './optimizedDeps' import type { ViteDevServer } from '..' import { checkPublicFile } from './asset' import { parse as parseJS } from 'acorn' @@ -48,7 +49,6 @@ import { performance } from 'perf_hooks' import { transformRequest } from '../server/transformRequest' import { isOptimizedDepFile, - createIsOptimizedDepUrl, getDepsCacheDir, optimizedDepNeedsInterop } from '../optimizer' @@ -62,6 +62,7 @@ const skipRE = /\.(map|json)$/ const canSkip = (id: string) => skipRE.test(id) || isDirectCSSRequest(id) const optimizedDepChunkRE = /\/chunk-[A-Z0-9]{8}\.js/ +const optimizedDepDynamicRE = /-[A-Z0-9]{8}\.js/ function isExplicitImportRequired(url: string) { return !isJSRequest(cleanUrl(url)) && !isCSSRequest(url) @@ -112,14 +113,12 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { extensions: [] }) let server: ViteDevServer - let isOptimizedDepUrl: (url: string) => boolean return { name: 'vite:import-analysis', configureServer(_server) { server = _server - isOptimizedDepUrl = createIsOptimizedDepUrl(server.config) }, async transform(source, importer, options) { @@ -198,19 +197,20 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { } let importerFile = importer - if ( - moduleListContains(config.optimizeDeps?.exclude, url) && - server._optimizeDepsMetadata - ) { - // if the dependency encountered in the optimized file was excluded from the optimization - // the dependency needs to be resolved starting from the original source location of the optimized file - // because starting from node_modules/.vite will not find the dependency if it was not hoisted - // (that is, if it is under node_modules directory in the package source of the optimized file) - for (const optimizedModule of Object.values( - server._optimizeDepsMetadata.optimized - )) { - if (optimizedModule.file === importerModule.file) { - importerFile = optimizedModule.src + if (moduleListContains(config.optimizeDeps?.exclude, url)) { + const optimizedDeps = server._optimizedDeps + if (optimizedDeps) { + await optimizedDeps.scanProcessing + + // if the dependency encountered in the optimized file was excluded from the optimization + // the dependency needs to be resolved starting from the original source location of the optimized file + // because starting from node_modules/.vite will not find the dependency if it was not hoisted + // (that is, if it is under node_modules directory in the package source of the optimized file) + for (const optimizedModule of optimizedDeps.metadata.depInfoList) { + if (!optimizedModule.src) continue // Ignore chunks + if (optimizedModule.file === importerModule.file) { + importerFile = optimizedModule.src + } } } } @@ -235,7 +235,7 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { const isSelfImport = !isRelative && cleanUrl(url) === cleanUrl(importer) // normalize all imports into resolved URLs - // e.g. `import 'foo'` -> `import '/@fs/.../node_modules/foo/index.js` + // e.g. `import 'foo'` -> `import '/@fs/.../node_modules/foo/index.js'` if (resolved.id.startsWith(root + '/')) { // in root: infer short absolute path from root url = resolved.id.slice(root.length) @@ -274,8 +274,8 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { // query can break 3rd party plugin's extension checks. if ( (isRelative || isSelfImport) && - !(isOptimizedDepUrl(url) && optimizedDepChunkRE.test(url)) && - !/[\?&]import=?\b/.test(url) + !/[\?&]import=?\b/.test(url) && + !url.match(DEP_VERSION_RE) ) { const versionMatch = importer.match(DEP_VERSION_RE) if (versionMatch) { @@ -305,6 +305,11 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { return [url, resolved.id] } + // Import rewrites, we do them after all the URLs have been resolved + // to help with the discovery of new dependencies. If we need to wait + // for each dependency there could be one reload per import + const importRewrites: (() => Promise)[] = [] + for (let index = 0; index < imports.length; index++) { const { s: start, @@ -361,7 +366,7 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { resolve ) str().prepend(importsString) - str().overwrite(expStart, endIndex, exp) + str().overwrite(expStart, endIndex, exp, { contentOnly: true }) imports.forEach((url) => { url = url.replace(base, '/') importedUrls.add(url) @@ -381,7 +386,7 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { continue } - const isDynamicImport = dynamicIndex >= 0 + const isDynamicImport = dynamicIndex > -1 // static import or valid string in dynamic import // If resolvable, let's resolve it @@ -431,56 +436,76 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { // record as safe modules server?.moduleGraph.safeModulesPath.add(fsPathFromUrl(url)) - // rewrite if (url !== specifier) { - let rewriteDone = false - if ( - isOptimizedDepFile(resolvedId, config) && - !resolvedId.match(optimizedDepChunkRE) - ) { - // for optimized cjs deps, support named imports by rewriting named imports to const assignments. - // internal optimized chunks don't need es interop and are excluded - - // The browserHash in resolvedId could be stale in which case there will be a full - // page reload. We could return a 404 in that case but it is safe to return the request - const file = cleanUrl(resolvedId) // Remove ?v={hash} - - const needsInterop = await optimizedDepNeedsInterop( - server._optimizeDepsMetadata!, - file - ) - - if (needsInterop === undefined) { - config.logger.error( - colors.red( - `Vite Error, ${url} optimized info should be defined` - ) + importRewrites.push(async () => { + let rewriteDone = false + if ( + server?._optimizedDeps && + isOptimizedDepFile(resolvedId, config) && + !resolvedId.match(optimizedDepChunkRE) + ) { + // for optimized cjs deps, support named imports by rewriting named imports to const assignments. + // internal optimized chunks don't need es interop and are excluded + + // The browserHash in resolvedId could be stale in which case there will be a full + // page reload. We could return a 404 in that case but it is safe to return the request + const file = cleanUrl(resolvedId) // Remove ?v={hash} + + const needsInterop = await optimizedDepNeedsInterop( + server._optimizedDeps!.metadata, + file ) - } else if (needsInterop) { - debug(`${url} needs interop`) - if (isDynamicImport) { - // rewrite `import('package')` to expose the default directly - str().overwrite( - dynamicIndex, - end + 1, - `import('${url}').then(m => m.default && m.default.__esModule ? m.default : ({ ...m.default, default: m.default }))` - ) - } else { - const exp = source.slice(expStart, expEnd) - const rewritten = transformCjsImport(exp, url, rawUrl, index) - if (rewritten) { - str().overwrite(expStart, expEnd, rewritten) + + if (needsInterop === undefined) { + // Non-entry dynamic imports from dependencies will reach here as there isn't + // optimize info for them, but they don't need es interop. If the request isn't + // a dynamic import, then it is an internal Vite error + if (!file.match(optimizedDepDynamicRE)) { + config.logger.error( + colors.red( + `Vite Error, ${url} optimized info should be defined` + ) + ) + } + } else if (needsInterop) { + debug(`${url} needs interop`) + if (isDynamicImport) { + // rewrite `import('package')` to expose the default directly + str().overwrite( + expStart, + expEnd, + `import('${url}').then(m => m.default && m.default.__esModule ? m.default : ({ ...m.default, default: m.default }))`, + { contentOnly: true } + ) } else { - // #1439 export * from '...' - str().overwrite(start, end, url) + const exp = source.slice(expStart, expEnd) + const rewritten = transformCjsImport( + exp, + url, + rawUrl, + index + ) + if (rewritten) { + str().overwrite(expStart, expEnd, rewritten, { + contentOnly: true + }) + } else { + // #1439 export * from '...' + str().overwrite(start, end, url, { contentOnly: true }) + } } + rewriteDone = true } - rewriteDone = true } - } - if (!rewriteDone) { - str().overwrite(start, end, isDynamicImport ? `'${url}'` : url) - } + if (!rewriteDone) { + str().overwrite( + start, + end, + isDynamicImport ? `'${url}'` : url, + { contentOnly: true } + ) + } + }) } // record for HMR import chain analysis @@ -518,7 +543,12 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { isExplicitImportRequired(url.slice(1, -1)) ) { needQueryInjectHelper = true - str().overwrite(start, end, `__vite__injectQuery(${url}, 'import')`) + str().overwrite( + start, + end, + `__vite__injectQuery(${url}, 'import')`, + { contentOnly: true } + ) } } } @@ -574,7 +604,9 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { ssr ) normalizedAcceptedUrls.add(normalized) - str().overwrite(start, end, JSON.stringify(normalized)) + str().overwrite(start, end, JSON.stringify(normalized), { + contentOnly: true + }) } // update the module graph for HMR analysis. @@ -624,10 +656,25 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { NULL_BYTE_PLACEHOLDER, '\0' ) - transformRequest(url, server, { ssr }) + transformRequest(url, server, { ssr }).catch((e) => { + if (e?.code === ERR_OUTDATED_OPTIMIZED_DEP) { + // This are expected errors + return + } + // Unexpected error, log the issue but avoid an unhandled exception + config.logger.error(e.message) + }) }) } + // Await for import rewrites that requires dependencies to be pre-bundled to + // know if es interop is needed after starting further transformRequest calls + // This will let Vite process deeper into the user code and find more missing + // dependencies before the next page reload + for (const rewrite of importRewrites) { + await rewrite() + } + if (s) { return s.toString() } else { diff --git a/packages/vite/src/node/plugins/importAnalysisBuild.ts b/packages/vite/src/node/plugins/importAnalysisBuild.ts index 87afd8e1f12b00..91ce663b9f8111 100644 --- a/packages/vite/src/node/plugins/importAnalysisBuild.ts +++ b/packages/vite/src/node/plugins/importAnalysisBuild.ts @@ -86,6 +86,7 @@ function preload(baseModule: () => Promise<{}>, deps?: string[]) { export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin { const ssr = !!config.build.ssr const insertPreload = !(ssr || !!config.build.lib) + const isWorker = config.isWorker const scriptRel = config.build.polyfillModulePreload ? `'modulepreload'` @@ -120,6 +121,11 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin { return } + if (isWorker) { + // preload method use `document` and can't run in the worker + return + } + await init let imports: readonly ImportSpecifier[] = [] @@ -132,7 +138,6 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin { if (!imports.length) { return null } - let s: MagicString | undefined const str = () => s || (s = new MagicString(source)) let needPreloadHelper = false @@ -142,6 +147,7 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin { s: start, e: end, ss: expStart, + se: expEnd, n: specifier, d: dynamicIndex } = imports[index] @@ -164,7 +170,7 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin { insertPreload ) str().prepend(importsString) - str().overwrite(expStart, endIndex, exp) + str().overwrite(expStart, endIndex, exp, { contentOnly: true }) if (!isEager) { needPreloadHelper = true } @@ -173,10 +179,9 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin { if (dynamicIndex > -1 && insertPreload) { needPreloadHelper = true - const dynamicEnd = source.indexOf(`)`, end) + 1 - const original = source.slice(dynamicIndex, dynamicEnd) + const original = source.slice(expStart, expEnd) const replacement = `${preloadMethod}(() => ${original},${isModernFlag}?"${preloadMarker}":void 0)` - str().overwrite(dynamicIndex, dynamicEnd, replacement) + str().overwrite(expStart, expEnd, replacement, { contentOnly: true }) } // Differentiate CSS imports that use the default export from those that @@ -191,7 +196,9 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin { !(bareImportRE.test(specifier) && !specifier.includes('/')) ) { const url = specifier.replace(/\?|$/, (m) => `?used${m ? '&' : ''}`) - str().overwrite(start, end, dynamicIndex > -1 ? `'${url}'` : url) + str().overwrite(start, end, dynamicIndex > -1 ? `'${url}'` : url, { + contentOnly: true + }) } } @@ -223,7 +230,8 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin { s.overwrite( match.index, match.index + isModernFlag.length, - isModern + isModern, + { contentOnly: true } ) } return { @@ -238,7 +246,7 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin { }, generateBundle({ format }, bundle) { - if (format !== 'es' || ssr) { + if (format !== 'es' || ssr || isWorker) { return } @@ -263,7 +271,8 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin { n: name, s: start, e: end, - d: dynamicIndex + ss: expStart, + se: expEnd } = imports[index] // check the chunk being imported let url = name @@ -302,7 +311,9 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin { hasRemovedPureCssChunk = true } - s.overwrite(dynamicIndex, end + 1, 'Promise.resolve({})') + s.overwrite(expStart, expEnd, 'Promise.resolve({})', { + contentOnly: true + }) } } } @@ -329,7 +340,8 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin { // main chunk is removed (hasRemovedPureCssChunk && deps.size > 0) ? `[${[...deps].map((d) => JSON.stringify(d)).join(',')}]` - : `[]` + : `[]`, + { contentOnly: true } ) } } diff --git a/packages/vite/src/node/plugins/optimizedDeps.ts b/packages/vite/src/node/plugins/optimizedDeps.ts index 8fbdca8d08905f..adab1bd9756251 100644 --- a/packages/vite/src/node/plugins/optimizedDeps.ts +++ b/packages/vite/src/node/plugins/optimizedDeps.ts @@ -3,7 +3,7 @@ import type { Plugin } from '../plugin' import colors from 'picocolors' import { DEP_VERSION_RE } from '../constants' import { cleanUrl, createDebugger } from '../utils' -import { isOptimizedDepFile, optimizeDepInfoFromFile } from '../optimizer' +import { isOptimizedDepFile, optimizedDepInfoFromFile } from '../optimizer' import type { ViteDevServer } from '..' export const ERR_OPTIMIZE_DEPS_PROCESSING_ERROR = @@ -25,7 +25,7 @@ export function optimizedDepsPlugin(): Plugin { async load(id) { if (server && isOptimizedDepFile(id, server.config)) { - const metadata = server?._optimizeDepsMetadata + const metadata = server?._optimizedDeps?.metadata if (metadata) { const file = cleanUrl(id) const versionMatch = id.match(DEP_VERSION_RE) @@ -34,7 +34,7 @@ export function optimizedDepsPlugin(): Plugin { : undefined // Search in both the currently optimized and newly discovered deps - const info = optimizeDepInfoFromFile(metadata, file) + const info = optimizedDepInfoFromFile(metadata, file) if (info) { if (browserHash && info.browserHash !== browserHash) { throwOutdatedRequest(id) @@ -49,9 +49,9 @@ export function optimizedDepsPlugin(): Plugin { throwProcessingError(id) return } - const newMetadata = server._optimizeDepsMetadata + const newMetadata = server._optimizedDeps?.metadata if (metadata !== newMetadata) { - const currentInfo = optimizeDepInfoFromFile(newMetadata!, file) + const currentInfo = optimizedDepInfoFromFile(newMetadata!, file) if (info.browserHash !== currentInfo?.browserHash) { throwOutdatedRequest(id) } diff --git a/packages/vite/src/node/plugins/preAlias.ts b/packages/vite/src/node/plugins/preAlias.ts index 75a0d8e5e6f9dc..dadb16aa4c28a9 100644 --- a/packages/vite/src/node/plugins/preAlias.ts +++ b/packages/vite/src/node/plugins/preAlias.ts @@ -13,9 +13,9 @@ export function preAliasPlugin(): Plugin { configureServer(_server) { server = _server }, - resolveId(id, importer, options) { - if (!options?.ssr && bareImportRE.test(id)) { - return tryOptimizedResolve(id, server, importer) + async resolveId(id, importer, options) { + if (!options?.ssr && bareImportRE.test(id) && !options?.scan) { + return await tryOptimizedResolve(id, server, importer) } } } diff --git a/packages/vite/src/node/plugins/resolve.ts b/packages/vite/src/node/plugins/resolve.ts index 683c82836ff39d..686c08b12c3248 100644 --- a/packages/vite/src/node/plugins/resolve.ts +++ b/packages/vite/src/node/plugins/resolve.ts @@ -7,7 +7,8 @@ import { SPECIAL_QUERY_RE, DEFAULT_EXTENSIONS, DEFAULT_MAIN_FIELDS, - OPTIMIZABLE_ENTRY_RE + OPTIMIZABLE_ENTRY_RE, + DEP_VERSION_RE } from '../constants' import { isBuiltin, @@ -29,7 +30,12 @@ import { isPossibleTsOutput, getPotentialTsSrcPaths } from '../utils' -import { createIsOptimizedDepUrl } from '../optimizer' +import { + createIsOptimizedDepUrl, + isOptimizedDepFile, + optimizedDepInfoFromFile, + optimizedDepInfoFromId +} from '../optimizer' import type { OptimizedDepInfo } from '../optimizer' import type { ViteDevServer, SSROptions } from '..' import type { PartialResolvedId } from 'rollup' @@ -78,6 +84,8 @@ export interface InternalResolveOptions extends ResolveOptions { // should also try import from `.ts/tsx/mts/cts` source file as fallback. isFromTsImporter?: boolean tryEsmOnly?: boolean + // True when resolving during the scan phase to discover dependencies + scan?: boolean } export function resolvePlugin(baseOptions: InternalResolveOptions): Plugin { @@ -101,7 +109,7 @@ export function resolvePlugin(baseOptions: InternalResolveOptions): Plugin { isOptimizedDepUrl = createIsOptimizedDepUrl(server.config) }, - resolveId(id, importer, resolveOpts) { + async resolveId(id, importer, resolveOpts) { const ssr = resolveOpts?.ssr === true if (id.startsWith(browserExternalId)) { return id @@ -122,7 +130,8 @@ export function resolvePlugin(baseOptions: InternalResolveOptions): Plugin { isRequire, ...baseOptions, - isFromTsImporter: isTsRequest(importer ?? '') + isFromTsImporter: isTsRequest(importer ?? ''), + scan: resolveOpts?.scan ?? baseOptions.scan } let res: string | PartialResolvedId | undefined @@ -131,9 +140,10 @@ export function resolvePlugin(baseOptions: InternalResolveOptions): Plugin { // tryFileResolve or /fs/ resolution but these files may not yet // exists if we are in the middle of a deps re-processing if (asSrc && isOptimizedDepUrl?.(id)) { - return id.startsWith(FS_PREFIX) + const optimizedPath = id.startsWith(FS_PREFIX) ? fsPathFromId(id) : normalizePath(ensureVolumeInPath(path.resolve(root, id.slice(1)))) + return optimizedPath } // explicit fs paths that starts with /@fs/* @@ -163,6 +173,25 @@ export function resolvePlugin(baseOptions: InternalResolveOptions): Plugin { // handle browser field mapping for relative imports const normalizedFsPath = normalizePath(fsPath) + + if ( + server?._optimizedDeps && + isOptimizedDepFile(normalizedFsPath, server!.config) + ) { + // Optimized files could not yet exist in disk, resolve to the full path + // Inject the current browserHash version if the path doesn't have one + if (!normalizedFsPath.match(DEP_VERSION_RE)) { + const browserHash = optimizedDepInfoFromFile( + server._optimizedDeps!.metadata!, + normalizedFsPath + )?.browserHash + if (browserHash) { + return injectQuery(normalizedFsPath, `v=${browserHash}`) + } + } + return normalizedFsPath + } + const pathFromBasedir = normalizedFsPath.slice(basedir.length) if (pathFromBasedir.startsWith('/node_modules/')) { // normalize direct imports from node_modules to bare imports, so the @@ -231,7 +260,8 @@ export function resolvePlugin(baseOptions: InternalResolveOptions): Plugin { asSrc && server && !ssr && - (res = tryOptimizedResolve(id, server, importer)) + !options.scan && + (res = await tryOptimizedResolve(id, server, importer)) ) { return res } @@ -585,7 +615,8 @@ export function tryNodeResolve( if ( !resolved.includes('node_modules') || // linked !server || // build - !server._registerMissingImport // initial esbuild scan phase + !server._optimizedDeps || // resolving before listening to the server + options.scan // initial esbuild scan phase ) { return { id: resolved } } @@ -606,14 +637,17 @@ export function tryNodeResolve( // otherwise we may introduce duplicated modules for externalized files // from pre-bundled deps. - const versionHash = server._optimizeDepsMetadata?.browserHash + const versionHash = server._optimizedDeps!.metadata.browserHash if (versionHash && isJsType) { resolved = injectQuery(resolved, `v=${versionHash}`) } } else { // this is a missing import, queue optimize-deps re-run and // get a resolved its optimized info - const optimizedInfo = server._registerMissingImport!(id, resolved, ssr) + const optimizedInfo = server._optimizedDeps!.registerMissingImport( + id, + resolved + ) resolved = getOptimizedUrl(optimizedInfo) } return { id: resolved! } @@ -623,19 +657,20 @@ export function tryNodeResolve( const getOptimizedUrl = (optimizedData: OptimizedDepInfo) => `${optimizedData.file}?v=${optimizedData.browserHash}` -export function tryOptimizedResolve( +export async function tryOptimizedResolve( id: string, server: ViteDevServer, importer?: string -): string | undefined { - const depData = server._optimizeDepsMetadata +): Promise { + const optimizedDeps = server._optimizedDeps + + if (!optimizedDeps) return - if (!depData) return + await optimizedDeps.scanProcessing - // check if id has been optimized - const isOptimized = depData.optimized[id] - if (isOptimized) { - return getOptimizedUrl(isOptimized) + const depInfo = optimizedDepInfoFromId(optimizedDeps.metadata, id) + if (depInfo) { + return getOptimizedUrl(depInfo) } if (!importer) return @@ -643,7 +678,10 @@ export function tryOptimizedResolve( // further check if id is imported by nested dependency let resolvedSrc: string | undefined - for (const [pkgPath, optimizedData] of Object.entries(depData.optimized)) { + for (const optimizedData of optimizedDeps.metadata.depInfoList) { + if (!optimizedData.src) continue // Ignore chunks + + const pkgPath = optimizedData.id // check for scenarios, e.g. // pkgPath => "my-lib > foo" // id => "foo" @@ -700,7 +738,11 @@ export function resolvePackageEntry( : isObject(data.browser) && data.browser['.'] if (browserEntry) { // check if the package also has a "module" field. - if (typeof data.module === 'string' && data.module !== browserEntry) { + if ( + !options.isRequire && + typeof data.module === 'string' && + data.module !== browserEntry + ) { // if both are present, we may have a problem: some package points both // to ESM, with "module" targeting Node.js, while some packages points // "module" to browser ESM and "browser" to UMD. diff --git a/packages/vite/src/node/plugins/workerImportMetaUrl.ts b/packages/vite/src/node/plugins/workerImportMetaUrl.ts index 837bbd45aa697d..233d83d066bcb7 100644 --- a/packages/vite/src/node/plugins/workerImportMetaUrl.ts +++ b/packages/vite/src/node/plugins/workerImportMetaUrl.ts @@ -15,6 +15,7 @@ import { parseRequest } from '../utils' import { ENV_ENTRY, ENV_PUBLIC_PATH } from '../constants' import MagicString from 'magic-string' import type { ViteDevServer } from '..' +import type { RollupError } from 'rollup' type WorkerType = 'classic' | 'module' | 'ignore' @@ -25,14 +26,26 @@ function getWorkerType( noCommentsCode: string, i: number ): WorkerType { + function err(e: string, pos: number) { + const error = new Error(e) as RollupError + error.pos = pos + throw error + } + const commaIndex = noCommentsCode.indexOf(',', i) if (commaIndex === -1) { return 'classic' } const endIndex = noCommentsCode.indexOf(')', i) + // case: ') ... ,' mean no worker options params + if (commaIndex > endIndex) { + return 'classic' + } + // need to find in comment code let workerOptsString = code.substring(commaIndex + 1, endIndex) + const hasViteIgnore = /\/\*\s*@vite-ignore\s*\*\//.test(workerOptsString) if (hasViteIgnore) { return 'ignore' @@ -49,9 +62,10 @@ function getWorkerType( workerOpts = JSON5.parse(workerOptsString) } catch (e) { // can't parse by JSON5, so the worker options had unexpect char. - throw new Error( + err( 'Vite is unable to parse the worker options as the value is not static.' + - 'To ignore this error, please use /* @vite-ignore */ in the worker options.' + 'To ignore this error, please use /* @vite-ignore */ in the worker options.', + commaIndex + 1 ) } @@ -155,7 +169,9 @@ export function workerImportMetaUrlPlugin(config: ResolvedConfig): Plugin { url = injectQuery(url, WORKER_FILE_ID) url = injectQuery(url, `type=${workerType}`) } - s.overwrite(urlIndex, urlIndex + exp.length, JSON.stringify(url)) + s.overwrite(urlIndex, urlIndex + exp.length, JSON.stringify(url), { + contentOnly: true + }) } if (s) { return { diff --git a/packages/vite/src/node/server/hmr.ts b/packages/vite/src/node/server/hmr.ts index eae184a64f4773..edb73785247b6f 100644 --- a/packages/vite/src/node/server/hmr.ts +++ b/packages/vite/src/node/server/hmr.ts @@ -47,7 +47,7 @@ export async function handleHMRUpdate( const isConfig = file === config.configFile const isConfigDependency = config.configFileDependencies.some( - (name) => file === path.resolve(name) + (name) => file === name ) const isEnv = config.inlineConfig.envFile !== false && diff --git a/packages/vite/src/node/server/index.ts b/packages/vite/src/node/server/index.ts index c198dd23294fdc..e8d4c3f1e5626d 100644 --- a/packages/vite/src/node/server/index.ts +++ b/packages/vite/src/node/server/index.ts @@ -44,8 +44,6 @@ import { transformRequest } from './transformRequest' import type { ESBuildTransformResult } from '../plugins/esbuild' import { transformWithEsbuild } from '../plugins/esbuild' import type { TransformOptions as EsbuildTransformOptions } from 'esbuild' -import type { DepOptimizationMetadata, OptimizedDepInfo } from '../optimizer' -import { createOptimizeDepsRun } from '../optimizer' import { ssrLoadModule } from '../ssr/ssrModuleLoader' import { resolveSSRExternal } from '../ssr/ssrExternal' import { @@ -53,7 +51,8 @@ import { ssrRewriteStacktrace } from '../ssr/ssrStacktrace' import { ssrTransform } from '../ssr/ssrTransform' -import { createMissingImporterRegisterFn } from '../optimizer/registerMissing' +import { createOptimizedDeps } from '../optimizer/registerMissing' +import type { OptimizedDeps } from '../optimizer' import { resolveHostname } from '../utils' import { searchForWorkspaceRoot } from './searchRoot' import { CLIENT_DIR } from '../constants' @@ -257,7 +256,7 @@ export interface ViteDevServer { /** * @internal */ - _optimizeDepsMetadata: DepOptimizationMetadata | null + _optimizedDeps: OptimizedDeps | null /** * Deps that are externalized * @internal @@ -284,16 +283,6 @@ export interface ViteDevServer { * @internal */ _forceOptimizeOnRestart: boolean - /** - * @internal - */ - _registerMissingImport: - | (( - id: string, - resolved: string, - ssr: boolean | undefined - ) => OptimizedDepInfo) - | null /** * @internal */ @@ -372,17 +361,18 @@ export async function createServer( }, transformIndexHtml: null!, // to be immediately set async ssrLoadModule(url, opts?: { fixStacktrace?: boolean }) { - let configFileDependencies: string[] = [] - const metadata = server._optimizeDepsMetadata - if (metadata) { - await metadata.processing - configFileDependencies = Object.keys(metadata.optimized) + if (!server._ssrExternals) { + let knownImports: string[] = [] + const optimizedDeps = server._optimizedDeps + if (optimizedDeps) { + await optimizedDeps.scanProcessing + knownImports = [ + ...Object.keys(optimizedDeps.metadata.optimized), + ...Object.keys(optimizedDeps.metadata.discovered) + ] + } + server._ssrExternals = resolveSSRExternal(config, knownImports) } - - server._ssrExternals ||= resolveSSRExternal( - config, - configFileDependencies - ) return ssrLoadModule( url, server, @@ -435,12 +425,11 @@ export async function createServer( return server._restartPromise }, - _optimizeDepsMetadata: null, + _optimizedDeps: null, _ssrExternals: null, _globImporters: Object.create(null), _restartPromise: null, _forceOptimizeOnRestart: false, - _registerMissingImport: null, _pendingRequests: new Map() } @@ -582,32 +571,15 @@ export async function createServer( // error handler middlewares.use(errorMiddleware(server, !!middlewareMode)) - const runOptimize = async () => { - const optimizeDeps = await createOptimizeDepsRun( - config, - config.server.force - ) - - // Don't await for the optimization to finish, we can start the - // server right away here - server._optimizeDepsMetadata = optimizeDeps.metadata - optimizeDeps.run() - - // While running the first optimizeDeps, _registerMissingImport is null - // so the resolve plugin resolves straight to node_modules during the - // deps discovery scan phase - server._registerMissingImport = createMissingImporterRegisterFn(server) - } - if (!middlewareMode && httpServer) { let isOptimized = false - // overwrite listen to run optimizer before server start + // overwrite listen to init optimizer before server start const listen = httpServer.listen.bind(httpServer) httpServer.listen = (async (port: number, ...args: any[]) => { if (!isOptimized) { try { await container.buildStart({}) - await runOptimize() + server._optimizedDeps = createOptimizedDeps(server) isOptimized = true } catch (e) { httpServer.emit('error', e) @@ -618,7 +590,7 @@ export async function createServer( }) as any } else { await container.buildStart({}) - await runOptimize() + server._optimizedDeps = createOptimizedDeps(server) } return server diff --git a/packages/vite/src/node/server/middlewares/indexHtml.ts b/packages/vite/src/node/server/middlewares/indexHtml.ts index 3c76d94c526930..ca2538bd9507ed 100644 --- a/packages/vite/src/node/server/middlewares/indexHtml.ts +++ b/packages/vite/src/node/server/middlewares/indexHtml.ts @@ -1,7 +1,7 @@ import fs from 'fs' import path from 'path' import MagicString from 'magic-string' -import type { AttributeNode, ElementNode } from '@vue/compiler-dom' +import type { AttributeNode, ElementNode, TextNode } from '@vue/compiler-dom' import { NodeTypes } from '@vue/compiler-dom' import type { Connect } from 'types/connect' import type { IndexHtmlTransformHook } from '../../plugins/html' @@ -38,7 +38,9 @@ function getHtmlFilename(url: string, server: ViteDevServer) { if (url.startsWith(FS_PREFIX)) { return decodeURIComponent(fsPathFromId(url)) } else { - return decodeURIComponent(path.join(server.config.root, url.slice(1))) + return decodeURIComponent( + normalizePath(path.join(server.config.root, url.slice(1))) + ) } } @@ -64,7 +66,8 @@ const processNodeUrl = ( s.overwrite( node.value!.loc.start.offset, node.value!.loc.end.offset, - `"${config.base + url.slice(1)}"` + `"${config.base + url.slice(1)}"`, + { contentOnly: true } ) } else if ( url.startsWith('.') && @@ -82,13 +85,14 @@ const processNodeUrl = ( `"${path.posix.join( path.posix.relative(originalUrl, '/'), url.slice(1) - )}"` + )}"`, + { contentOnly: true } ) } } const devHtmlHook: IndexHtmlTransformHook = async ( html, - { path: htmlPath, server, originalUrl } + { path: htmlPath, filename, server, originalUrl } ) => { const { config, moduleGraph } = server! const base = config.base || '/' @@ -102,12 +106,17 @@ const devHtmlHook: IndexHtmlTransformHook = async ( const url = filePath.replace(normalizePath(config.root), '') - const contents = node.children - .map((child: any) => child.content || '') - .join('') + const contentNode = node.children[0] as TextNode + + const code = contentNode.content + const map = new MagicString(html) + .snip(contentNode.loc.start.offset, contentNode.loc.end.offset) + .generateMap({ hires: true }) + map.sources = [filename] + map.file = filename // add HTML Proxy to Map - addToHTMLProxyCache(config, url, inlineModuleIndex, contents) + addToHTMLProxyCache(config, url, inlineModuleIndex, { code, map }) // inline js module. convert to src="proxy" const modulePath = `${ @@ -123,7 +132,8 @@ const devHtmlHook: IndexHtmlTransformHook = async ( s.overwrite( node.loc.start.offset, node.loc.end.offset, - `` + ``, + { contentOnly: true } ) } @@ -138,7 +148,7 @@ const devHtmlHook: IndexHtmlTransformHook = async ( if (src) { processNodeUrl(src, s, config, htmlPath, originalUrl, moduleGraph) - } else if (isModule) { + } else if (isModule && node.children.length) { addInlineModule(node, 'js') } } diff --git a/packages/vite/src/node/server/pluginContainer.ts b/packages/vite/src/node/server/pluginContainer.ts index 2f9c171de5d2e5..5efc2670c0f81a 100644 --- a/packages/vite/src/node/server/pluginContainer.ts +++ b/packages/vite/src/node/server/pluginContainer.ts @@ -51,7 +51,7 @@ import type { import * as acorn from 'acorn' import type { RawSourceMap } from '@ampproject/remapping' import { TraceMap, originalPositionFor } from '@jridgewell/trace-mapping' -import { combineSourcemaps } from '../utils' +import { cleanUrl, combineSourcemaps } from '../utils' import MagicString from 'magic-string' import type { FSWatcher } from 'chokidar' import { @@ -90,6 +90,10 @@ export interface PluginContainer { options?: { skip?: Set ssr?: boolean + /** + * @internal + */ + scan?: boolean } ): Promise transform( @@ -212,6 +216,7 @@ export async function createPluginContainer( class Context implements PluginContext { meta = minimalContext.meta ssr = false + _scan = false _activePlugin: Plugin | null _activeId: string | null = null _activeCode: string | null = null @@ -241,7 +246,11 @@ export async function createPluginContainer( skip = new Set(this._resolveSkips) skip.add(this._activePlugin) } - let out = await container.resolveId(id, importer, { skip, ssr: this.ssr }) + let out = await container.resolveId(id, importer, { + skip, + ssr: this.ssr, + scan: this._scan + }) if (typeof out === 'string') out = { id: out } return out as ResolvedId | null } @@ -419,7 +428,7 @@ export async function createPluginContainer( if (!combinedMap) { combinedMap = m as SourceMap } else { - combinedMap = combineSourcemaps(this.filename, [ + combinedMap = combineSourcemaps(cleanUrl(this.filename), [ { ...(m as RawSourceMap), sourcesContent: combinedMap.sourcesContent @@ -433,7 +442,7 @@ export async function createPluginContainer( ? new MagicString(this.originalCode).generateMap({ includeContent: true, hires: true, - source: this.filename + source: cleanUrl(this.filename) }) : null } @@ -487,8 +496,10 @@ export async function createPluginContainer( async resolveId(rawId, importer = join(root, 'index.html'), options) { const skip = options?.skip const ssr = options?.ssr + const scan = !!options?.scan const ctx = new Context() ctx.ssr = !!ssr + ctx._scan = scan ctx._resolveSkips = skip const resolveStart = isDebug ? performance.now() : 0 @@ -505,7 +516,7 @@ export async function createPluginContainer( ctx as any, rawId, importer, - { ssr } + { ssr, scan } ) if (!result) continue diff --git a/packages/vite/src/node/server/send.ts b/packages/vite/src/node/server/send.ts index 43f0fe1660b2eb..a52d17d17458ba 100644 --- a/packages/vite/src/node/server/send.ts +++ b/packages/vite/src/node/server/send.ts @@ -1,8 +1,7 @@ import type { IncomingMessage, OutgoingHttpHeaders, ServerResponse } from 'http' import getEtag from 'etag' import type { SourceMap } from 'rollup' - -const isDebug = process.env.DEBUG +import { getCodeWithSourcemap } from './sourcemap' const alias: Record = { js: 'application/javascript', @@ -38,7 +37,8 @@ export function send( if (req.headers['if-none-match'] === etag) { res.statusCode = 304 - return res.end() + res.end() + return } res.setHeader('Content-Type', alias[type] || type) @@ -53,24 +53,12 @@ export function send( // inject source map reference if (map && map.mappings) { - if (isDebug) { - content += `\n/*${JSON.stringify(map, null, 2).replace( - /\*\//g, - '*\\/' - )}*/\n` + if (type === 'js' || type === 'css') { + content = getCodeWithSourcemap(type, content.toString(), map) } - content += genSourceMapString(map) } res.statusCode = 200 - return res.end(content) -} - -function genSourceMapString(map: SourceMap | string | undefined) { - if (typeof map !== 'string') { - map = JSON.stringify(map) - } - return `\n//# sourceMappingURL=data:application/json;base64,${Buffer.from( - map - ).toString('base64')}` + res.end(content) + return } diff --git a/packages/vite/src/node/server/sourcemap.ts b/packages/vite/src/node/server/sourcemap.ts index c6fc3b1f2579bf..dc77c4a4714298 100644 --- a/packages/vite/src/node/server/sourcemap.ts +++ b/packages/vite/src/node/server/sourcemap.ts @@ -1,7 +1,9 @@ import path from 'path' import { promises as fs } from 'fs' import type { Logger } from '../logger' -import { createDebugger } from '../utils' +import { createDebugger, normalizePath } from '../utils' +import type { SourceMap } from 'rollup' +import { maybeVirtualHtmlSet } from '../plugins/html' const isDebug = !!process.env.DEBUG const debug = createDebugger('vite:sourcemap', { @@ -41,6 +43,7 @@ export async function injectSourcesContent( sourcePath = path.resolve(sourceRoot, sourcePath) } return fs.readFile(sourcePath, 'utf-8').catch(() => { + if (maybeVirtualHtmlSet.has(normalizePath(sourcePath))) return null missingSources.push(sourcePath) return null }) @@ -57,3 +60,28 @@ export async function injectSourcesContent( isDebug && debug(`Missing sources:\n ` + missingSources.join(`\n `)) } } + +function genSourceMapUrl(map: SourceMap | string | undefined) { + if (typeof map !== 'string') { + map = JSON.stringify(map) + } + return `data:application/json;base64,${Buffer.from(map).toString('base64')}` +} + +export function getCodeWithSourcemap( + type: 'js' | 'css', + code: string, + map: SourceMap | null +) { + if (isDebug) { + code += `\n/*${JSON.stringify(map, null, 2).replace(/\*\//g, '*\\/')}*/\n` + } + + if (type === 'js') { + code += `\n//# sourceMappingURL=${genSourceMapUrl(map ?? undefined)}` + } else if (type === 'css') { + code += `\n/*# sourceMappingURL=${genSourceMapUrl(map ?? undefined)} */` + } + + return code +} diff --git a/packages/vite/src/node/server/transformRequest.ts b/packages/vite/src/node/server/transformRequest.ts index c8b38c0b31ec77..baafe95e8416f3 100644 --- a/packages/vite/src/node/server/transformRequest.ts +++ b/packages/vite/src/node/server/transformRequest.ts @@ -63,7 +63,7 @@ export function transformRequest( // In all cases, the next time this module is requested, it should be // re-processed. // - // We save the timestap when we start processing and compare it with the + // We save the timestamp when we start processing and compare it with the // last time this module is invalidated const timestamp = Date.now() diff --git a/packages/vite/src/node/server/ws.ts b/packages/vite/src/node/server/ws.ts index c8da5e4ab6e82f..a01d0bd3225571 100644 --- a/packages/vite/src/node/server/ws.ts +++ b/packages/vite/src/node/server/ws.ts @@ -3,35 +3,98 @@ import type { Server } from 'http' import { STATUS_CODES } from 'http' import type { ServerOptions as HttpsServerOptions } from 'https' import { createServer as createHttpsServer } from 'https' -import type { ServerOptions } from 'ws' -import { WebSocketServer as WebSocket } from 'ws' -import type { WebSocket as WebSocketTypes } from 'types/ws' -import type { ErrorPayload, HMRPayload } from 'types/hmrPayload' +import type { ServerOptions, WebSocket as WebSocketRaw } from 'ws' +import { WebSocketServer as WebSocketServerRaw } from 'ws' +import type { CustomPayload, ErrorPayload, HMRPayload } from 'types/hmrPayload' +import type { InferCustomEventPayload } from 'types/customEvent' import type { ResolvedConfig } from '..' import { isObject } from '../utils' import type { Socket } from 'net' + export const HMR_HEADER = 'vite-hmr' +export type WebSocketCustomListener = ( + data: T, + client: WebSocketClient +) => void + export interface WebSocketServer { - on: WebSocketTypes.Server['on'] - off: WebSocketTypes.Server['off'] + /** + * Get all connected clients. + */ + clients: Set + /** + * Boardcast events to all clients + */ send(payload: HMRPayload): void + /** + * Send custom event + */ + send(event: T, payload?: InferCustomEventPayload): void + /** + * Disconnect all clients and terminate the server. + */ close(): Promise + /** + * Handle custom event emitted by `import.meta.hot.send` + */ + on: WebSocketServerRaw['on'] & { + ( + event: T, + listener: WebSocketCustomListener> + ): void + } + /** + * Unregister event listener. + */ + off: WebSocketServerRaw['off'] & { + (event: string, listener: Function): void + } +} + +export interface WebSocketClient { + /** + * Send event to the client + */ + send(payload: HMRPayload): void + /** + * Send custom event + */ + send(event: string, payload?: CustomPayload['data']): void + /** + * The raw WebSocket instance + * @advanced + */ + socket: WebSocketRaw } +const wsServerEvents = [ + 'connection', + 'error', + 'headers', + 'listening', + 'message' +] + export function createWebSocketServer( server: Server | null, config: ResolvedConfig, httpsOptions?: HttpsServerOptions ): WebSocketServer { - let wss: WebSocket + let wss: WebSocketServerRaw let httpsServer: Server | undefined = undefined const hmr = isObject(config.server.hmr) && config.server.hmr - const wsServer = (hmr && hmr.server) || server + const hmrServer = hmr && hmr.server + const hmrPort = hmr && hmr.port + // TODO: the main server port may not have been chosen yet as it may use the next available + const portsAreCompatible = !hmrPort || hmrPort === config.server.port + const wsServer = hmrServer || (portsAreCompatible && server) + const customListeners = new Map>>() + const clientsMap = new WeakMap() if (wsServer) { - wss = new WebSocket({ noServer: true }) + wss = new WebSocketServerRaw({ noServer: true }) wsServer.on('upgrade', (req, socket, head) => { if (req.headers['sec-websocket-protocol'] === HMR_HEADER) { wss.handleUpgrade(req, socket as Socket, head, (ws) => { @@ -41,7 +104,7 @@ export function createWebSocketServer( }) } else { const websocketServerOptions: ServerOptions = {} - const port = (hmr && hmr.port) || 24678 + const port = hmrPort || 24678 const host = (hmr && hmr.host) || undefined if (httpsOptions) { // if we're serving the middlewares over https, the ws library doesn't support automatically creating an https server, so we need to do it ourselves @@ -72,10 +135,22 @@ export function createWebSocketServer( } // vite dev server in middleware mode - wss = new WebSocket(websocketServerOptions) + wss = new WebSocketServerRaw(websocketServerOptions) } wss.on('connection', (socket) => { + socket.on('message', (raw) => { + if (!customListeners.size) return + let parsed: any + try { + parsed = JSON.parse(String(raw)) + } catch {} + if (!parsed || parsed.type !== 'custom' || !parsed.event) return + const listeners = customListeners.get(parsed.event) + if (!listeners?.size) return + const client = getSocketClent(socket) + listeners.forEach((listener) => listener(parsed.data, client)) + }) socket.send(JSON.stringify({ type: 'connected' })) if (bufferedError) { socket.send(JSON.stringify(bufferedError)) @@ -92,6 +167,30 @@ export function createWebSocketServer( } }) + // Provide a wrapper to the ws client so we can send messages in JSON format + // To be consistent with server.ws.send + function getSocketClent(socket: WebSocketRaw) { + if (!clientsMap.has(socket)) { + clientsMap.set(socket, { + send: (...args) => { + let payload: HMRPayload + if (typeof args[0] === 'string') { + payload = { + type: 'custom', + event: args[0], + data: args[1] + } + } else { + payload = args[0] + } + socket.send(JSON.stringify(payload)) + }, + socket + }) + } + return clientsMap.get(socket)! + } + // On page reloads, if a file fails to compile and returns 500, the server // sends the error payload before the client connection is established. // If we have no open clients, buffer the error and send it to the next @@ -99,9 +198,39 @@ export function createWebSocketServer( let bufferedError: ErrorPayload | null = null return { - on: wss.on.bind(wss), - off: wss.off.bind(wss), - send(payload: HMRPayload) { + on: ((event: string, fn: () => void) => { + if (wsServerEvents.includes(event)) wss.on(event, fn) + else { + if (!customListeners.has(event)) { + customListeners.set(event, new Set()) + } + customListeners.get(event)!.add(fn) + } + }) as WebSocketServer['on'], + off: ((event: string, fn: () => void) => { + if (wsServerEvents.includes(event)) { + wss.off(event, fn) + } else { + customListeners.get(event)?.delete(fn) + } + }) as WebSocketServer['off'], + + get clients() { + return new Set(Array.from(wss.clients).map(getSocketClent)) + }, + + send(...args: any[]) { + let payload: HMRPayload + if (typeof args[0] === 'string') { + payload = { + type: 'custom', + event: args[0], + data: args[1] + } + } else { + payload = args[0] + } + if (payload.type === 'error' && !wss.clients.size) { bufferedError = payload return diff --git a/packages/vite/src/node/ssr/__tests__/ssrExternal.spec.ts b/packages/vite/src/node/ssr/__tests__/ssrExternal.spec.ts new file mode 100644 index 00000000000000..ad16534b088e2b --- /dev/null +++ b/packages/vite/src/node/ssr/__tests__/ssrExternal.spec.ts @@ -0,0 +1,5 @@ +import { stripNesting } from '../ssrExternal' + +test('stripNesting', async () => { + expect(stripNesting(['c', 'p1>c1', 'p2 > c2'])).toEqual(['c', 'c1', 'c2']) +}) diff --git a/packages/vite/src/node/ssr/ssrExternal.ts b/packages/vite/src/node/ssr/ssrExternal.ts index 0e2eade85c21f1..800a2307dabae6 100644 --- a/packages/vite/src/node/ssr/ssrExternal.ts +++ b/packages/vite/src/node/ssr/ssrExternal.ts @@ -14,6 +14,16 @@ import { createFilter } from '@rollup/pluginutils' const debug = createDebugger('vite:ssr-external') +/** + * Converts "parent > child" syntax to just "child" + */ +export function stripNesting(packages: string[]) { + return packages.map((s) => { + const arr = s.split('>') + return arr[arr.length - 1].trim() + }) +} + /** * Heuristics for determining whether a dependency should be externalized for * server-side rendering. @@ -22,6 +32,10 @@ export function resolveSSRExternal( config: ResolvedConfig, knownImports: string[] ): string[] { + // strip nesting since knownImports may be passed in from optimizeDeps which + // supports a "parent > child" syntax + knownImports = stripNesting(knownImports) + const ssrConfig = config.ssr if (ssrConfig?.noExternal === true) { return [] diff --git a/packages/vite/src/node/ssr/ssrManifestPlugin.ts b/packages/vite/src/node/ssr/ssrManifestPlugin.ts index 1e00853402ba5d..69184150bb97b7 100644 --- a/packages/vite/src/node/ssr/ssrManifestPlugin.ts +++ b/packages/vite/src/node/ssr/ssrManifestPlugin.ts @@ -45,37 +45,30 @@ export function ssrManifestPlugin(config: ResolvedConfig): Plugin { } if (imports.length) { for (let index = 0; index < imports.length; index++) { - const { - s: start, - e: end, - n: name, - d: dynamicIndex - } = imports[index] - if (dynamicIndex) { - // check the chunk being imported - const url = code.slice(start, end) - const deps: string[] = [] - const ownerFilename = chunk.fileName - // literal import - trace direct imports and add to deps - const analyzed: Set = new Set() - const addDeps = (filename: string) => { - if (filename === ownerFilename) return - if (analyzed.has(filename)) return - analyzed.add(filename) - const chunk = bundle[filename] as OutputChunk | undefined - if (chunk) { - chunk.viteMetadata.importedCss.forEach((file) => { - deps.push(`/${file}`) - }) - chunk.imports.forEach(addDeps) - } + const { s: start, e: end, n: name } = imports[index] + // check the chunk being imported + const url = code.slice(start, end) + const deps: string[] = [] + const ownerFilename = chunk.fileName + // literal import - trace direct imports and add to deps + const analyzed: Set = new Set() + const addDeps = (filename: string) => { + if (filename === ownerFilename) return + if (analyzed.has(filename)) return + analyzed.add(filename) + const chunk = bundle[filename] as OutputChunk | undefined + if (chunk) { + chunk.viteMetadata.importedCss.forEach((file) => { + deps.push(`/${file}`) + }) + chunk.imports.forEach(addDeps) } - const normalizedFile = normalizePath( - join(dirname(chunk.fileName), url.slice(1, -1)) - ) - addDeps(normalizedFile) - ssrManifest[basename(name!)] = deps } + const normalizedFile = normalizePath( + join(dirname(chunk.fileName), url.slice(1, -1)) + ) + addDeps(normalizedFile) + ssrManifest[basename(name!)] = deps } } } diff --git a/packages/vite/src/node/ssr/ssrTransform.ts b/packages/vite/src/node/ssr/ssrTransform.ts index a559e62c826a99..56b75f8dd14913 100644 --- a/packages/vite/src/node/ssr/ssrTransform.ts +++ b/packages/vite/src/node/ssr/ssrTransform.ts @@ -158,7 +158,8 @@ export async function ssrTransform( s.overwrite( node.start, node.start + 14 /* 'export default'.length */, - `${ssrModuleExportsKey}.default =` + `${ssrModuleExportsKey}.default =`, + { contentOnly: true } ) } } @@ -207,14 +208,16 @@ export async function ssrTransform( s.prependRight(topNode.start, `const ${id.name} = ${binding};\n`) } } else { - s.overwrite(id.start, id.end, binding) + s.overwrite(id.start, id.end, binding, { contentOnly: true }) } }, onImportMeta(node) { - s.overwrite(node.start, node.end, ssrImportMetaKey) + s.overwrite(node.start, node.end, ssrImportMetaKey, { contentOnly: true }) }, onDynamicImport(node) { - s.overwrite(node.start, node.start + 6, ssrDynamicImportKey) + s.overwrite(node.start, node.start + 6, ssrDynamicImportKey, { + contentOnly: true + }) if (node.type === 'ImportExpression' && node.source.type === 'Literal') { dynamicDeps.add(node.source.value as string) } diff --git a/packages/vite/src/node/utils.ts b/packages/vite/src/node/utils.ts index cca8df5750ec49..edb3410751868a 100644 --- a/packages/vite/src/node/utils.ts +++ b/packages/vite/src/node/utils.ts @@ -575,6 +575,26 @@ export async function processSrcSet( }, '') } +function escapeToLinuxLikePath(path: string) { + if (/^[A-Z]:/.test(path)) { + return path.replace(/^([A-Z]):\//, '/windows/$1/') + } + if (/^\/[^/]/.test(path)) { + return `/linux${path}` + } + return path +} + +function unescapeToLinuxLikePath(path: string) { + if (path.startsWith('/linux/')) { + return path.slice('/linux'.length) + } + if (path.startsWith('/windows/')) { + return path.replace(/^\/windows\/([A-Z])\//, '$1:/') + } + return path +} + // based on https://github.com/sveltejs/svelte/blob/abf11bb02b2afbd3e4cac509a0f70e318c306364/src/compiler/utils/mapped_code.ts#L221 const nullSourceMap: RawSourceMap = { names: [], @@ -593,6 +613,21 @@ export function combineSourcemaps( return { ...nullSourceMap } } + // hack for parse broken with normalized absolute paths on windows (C:/path/to/something). + // escape them to linux like paths + // also avoid mutation here to prevent breaking plugin's using cache to generate sourcemaps like vue (see #7442) + sourcemapList = sourcemapList.map((sourcemap) => { + const newSourcemaps = { ...sourcemap } + newSourcemaps.sources = sourcemap.sources.map((source) => + source ? escapeToLinuxLikePath(source) : null + ) + if (sourcemap.sourceRoot) { + newSourcemaps.sourceRoot = escapeToLinuxLikePath(sourcemap.sourceRoot) + } + return newSourcemaps + }) + const escapedFilename = escapeToLinuxLikePath(filename) + // We don't declare type here so we can convert/fake/map as RawSourceMap let map //: SourceMap let mapIndex = 1 @@ -604,10 +639,10 @@ export function combineSourcemaps( map = remapping( sourcemapList[0], function loader(sourcefile) { - if (sourcefile === filename && sourcemapList[mapIndex]) { + if (sourcefile === escapedFilename && sourcemapList[mapIndex]) { return sourcemapList[mapIndex++] } else { - return { ...nullSourceMap } + return null } }, true @@ -617,6 +652,12 @@ export function combineSourcemaps( delete map.file } + // unescape the previous hack + map.sources = map.sources.map((source) => + source ? unescapeToLinuxLikePath(source) : source + ) + map.file = filename + return map as RawSourceMap } diff --git a/packages/vite/types/customEvent.d.ts b/packages/vite/types/customEvent.d.ts index c38a4ac940ff6e..aacf1554b0de75 100644 --- a/packages/vite/types/customEvent.d.ts +++ b/packages/vite/types/customEvent.d.ts @@ -1,5 +1,16 @@ -// See https://stackoverflow.com/a/63549561. -export type CustomEventName = (T extends `vite:${T}` - ? never - : T) & - (`vite:${T}` extends T ? never : T) +import type { + ErrorPayload, + FullReloadPayload, + PrunePayload, + UpdatePayload +} from './hmrPayload' + +export interface CustomEventMap { + 'vite:beforeUpdate': UpdatePayload + 'vite:beforePrune': PrunePayload + 'vite:beforeFullReload': FullReloadPayload + 'vite:error': ErrorPayload +} + +export type InferCustomEventPayload = + T extends keyof CustomEventMap ? CustomEventMap[T] : unknown diff --git a/packages/vite/types/hot.d.ts b/packages/vite/types/hot.d.ts new file mode 100644 index 00000000000000..f06846ff59d530 --- /dev/null +++ b/packages/vite/types/hot.d.ts @@ -0,0 +1,25 @@ +import type { InferCustomEventPayload } from './customEvent' + +export interface ViteHotContext { + readonly data: any + + accept(): void + accept(cb: (mod: any) => void): void + accept(dep: string, cb: (mod: any) => void): void + accept(deps: readonly string[], cb: (mods: any[]) => void): void + + /** + * @deprecated + */ + acceptDeps(): never + + dispose(cb: (data: any) => void): void + decline(): void + invalidate(): void + + on( + event: T, + cb: (payload: InferCustomEventPayload) => void + ): void + send(event: T, data?: InferCustomEventPayload): void +} diff --git a/packages/vite/types/importMeta.d.ts b/packages/vite/types/importMeta.d.ts index 56b82125381e20..9b57fd120a7ba9 100644 --- a/packages/vite/types/importMeta.d.ts +++ b/packages/vite/types/importMeta.d.ts @@ -20,46 +20,7 @@ interface GlobOptions { interface ImportMeta { url: string - readonly hot?: { - readonly data: any - - accept(): void - accept(cb: (mod: any) => void): void - accept(dep: string, cb: (mod: any) => void): void - accept(deps: readonly string[], cb: (mods: any[]) => void): void - - /** - * @deprecated - */ - acceptDeps(): never - - dispose(cb: (data: any) => void): void - decline(): void - invalidate(): void - - on: { - ( - event: 'vite:beforeUpdate', - cb: (payload: import('./hmrPayload').UpdatePayload) => void - ): void - ( - event: 'vite:beforePrune', - cb: (payload: import('./hmrPayload').PrunePayload) => void - ): void - ( - event: 'vite:beforeFullReload', - cb: (payload: import('./hmrPayload').FullReloadPayload) => void - ): void - ( - event: 'vite:error', - cb: (payload: import('./hmrPayload').ErrorPayload) => void - ): void - ( - event: import('./customEvent').CustomEventName, - cb: (data: any) => void - ): void - } - } + readonly hot?: import('./hot').ViteHotContext readonly env: ImportMetaEnv diff --git a/packages/vite/types/ws.d.ts b/packages/vite/types/ws.d.ts index 4f85bb87d5bc3d..29732ebf3e0d8a 100644 --- a/packages/vite/types/ws.d.ts +++ b/packages/vite/types/ws.d.ts @@ -1,4 +1,7 @@ -// Type definitions for ws 8.2 +// Modified and inlined to avoid extra dependency +// Source: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/ws/index.d.ts + +// Type definitions for ws 8.5 // Project: https://github.com/websockets/ws // Definitions by: Paul Loyd // Margus Lamp @@ -7,6 +10,7 @@ // teidesu // Bartosz Wojtkowiak // Kyle Hensel +// Samuel Skeen // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped /// @@ -40,6 +44,8 @@ declare class WebSocket extends EventEmitter { binaryType: 'nodebuffer' | 'arraybuffer' | 'fragments' readonly bufferedAmount: number readonly extensions: string + /** Indicates whether the websocket is paused */ + readonly isPaused: boolean readonly protocol: string /** The current state of the connection */ readonly readyState: @@ -58,11 +64,12 @@ declare class WebSocket extends EventEmitter { /** The connection is closed. */ readonly CLOSED: 3 - onopen: (event: WebSocket.Event) => void - onerror: (event: WebSocket.ErrorEvent) => void - onclose: (event: WebSocket.CloseEvent) => void - onmessage: (event: WebSocket.MessageEvent) => void + onopen: ((event: WebSocket.Event) => void) | null + onerror: ((event: WebSocket.ErrorEvent) => void) | null + onclose: ((event: WebSocket.CloseEvent) => void) | null + onmessage: ((event: WebSocket.MessageEvent) => void) | null + constructor(address: null) constructor( address: string | URL, options?: WebSocket.ClientOptions | ClientRequestArgs @@ -89,6 +96,18 @@ declare class WebSocket extends EventEmitter { ): void terminate(): void + /** + * Pause the websocket causing it to stop emitting events. Some events can still be + * emitted after this is called, until all buffered data is consumed. This method + * is a noop if the ready state is `CONNECTING` or `CLOSED`. + */ + pause(): void + /** + * Make a paused socket resume emitting events. This method is a noop if the ready + * state is `CONNECTING` or `CLOSED`. + */ + resume(): void + // HTML5 WebSocket events addEventListener( method: 'message', @@ -281,7 +300,7 @@ declare class WebSocket extends EventEmitter { } declare const WebSocketAlias: typeof WebSocket -type WebSocketAlias = WebSocket +interface WebSocketAlias extends WebSocket {} // tslint:disable-line no-empty-interface declare namespace WebSocket { /** @@ -328,6 +347,7 @@ declare namespace WebSocket { interface ClientOptions extends SecureContextOptions { protocol?: string | undefined followRedirects?: boolean | undefined + generateMask?(mask: Buffer): void handshakeTimeout?: number | undefined maxRedirects?: number | undefined perMessageDeflate?: boolean | PerMessageDeflateOptions | undefined @@ -341,6 +361,7 @@ declare namespace WebSocket { checkServerIdentity?(servername: string, cert: CertMeta): boolean rejectUnauthorized?: boolean | undefined maxPayload?: number | undefined + skipUTF8Validation?: boolean | undefined } interface PerMessageDeflateOptions { @@ -415,6 +436,7 @@ declare namespace WebSocket { perMessageDeflate?: boolean | PerMessageDeflateOptions | undefined maxPayload?: number | undefined skipUTF8Validation?: boolean | undefined + WebSocket?: typeof WebSocket.WebSocket | undefined } interface AddressInfo { @@ -424,10 +446,10 @@ declare namespace WebSocket { } // WebSocket Server - class Server extends EventEmitter { + class Server extends EventEmitter { options: ServerOptions path: string - clients: Set + clients: Set constructor(options?: ServerOptions, callback?: () => void) @@ -437,56 +459,59 @@ declare namespace WebSocket { request: IncomingMessage, socket: Duplex, upgradeHead: Buffer, - callback: (client: WebSocket, request: IncomingMessage) => void + callback: (client: T, request: IncomingMessage) => void ): void shouldHandle(request: IncomingMessage): boolean | Promise // Events on( event: 'connection', - cb: (this: Server, socket: WebSocket, request: IncomingMessage) => void + cb: (this: Server, socket: T, request: IncomingMessage) => void ): this - on(event: 'error', cb: (this: Server, error: Error) => void): this + on(event: 'error', cb: (this: Server, error: Error) => void): this on( event: 'headers', - cb: (this: Server, headers: string[], request: IncomingMessage) => void + cb: (this: Server, headers: string[], request: IncomingMessage) => void ): this - on(event: 'close' | 'listening', cb: (this: Server) => void): this + on(event: 'close' | 'listening', cb: (this: Server) => void): this on( event: string | symbol, - listener: (this: Server, ...args: any[]) => void + listener: (this: Server, ...args: any[]) => void ): this once( event: 'connection', - cb: (this: Server, socket: WebSocket, request: IncomingMessage) => void + cb: (this: Server, socket: T, request: IncomingMessage) => void ): this - once(event: 'error', cb: (this: Server, error: Error) => void): this + once(event: 'error', cb: (this: Server, error: Error) => void): this once( event: 'headers', - cb: (this: Server, headers: string[], request: IncomingMessage) => void + cb: (this: Server, headers: string[], request: IncomingMessage) => void + ): this + once(event: 'close' | 'listening', cb: (this: Server) => void): this + once( + event: string | symbol, + listener: (this: Server, ...args: any[]) => void ): this - once(event: 'close' | 'listening', cb: (this: Server) => void): this - once(event: string | symbol, listener: (...args: any[]) => void): this off( event: 'connection', - cb: (this: Server, socket: WebSocket, request: IncomingMessage) => void + cb: (this: Server, socket: T, request: IncomingMessage) => void ): this - off(event: 'error', cb: (this: Server, error: Error) => void): this + off(event: 'error', cb: (this: Server, error: Error) => void): this off( event: 'headers', - cb: (this: Server, headers: string[], request: IncomingMessage) => void + cb: (this: Server, headers: string[], request: IncomingMessage) => void ): this - off(event: 'close' | 'listening', cb: (this: Server) => void): this + off(event: 'close' | 'listening', cb: (this: Server) => void): this off( event: string | symbol, - listener: (this: Server, ...args: any[]) => void + listener: (this: Server, ...args: any[]) => void ): this addListener( event: 'connection', - cb: (client: WebSocket, request: IncomingMessage) => void + cb: (client: T, request: IncomingMessage) => void ): this addListener(event: 'error', cb: (err: Error) => void): this addListener( @@ -499,7 +524,7 @@ declare namespace WebSocket { listener: (...args: any[]) => void ): this - removeListener(event: 'connection', cb: (client: WebSocket) => void): this + removeListener(event: 'connection', cb: (client: T) => void): this removeListener(event: 'error', cb: (err: Error) => void): this removeListener( event: 'headers', @@ -513,9 +538,9 @@ declare namespace WebSocket { } const WebSocketServer: typeof Server - type WebSocketServer = Server + interface WebSocketServer extends Server {} // tslint:disable-line no-empty-interface const WebSocket: typeof WebSocketAlias - type WebSocket = WebSocketAlias + interface WebSocket extends WebSocketAlias {} // tslint:disable-line no-empty-interface // WebSocket stream function createWebSocketStream( @@ -524,5 +549,5 @@ declare namespace WebSocket { ): Duplex } -//export = WebSocket; +// export = WebSocket export { WebSocket, WebSocketAlias } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 58c1ee050f7c26..a09304a6c8f50d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,86 +8,86 @@ importers: .: specifiers: - '@microsoft/api-extractor': ^7.19.4 + '@microsoft/api-extractor': ^7.19.5 '@types/fs-extra': ^9.0.13 - '@types/jest': ^27.4.0 - '@types/node': ^16.11.22 + '@types/jest': ^27.4.1 + '@types/node': ^16.11.26 '@types/prompts': ^2.0.14 '@types/semver': ^7.3.9 - '@typescript-eslint/eslint-plugin': ^5.11.0 - '@typescript-eslint/parser': ^5.11.0 + '@typescript-eslint/eslint-plugin': ^5.16.0 + '@typescript-eslint/parser': ^5.16.0 conventional-changelog-cli: ^2.2.2 cross-env: ^7.0.3 - esbuild: ^0.14.14 - eslint: ^8.8.0 - eslint-define-config: ^1.2.4 + esbuild: ^0.14.27 + eslint: ^8.12.0 + eslint-define-config: ^1.3.0 eslint-plugin-node: ^11.1.0 execa: ^5.1.1 - fs-extra: ^10.0.0 + fs-extra: ^10.0.1 jest: ^27.5.1 - lint-staged: ^12.3.3 - minimist: ^1.2.5 + lint-staged: ^12.3.7 + minimist: ^1.2.6 node-fetch: ^2.6.6 npm-run-all: ^4.1.5 picocolors: ^1.0.0 - playwright-chromium: ^1.18.1 - prettier: 2.5.1 + playwright-chromium: ^1.20.1 + prettier: 2.6.1 prompts: ^2.4.2 rimraf: ^3.0.2 rollup: ^2.59.0 semver: ^7.3.5 simple-git-hooks: ^2.7.0 sirv: ^2.0.2 - ts-jest: ^27.1.3 + ts-jest: ^27.1.4 ts-node: ^10.4.0 typescript: ~4.5.4 vite: workspace:* - vitepress: ^0.21.6 + vitepress: ^0.22.3 devDependencies: - '@microsoft/api-extractor': 7.19.4 + '@microsoft/api-extractor': 7.19.5 '@types/fs-extra': 9.0.13 - '@types/jest': 27.4.0 - '@types/node': 16.11.22 + '@types/jest': 27.4.1 + '@types/node': 16.11.26 '@types/prompts': 2.0.14 '@types/semver': 7.3.9 - '@typescript-eslint/eslint-plugin': 5.11.0_1659739a34b564cc1aa1228518173088 - '@typescript-eslint/parser': 5.11.0_eslint@8.8.0+typescript@4.5.4 + '@typescript-eslint/eslint-plugin': 5.16.0_e8f8f41828c0dd0ac8e32e1859a7f4f7 + '@typescript-eslint/parser': 5.16.0_eslint@8.12.0+typescript@4.5.4 conventional-changelog-cli: 2.2.2 cross-env: 7.0.3 - esbuild: 0.14.14 - eslint: 8.8.0 - eslint-define-config: 1.2.4 - eslint-plugin-node: 11.1.0_eslint@8.8.0 + esbuild: 0.14.27 + eslint: 8.12.0 + eslint-define-config: 1.3.0 + eslint-plugin-node: 11.1.0_eslint@8.12.0 execa: 5.1.1 - fs-extra: 10.0.0 + fs-extra: 10.0.1 jest: 27.5.1_ts-node@10.4.0 - lint-staged: 12.3.3 - minimist: 1.2.5 + lint-staged: 12.3.7 + minimist: 1.2.6 node-fetch: 2.6.6 npm-run-all: 4.1.5 picocolors: 1.0.0 - playwright-chromium: 1.18.1 - prettier: 2.5.1 + playwright-chromium: 1.20.1 + prettier: 2.6.1 prompts: 2.4.2 rimraf: 3.0.2 rollup: 2.62.0 semver: 7.3.5 simple-git-hooks: 2.7.0 sirv: 2.0.2 - ts-jest: 27.1.3_83f39b7ecbbd8f6012802ab3141c12c4 - ts-node: 10.4.0_afa64049ed426af4e84a055f796a9f2e + ts-jest: 27.1.4_4dfe14e0e8266437469ae0475a5c09ac + ts-node: 10.4.0_44ef5af6cbbc24239b4e70b5c7b0d7a6 typescript: 4.5.4 vite: link:packages/vite - vitepress: 0.21.6 + vitepress: 0.22.3 packages/create-vite: specifiers: kolorist: ^1.5.1 - minimist: ^1.2.5 + minimist: ^1.2.6 prompts: ^2.4.2 dependencies: kolorist: 1.5.1 - minimist: 1.2.5 + minimist: 1.2.6 prompts: 2.4.2 packages/playground: @@ -150,6 +150,20 @@ importers: packages/playground/css-codesplit-cjs: specifiers: {} + packages/playground/css-sourcemap: + specifiers: + convert-source-map: ^1.8.0 + less: ^4.1.2 + magic-string: ^0.25.7 + sass: ^1.43.4 + stylus: ^0.55.0 + devDependencies: + convert-source-map: 1.8.0 + less: 4.1.2 + magic-string: 0.25.7 + sass: 1.45.1 + stylus: 0.55.0 + packages/playground/css/css-dep: specifiers: {} @@ -299,6 +313,7 @@ importers: dep-linked: link:./dep-linked dep-linked-include: link:./dep-linked-include dep-not-js: file:./dep-not-js + dep-with-dynamic-import: file:./dep-with-dynamic-import lodash-es: ^4.17.21 nested-exclude: file:./nested-exclude phoenix: ^1.6.2 @@ -317,6 +332,7 @@ importers: dep-linked: link:dep-linked dep-linked-include: link:dep-linked-include dep-not-js: link:dep-not-js + dep-with-dynamic-import: link:dep-with-dynamic-import lodash-es: 4.17.21 nested-exclude: link:nested-exclude phoenix: 1.6.5 @@ -353,6 +369,9 @@ importers: packages/playground/optimize-deps/dep-not-js: specifiers: {} + packages/playground/optimize-deps/dep-with-dynamic-import: + specifiers: {} + packages/playground/optimize-deps/nested-exclude: specifiers: nested-include: link:./nested-include @@ -437,6 +456,7 @@ importers: '@babel/runtime': ^7.16.0 es5-ext: 0.10.53 normalize.css: ^8.0.1 + require-pkg-with-module-field: link:./require-pkg-with-module-field resolve-browser-field: link:./browser-field resolve-custom-condition: link:./custom-condition resolve-custom-main-field: link:./custom-main-field @@ -447,6 +467,7 @@ importers: '@babel/runtime': 7.16.5 es5-ext: 0.10.53 normalize.css: 8.0.1 + require-pkg-with-module-field: link:require-pkg-with-module-field resolve-browser-field: link:browser-field resolve-custom-condition: link:custom-condition resolve-custom-main-field: link:custom-main-field @@ -478,6 +499,12 @@ importers: packages/playground/resolve/inline-package: specifiers: {} + packages/playground/resolve/require-pkg-with-module-field: + specifiers: + bignumber.js: 9.0.2 + dependencies: + bignumber.js: 9.0.2 + packages/playground/ssr-deps: specifiers: bcrypt: ^5.0.1 @@ -681,6 +708,21 @@ importers: devDependencies: '@vitejs/plugin-vue': link:../../plugin-vue + packages/playground/vue-sourcemap: + specifiers: + '@vitejs/plugin-vue': workspace:* + convert-source-map: ^1.8.0 + less: ^4.1.2 + sass: ^1.43.4 + vue: ^3.2.31 + dependencies: + vue: 3.2.31 + devDependencies: + '@vitejs/plugin-vue': link:../../plugin-vue + convert-source-map: 1.8.0 + less: 4.1.2 + sass: 1.45.1 + packages/playground/wasm: specifiers: {} @@ -692,87 +734,87 @@ importers: packages/plugin-legacy: specifiers: - '@babel/standalone': ^7.17.2 - core-js: ^3.21.0 - magic-string: ^0.25.7 + '@babel/standalone': ^7.17.8 + core-js: ^3.21.1 + magic-string: ^0.26.1 regenerator-runtime: ^0.13.9 systemjs: ^6.12.1 dependencies: - '@babel/standalone': 7.17.2 - core-js: 3.21.0 - magic-string: 0.25.7 + '@babel/standalone': 7.17.8 + core-js: 3.21.1 + magic-string: 0.26.1 regenerator-runtime: 0.13.9 systemjs: 6.12.1 packages/plugin-react: specifiers: - '@babel/core': ^7.17.2 - '@babel/plugin-transform-react-jsx': ^7.16.7 + '@babel/core': ^7.17.8 + '@babel/plugin-transform-react-jsx': ^7.17.3 '@babel/plugin-transform-react-jsx-development': ^7.16.7 '@babel/plugin-transform-react-jsx-self': ^7.16.7 '@babel/plugin-transform-react-jsx-source': ^7.16.7 - '@rollup/pluginutils': ^4.1.2 + '@rollup/pluginutils': ^4.2.0 react-refresh: ^0.11.0 resolve: ^1.22.0 dependencies: - '@babel/core': 7.17.2 - '@babel/plugin-transform-react-jsx': 7.16.7_@babel+core@7.17.2 - '@babel/plugin-transform-react-jsx-development': 7.16.7_@babel+core@7.17.2 - '@babel/plugin-transform-react-jsx-self': 7.16.7_@babel+core@7.17.2 - '@babel/plugin-transform-react-jsx-source': 7.16.7_@babel+core@7.17.2 - '@rollup/pluginutils': 4.1.2 + '@babel/core': 7.17.8 + '@babel/plugin-transform-react-jsx': 7.17.3_@babel+core@7.17.8 + '@babel/plugin-transform-react-jsx-development': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-transform-react-jsx-self': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-transform-react-jsx-source': 7.16.7_@babel+core@7.17.8 + '@rollup/pluginutils': 4.2.0 react-refresh: 0.11.0 resolve: 1.22.0 packages/plugin-vue: specifiers: - '@rollup/pluginutils': ^4.1.2 + '@rollup/pluginutils': ^4.2.0 '@types/hash-sum': ^1.0.0 - debug: ^4.3.3 + debug: ^4.3.4 hash-sum: ^2.0.0 rollup: ^2.59.0 slash: ^4.0.0 source-map: ^0.6.1 - vue: ^3.2.30 + vue: ^3.2.31 devDependencies: - '@rollup/pluginutils': 4.1.2 + '@rollup/pluginutils': 4.2.0 '@types/hash-sum': 1.0.0 - debug: 4.3.3 + debug: 4.3.4 hash-sum: 2.0.0 rollup: 2.62.0 slash: 4.0.0 source-map: 0.6.1 - vue: 3.2.30 + vue: 3.2.31 packages/plugin-vue-jsx: specifiers: - '@babel/core': ^7.17.2 + '@babel/core': ^7.17.8 '@babel/plugin-syntax-import-meta': ^7.10.4 '@babel/plugin-transform-typescript': ^7.16.8 - '@rollup/pluginutils': ^4.1.2 + '@rollup/pluginutils': ^4.2.0 '@vue/babel-plugin-jsx': ^1.1.1 hash-sum: ^2.0.0 dependencies: - '@babel/core': 7.17.2 - '@babel/plugin-syntax-import-meta': 7.10.4_@babel+core@7.17.2 - '@babel/plugin-transform-typescript': 7.16.8_@babel+core@7.17.2 - '@rollup/pluginutils': 4.1.2 - '@vue/babel-plugin-jsx': 1.1.1_@babel+core@7.17.2 + '@babel/core': 7.17.8 + '@babel/plugin-syntax-import-meta': 7.10.4_@babel+core@7.17.8 + '@babel/plugin-transform-typescript': 7.16.8_@babel+core@7.17.8 + '@rollup/pluginutils': 4.2.0 + '@vue/babel-plugin-jsx': 1.1.1_@babel+core@7.17.8 hash-sum: 2.0.0 packages/vite: specifiers: - '@ampproject/remapping': ^2.1.0 - '@babel/parser': ^7.17.0 + '@ampproject/remapping': ^2.1.2 + '@babel/parser': ^7.17.8 '@babel/types': ^7.17.0 - '@jridgewell/trace-mapping': ^0.3.2 + '@jridgewell/trace-mapping': ^0.3.4 '@rollup/plugin-alias': ^3.1.9 - '@rollup/plugin-commonjs': ^21.0.1 + '@rollup/plugin-commonjs': ^21.0.3 '@rollup/plugin-dynamic-import-vars': ^1.4.2 '@rollup/plugin-json': ^4.1.0 '@rollup/plugin-node-resolve': 13.1.3 - '@rollup/plugin-typescript': ^8.3.0 - '@rollup/pluginutils': ^4.1.2 + '@rollup/plugin-typescript': ^8.3.1 + '@rollup/pluginutils': ^4.2.0 '@types/convert-source-map': ^1.5.2 '@types/cross-spawn': ^6.0.2 '@types/debug': ^4.1.7 @@ -781,12 +823,12 @@ importers: '@types/less': ^3.0.3 '@types/micromatch': ^4.0.2 '@types/mime': ^2.0.3 - '@types/node': ^16.11.22 + '@types/node': ^16.11.26 '@types/resolve': ^1.20.1 '@types/sass': ~1.43.1 '@types/stylus': ^0.48.36 - '@types/ws': ^8.2.2 - '@vue/compiler-dom': ^3.2.30 + '@types/ws': ^8.5.3 + '@vue/compiler-dom': ^3.2.31 acorn: ^8.7.0 cac: 6.7.9 chokidar: ^3.5.3 @@ -795,61 +837,62 @@ importers: convert-source-map: ^1.8.0 cors: ^2.8.5 cross-spawn: ^7.0.3 - debug: ^4.3.3 + debug: ^4.3.4 dotenv: ^14.3.2 dotenv-expand: ^5.1.0 - es-module-lexer: ^0.9.3 - esbuild: ^0.14.14 + es-module-lexer: ^0.10.4 + esbuild: ^0.14.27 estree-walker: ^2.0.2 etag: ^1.8.1 fast-glob: ^3.2.11 fsevents: ~2.3.2 http-proxy: ^1.18.1 - json5: ^2.2.0 + json5: ^2.2.1 launch-editor-middleware: ^2.3.0 - magic-string: ^0.25.7 - micromatch: ^4.0.4 + magic-string: ^0.26.1 + micromatch: ^4.0.5 mrmime: ^1.0.0 - node-forge: ^1.2.1 + node-forge: ^1.3.0 okie: ^1.0.1 open: ^8.4.0 periscopic: ^2.0.3 picocolors: ^1.0.0 - postcss: ^8.4.6 - postcss-import: ^14.0.2 + postcss: ^8.4.12 + postcss-import: ^14.1.0 postcss-load-config: ^3.1.3 - postcss-modules: ^4.3.0 + postcss-modules: ^4.3.1 resolve: ^1.22.0 resolve.exports: ^1.1.0 rollup: ^2.59.0 rollup-plugin-license: ^2.6.1 sirv: ^2.0.2 + source-map-js: ^1.0.2 source-map-support: ^0.5.21 strip-ansi: ^6.0.1 - terser: ^5.10.0 - tsconfck: ^1.2.0 + terser: ^5.12.1 + tsconfck: ^1.2.1 tslib: ^2.3.1 types: link:./types ws: ^8.5.0 dependencies: - esbuild: 0.14.14 - postcss: 8.4.6 + esbuild: 0.14.27 + postcss: 8.4.12 resolve: 1.22.0 rollup: 2.62.0 optionalDependencies: fsevents: 2.3.2 devDependencies: - '@ampproject/remapping': 2.1.0 - '@babel/parser': 7.17.0 + '@ampproject/remapping': 2.1.2 + '@babel/parser': 7.17.8 '@babel/types': 7.17.0 - '@jridgewell/trace-mapping': 0.3.2 + '@jridgewell/trace-mapping': 0.3.4 '@rollup/plugin-alias': 3.1.9_rollup@2.62.0 - '@rollup/plugin-commonjs': 21.0.1_rollup@2.62.0 + '@rollup/plugin-commonjs': 21.0.3_rollup@2.62.0 '@rollup/plugin-dynamic-import-vars': 1.4.2_rollup@2.62.0 '@rollup/plugin-json': 4.1.0_rollup@2.62.0 '@rollup/plugin-node-resolve': 13.1.3_rollup@2.62.0 - '@rollup/plugin-typescript': 8.3.0_7c5ff569c0887b4f0035eb7cb6988163 - '@rollup/pluginutils': 4.1.2 + '@rollup/plugin-typescript': 8.3.1_7c5ff569c0887b4f0035eb7cb6988163 + '@rollup/pluginutils': 4.2.0 '@types/convert-source-map': 1.5.2 '@types/cross-spawn': 6.0.2 '@types/debug': 4.1.7 @@ -858,12 +901,12 @@ importers: '@types/less': 3.0.3 '@types/micromatch': 4.0.2 '@types/mime': 2.0.3 - '@types/node': 16.11.22 + '@types/node': 16.11.26 '@types/resolve': 1.20.1 '@types/sass': 1.43.1 '@types/stylus': 0.48.36 - '@types/ws': 8.2.2 - '@vue/compiler-dom': 3.2.30 + '@types/ws': 8.5.3 + '@vue/compiler-dom': 3.2.31 acorn: 8.7.0 cac: 6.7.9 chokidar: 3.5.3 @@ -872,34 +915,35 @@ importers: convert-source-map: 1.8.0 cors: 2.8.5 cross-spawn: 7.0.3 - debug: 4.3.3 + debug: 4.3.4 dotenv: 14.3.2 dotenv-expand: 5.1.0 - es-module-lexer: 0.9.3 + es-module-lexer: 0.10.4 estree-walker: 2.0.2 etag: 1.8.1 fast-glob: 3.2.11 - http-proxy: 1.18.1_debug@4.3.3 - json5: 2.2.0 + http-proxy: 1.18.1_debug@4.3.4 + json5: 2.2.1 launch-editor-middleware: 2.3.0 - magic-string: 0.25.7 - micromatch: 4.0.4 + magic-string: 0.26.1 + micromatch: 4.0.5 mrmime: 1.0.0 - node-forge: 1.2.1 + node-forge: 1.3.0 okie: 1.0.1 open: 8.4.0 periscopic: 2.0.3 picocolors: 1.0.0 - postcss-import: 14.0.2_postcss@8.4.6 + postcss-import: 14.1.0_postcss@8.4.12 postcss-load-config: 3.1.3_ts-node@10.4.0 - postcss-modules: 4.3.0_postcss@8.4.6 + postcss-modules: 4.3.1_postcss@8.4.12 resolve.exports: 1.1.0 rollup-plugin-license: 2.6.1_rollup@2.62.0 sirv: 2.0.2 + source-map-js: 1.0.2 source-map-support: 0.5.21 strip-ansi: 6.0.1 - terser: 5.10.0_acorn@8.7.0 - tsconfck: 1.2.0_typescript@4.5.4 + terser: 5.12.1 + tsconfck: 1.2.1_typescript@4.5.4 tslib: 2.3.1 types: link:types ws: 8.5.0 @@ -1020,7 +1064,14 @@ packages: resolution: {integrity: sha512-d5RysTlJ7hmw5Tw4UxgxcY3lkMe92n8sXCcuLPAyIAHK6j8DefDwtGnVVDgOnv+RnEosulDJ9NPKQL27bDId0g==} engines: {node: '>=6.0.0'} dependencies: - '@jridgewell/trace-mapping': 0.3.2 + '@jridgewell/trace-mapping': 0.3.4 + dev: true + + /@ampproject/remapping/2.1.2: + resolution: {integrity: sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/trace-mapping': 0.3.4 /@babel/code-frame/7.16.0: resolution: {integrity: sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA==} @@ -1037,6 +1088,12 @@ packages: /@babel/compat-data/7.16.4: resolution: {integrity: sha512-1o/jo7D+kC9ZjHX5v+EHrdjl3PhxMrLSOTGsOdHJ+KL8HCaEK6ehrVL2RS6oHDZp+L7xLirLrPmQtEng769J/Q==} engines: {node: '>=6.9.0'} + dev: true + + /@babel/compat-data/7.17.7: + resolution: {integrity: sha512-p8pdE6j0a29TNGebNm7NzYZWB3xVZJBZ7XGs42uAKzQo8VQ3F0By/cQCtUEABwIqw5zo6WA4NbmxsfzADzMKnQ==} + engines: {node: '>=6.9.0'} + dev: false /@babel/core/7.17.2: resolution: {integrity: sha512-R3VH5G42VSDolRHyUO4V2cfag8WHcZyxdq5Z/m8Xyb92lW/Erm/6kM+XtRFGf3Mulre3mveni2NHfEUws8wSvw==} @@ -1053,12 +1110,36 @@ packages: '@babel/traverse': 7.17.0 '@babel/types': 7.17.0 convert-source-map: 1.8.0 + debug: 4.3.4 + gensync: 1.0.0-beta.2 + json5: 2.2.1 + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/core/7.17.8: + resolution: {integrity: sha512-OdQDV/7cRBtJHLSOBqqbYNkOcydOgnX59TZx4puf41fzcVtN3e/4yqY8lMQsK+5X2lJtAdmA+6OHqsj1hBJ4IQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@ampproject/remapping': 2.1.2 + '@babel/code-frame': 7.16.7 + '@babel/generator': 7.17.7 + '@babel/helper-compilation-targets': 7.17.7_@babel+core@7.17.8 + '@babel/helper-module-transforms': 7.17.7 + '@babel/helpers': 7.17.8 + '@babel/parser': 7.17.8 + '@babel/template': 7.16.7 + '@babel/traverse': 7.17.3 + '@babel/types': 7.17.0 + convert-source-map: 1.8.0 debug: 4.3.3 gensync: 1.0.0-beta.2 json5: 2.2.0 semver: 6.3.0 transitivePeerDependencies: - supports-color + dev: false /@babel/generator/7.16.5: resolution: {integrity: sha512-kIvCdjZqcdKqoDbVVdt5R99icaRtrtYhYK/xux5qiWCBmfdvEYMFZ68QCrpE5cbFM1JsuArUNs1ZkuKtTtUcZA==} @@ -1085,6 +1166,16 @@ packages: '@babel/types': 7.17.0 jsesc: 2.5.2 source-map: 0.5.7 + dev: true + + /@babel/generator/7.17.7: + resolution: {integrity: sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.17.0 + jsesc: 2.5.2 + source-map: 0.5.7 + dev: false /@babel/helper-annotate-as-pure/7.16.7: resolution: {integrity: sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==} @@ -1104,14 +1195,28 @@ packages: '@babel/helper-validator-option': 7.16.7 browserslist: 4.19.1 semver: 6.3.0 + dev: true - /@babel/helper-create-class-features-plugin/7.16.10_@babel+core@7.17.2: + /@babel/helper-compilation-targets/7.17.7_@babel+core@7.17.8: + resolution: {integrity: sha512-UFzlz2jjd8kroj0hmCFV5zr+tQPi1dpC2cRsDV/3IEW8bJfCPrPpmcSN6ZS8RqIq4LXcmpipCQFPddyFA5Yc7w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/compat-data': 7.17.7 + '@babel/core': 7.17.8 + '@babel/helper-validator-option': 7.16.7 + browserslist: 4.19.1 + semver: 6.3.0 + dev: false + + /@babel/helper-create-class-features-plugin/7.16.10_@babel+core@7.17.8: resolution: {integrity: sha512-wDeej0pu3WN/ffTxMNCPW5UCiOav8IcLRxSIyp/9+IF2xJUM9h/OYjg0IJLHaL6F8oU8kqMz9nc1vryXhMsgXg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.17.2 + '@babel/core': 7.17.8 '@babel/helper-annotate-as-pure': 7.16.7 '@babel/helper-environment-visitor': 7.16.7 '@babel/helper-function-name': 7.16.7 @@ -1173,7 +1278,7 @@ packages: resolution: {integrity: sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.16.8 + '@babel/types': 7.17.0 /@babel/helper-module-transforms/7.16.7: resolution: {integrity: sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng==} @@ -1189,6 +1294,23 @@ packages: '@babel/types': 7.17.0 transitivePeerDependencies: - supports-color + dev: true + + /@babel/helper-module-transforms/7.17.7: + resolution: {integrity: sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-environment-visitor': 7.16.7 + '@babel/helper-module-imports': 7.16.7 + '@babel/helper-simple-access': 7.17.7 + '@babel/helper-split-export-declaration': 7.16.7 + '@babel/helper-validator-identifier': 7.16.7 + '@babel/template': 7.16.7 + '@babel/traverse': 7.17.3 + '@babel/types': 7.17.0 + transitivePeerDependencies: + - supports-color + dev: false /@babel/helper-optimise-call-expression/7.16.7: resolution: {integrity: sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==} @@ -1223,6 +1345,14 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.17.0 + dev: true + + /@babel/helper-simple-access/7.17.7: + resolution: {integrity: sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.17.0 + dev: false /@babel/helper-split-export-declaration/7.16.7: resolution: {integrity: sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==} @@ -1251,6 +1381,18 @@ packages: '@babel/types': 7.17.0 transitivePeerDependencies: - supports-color + dev: true + + /@babel/helpers/7.17.8: + resolution: {integrity: sha512-QcL86FGxpfSJwGtAvv4iG93UL6bmqBdmoVY0CMCU2g+oD2ezQse3PT5Pa+jiD6LJndBQi0EDlpzOWNlLuhz5gw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.16.7 + '@babel/traverse': 7.17.3 + '@babel/types': 7.17.0 + transitivePeerDependencies: + - supports-color + dev: false /@babel/highlight/7.16.0: resolution: {integrity: sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g==} @@ -1283,6 +1425,12 @@ packages: resolution: {integrity: sha512-VKXSCQx5D8S04ej+Dqsr1CzYvvWgf20jIw2D+YhQCrIlr2UZGaDds23Y0xg75/skOxpLCRpUZvk/1EAVkGoDOw==} engines: {node: '>=6.0.0'} hasBin: true + dev: true + + /@babel/parser/7.17.8: + resolution: {integrity: sha512-BoHhDJrJXqcg+ZL16Xv39H9n+AqJ4pcDrQBGZN+wHxIysrLZ3/ECwCBUch/1zUNhnsXULcONU3Ei5Hmkfk6kiQ==} + engines: {node: '>=6.0.0'} + hasBin: true /@babel/plugin-proposal-pipeline-operator/7.16.5: resolution: {integrity: sha512-aMw3gPJYa2F6mVnL6QuHr9NtAScspBPTVXU2kaup7FVl02Hr4tY2diaGNdismAOmiroWa/2ENy4EFyoz81ACLg==} @@ -1328,6 +1476,16 @@ packages: dependencies: '@babel/core': 7.17.2 '@babel/helper-plugin-utils': 7.16.5 + dev: true + + /@babel/plugin-syntax-import-meta/7.10.4_@babel+core@7.17.8: + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.17.8 + '@babel/helper-plugin-utils': 7.16.5 + dev: false /@babel/plugin-syntax-json-strings/7.8.3_@babel+core@7.17.2: resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} @@ -1347,23 +1505,23 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-jsx/7.16.5_@babel+core@7.17.2: + /@babel/plugin-syntax-jsx/7.16.5_@babel+core@7.17.8: resolution: {integrity: sha512-42OGssv9NPk4QHKVgIHlzeLgPOW5rGgfV5jzG90AhcXXIv6hu/eqj63w4VgvRxdvZY3AlYeDgPiSJ3BqAd1Y6Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.2 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: false - /@babel/plugin-syntax-jsx/7.16.7_@babel+core@7.17.2: + /@babel/plugin-syntax-jsx/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.2 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: false @@ -1448,61 +1606,72 @@ packages: dependencies: '@babel/core': 7.17.2 '@babel/helper-plugin-utils': 7.16.7 + dev: true - /@babel/plugin-transform-react-jsx-development/7.16.7_@babel+core@7.17.2: + /@babel/plugin-syntax-typescript/7.16.7_@babel+core@7.17.8: + resolution: {integrity: sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.17.8 + '@babel/helper-plugin-utils': 7.16.7 + dev: false + + /@babel/plugin-transform-react-jsx-development/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-RMvQWvpla+xy6MlBpPlrKZCMRs2AGiHOGHY3xRwl0pEeim348dDyxeH4xBsMPbIMhujeq7ihE702eM2Ew0Wo+A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.2 - '@babel/plugin-transform-react-jsx': 7.16.7_@babel+core@7.17.2 + '@babel/core': 7.17.8 + '@babel/plugin-transform-react-jsx': 7.17.3_@babel+core@7.17.8 dev: false - /@babel/plugin-transform-react-jsx-self/7.16.7_@babel+core@7.17.2: + /@babel/plugin-transform-react-jsx-self/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-oe5VuWs7J9ilH3BCCApGoYjHoSO48vkjX2CbA5bFVhIuO2HKxA3vyF7rleA4o6/4rTDbk6r8hBW7Ul8E+UZrpA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.2 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: false - /@babel/plugin-transform-react-jsx-source/7.16.7_@babel+core@7.17.2: + /@babel/plugin-transform-react-jsx-source/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-rONFiQz9vgbsnaMtQlZCjIRwhJvlrPET8TabIUK2hzlXw9B9s2Ieaxte1SCOOXMbWRHodbKixNf3BLcWVOQ8Bw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.2 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: false - /@babel/plugin-transform-react-jsx/7.16.7_@babel+core@7.17.2: - resolution: {integrity: sha512-8D16ye66fxiE8m890w0BpPpngG9o9OVBBy0gH2E+2AR7qMR2ZpTYJEqLxAsoroenMId0p/wMW+Blc0meDgu0Ag==} + /@babel/plugin-transform-react-jsx/7.17.3_@babel+core@7.17.8: + resolution: {integrity: sha512-9tjBm4O07f7mzKSIlEmPdiE6ub7kfIe6Cd+w+oQebpATfTQMAgW+YOuWxogbKVTulA+MEO7byMeIUtQ1z+z+ZQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.2 + '@babel/core': 7.17.8 '@babel/helper-annotate-as-pure': 7.16.7 '@babel/helper-module-imports': 7.16.7 '@babel/helper-plugin-utils': 7.16.7 - '@babel/plugin-syntax-jsx': 7.16.7_@babel+core@7.17.2 - '@babel/types': 7.16.8 + '@babel/plugin-syntax-jsx': 7.16.7_@babel+core@7.17.8 + '@babel/types': 7.17.0 dev: false - /@babel/plugin-transform-typescript/7.16.8_@babel+core@7.17.2: + /@babel/plugin-transform-typescript/7.16.8_@babel+core@7.17.8: resolution: {integrity: sha512-bHdQ9k7YpBDO2d0NVfkj51DpQcvwIzIusJ7mEUaMlbZq3Kt/U47j24inXZHQ5MDiYpCs+oZiwnXyKedE8+q7AQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.2 - '@babel/helper-create-class-features-plugin': 7.16.10_@babel+core@7.17.2 + '@babel/core': 7.17.8 + '@babel/helper-create-class-features-plugin': 7.16.10_@babel+core@7.17.8 '@babel/helper-plugin-utils': 7.16.7 - '@babel/plugin-syntax-typescript': 7.16.7_@babel+core@7.17.2 + '@babel/plugin-syntax-typescript': 7.16.7_@babel+core@7.17.8 transitivePeerDependencies: - supports-color dev: false @@ -1513,8 +1682,8 @@ packages: dependencies: regenerator-runtime: 0.13.9 - /@babel/standalone/7.17.2: - resolution: {integrity: sha512-Adjbjnlk0IBuBEldyuicdIeq1P/YI5nfm7HnOVd8blGDRetPW2NllESjlrItMKORWVuILWqKe10D+b8yEybeBA==} + /@babel/standalone/7.17.8: + resolution: {integrity: sha512-tr3SDpVnxR/fzrxyG+HZPAyEA9eTHZIAjy4eqrc7m+KBwsdo1YvTbUfJ6teWHQ177mk6GmdmltsIiOYCcvRPWA==} engines: {node: '>=6.9.0'} dev: false @@ -1532,7 +1701,7 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/code-frame': 7.16.7 - '@babel/parser': 7.17.0 + '@babel/parser': 7.17.8 '@babel/types': 7.17.0 /@babel/traverse/7.16.10: @@ -1583,10 +1752,29 @@ packages: '@babel/helper-split-export-declaration': 7.16.7 '@babel/parser': 7.17.0 '@babel/types': 7.17.0 + debug: 4.3.4 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/traverse/7.17.3: + resolution: {integrity: sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.16.7 + '@babel/generator': 7.17.7 + '@babel/helper-environment-visitor': 7.16.7 + '@babel/helper-function-name': 7.16.7 + '@babel/helper-hoist-variables': 7.16.7 + '@babel/helper-split-export-declaration': 7.16.7 + '@babel/parser': 7.17.8 + '@babel/types': 7.17.0 debug: 4.3.3 globals: 11.12.0 transitivePeerDependencies: - supports-color + dev: false /@babel/types/7.16.0: resolution: {integrity: sha512-PJgg/k3SdLsGb3hhisFvtLOw5ts113klrpLuIPtCJIU+BB24fqq6lf8RWqKJEjzqXR9AEH1rIb5XTqwBHB+kQg==} @@ -1740,15 +1928,15 @@ packages: resolution: {integrity: sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==} dev: false - /@eslint/eslintrc/1.0.5: - resolution: {integrity: sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ==} + /@eslint/eslintrc/1.2.1: + resolution: {integrity: sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: ajv: 6.12.6 - debug: 4.3.3 - espree: 9.3.0 + debug: 4.3.4 + espree: 9.3.1 globals: 13.12.0 - ignore: 4.0.6 + ignore: 5.2.0 import-fresh: 3.3.0 js-yaml: 4.1.0 minimatch: 3.0.4 @@ -1762,7 +1950,7 @@ packages: engines: {node: '>=10.10.0'} dependencies: '@humanwhocodes/object-schema': 1.2.1 - debug: 4.3.3 + debug: 4.3.4 minimatch: 3.0.4 transitivePeerDependencies: - supports-color @@ -1802,7 +1990,7 @@ packages: engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: '@jest/types': 27.5.1 - '@types/node': 16.11.22 + '@types/node': 16.11.26 chalk: 4.1.2 jest-message-util: 27.5.1 jest-util: 27.5.1 @@ -1823,7 +2011,7 @@ packages: '@jest/test-result': 27.5.1 '@jest/transform': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 16.11.22 + '@types/node': 16.11.26 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.8.1 @@ -1860,7 +2048,7 @@ packages: dependencies: '@jest/fake-timers': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 16.11.22 + '@types/node': 16.11.26 jest-mock: 27.5.1 dev: true @@ -1870,7 +2058,7 @@ packages: dependencies: '@jest/types': 27.5.1 '@sinonjs/fake-timers': 8.1.0 - '@types/node': 16.11.22 + '@types/node': 16.11.26 jest-message-util: 27.5.1 jest-mock: 27.5.1 jest-util: 27.5.1 @@ -1899,7 +2087,7 @@ packages: '@jest/test-result': 27.5.1 '@jest/transform': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 16.11.22 + '@types/node': 16.11.26 chalk: 4.1.2 collect-v8-coverage: 1.0.1 exit: 0.1.2 @@ -1977,39 +2165,28 @@ packages: - supports-color dev: true - /@jest/types/27.4.2: - resolution: {integrity: sha512-j35yw0PMTPpZsUoOBiuHzr1zTYoad1cVIE0ajEjcrJONxxrko/IRGKkXx3os0Nsi4Hu3+5VmDbVfq5WhG/pWAg==} - engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - dependencies: - '@types/istanbul-lib-coverage': 2.0.4 - '@types/istanbul-reports': 3.0.1 - '@types/node': 16.11.22 - '@types/yargs': 16.0.4 - chalk: 4.1.2 - dev: true - /@jest/types/27.5.1: resolution: {integrity: sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: '@types/istanbul-lib-coverage': 2.0.4 '@types/istanbul-reports': 3.0.1 - '@types/node': 16.11.22 + '@types/node': 16.11.26 '@types/yargs': 16.0.4 chalk: 4.1.2 dev: true - /@jridgewell/resolve-uri/3.0.3: - resolution: {integrity: sha512-fuIOnc81C5iRNevb/XPiM8Khp9bVjreydRQ37rt0C/dY0PAW1DRvEM3WrKX/5rStS5lbgwS0FCgqSndh9tvK5w==} - engines: {node: '>=10.0.0'} + /@jridgewell/resolve-uri/3.0.5: + resolution: {integrity: sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==} + engines: {node: '>=6.0.0'} /@jridgewell/sourcemap-codec/1.4.10: resolution: {integrity: sha512-Ht8wIW5v165atIX1p+JvKR5ONzUyF4Ac8DZIQ5kZs9zrb6M8SJNXpx1zn04rn65VjBMygRoMXcyYwNK0fT7bEg==} - /@jridgewell/trace-mapping/0.3.2: - resolution: {integrity: sha512-9KzzH4kMjA2XmBRHfqG2/Vtl7s92l6uNDd0wW7frDE+EUvQFGqNXhWp0UGJjSkt3v2AYjzOZn1QO9XaTNJIt1Q==} + /@jridgewell/trace-mapping/0.3.4: + resolution: {integrity: sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ==} dependencies: - '@jridgewell/resolve-uri': 3.0.3 + '@jridgewell/resolve-uri': 3.0.5 '@jridgewell/sourcemap-codec': 1.4.10 /@mapbox/node-pre-gyp/1.0.8: @@ -2029,24 +2206,24 @@ packages: - supports-color dev: false - /@microsoft/api-extractor-model/7.15.3: - resolution: {integrity: sha512-NkSjolmSI7NGvbdz0Y7kjQfdpD+j9E5CwXTxEyjDqxd10MI7GXV8DnAsQ57GFJcgHKgTjf2aUnYfMJ9w3aMicw==} + /@microsoft/api-extractor-model/7.15.4: + resolution: {integrity: sha512-9bIXQKKQr5jAH1c9atXrukr4ua30fhqxMwWIOOjEnexPBPu3nhy9lC4/GpE0kPUp1Al3wSXgFnOEGzEH+HFz+w==} dependencies: '@microsoft/tsdoc': 0.13.2 '@microsoft/tsdoc-config': 0.15.2 - '@rushstack/node-core-library': 3.45.0 + '@rushstack/node-core-library': 3.45.1 dev: true - /@microsoft/api-extractor/7.19.4: - resolution: {integrity: sha512-iehC6YA3DGJvxTUaK7HUtQmP6hAQU07+Q/OR8TG4dVR6KpqCi9UPEVk8AgCvQkiK+6FbVEFQTx0qLuYk4EeuHg==} + /@microsoft/api-extractor/7.19.5: + resolution: {integrity: sha512-ra5r8P7PocOpemrZRccI3Tf1+wukI0gT6ncRB448QSxSYlmqKuvez95YUSYPwHIN/ztKL0cn5PfMOauU1lZfGQ==} hasBin: true dependencies: - '@microsoft/api-extractor-model': 7.15.3 + '@microsoft/api-extractor-model': 7.15.4 '@microsoft/tsdoc': 0.13.2 '@microsoft/tsdoc-config': 0.15.2 - '@rushstack/node-core-library': 3.45.0 - '@rushstack/rig-package': 0.3.7 - '@rushstack/ts-command-line': 4.10.6 + '@rushstack/node-core-library': 3.45.1 + '@rushstack/rig-package': 0.3.8 + '@rushstack/ts-command-line': 4.10.7 colors: 1.2.5 lodash: 4.17.21 resolve: 1.17.0 @@ -2137,8 +2314,8 @@ packages: slash: 3.0.0 dev: true - /@rollup/plugin-commonjs/21.0.1_rollup@2.62.0: - resolution: {integrity: sha512-EA+g22lbNJ8p5kuZJUYyhhDK7WgJckW5g4pNN7n4mAFUM96VuwUnNT3xr2Db2iCZPI1pJPbGyfT5mS9T1dHfMg==} + /@rollup/plugin-commonjs/21.0.3_rollup@2.62.0: + resolution: {integrity: sha512-ThGfwyvcLc6cfP/MWxA5ACF+LZCvsuhUq7V5134Az1oQWsiC7lNpLT4mJI86WQunK7BYmpUiHmMk2Op6OAHs0g==} engines: {node: '>= 8.0.0'} peerDependencies: rollup: ^2.38.3 @@ -2159,7 +2336,7 @@ packages: peerDependencies: rollup: ^1.20.0||^2.0.0 dependencies: - '@rollup/pluginutils': 4.1.2 + '@rollup/pluginutils': 4.2.0 estree-walker: 2.0.2 fast-glob: 3.2.11 magic-string: 0.25.7 @@ -2190,8 +2367,8 @@ packages: rollup: 2.62.0 dev: true - /@rollup/plugin-typescript/8.3.0_7c5ff569c0887b4f0035eb7cb6988163: - resolution: {integrity: sha512-I5FpSvLbtAdwJ+naznv+B4sjXZUcIvLLceYpITAn7wAP8W0wqc5noLdGIp9HGVntNhRWXctwPYrSSFQxtl0FPA==} + /@rollup/plugin-typescript/8.3.1_7c5ff569c0887b4f0035eb7cb6988163: + resolution: {integrity: sha512-84rExe3ICUBXzqNX48WZV2Jp3OddjTMX97O2Py6D1KJaGSwWp0mDHXj+bCGNJqWHIEKDIT2U0sDjhP4czKi6cA==} engines: {node: '>=8.0.0'} peerDependencies: rollup: ^2.14.0 @@ -2217,15 +2394,15 @@ packages: rollup: 2.62.0 dev: true - /@rollup/pluginutils/4.1.2: - resolution: {integrity: sha512-ROn4qvkxP9SyPeHaf7uQC/GPFY6L/OWy9+bd9AwcjOAWQwxRscoEyAUD8qCY5o5iL4jqQwoLk2kaTKJPb/HwzQ==} + /@rollup/pluginutils/4.2.0: + resolution: {integrity: sha512-2WUyJNRkyH5p487pGnn4tWAsxhEFKN/pT8CMgHshd5H+IXkOnKvKZwsz5ZWz+YCXkleZRAU5kwbfgF8CPfDRqA==} engines: {node: '>= 8.0.0'} dependencies: estree-walker: 2.0.2 picomatch: 2.3.0 - /@rushstack/node-core-library/3.45.0: - resolution: {integrity: sha512-YMuIJl19vQT1+g/OU9mLY6T5ZBT9uDlmeXExDQACpGuxTJW+LHNbk/lRX+eCApQI2eLBlaL4U68r3kZlqwbdmw==} + /@rushstack/node-core-library/3.45.1: + resolution: {integrity: sha512-BwdssTNe007DNjDBxJgInHg8ePytIPyT0La7ZZSQZF9+rSkT42AygXPGvbGsyFfEntjr4X37zZSJI7yGzL16cQ==} dependencies: '@types/node': 12.20.24 colors: 1.2.5 @@ -2238,15 +2415,15 @@ packages: z-schema: 5.0.2 dev: true - /@rushstack/rig-package/0.3.7: - resolution: {integrity: sha512-pzMsTSeTC8IiZ6EJLr53gGMvhT4oLWH+hxD7907cHyWuIUlEXFtu/2pK25vUQT13nKp5DJCWxXyYoGRk/h6rtA==} + /@rushstack/rig-package/0.3.8: + resolution: {integrity: sha512-MDWg1xovea99PWloSiYMjFcCLsrdjFtYt6aOyHNs5ojn5mxrzR6U9F83hvbQjTWnKPMvZtr0vcek+4n+OQOp3Q==} dependencies: resolve: 1.17.0 strip-json-comments: 3.1.1 dev: true - /@rushstack/ts-command-line/4.10.6: - resolution: {integrity: sha512-Y3GkUag39sTIlukDg9mUp8MCHrrlJ27POrBNRQGc/uF+VVgX8M7zMzHch5zP6O1QVquWgD7Engdpn2piPYaS/g==} + /@rushstack/ts-command-line/4.10.7: + resolution: {integrity: sha512-CjS+DfNXUSO5Ab2wD1GBGtUTnB02OglRWGqfaTcac9Jn45V5MeUOsq/wA8wEeS5Y/3TZ2P1k+IWdVDiuOFP9Og==} dependencies: '@types/argparse': 1.0.38 argparse: 1.0.10 @@ -2335,7 +2512,7 @@ packages: /@types/cross-spawn/6.0.2: resolution: {integrity: sha512-KuwNhp3eza+Rhu8IFI5HUXRP0LIhqH5cAjubUvGXXthh4YYBuP2ntwEX+Cz8GJoZUHlKo247wPWOfA9LYEq4cw==} dependencies: - '@types/node': 16.11.22 + '@types/node': 16.11.26 dev: true /@types/debug/4.1.7: @@ -2355,19 +2532,19 @@ packages: /@types/etag/1.8.1: resolution: {integrity: sha512-bsKkeSqN7HYyYntFRAmzcwx/dKW4Wa+KVMTInANlI72PWLQmOpZu96j0OqHZGArW4VQwCmJPteQlXaUDeOB0WQ==} dependencies: - '@types/node': 16.11.22 + '@types/node': 16.11.26 dev: true /@types/fs-extra/9.0.13: resolution: {integrity: sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==} dependencies: - '@types/node': 16.11.22 + '@types/node': 16.11.26 dev: true /@types/graceful-fs/4.1.5: resolution: {integrity: sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==} dependencies: - '@types/node': 16.11.22 + '@types/node': 16.11.26 dev: true /@types/hash-sum/1.0.0: @@ -2390,11 +2567,11 @@ packages: '@types/istanbul-lib-report': 3.0.0 dev: true - /@types/jest/27.4.0: - resolution: {integrity: sha512-gHl8XuC1RZ8H2j5sHv/JqsaxXkDDM9iDOgu0Wp8sjs4u/snb2PVehyWXJPr+ORA0RPpgw231mnutWI1+0hgjIQ==} + /@types/jest/27.4.1: + resolution: {integrity: sha512-23iPJADSmicDVrWk+HT58LMJtzLAnB2AgIzplQuq/bSrGaxCrlvRFjGbXmamnnk/mAmCdLStiGqggu28ocUyiw==} dependencies: - jest-diff: 27.4.2 - pretty-format: 27.4.2 + jest-matcher-utils: 27.5.1 + pretty-format: 27.5.1 dev: true /@types/json-schema/7.0.9: @@ -2431,8 +2608,8 @@ packages: resolution: {integrity: sha512-qjd88DrCxupx/kJD5yQgZdcYKZKSIGBVDIBE1/LTGcNm3d2Np/jxojkdePDdfnBHJc5W7vSMpbJ1aB7p/Py69A==} dev: true - /@types/node/16.11.22: - resolution: {integrity: sha512-DYNtJWauMQ9RNpesl4aVothr97/tIJM8HbyOXJ0AYT1Z2bEjLHyfjOBPAQQVMLf8h3kSShYfNk8Wnto8B2zHUA==} + /@types/node/16.11.26: + resolution: {integrity: sha512-GZ7bu5A6+4DtG7q9GsoHXy3ALcgeIHP4NnL0Vv2wu0uUB/yQex26v0tf6/na1mm0+bS9Uw+0DFex7aaKr2qawQ==} dev: true /@types/normalize-package-data/2.4.1: @@ -2449,13 +2626,13 @@ packages: /@types/prompts/2.0.14: resolution: {integrity: sha512-HZBd99fKxRWpYCErtm2/yxUZv6/PBI9J7N4TNFffl5JbrYMHBwF25DjQGTW3b3jmXq+9P6/8fCIb2ee57BFfYA==} dependencies: - '@types/node': 16.11.22 + '@types/node': 16.11.26 dev: true /@types/resolve/1.17.1: resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==} dependencies: - '@types/node': 16.11.22 + '@types/node': 16.11.26 dev: true /@types/resolve/1.20.1: @@ -2465,7 +2642,7 @@ packages: /@types/sass/1.43.1: resolution: {integrity: sha512-BPdoIt1lfJ6B7rw35ncdwBZrAssjcwzI5LByIrYs+tpXlj/CAkuVdRsgZDdP4lq5EjyWzwxZCqAoFyHKFwp32g==} dependencies: - '@types/node': 16.11.22 + '@types/node': 16.11.26 dev: true /@types/semver/7.3.9: @@ -2483,13 +2660,13 @@ packages: /@types/stylus/0.48.36: resolution: {integrity: sha512-7klEq45BUE8ZJWkYWy1E442DcCs0wi0FkFY1Tjr6EJ7edL77t9w/QmOwlkFumBMqHlatDBtrA2xgfRrGqkUkzg==} dependencies: - '@types/node': 16.11.22 + '@types/node': 16.11.26 dev: true - /@types/ws/8.2.2: - resolution: {integrity: sha512-NOn5eIcgWLOo6qW8AcuLZ7G8PycXu0xTxxkS6Q18VWFxgPUSOwV0pBj2a/4viNZVu25i7RIB7GttdkAIUUXOOg==} + /@types/ws/8.5.3: + resolution: {integrity: sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==} dependencies: - '@types/node': 16.11.22 + '@types/node': 16.11.26 dev: true /@types/yargs-parser/20.2.1: @@ -2506,12 +2683,12 @@ packages: resolution: {integrity: sha512-8uALY5LTvSuHgloDVUvWP3pIauILm+8/0pDMokuDYIoNsOkSwd5AiHBTSEJjKTDcZr5z8UpgOWZkxBF4iJftoA==} requiresBuild: true dependencies: - '@types/node': 16.11.22 + '@types/node': 16.11.26 dev: true optional: true - /@typescript-eslint/eslint-plugin/5.11.0_1659739a34b564cc1aa1228518173088: - resolution: {integrity: sha512-HJh33bgzXe6jGRocOj4FmefD7hRY4itgjzOrSs3JPrTNXsX7j5+nQPciAUj/1nZtwo2kAc3C75jZO+T23gzSGw==} + /@typescript-eslint/eslint-plugin/5.16.0_e8f8f41828c0dd0ac8e32e1859a7f4f7: + resolution: {integrity: sha512-SJoba1edXvQRMmNI505Uo4XmGbxCK9ARQpkvOd00anxzri9RNQk0DDCxD+LIl+jYhkzOJiOMMKYEHnHEODjdCw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: '@typescript-eslint/parser': ^5.0.0 @@ -2521,12 +2698,12 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/parser': 5.11.0_eslint@8.8.0+typescript@4.5.4 - '@typescript-eslint/scope-manager': 5.11.0 - '@typescript-eslint/type-utils': 5.11.0_eslint@8.8.0+typescript@4.5.4 - '@typescript-eslint/utils': 5.11.0_eslint@8.8.0+typescript@4.5.4 - debug: 4.3.3 - eslint: 8.8.0 + '@typescript-eslint/parser': 5.16.0_eslint@8.12.0+typescript@4.5.4 + '@typescript-eslint/scope-manager': 5.16.0 + '@typescript-eslint/type-utils': 5.16.0_eslint@8.12.0+typescript@4.5.4 + '@typescript-eslint/utils': 5.16.0_eslint@8.12.0+typescript@4.5.4 + debug: 4.3.4 + eslint: 8.12.0 functional-red-black-tree: 1.0.1 ignore: 5.2.0 regexpp: 3.2.0 @@ -2537,8 +2714,8 @@ packages: - supports-color dev: true - /@typescript-eslint/parser/5.11.0_eslint@8.8.0+typescript@4.5.4: - resolution: {integrity: sha512-x0DCjetHZYBRovJdr3U0zG9OOdNXUaFLJ82ehr1AlkArljJuwEsgnud+Q7umlGDFLFrs8tU8ybQDFocp/eX8mQ==} + /@typescript-eslint/parser/5.16.0_eslint@8.12.0+typescript@4.5.4: + resolution: {integrity: sha512-fkDq86F0zl8FicnJtdXakFs4lnuebH6ZADDw6CYQv0UZeIjHvmEw87m9/29nk2Dv5Lmdp0zQ3zDQhiMWQf/GbA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -2547,26 +2724,26 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/scope-manager': 5.11.0 - '@typescript-eslint/types': 5.11.0 - '@typescript-eslint/typescript-estree': 5.11.0_typescript@4.5.4 - debug: 4.3.3 - eslint: 8.8.0 + '@typescript-eslint/scope-manager': 5.16.0 + '@typescript-eslint/types': 5.16.0 + '@typescript-eslint/typescript-estree': 5.16.0_typescript@4.5.4 + debug: 4.3.4 + eslint: 8.12.0 typescript: 4.5.4 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/scope-manager/5.11.0: - resolution: {integrity: sha512-z+K4LlahDFVMww20t/0zcA7gq/NgOawaLuxgqGRVKS0PiZlCTIUtX0EJbC0BK1JtR4CelmkPK67zuCgpdlF4EA==} + /@typescript-eslint/scope-manager/5.16.0: + resolution: {integrity: sha512-P+Yab2Hovg8NekLIR/mOElCDPyGgFZKhGoZA901Yax6WR6HVeGLbsqJkZ+Cvk5nts/dAlFKm8PfL43UZnWdpIQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: - '@typescript-eslint/types': 5.11.0 - '@typescript-eslint/visitor-keys': 5.11.0 + '@typescript-eslint/types': 5.16.0 + '@typescript-eslint/visitor-keys': 5.16.0 dev: true - /@typescript-eslint/type-utils/5.11.0_eslint@8.8.0+typescript@4.5.4: - resolution: {integrity: sha512-wDqdsYO6ofLaD4DsGZ0jGwxp4HrzD2YKulpEZXmgN3xo4BHJwf7kq49JTRpV0Gx6bxkSUmc9s0EIK1xPbFFpIA==} + /@typescript-eslint/type-utils/5.16.0_eslint@8.12.0+typescript@4.5.4: + resolution: {integrity: sha512-SKygICv54CCRl1Vq5ewwQUJV/8padIWvPgCxlWPGO/OgQLCijY9G7lDu6H+mqfQtbzDNlVjzVWQmeqbLMBLEwQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: '*' @@ -2575,22 +2752,22 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/utils': 5.11.0_eslint@8.8.0+typescript@4.5.4 - debug: 4.3.3 - eslint: 8.8.0 + '@typescript-eslint/utils': 5.16.0_eslint@8.12.0+typescript@4.5.4 + debug: 4.3.4 + eslint: 8.12.0 tsutils: 3.21.0_typescript@4.5.4 typescript: 4.5.4 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/types/5.11.0: - resolution: {integrity: sha512-cxgBFGSRCoBEhvSVLkKw39+kMzUKHlJGVwwMbPcTZX3qEhuXhrjwaZXWMxVfxDgyMm+b5Q5b29Llo2yow8Y7xQ==} + /@typescript-eslint/types/5.16.0: + resolution: {integrity: sha512-oUorOwLj/3/3p/HFwrp6m/J2VfbLC8gjW5X3awpQJ/bSG+YRGFS4dpsvtQ8T2VNveV+LflQHjlLvB6v0R87z4g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /@typescript-eslint/typescript-estree/5.11.0_typescript@4.5.4: - resolution: {integrity: sha512-yVH9hKIv3ZN3lw8m/Jy5I4oXO4ZBMqijcXCdA4mY8ull6TPTAoQnKKrcZ0HDXg7Bsl0Unwwx7jcXMuNZc0m4lg==} + /@typescript-eslint/typescript-estree/5.16.0_typescript@4.5.4: + resolution: {integrity: sha512-SE4VfbLWUZl9MR+ngLSARptUv2E8brY0luCdgmUevU6arZRY/KxYoLI/3V/yxaURR8tLRN7bmZtJdgmzLHI6pQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: typescript: '*' @@ -2598,9 +2775,9 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/types': 5.11.0 - '@typescript-eslint/visitor-keys': 5.11.0 - debug: 4.3.3 + '@typescript-eslint/types': 5.16.0 + '@typescript-eslint/visitor-keys': 5.16.0 + debug: 4.3.4 globby: 11.0.4 is-glob: 4.0.3 semver: 7.3.5 @@ -2610,41 +2787,41 @@ packages: - supports-color dev: true - /@typescript-eslint/utils/5.11.0_eslint@8.8.0+typescript@4.5.4: - resolution: {integrity: sha512-g2I480tFE1iYRDyMhxPAtLQ9HAn0jjBtipgTCZmd9I9s11OV8CTsG+YfFciuNDcHqm4csbAgC2aVZCHzLxMSUw==} + /@typescript-eslint/utils/5.16.0_eslint@8.12.0+typescript@4.5.4: + resolution: {integrity: sha512-iYej2ER6AwmejLWMWzJIHy3nPJeGDuCqf8Jnb+jAQVoPpmWzwQOfa9hWVB8GIQE5gsCv/rfN4T+AYb/V06WseQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: '@types/json-schema': 7.0.9 - '@typescript-eslint/scope-manager': 5.11.0 - '@typescript-eslint/types': 5.11.0 - '@typescript-eslint/typescript-estree': 5.11.0_typescript@4.5.4 - eslint: 8.8.0 + '@typescript-eslint/scope-manager': 5.16.0 + '@typescript-eslint/types': 5.16.0 + '@typescript-eslint/typescript-estree': 5.16.0_typescript@4.5.4 + eslint: 8.12.0 eslint-scope: 5.1.1 - eslint-utils: 3.0.0_eslint@8.8.0 + eslint-utils: 3.0.0_eslint@8.12.0 transitivePeerDependencies: - supports-color - typescript dev: true - /@typescript-eslint/visitor-keys/5.11.0: - resolution: {integrity: sha512-E8w/vJReMGuloGxJDkpPlGwhxocxOpSVgSvjiLO5IxZPmxZF30weOeJYyPSEACwM+X4NziYS9q+WkN/2DHYQwA==} + /@typescript-eslint/visitor-keys/5.16.0: + resolution: {integrity: sha512-jqxO8msp5vZDhikTwq9ubyMHqZ67UIvawohr4qF3KhlpL7gzSjOd+8471H3nh5LyABkaI85laEKKU8SnGUK5/g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: - '@typescript-eslint/types': 5.11.0 - eslint-visitor-keys: 3.2.0 + '@typescript-eslint/types': 5.16.0 + eslint-visitor-keys: 3.3.0 dev: true /@vue/babel-helper-vue-transform-on/1.0.2: resolution: {integrity: sha512-hz4R8tS5jMn8lDq6iD+yWL6XNB699pGIVLk7WSJnn1dbpjaazsjZQkieJoRX6gW5zpYSCFqQ7jUquPNY65tQYA==} dev: false - /@vue/babel-plugin-jsx/1.1.1_@babel+core@7.17.2: + /@vue/babel-plugin-jsx/1.1.1_@babel+core@7.17.8: resolution: {integrity: sha512-j2uVfZjnB5+zkcbc/zsOc0fSNGCMMjaEXP52wdwdIfn0qjFfEYpYZBFKFg+HHnQeJCVrjOeO0YxgaL7DMrym9w==} dependencies: '@babel/helper-module-imports': 7.16.0 - '@babel/plugin-syntax-jsx': 7.16.5_@babel+core@7.17.2 + '@babel/plugin-syntax-jsx': 7.16.5_@babel+core@7.17.8 '@babel/template': 7.16.0 '@babel/traverse': 7.16.5 '@babel/types': 7.16.0 @@ -2665,23 +2842,13 @@ packages: estree-walker: 2.0.2 source-map: 0.6.1 - /@vue/compiler-core/3.2.29: - resolution: {integrity: sha512-RePZ/J4Ub3sb7atQw6V6Rez+/5LCRHGFlSetT3N4VMrejqJnNPXKUt5AVm/9F5MJriy2w/VudEIvgscCfCWqxw==} + /@vue/compiler-core/3.2.31: + resolution: {integrity: sha512-aKno00qoA4o+V/kR6i/pE+aP+esng5siNAVQ422TkBNM6qA4veXiZbSe8OTXHXquEi/f6Akc+nLfB4JGfe4/WQ==} dependencies: - '@babel/parser': 7.17.0 - '@vue/shared': 3.2.29 + '@babel/parser': 7.17.8 + '@vue/shared': 3.2.31 estree-walker: 2.0.2 source-map: 0.6.1 - dev: true - - /@vue/compiler-core/3.2.30: - resolution: {integrity: sha512-64fq1KfcR+k3Vlw+IsBM2VhV5B+2IP3YxvKU8LWCDLrkmlXtbf2eMK6+0IwX5KP41D0f1gzryIiXR7P8cB9O5Q==} - dependencies: - '@babel/parser': 7.17.0 - '@vue/shared': 3.2.30 - estree-walker: 2.0.2 - source-map: 0.6.1 - dev: true /@vue/compiler-dom/3.2.26: resolution: {integrity: sha512-smBfaOW6mQDxcT3p9TKT6mE22vjxjJL50GFVJiI0chXYGU/xzC05QRGrW3HHVuJrmLTLx5zBhsZ2dIATERbarg==} @@ -2689,19 +2856,11 @@ packages: '@vue/compiler-core': 3.2.26 '@vue/shared': 3.2.26 - /@vue/compiler-dom/3.2.29: - resolution: {integrity: sha512-y26vK5khdNS9L3ckvkqJk/78qXwWb75Ci8iYLb67AkJuIgyKhIOcR1E8RIt4mswlVCIeI9gQ+fmtdhaiTAtrBQ==} - dependencies: - '@vue/compiler-core': 3.2.29 - '@vue/shared': 3.2.29 - dev: true - - /@vue/compiler-dom/3.2.30: - resolution: {integrity: sha512-t7arHz2SXLCXlF2fdGDFVbhENbGMez254Z5edUqb//6WXJU1lC7GvSkUE7i5x8WSjgfqt60i0V8zdmk16rvLdw==} + /@vue/compiler-dom/3.2.31: + resolution: {integrity: sha512-60zIlFfzIDf3u91cqfqy9KhCKIJgPeqxgveH2L+87RcGU/alT6BRrk5JtUso0OibH3O7NXuNOQ0cDc9beT0wrg==} dependencies: - '@vue/compiler-core': 3.2.30 - '@vue/shared': 3.2.30 - dev: true + '@vue/compiler-core': 3.2.31 + '@vue/shared': 3.2.31 /@vue/compiler-sfc/3.2.26: resolution: {integrity: sha512-ePpnfktV90UcLdsDQUh2JdiTuhV0Skv2iYXxfNMOK/F3Q+2BO0AulcVcfoksOpTJGmhhfosWfMyEaEf0UaWpIw==} @@ -2717,35 +2876,19 @@ packages: postcss: 8.4.5 source-map: 0.6.1 - /@vue/compiler-sfc/3.2.29: - resolution: {integrity: sha512-X9+0dwsag2u6hSOP/XsMYqFti/edvYvxamgBgCcbSYuXx1xLZN+dS/GvQKM4AgGS4djqo0jQvWfIXdfZ2ET68g==} - dependencies: - '@babel/parser': 7.17.0 - '@vue/compiler-core': 3.2.29 - '@vue/compiler-dom': 3.2.29 - '@vue/compiler-ssr': 3.2.29 - '@vue/reactivity-transform': 3.2.29 - '@vue/shared': 3.2.29 - estree-walker: 2.0.2 - magic-string: 0.25.7 - postcss: 8.4.5 - source-map: 0.6.1 - dev: true - - /@vue/compiler-sfc/3.2.30: - resolution: {integrity: sha512-P/5YpILtcQY92z72gxhkyOUPHVskEzhSrvYi91Xcr+csOxaDaYU5OqOxCzZKcf3Og70Tat404vO1OHrwprN90A==} + /@vue/compiler-sfc/3.2.31: + resolution: {integrity: sha512-748adc9msSPGzXgibHiO6T7RWgfnDcVQD+VVwYgSsyyY8Ans64tALHZANrKtOzvkwznV/F4H7OAod/jIlp/dkQ==} dependencies: - '@babel/parser': 7.17.0 - '@vue/compiler-core': 3.2.30 - '@vue/compiler-dom': 3.2.30 - '@vue/compiler-ssr': 3.2.30 - '@vue/reactivity-transform': 3.2.30 - '@vue/shared': 3.2.30 + '@babel/parser': 7.17.8 + '@vue/compiler-core': 3.2.31 + '@vue/compiler-dom': 3.2.31 + '@vue/compiler-ssr': 3.2.31 + '@vue/reactivity-transform': 3.2.31 + '@vue/shared': 3.2.31 estree-walker: 2.0.2 magic-string: 0.25.7 - postcss: 8.4.5 + postcss: 8.4.12 source-map: 0.6.1 - dev: true /@vue/compiler-ssr/3.2.26: resolution: {integrity: sha512-2mywLX0ODc4Zn8qBoA2PDCsLEZfpUGZcyoFRLSOjyGGK6wDy2/5kyDOWtf0S0UvtoyVq95OTSGIALjZ4k2q/ag==} @@ -2753,19 +2896,11 @@ packages: '@vue/compiler-dom': 3.2.26 '@vue/shared': 3.2.26 - /@vue/compiler-ssr/3.2.29: - resolution: {integrity: sha512-LrvQwXlx66uWsB9/VydaaqEpae9xtmlUkeSKF6aPDbzx8M1h7ukxaPjNCAXuFd3fUHblcri8k42lfimHfzMICA==} + /@vue/compiler-ssr/3.2.31: + resolution: {integrity: sha512-mjN0rqig+A8TVDnsGPYJM5dpbjlXeHUm2oZHZwGyMYiGT/F4fhJf/cXy8QpjnLQK4Y9Et4GWzHn9PS8AHUnSkw==} dependencies: - '@vue/compiler-dom': 3.2.29 - '@vue/shared': 3.2.29 - dev: true - - /@vue/compiler-ssr/3.2.30: - resolution: {integrity: sha512-OUh3MwAu/PsD7VN3UOdBbTkltkrUCNouSht47+CMRzpUR5+ta7+xyMAVHeq8wg4YZenWaJimbR5TL35Ka4Vk6g==} - dependencies: - '@vue/compiler-dom': 3.2.30 - '@vue/shared': 3.2.30 - dev: true + '@vue/compiler-dom': 3.2.31 + '@vue/shared': 3.2.31 /@vue/devtools-api/6.0.0-beta.21.1: resolution: {integrity: sha512-FqC4s3pm35qGVeXRGOjTsRzlkJjrBLriDS9YXbflHLsfA9FrcKzIyWnLXoNm+/7930E8rRakXuAc2QkC50swAw==} @@ -2780,42 +2915,24 @@ packages: estree-walker: 2.0.2 magic-string: 0.25.7 - /@vue/reactivity-transform/3.2.29: - resolution: {integrity: sha512-YF6HdOuhdOw6KyRm59+3rML8USb9o8mYM1q+SH0G41K3/q/G7uhPnHGKvspzceD7h9J3VR1waOQ93CUZj7J7OA==} + /@vue/reactivity-transform/3.2.31: + resolution: {integrity: sha512-uS4l4z/W7wXdI+Va5pgVxBJ345wyGFKvpPYtdSgvfJfX/x2Ymm6ophQlXXB6acqGHtXuBqNyyO3zVp9b1r0MOA==} dependencies: - '@babel/parser': 7.17.0 - '@vue/compiler-core': 3.2.29 - '@vue/shared': 3.2.29 + '@babel/parser': 7.17.8 + '@vue/compiler-core': 3.2.31 + '@vue/shared': 3.2.31 estree-walker: 2.0.2 magic-string: 0.25.7 - dev: true - - /@vue/reactivity-transform/3.2.30: - resolution: {integrity: sha512-Le5XzCJyK3qTjoTnvQG/Ehu8fYjayauMNFyMaEnwFlm/avDofpuibpS9u+/6AgzsGnVWN+i0Jgf25bJd9DIwMw==} - dependencies: - '@babel/parser': 7.17.0 - '@vue/compiler-core': 3.2.30 - '@vue/shared': 3.2.30 - estree-walker: 2.0.2 - magic-string: 0.25.7 - dev: true /@vue/reactivity/3.2.26: resolution: {integrity: sha512-h38bxCZLW6oFJVDlCcAiUKFnXI8xP8d+eO0pcDxx+7dQfSPje2AO6M9S9QO6MrxQB7fGP0DH0dYQ8ksf6hrXKQ==} dependencies: '@vue/shared': 3.2.26 - /@vue/reactivity/3.2.29: - resolution: {integrity: sha512-Ryhb6Gy62YolKXH1gv42pEqwx7zs3n8gacRVZICSgjQz8Qr8QeCcFygBKYfJm3o1SccR7U+bVBQDWZGOyG1k4g==} - dependencies: - '@vue/shared': 3.2.29 - dev: true - - /@vue/reactivity/3.2.30: - resolution: {integrity: sha512-qlNKbkRn2JiGxVUEdoXbLAy+vcuHUCcq+YH2uXWz0BNMvXY2plmz+oqsw+694llwmYLkke5lbdYF4DIupisIkg==} + /@vue/reactivity/3.2.31: + resolution: {integrity: sha512-HVr0l211gbhpEKYr2hYe7hRsV91uIVGFYNHj73njbARVGHQvIojkImKMaZNDdoDZOIkMsBc9a1sMqR+WZwfSCw==} dependencies: - '@vue/shared': 3.2.30 - dev: true + '@vue/shared': 3.2.31 /@vue/runtime-core/3.2.26: resolution: {integrity: sha512-BcYi7qZ9Nn+CJDJrHQ6Zsmxei2hDW0L6AB4vPvUQGBm2fZyC0GXd/4nVbyA2ubmuhctD5RbYY8L+5GUJszv9mQ==} @@ -2823,19 +2940,11 @@ packages: '@vue/reactivity': 3.2.26 '@vue/shared': 3.2.26 - /@vue/runtime-core/3.2.29: - resolution: {integrity: sha512-VMvQuLdzoTGmCwIKTKVwKmIL0qcODIqe74JtK1pVr5lnaE0l25hopodmPag3RcnIcIXe+Ye3B2olRCn7fTCgig==} - dependencies: - '@vue/reactivity': 3.2.29 - '@vue/shared': 3.2.29 - dev: true - - /@vue/runtime-core/3.2.30: - resolution: {integrity: sha512-RTi7xH0Ht/6wfbo2WFBMJTEiyWFTqGhrksJm8lz6E+auO6lXZ6Eq3gPNfLt47GDWCm4xyrv+rs5R4UbarPEQ1Q==} + /@vue/runtime-core/3.2.31: + resolution: {integrity: sha512-Kcog5XmSY7VHFEMuk4+Gap8gUssYMZ2+w+cmGI6OpZWYOEIcbE0TPzzPHi+8XTzAgx1w/ZxDFcXhZeXN5eKWsA==} dependencies: - '@vue/reactivity': 3.2.30 - '@vue/shared': 3.2.30 - dev: true + '@vue/reactivity': 3.2.31 + '@vue/shared': 3.2.31 /@vue/runtime-dom/3.2.26: resolution: {integrity: sha512-dY56UIiZI+gjc4e8JQBwAifljyexfVCkIAu/WX8snh8vSOt/gMSEGwPRcl2UpYpBYeyExV8WCbgvwWRNt9cHhQ==} @@ -2844,21 +2953,12 @@ packages: '@vue/shared': 3.2.26 csstype: 2.6.19 - /@vue/runtime-dom/3.2.29: - resolution: {integrity: sha512-YJgLQLwr+SQyORzTsBQLL5TT/5UiV83tEotqjL7F9aFDIQdFBTCwpkCFvX9jqwHoyi9sJqM9XtTrMcc8z/OjPA==} + /@vue/runtime-dom/3.2.31: + resolution: {integrity: sha512-N+o0sICVLScUjfLG7u9u5XCjvmsexAiPt17GNnaWHJUfsKed5e85/A3SWgKxzlxx2SW/Hw7RQxzxbXez9PtY3g==} dependencies: - '@vue/runtime-core': 3.2.29 - '@vue/shared': 3.2.29 + '@vue/runtime-core': 3.2.31 + '@vue/shared': 3.2.31 csstype: 2.6.19 - dev: true - - /@vue/runtime-dom/3.2.30: - resolution: {integrity: sha512-a3+jrncDvEFQmB+v9k0VyT4/Y3XO6OAueCroXXY4yLyr6PJeyxljweV5TzvW0rvVzH9sZO0QAvG76Lo+6C92Qw==} - dependencies: - '@vue/runtime-core': 3.2.30 - '@vue/shared': 3.2.30 - csstype: 2.6.19 - dev: true /@vue/server-renderer/3.2.26_vue@3.2.26: resolution: {integrity: sha512-Jp5SggDUvvUYSBIvYEhy76t4nr1vapY/FIFloWmQzn7UxqaHrrBpbxrqPcTrSgGrcaglj0VBp22BKJNre4aA1w==} @@ -2869,36 +2969,20 @@ packages: '@vue/shared': 3.2.26 vue: 3.2.26 - /@vue/server-renderer/3.2.29_vue@3.2.29: - resolution: {integrity: sha512-lpiYx7ciV7rWfJ0tPkoSOlLmwqBZ9FTmQm33S+T4g0j1fO/LmhJ9b9Ctl1o5xvIFVDk9QkSUWANZn7H2pXuxVw==} + /@vue/server-renderer/3.2.31_vue@3.2.31: + resolution: {integrity: sha512-8CN3Zj2HyR2LQQBHZ61HexF5NReqngLT3oahyiVRfSSvak+oAvVmu8iNLSu6XR77Ili2AOpnAt1y8ywjjqtmkg==} peerDependencies: - vue: 3.2.29 + vue: 3.2.31 dependencies: - '@vue/compiler-ssr': 3.2.29 - '@vue/shared': 3.2.29 - vue: 3.2.29 - dev: true - - /@vue/server-renderer/3.2.30_vue@3.2.30: - resolution: {integrity: sha512-pzb8J/w+JdZVOtuKFlirGqrs4GP60FXGDJySw3WV2pCetuFstaacDrnymEeSo3ohAD+Qjv7zAG+Y7OvkdxQxmQ==} - peerDependencies: - vue: 3.2.30 - dependencies: - '@vue/compiler-ssr': 3.2.30 - '@vue/shared': 3.2.30 - vue: 3.2.30 - dev: true + '@vue/compiler-ssr': 3.2.31 + '@vue/shared': 3.2.31 + vue: 3.2.31 /@vue/shared/3.2.26: resolution: {integrity: sha512-vPV6Cq+NIWbH5pZu+V+2QHE9y1qfuTq49uNWw4f7FDEeZaDU2H2cx5jcUZOAKW7qTrUS4k6qZPbMy1x4N96nbA==} - /@vue/shared/3.2.29: - resolution: {integrity: sha512-BjNpU8OK6Z0LVzGUppEk0CMYm/hKDnZfYdjSmPOs0N+TR1cLKJAkDwW8ASZUvaaSLEi6d3hVM7jnWnX+6yWnHw==} - dev: true - - /@vue/shared/3.2.30: - resolution: {integrity: sha512-B3HouBtUxcfu2w2d+VhdLcVBXKYYhXiFMAfQ+hoe8NUhKkPRkWDIqhpuehCZxVQ3S2dN1P1WfKGlxGC+pfmxGg==} - dev: true + /@vue/shared/3.2.31: + resolution: {integrity: sha512-ymN2pj6zEjiKJZbrf98UM2pfDd6F2H7ksKw7NDt/ZZ1fh5Ei39X5tABugtT03ZRlWd9imccoK0hE8hpjpU7irQ==} /@wessberg/stringutil/1.0.19: resolution: {integrity: sha512-9AZHVXWlpN8Cn9k5BC/O0Dzb9E9xfEMXzYrNunwvkUTvuK7xgQPVRZpLo+jWCOZ5r8oBa8NIrHuPEu1hzbb6bg==} @@ -2980,7 +3064,7 @@ packages: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} engines: {node: '>= 6.0.0'} dependencies: - debug: 4.3.3 + debug: 4.3.4 transitivePeerDependencies: - supports-color @@ -3063,7 +3147,7 @@ packages: engines: {node: '>= 8'} dependencies: normalize-path: 3.0.0 - picomatch: 2.3.0 + picomatch: 2.3.1 /aproba/2.0.0: resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} @@ -3278,6 +3362,10 @@ packages: - supports-color dev: false + /bignumber.js/9.0.2: + resolution: {integrity: sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw==} + dev: false + /binary-extensions/2.2.0: resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} engines: {node: '>=8'} @@ -3599,6 +3687,11 @@ packages: engines: {node: '>=0.1.90'} dev: true + /colors/1.4.0: + resolution: {integrity: sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==} + engines: {node: '>=0.1.90'} + dev: true + /combined-stream/1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} @@ -3884,8 +3977,8 @@ packages: is-what: 3.14.1 dev: true - /core-js/3.21.0: - resolution: {integrity: sha512-YUdI3fFu4TF/2WykQ2xzSiTQdldLB4KVuL9WeAy5XONZYt5Cun/fpQvctoKbCgvPhmzADeesTk/j2Rdx77AcKQ==} + /core-js/3.21.1: + resolution: {integrity: sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig==} requiresBuild: true dev: false @@ -4063,8 +4156,19 @@ packages: dependencies: ms: 2.1.2 - /debug/4.3.3_supports-color@9.2.1: - resolution: {integrity: sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==} + /debug/4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + + /debug/4.3.4_supports-color@9.2.1: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} engines: {node: '>=6.0'} peerDependencies: supports-color: '*' @@ -4186,11 +4290,6 @@ packages: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} dev: false - /diff-sequences/27.4.0: - resolution: {integrity: sha512-YqiQzkrsmHMH5uuh8OdQFU9/ZpADnwzml8z0O5HvRNda+5UZsaX/xN+AAxfR2hWq1Y7HZnAzO9J5lJXOuDz2Ww==} - engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - dev: true - /diff-sequences/27.5.1: resolution: {integrity: sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -4326,8 +4425,8 @@ packages: unbox-primitive: 1.0.1 dev: true - /es-module-lexer/0.9.3: - resolution: {integrity: sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==} + /es-module-lexer/0.10.4: + resolution: {integrity: sha512-n5bOGUnrmuCKyMkmHNtC1ObnUx8AgFcKWe2mbxb6jYzuK81W0Rk3Z//sCoGJuxWzos8R2w48TemGIFqZsTY6YA==} dev: true /es-to-primitive/1.2.1: @@ -4362,155 +4461,192 @@ packages: ext: 1.6.0 dev: false - /esbuild-android-arm64/0.14.14: - resolution: {integrity: sha512-be/Uw6DdpQiPfula1J4bdmA+wtZ6T3BRCZsDMFB5X+k0Gp8TIh9UvmAcqvKNnbRAafSaXG3jPCeXxDKqnc8hFQ==} + /esbuild-android-64/0.14.27: + resolution: {integrity: sha512-LuEd4uPuj/16Y8j6kqy3Z2E9vNY9logfq8Tq+oTE2PZVuNs3M1kj5Qd4O95ee66yDGb3isaOCV7sOLDwtMfGaQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + optional: true + + /esbuild-android-arm64/0.14.27: + resolution: {integrity: sha512-E8Ktwwa6vX8q7QeJmg8yepBYXaee50OdQS3BFtEHKrzbV45H4foMOeEE7uqdjGQZFBap5VAqo7pvjlyA92wznQ==} + engines: {node: '>=12'} cpu: [arm64] os: [android] requiresBuild: true optional: true - /esbuild-darwin-64/0.14.14: - resolution: {integrity: sha512-BEexYmjWafcISK8cT6O98E3TfcLuZL8DKuubry6G54n2+bD4GkoRD6HYUOnCkfl2p7jodA+s4369IjSFSWjtHg==} + /esbuild-darwin-64/0.14.27: + resolution: {integrity: sha512-czw/kXl/1ZdenPWfw9jDc5iuIYxqUxgQ/Q+hRd4/3udyGGVI31r29LCViN2bAJgGvQkqyLGVcG03PJPEXQ5i2g==} + engines: {node: '>=12'} cpu: [x64] os: [darwin] requiresBuild: true optional: true - /esbuild-darwin-arm64/0.14.14: - resolution: {integrity: sha512-tnBKm41pDOB1GtZ8q/w26gZlLLRzVmP8fdsduYjvM+yFD7E2DLG4KbPAqFMWm4Md9B+DitBglP57FY7AznxbTg==} + /esbuild-darwin-arm64/0.14.27: + resolution: {integrity: sha512-BEsv2U2U4o672oV8+xpXNxN9bgqRCtddQC6WBh4YhXKDcSZcdNh7+6nS+DM2vu7qWIWNA4JbRG24LUUYXysimQ==} + engines: {node: '>=12'} cpu: [arm64] os: [darwin] requiresBuild: true optional: true - /esbuild-freebsd-64/0.14.14: - resolution: {integrity: sha512-Q9Rx6sgArOHalQtNwAaIzJ6dnQ8A+I7f/RsQsdkS3JrdzmnlFo8JEVofTmwVQLoIop7OKUqIVOGP4PoQcwfVMA==} + /esbuild-freebsd-64/0.14.27: + resolution: {integrity: sha512-7FeiFPGBo+ga+kOkDxtPmdPZdayrSzsV9pmfHxcyLKxu+3oTcajeZlOO1y9HW+t5aFZPiv7czOHM4KNd0tNwCA==} + engines: {node: '>=12'} cpu: [x64] os: [freebsd] requiresBuild: true optional: true - /esbuild-freebsd-arm64/0.14.14: - resolution: {integrity: sha512-TJvq0OpLM7BkTczlyPIphcvnwrQwQDG1HqxzoYePWn26SMUAlt6wrLnEvxdbXAvNvDLVzG83kA+JimjK7aRNBA==} + /esbuild-freebsd-arm64/0.14.27: + resolution: {integrity: sha512-8CK3++foRZJluOWXpllG5zwAVlxtv36NpHfsbWS7TYlD8S+QruXltKlXToc/5ZNzBK++l6rvRKELu/puCLc7jA==} + engines: {node: '>=12'} cpu: [arm64] os: [freebsd] requiresBuild: true optional: true - /esbuild-linux-32/0.14.14: - resolution: {integrity: sha512-h/CrK9Baimt5VRbu8gqibWV7e1P9l+mkanQgyOgv0Ng3jHT1NVFC9e6rb1zbDdaJVmuhWX5xVliUA5bDDCcJeg==} + /esbuild-linux-32/0.14.27: + resolution: {integrity: sha512-qhNYIcT+EsYSBClZ5QhLzFzV5iVsP1YsITqblSaztr3+ZJUI+GoK8aXHyzKd7/CKKuK93cxEMJPpfi1dfsOfdw==} + engines: {node: '>=12'} cpu: [ia32] os: [linux] requiresBuild: true optional: true - /esbuild-linux-64/0.14.14: - resolution: {integrity: sha512-IC+wAiIg/egp5OhQp4W44D9PcBOH1b621iRn1OXmlLzij9a/6BGr9NMIL4CRwz4j2kp3WNZu5sT473tYdynOuQ==} + /esbuild-linux-64/0.14.27: + resolution: {integrity: sha512-ESjck9+EsHoTaKWlFKJpPZRN26uiav5gkI16RuI8WBxUdLrrAlYuYSndxxKgEn1csd968BX/8yQZATYf/9+/qg==} + engines: {node: '>=12'} cpu: [x64] os: [linux] requiresBuild: true optional: true - /esbuild-linux-arm/0.14.14: - resolution: {integrity: sha512-gxpOaHOPwp7zSmcKYsHrtxabScMqaTzfSQioAMUaB047YiMuDBzqVcKBG8OuESrYkGrL9DDljXr/mQNg7pbdaQ==} + /esbuild-linux-arm/0.14.27: + resolution: {integrity: sha512-JnnmgUBdqLQO9hoNZQqNHFWlNpSX82vzB3rYuCJMhtkuaWQEmQz6Lec1UIxJdC38ifEghNTBsF9bbe8dFilnCw==} + engines: {node: '>=12'} cpu: [arm] os: [linux] requiresBuild: true optional: true - /esbuild-linux-arm64/0.14.14: - resolution: {integrity: sha512-6QVul3RI4M5/VxVIRF/I5F+7BaxzR3DfNGoqEVSCZqUbgzHExPn+LXr5ly1C7af2Kw4AHpo+wDqx8A4ziP9avw==} + /esbuild-linux-arm64/0.14.27: + resolution: {integrity: sha512-no6Mi17eV2tHlJnqBHRLekpZ2/VYx+NfGxKcBE/2xOMYwctsanCaXxw4zapvNrGE9X38vefVXLz6YCF8b1EHiQ==} + engines: {node: '>=12'} cpu: [arm64] os: [linux] requiresBuild: true optional: true - /esbuild-linux-mips64le/0.14.14: - resolution: {integrity: sha512-4Jl5/+xoINKbA4cesH3f4R+q0vltAztZ6Jm8YycS8lNhN1pgZJBDxWfI6HUMIAdkKlIpR1PIkA9aXQgZ8sxFAg==} + /esbuild-linux-mips64le/0.14.27: + resolution: {integrity: sha512-NolWP2uOvIJpbwpsDbwfeExZOY1bZNlWE/kVfkzLMsSgqeVcl5YMen/cedRe9mKnpfLli+i0uSp7N+fkKNU27A==} + engines: {node: '>=12'} cpu: [mips64el] os: [linux] requiresBuild: true optional: true - /esbuild-linux-ppc64le/0.14.14: - resolution: {integrity: sha512-BitW37GxeebKxqYNl4SVuSdnIJAzH830Lr6Mkq3pBHXtzQay0vK+IeOR/Ele1GtNVJ+/f8wYM53tcThkv5SC5w==} + /esbuild-linux-ppc64le/0.14.27: + resolution: {integrity: sha512-/7dTjDvXMdRKmsSxKXeWyonuGgblnYDn0MI1xDC7J1VQXny8k1qgNp6VmrlsawwnsymSUUiThhkJsI+rx0taNA==} + engines: {node: '>=12'} cpu: [ppc64] os: [linux] requiresBuild: true optional: true - /esbuild-linux-s390x/0.14.14: - resolution: {integrity: sha512-vLj6p76HOZG3wfuTr5MyO3qW5iu8YdhUNxuY+tx846rPo7GcKtYSPMusQjeVEfZlJpSYoR+yrNBBxq+qVF9zrw==} + /esbuild-linux-riscv64/0.14.27: + resolution: {integrity: sha512-D+aFiUzOJG13RhrSmZgrcFaF4UUHpqj7XSKrIiCXIj1dkIkFqdrmqMSOtSs78dOtObWiOrFCDDzB24UyeEiNGg==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + optional: true + + /esbuild-linux-s390x/0.14.27: + resolution: {integrity: sha512-CD/D4tj0U4UQjELkdNlZhQ8nDHU5rBn6NGp47Hiz0Y7/akAY5i0oGadhEIg0WCY/HYVXFb3CsSPPwaKcTOW3bg==} + engines: {node: '>=12'} cpu: [s390x] os: [linux] requiresBuild: true optional: true - /esbuild-netbsd-64/0.14.14: - resolution: {integrity: sha512-fn8looXPQhpVqUyCBWUuPjesH+yGIyfbIQrLKG05rr1Kgm3rZD/gaYrd3Wpmf5syVZx70pKZPvdHp8OTA+y7cQ==} + /esbuild-netbsd-64/0.14.27: + resolution: {integrity: sha512-h3mAld69SrO1VoaMpYl3a5FNdGRE/Nqc+E8VtHOag4tyBwhCQXxtvDDOAKOUQexBGca0IuR6UayQ4ntSX5ij1Q==} + engines: {node: '>=12'} cpu: [x64] os: [netbsd] requiresBuild: true optional: true - /esbuild-openbsd-64/0.14.14: - resolution: {integrity: sha512-HdAnJ399pPff3SKbd8g+P4o5znseni5u5n5rJ6Z7ouqOdgbOwHe2ofZbMow17WMdNtz1IyOZk2Wo9Ve6/lZ4Rg==} + /esbuild-openbsd-64/0.14.27: + resolution: {integrity: sha512-xwSje6qIZaDHXWoPpIgvL+7fC6WeubHHv18tusLYMwL+Z6bEa4Pbfs5IWDtQdHkArtfxEkIZz77944z8MgDxGw==} + engines: {node: '>=12'} cpu: [x64] os: [openbsd] requiresBuild: true optional: true - /esbuild-sunos-64/0.14.14: - resolution: {integrity: sha512-bmDHa99ulsGnYlh/xjBEfxoGuC8CEG5OWvlgD+pF7bKKiVTbtxqVCvOGEZeoDXB+ja6AvHIbPxrEE32J+m5nqQ==} + /esbuild-sunos-64/0.14.27: + resolution: {integrity: sha512-/nBVpWIDjYiyMhuqIqbXXsxBc58cBVH9uztAOIfWShStxq9BNBik92oPQPJ57nzWXRNKQUEFWr4Q98utDWz7jg==} + engines: {node: '>=12'} cpu: [x64] os: [sunos] requiresBuild: true optional: true - /esbuild-windows-32/0.14.14: - resolution: {integrity: sha512-6tVooQcxJCNenPp5GHZBs/RLu31q4B+BuF4MEoRxswT+Eq2JGF0ZWDRQwNKB8QVIo3t6Svc5wNGez+CwKNQjBg==} + /esbuild-windows-32/0.14.27: + resolution: {integrity: sha512-Q9/zEjhZJ4trtWhFWIZvS/7RUzzi8rvkoaS9oiizkHTTKd8UxFwn/Mm2OywsAfYymgUYm8+y2b+BKTNEFxUekw==} + engines: {node: '>=12'} cpu: [ia32] os: [win32] requiresBuild: true optional: true - /esbuild-windows-64/0.14.14: - resolution: {integrity: sha512-kl3BdPXh0/RD/dad41dtzj2itMUR4C6nQbXQCyYHHo4zoUoeIXhpCrSl7BAW1nv5EFL8stT1V+TQVXGZca5A2A==} + /esbuild-windows-64/0.14.27: + resolution: {integrity: sha512-b3y3vTSl5aEhWHK66ngtiS/c6byLf6y/ZBvODH1YkBM+MGtVL6jN38FdHUsZasCz9gFwYs/lJMVY9u7GL6wfYg==} + engines: {node: '>=12'} cpu: [x64] os: [win32] requiresBuild: true optional: true - /esbuild-windows-arm64/0.14.14: - resolution: {integrity: sha512-dCm1wTOm6HIisLanmybvRKvaXZZo4yEVrHh1dY0v582GThXJOzuXGja1HIQgV09RpSHYRL3m4KoUBL00l6SWEg==} + /esbuild-windows-arm64/0.14.27: + resolution: {integrity: sha512-I/reTxr6TFMcR5qbIkwRGvldMIaiBu2+MP0LlD7sOlNXrfqIl9uNjsuxFPGEG4IRomjfQ5q8WT+xlF/ySVkqKg==} + engines: {node: '>=12'} cpu: [arm64] os: [win32] requiresBuild: true optional: true - /esbuild/0.14.14: - resolution: {integrity: sha512-aiK4ddv+uui0k52OqSHu4xxu+SzOim7Rlz4i25pMEiC8rlnGU0HJ9r+ZMfdWL5bzifg+nhnn7x4NSWTeehYblg==} + /esbuild/0.14.27: + resolution: {integrity: sha512-MZQt5SywZS3hA9fXnMhR22dv0oPGh6QtjJRIYbgL1AeqAoQZE+Qn5ppGYQAoHv/vq827flj4tIJ79Mrdiwk46Q==} + engines: {node: '>=12'} hasBin: true requiresBuild: true optionalDependencies: - esbuild-android-arm64: 0.14.14 - esbuild-darwin-64: 0.14.14 - esbuild-darwin-arm64: 0.14.14 - esbuild-freebsd-64: 0.14.14 - esbuild-freebsd-arm64: 0.14.14 - esbuild-linux-32: 0.14.14 - esbuild-linux-64: 0.14.14 - esbuild-linux-arm: 0.14.14 - esbuild-linux-arm64: 0.14.14 - esbuild-linux-mips64le: 0.14.14 - esbuild-linux-ppc64le: 0.14.14 - esbuild-linux-s390x: 0.14.14 - esbuild-netbsd-64: 0.14.14 - esbuild-openbsd-64: 0.14.14 - esbuild-sunos-64: 0.14.14 - esbuild-windows-32: 0.14.14 - esbuild-windows-64: 0.14.14 - esbuild-windows-arm64: 0.14.14 + esbuild-android-64: 0.14.27 + esbuild-android-arm64: 0.14.27 + esbuild-darwin-64: 0.14.27 + esbuild-darwin-arm64: 0.14.27 + esbuild-freebsd-64: 0.14.27 + esbuild-freebsd-arm64: 0.14.27 + esbuild-linux-32: 0.14.27 + esbuild-linux-64: 0.14.27 + esbuild-linux-arm: 0.14.27 + esbuild-linux-arm64: 0.14.27 + esbuild-linux-mips64le: 0.14.27 + esbuild-linux-ppc64le: 0.14.27 + esbuild-linux-riscv64: 0.14.27 + esbuild-linux-s390x: 0.14.27 + esbuild-netbsd-64: 0.14.27 + esbuild-openbsd-64: 0.14.27 + esbuild-sunos-64: 0.14.27 + esbuild-windows-32: 0.14.27 + esbuild-windows-64: 0.14.27 + esbuild-windows-arm64: 0.14.27 /escalade/3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} @@ -4547,30 +4683,30 @@ packages: source-map: 0.6.1 dev: true - /eslint-define-config/1.2.4: - resolution: {integrity: sha512-HTdOfrqthSd6lpl/fRp2+BKSCR/d+knNi66c6mOIxEYjorSkqRdLkmPhmLAW5akOp3+MuP25YgKcFHSsknaigw==} - engines: {node: '>= 16.9.0', npm: '>= 7.0.0', pnpm: '>= 6.29.1'} + /eslint-define-config/1.3.0: + resolution: {integrity: sha512-sFbHUnaXdJfG74c0EfFjXajjM3ugDVOMteKBnddCHQP5eas6p3nmS7PbSVhyZ8Y9DaNNtFbzlovdGmVdTwrHcw==} + engines: {node: '>= 16.9.0', npm: '>= 7.0.0', pnpm: '>= 6.32.2'} dev: true - /eslint-plugin-es/3.0.1_eslint@8.8.0: + /eslint-plugin-es/3.0.1_eslint@8.12.0: resolution: {integrity: sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==} engines: {node: '>=8.10.0'} peerDependencies: eslint: '>=4.19.1' dependencies: - eslint: 8.8.0 + eslint: 8.12.0 eslint-utils: 2.1.0 regexpp: 3.2.0 dev: true - /eslint-plugin-node/11.1.0_eslint@8.8.0: + /eslint-plugin-node/11.1.0_eslint@8.12.0: resolution: {integrity: sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==} engines: {node: '>=8.10.0'} peerDependencies: eslint: '>=5.16.0' dependencies: - eslint: 8.8.0 - eslint-plugin-es: 3.0.1_eslint@8.8.0 + eslint: 8.12.0 + eslint-plugin-es: 3.0.1_eslint@8.12.0 eslint-utils: 2.1.0 ignore: 5.2.0 minimatch: 3.0.4 @@ -4586,8 +4722,8 @@ packages: estraverse: 4.3.0 dev: true - /eslint-scope/7.1.0: - resolution: {integrity: sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg==} + /eslint-scope/7.1.1: + resolution: {integrity: sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: esrecurse: 4.3.0 @@ -4601,13 +4737,13 @@ packages: eslint-visitor-keys: 1.3.0 dev: true - /eslint-utils/3.0.0_eslint@8.8.0: + /eslint-utils/3.0.0_eslint@8.12.0: resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} peerDependencies: eslint: '>=5' dependencies: - eslint: 8.8.0 + eslint: 8.12.0 eslint-visitor-keys: 2.1.0 dev: true @@ -4621,28 +4757,28 @@ packages: engines: {node: '>=10'} dev: true - /eslint-visitor-keys/3.2.0: - resolution: {integrity: sha512-IOzT0X126zn7ALX0dwFiUQEdsfzrm4+ISsQS8nukaJXwEyYKRSnEIIDULYg1mCtGp7UUXgfGl7BIolXREQK+XQ==} + /eslint-visitor-keys/3.3.0: + resolution: {integrity: sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /eslint/8.8.0: - resolution: {integrity: sha512-H3KXAzQGBH1plhYS3okDix2ZthuYJlQQEGE5k0IKuEqUSiyu4AmxxlJ2MtTYeJ3xB4jDhcYCwGOg2TXYdnDXlQ==} + /eslint/8.12.0: + resolution: {integrity: sha512-it1oBL9alZg1S8UycLm5YDMAkIhtH6FtAzuZs6YvoGVldWjbS08BkAdb/ymP9LlAyq8koANu32U7Ib/w+UNh8Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true dependencies: - '@eslint/eslintrc': 1.0.5 + '@eslint/eslintrc': 1.2.1 '@humanwhocodes/config-array': 0.9.2 ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 - debug: 4.3.3 + debug: 4.3.4 doctrine: 3.0.0 escape-string-regexp: 4.0.0 - eslint-scope: 7.1.0 - eslint-utils: 3.0.0_eslint@8.8.0 - eslint-visitor-keys: 3.2.0 - espree: 9.3.0 + eslint-scope: 7.1.1 + eslint-utils: 3.0.0_eslint@8.12.0 + eslint-visitor-keys: 3.3.0 + espree: 9.3.1 esquery: 1.4.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 @@ -4670,13 +4806,13 @@ packages: - supports-color dev: true - /espree/9.3.0: - resolution: {integrity: sha512-d/5nCsb0JcqsSEeQzFZ8DH1RmxPcglRWh24EFTlUEmCKoehXGdpsx0RkHDubqUI8LSAIKMQp4r9SzQ3n+sm4HQ==} + /espree/9.3.1: + resolution: {integrity: sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: acorn: 8.7.0 acorn-jsx: 5.3.2_acorn@8.7.0 - eslint-visitor-keys: 3.2.0 + eslint-visitor-keys: 3.3.0 dev: true /esprima/4.0.1: @@ -4812,7 +4948,7 @@ packages: engines: {node: '>= 10.17.0'} hasBin: true dependencies: - debug: 4.3.3 + debug: 4.3.4 get-stream: 5.2.0 yauzl: 2.10.0 optionalDependencies: @@ -4974,6 +5110,16 @@ packages: graceful-fs: 4.2.8 jsonfile: 6.1.0 universalify: 2.0.0 + dev: false + + /fs-extra/10.0.1: + resolution: {integrity: sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag==} + engines: {node: '>=12'} + dependencies: + graceful-fs: 4.2.9 + jsonfile: 6.1.0 + universalify: 2.0.0 + dev: true /fs-extra/7.0.1: resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} @@ -5170,6 +5316,7 @@ packages: /graceful-fs/4.2.8: resolution: {integrity: sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==} + dev: false /graceful-fs/4.2.9: resolution: {integrity: sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==} @@ -5179,7 +5326,7 @@ packages: engines: {node: '>=0.4.7'} hasBin: true dependencies: - minimist: 1.2.5 + minimist: 1.2.6 neo-async: 2.6.2 source-map: 0.6.1 wordwrap: 1.0.0 @@ -5315,12 +5462,12 @@ packages: dependencies: '@tootallnate/once': 1.1.2 agent-base: 6.0.2 - debug: 4.3.3 + debug: 4.3.4 transitivePeerDependencies: - supports-color dev: true - /http-proxy/1.18.1_debug@4.3.3: + /http-proxy/1.18.1_debug@4.3.4: resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==} engines: {node: '>=8.0.0'} dependencies: @@ -5336,7 +5483,7 @@ packages: engines: {node: '>= 6'} dependencies: agent-base: 6.0.2 - debug: 4.3.3 + debug: 4.3.4 transitivePeerDependencies: - supports-color @@ -5356,18 +5503,13 @@ packages: resolution: {integrity: sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=} dev: true - /icss-utils/5.1.0_postcss@8.4.6: + /icss-utils/5.1.0_postcss@8.4.12: resolution: {integrity: sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==} engines: {node: ^10 || ^12 || >= 14} peerDependencies: postcss: ^8.1.0 dependencies: - postcss: 8.4.6 - dev: true - - /ignore/4.0.6: - resolution: {integrity: sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==} - engines: {node: '>= 4'} + postcss: 8.4.12 dev: true /ignore/5.2.0: @@ -5725,7 +5867,7 @@ packages: resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} engines: {node: '>=10'} dependencies: - debug: 4.3.3 + debug: 4.3.4 istanbul-lib-coverage: 3.2.0 source-map: 0.6.1 transitivePeerDependencies: @@ -5756,7 +5898,7 @@ packages: '@jest/environment': 27.5.1 '@jest/test-result': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 16.11.22 + '@types/node': 16.11.26 chalk: 4.1.2 co: 4.6.0 dedent: 0.7.0 @@ -5839,7 +5981,7 @@ packages: pretty-format: 27.5.1 slash: 3.0.0 strip-json-comments: 3.1.1 - ts-node: 10.4.0_afa64049ed426af4e84a055f796a9f2e + ts-node: 10.4.0_44ef5af6cbbc24239b4e70b5c7b0d7a6 transitivePeerDependencies: - bufferutil - canvas @@ -5847,16 +5989,6 @@ packages: - utf-8-validate dev: true - /jest-diff/27.4.2: - resolution: {integrity: sha512-ujc9ToyUZDh9KcqvQDkk/gkbf6zSaeEg9AiBxtttXW59H/AcqEYp1ciXAtJp+jXWva5nAf/ePtSsgWwE5mqp4Q==} - engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - dependencies: - chalk: 4.1.2 - diff-sequences: 27.4.0 - jest-get-type: 27.4.0 - pretty-format: 27.4.2 - dev: true - /jest-diff/27.5.1: resolution: {integrity: sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -5892,7 +6024,7 @@ packages: '@jest/environment': 27.5.1 '@jest/fake-timers': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 16.11.22 + '@types/node': 16.11.26 jest-mock: 27.5.1 jest-util: 27.5.1 jsdom: 16.7.0 @@ -5910,16 +6042,11 @@ packages: '@jest/environment': 27.5.1 '@jest/fake-timers': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 16.11.22 + '@types/node': 16.11.26 jest-mock: 27.5.1 jest-util: 27.5.1 dev: true - /jest-get-type/27.4.0: - resolution: {integrity: sha512-tk9o+ld5TWq41DkK14L4wox4s2D9MtTpKaAVzXfr5CUKm5ZK2ExcaFE0qls2W71zE/6R2TxxrK9w2r6svAFDBQ==} - engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - dev: true - /jest-get-type/27.5.1: resolution: {integrity: sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -5931,7 +6058,7 @@ packages: dependencies: '@jest/types': 27.5.1 '@types/graceful-fs': 4.1.5 - '@types/node': 16.11.22 + '@types/node': 16.11.26 anymatch: 3.1.2 fb-watchman: 2.0.1 graceful-fs: 4.2.9 @@ -5953,7 +6080,7 @@ packages: '@jest/source-map': 27.5.1 '@jest/test-result': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 16.11.22 + '@types/node': 16.11.26 chalk: 4.1.2 co: 4.6.0 expect: 27.5.1 @@ -6008,7 +6135,7 @@ packages: engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: '@jest/types': 27.5.1 - '@types/node': 16.11.22 + '@types/node': 16.11.26 dev: true /jest-pnp-resolver/1.2.2_jest-resolve@27.5.1: @@ -6064,7 +6191,7 @@ packages: '@jest/test-result': 27.5.1 '@jest/transform': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 16.11.22 + '@types/node': 16.11.26 chalk: 4.1.2 emittery: 0.8.1 graceful-fs: 4.2.9 @@ -6121,7 +6248,7 @@ packages: resolution: {integrity: sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: - '@types/node': 16.11.22 + '@types/node': 16.11.26 graceful-fs: 4.2.9 dev: true @@ -6155,24 +6282,12 @@ packages: - supports-color dev: true - /jest-util/27.4.2: - resolution: {integrity: sha512-YuxxpXU6nlMan9qyLuxHaMMOzXAl5aGZWCSzben5DhLHemYQxCc4YK+4L3ZrCutT8GPQ+ui9k5D8rUJoDioMnA==} - engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - dependencies: - '@jest/types': 27.4.2 - '@types/node': 16.11.22 - chalk: 4.1.2 - ci-info: 3.3.0 - graceful-fs: 4.2.9 - picomatch: 2.3.0 - dev: true - /jest-util/27.5.1: resolution: {integrity: sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: '@jest/types': 27.5.1 - '@types/node': 16.11.22 + '@types/node': 16.11.26 chalk: 4.1.2 ci-info: 3.3.0 graceful-fs: 4.2.9 @@ -6197,7 +6312,7 @@ packages: dependencies: '@jest/test-result': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 16.11.22 + '@types/node': 16.11.26 ansi-escapes: 4.3.2 chalk: 4.1.2 jest-util: 27.5.1 @@ -6208,7 +6323,7 @@ packages: resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} engines: {node: '>= 10.13.0'} dependencies: - '@types/node': 16.11.22 + '@types/node': 16.11.26 merge-stream: 2.0.0 supports-color: 8.1.1 dev: true @@ -6336,6 +6451,13 @@ packages: hasBin: true dependencies: minimist: 1.2.5 + dev: false + + /json5/2.2.1: + resolution: {integrity: sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==} + engines: {node: '>=6'} + hasBin: true + dev: true /jsonfile/4.0.0: resolution: {integrity: sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=} @@ -6439,21 +6561,22 @@ packages: /lines-and-columns/1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - /lint-staged/12.3.3: - resolution: {integrity: sha512-OqcLsqcPOqzvsfkxjeBpZylgJ3SRG1RYqc9LxC6tkt6tNsq1bNVkAixBwX09f6CobcHswzqVOCBpFR1Fck0+ag==} + /lint-staged/12.3.7: + resolution: {integrity: sha512-/S4D726e2GIsDVWIk1XGvheCaDm1SJRQp8efamZFWJxQMVEbOwSysp7xb49Oo73KYCdy97mIWinhlxcoNqIfIQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} hasBin: true dependencies: cli-truncate: 3.1.0 colorette: 2.0.16 commander: 8.3.0 - debug: 4.3.3_supports-color@9.2.1 + debug: 4.3.4_supports-color@9.2.1 execa: 5.1.1 lilconfig: 2.0.4 listr2: 4.0.2 micromatch: 4.0.4 normalize-path: 3.0.0 object-inspect: 1.12.0 + pidtree: 0.5.0 string-argv: 0.3.1 supports-color: 9.2.1 yaml: 1.10.2 @@ -6585,6 +6708,12 @@ packages: dependencies: sourcemap-codec: 1.4.8 + /magic-string/0.26.1: + resolution: {integrity: sha512-ndThHmvgtieXe8J/VGPjG+Apu7v7ItcD5mhEIvOscWjPF/ccOiLxHaSuCAS2G+3x4GKsAbT8u7zdyamupui8Tg==} + engines: {node: '>=12'} + dependencies: + sourcemap-codec: 1.4.8 + /make-dir/2.1.0: resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} engines: {node: '>=6'} @@ -6672,6 +6801,14 @@ packages: braces: 3.0.2 picomatch: 2.3.0 + /micromatch/4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + dev: true + /mime-db/1.46.0: resolution: {integrity: sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ==} engines: {node: '>= 0.6'} @@ -6700,11 +6837,12 @@ packages: resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} engines: {node: '>=4'} hasBin: true + requiresBuild: true dev: true - /mime/2.6.0: - resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==} - engines: {node: '>=4.0.0'} + /mime/3.0.0: + resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} + engines: {node: '>=10.0.0'} hasBin: true dev: true @@ -6784,6 +6922,10 @@ packages: /minimist/1.2.5: resolution: {integrity: sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==} + dev: false + + /minimist/1.2.6: + resolution: {integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==} /minipass/3.1.6: resolution: {integrity: sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==} @@ -6845,11 +6987,10 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - /nanoid/3.2.0: - resolution: {integrity: sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==} + /nanoid/3.3.1: + resolution: {integrity: sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - dev: false /natural-compare/1.4.0: resolution: {integrity: sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=} @@ -6914,8 +7055,8 @@ packages: engines: {node: '>= 6.0.0'} dev: true - /node-forge/1.2.1: - resolution: {integrity: sha512-Fcvtbb+zBcZXbTTVwqGA5W+MKBj56UjVRevvchv5XrcyXbmNdesfZL37nlcWOfpgHhgmxApw3tQbTr4CqNmX4w==} + /node-forge/1.3.0: + resolution: {integrity: sha512-08ARB91bUi6zNKzVmaj3QO7cr397uiDT2nJ63cHjyNtCTWIgvS47j3eT0WfzUwS9+6Z5YshRaoasFkXCKrIYbA==} engines: {node: '>= 6.13.0'} dev: true @@ -7259,12 +7400,22 @@ packages: resolution: {integrity: sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==} engines: {node: '>=8.6'} + /picomatch/2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + /pidtree/0.3.1: resolution: {integrity: sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==} engines: {node: '>=0.10'} hasBin: true dev: true + /pidtree/0.5.0: + resolution: {integrity: sha512-9nxspIM7OpZuhBxPg73Zvyq7j1QMPMPsGKTqRc2XOaFQauDvoNz9fM1Wdkjmeo7l9GXOZiRs97sPkuayl39wjA==} + engines: {node: '>=0.10'} + hasBin: true + dev: true + /pify/2.3.0: resolution: {integrity: sha1-7RQaasBDqEnqWISY59yosVMw6Qw=} engines: {node: '>=0.10.0'} @@ -7286,6 +7437,13 @@ packages: engines: {node: '>= 6'} dev: true + /pixelmatch/5.2.1: + resolution: {integrity: sha512-WjcAdYSnKrrdDdqTcVEY7aB7UhhwjYQKYhHiBXdJef0MOaQeYpUdQ+iVyBLa5YBKS8MPVPPMX7rpOByISLpeEQ==} + hasBin: true + dependencies: + pngjs: 4.0.1 + dev: true + /pkg-dir/4.2.0: resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} engines: {node: '>=8'} @@ -7293,38 +7451,40 @@ packages: find-up: 4.1.0 dev: true - /playwright-chromium/1.18.1: - resolution: {integrity: sha512-DHAOdzZhhu4pMe9yg2zL49JSGXLHTO+DL76duukoy807o+ccu1tEbqyUId46ogLYk7rOjblVK6o7YG/vyVCasQ==} + /playwright-chromium/1.20.1: + resolution: {integrity: sha512-zDJm59GEOWrHqpByblzaKI+bpswd3nrheCoAGOTBDX7MsQYwAV/ZBS2aCJzeGxDt/67brq/fQuZse3GwnCk+6A==} engines: {node: '>=12'} hasBin: true requiresBuild: true dependencies: - playwright-core: 1.18.1 + playwright-core: 1.20.1 transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate dev: true - /playwright-core/1.18.1: - resolution: {integrity: sha512-NALGl8R1GHzGLlhUApmpmfh6M1rrrPcDTygWvhTbprxwGB9qd/j9DRwyn4HTQcUB6o0/VOpo46fH9ez3+D/Rog==} + /playwright-core/1.20.1: + resolution: {integrity: sha512-A8ZsZ09gaSbxP0UijoLyzp3LJc0kWMxDooLPi+mm4/5iYnTbd6PF5nKjoFw1a7KwjZIEgdhJduah4BcUIh+IPA==} engines: {node: '>=12'} hasBin: true dependencies: + colors: 1.4.0 commander: 8.3.0 debug: 4.3.3 extract-zip: 2.0.1 https-proxy-agent: 5.0.0 jpeg-js: 0.4.3 - mime: 2.6.0 - pngjs: 5.0.0 + mime: 3.0.0 + pixelmatch: 5.2.1 + pngjs: 6.0.0 progress: 2.0.3 proper-lockfile: 4.1.2 proxy-from-env: 1.1.0 rimraf: 3.0.2 socks-proxy-agent: 6.1.1 stack-utils: 2.0.5 - ws: 7.5.6 + ws: 8.4.2 yauzl: 2.10.0 yazl: 2.5.1 transitivePeerDependencies: @@ -7333,18 +7493,23 @@ packages: - utf-8-validate dev: true - /pngjs/5.0.0: - resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==} - engines: {node: '>=10.13.0'} + /pngjs/4.0.1: + resolution: {integrity: sha512-rf5+2/ioHeQxR6IxuYNYGFytUyG3lma/WW1nsmjeHlWwtb2aByla6dkVc8pmJ9nplzkTA0q2xx7mMWrOTqT4Gg==} + engines: {node: '>=8.0.0'} + dev: true + + /pngjs/6.0.0: + resolution: {integrity: sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==} + engines: {node: '>=12.13.0'} dev: true - /postcss-import/14.0.2_postcss@8.4.6: - resolution: {integrity: sha512-BJ2pVK4KhUyMcqjuKs9RijV5tatNzNa73e/32aBVE/ejYPe37iH+6vAu9WvqUkB5OAYgLHzbSvzHnorybJCm9g==} + /postcss-import/14.1.0_postcss@8.4.12: + resolution: {integrity: sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==} engines: {node: '>=10.0.0'} peerDependencies: postcss: ^8.0.0 dependencies: - postcss: 8.4.6 + postcss: 8.4.12 postcss-value-parser: 4.2.0 read-cache: 1.0.0 resolve: 1.22.0 @@ -7369,7 +7534,7 @@ packages: dependencies: import-cwd: 3.0.0 lilconfig: 2.0.4 - ts-node: 10.4.0_afa64049ed426af4e84a055f796a9f2e + ts-node: 10.4.0_44ef5af6cbbc24239b4e70b5c7b0d7a6 yaml: 1.10.2 dev: false @@ -7383,64 +7548,64 @@ packages: optional: true dependencies: lilconfig: 2.0.4 - ts-node: 10.4.0_afa64049ed426af4e84a055f796a9f2e + ts-node: 10.4.0_44ef5af6cbbc24239b4e70b5c7b0d7a6 yaml: 1.10.2 dev: true - /postcss-modules-extract-imports/3.0.0_postcss@8.4.6: + /postcss-modules-extract-imports/3.0.0_postcss@8.4.12: resolution: {integrity: sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==} engines: {node: ^10 || ^12 || >= 14} peerDependencies: postcss: ^8.1.0 dependencies: - postcss: 8.4.6 + postcss: 8.4.12 dev: true - /postcss-modules-local-by-default/4.0.0_postcss@8.4.6: + /postcss-modules-local-by-default/4.0.0_postcss@8.4.12: resolution: {integrity: sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==} engines: {node: ^10 || ^12 || >= 14} peerDependencies: postcss: ^8.1.0 dependencies: - icss-utils: 5.1.0_postcss@8.4.6 - postcss: 8.4.6 + icss-utils: 5.1.0_postcss@8.4.12 + postcss: 8.4.12 postcss-selector-parser: 6.0.8 postcss-value-parser: 4.2.0 dev: true - /postcss-modules-scope/3.0.0_postcss@8.4.6: + /postcss-modules-scope/3.0.0_postcss@8.4.12: resolution: {integrity: sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==} engines: {node: ^10 || ^12 || >= 14} peerDependencies: postcss: ^8.1.0 dependencies: - postcss: 8.4.6 + postcss: 8.4.12 postcss-selector-parser: 6.0.8 dev: true - /postcss-modules-values/4.0.0_postcss@8.4.6: + /postcss-modules-values/4.0.0_postcss@8.4.12: resolution: {integrity: sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==} engines: {node: ^10 || ^12 || >= 14} peerDependencies: postcss: ^8.1.0 dependencies: - icss-utils: 5.1.0_postcss@8.4.6 - postcss: 8.4.6 + icss-utils: 5.1.0_postcss@8.4.12 + postcss: 8.4.12 dev: true - /postcss-modules/4.3.0_postcss@8.4.6: - resolution: {integrity: sha512-zoUttLDSsbWDinJM9jH37o7hulLRyEgH6fZm2PchxN7AZ8rkdWiALyNhnQ7+jg7cX9f10m6y5VhHsrjO0Mf/DA==} + /postcss-modules/4.3.1_postcss@8.4.12: + resolution: {integrity: sha512-ItUhSUxBBdNamkT3KzIZwYNNRFKmkJrofvC2nWab3CPKhYBQ1f27XXh1PAPE27Psx58jeelPsxWB/+og+KEH0Q==} peerDependencies: postcss: ^8.0.0 dependencies: generic-names: 4.0.0 icss-replace-symbols: 1.1.0 lodash.camelcase: 4.3.0 - postcss: 8.4.6 - postcss-modules-extract-imports: 3.0.0_postcss@8.4.6 - postcss-modules-local-by-default: 4.0.0_postcss@8.4.6 - postcss-modules-scope: 3.0.0_postcss@8.4.6 - postcss-modules-values: 4.0.0_postcss@8.4.6 + postcss: 8.4.12 + postcss-modules-extract-imports: 3.0.0_postcss@8.4.12 + postcss-modules-local-by-default: 4.0.0_postcss@8.4.12 + postcss-modules-scope: 3.0.0_postcss@8.4.12 + postcss-modules-values: 4.0.0_postcss@8.4.12 string-hash: 1.1.3 dev: true @@ -7466,22 +7631,21 @@ packages: /postcss-value-parser/4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - /postcss/8.4.5: - resolution: {integrity: sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==} + /postcss/8.4.12: + resolution: {integrity: sha512-lg6eITwYe9v6Hr5CncVbK70SoioNQIq81nsaG86ev5hAidQvmOeETBqs7jm43K2F5/Ley3ytDtriImV6TpNiSg==} engines: {node: ^10 || ^12 || >=14} dependencies: - nanoid: 3.1.30 + nanoid: 3.3.1 picocolors: 1.0.0 source-map-js: 1.0.2 - /postcss/8.4.6: - resolution: {integrity: sha512-OovjwIzs9Te46vlEx7+uXB0PLijpwjXGKXjVGGPIGubGpq7uh5Xgf6D6FiJ/SzJMBosHDp6a2hiXOS97iBXcaA==} + /postcss/8.4.5: + resolution: {integrity: sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==} engines: {node: ^10 || ^12 || >=14} dependencies: - nanoid: 3.2.0 + nanoid: 3.1.30 picocolors: 1.0.0 source-map-js: 1.0.2 - dev: false /preact/10.6.4: resolution: {integrity: sha512-WyosM7pxGcndU8hY0OQlLd54tOU+qmG45QXj2dAYrL11HoyU/EzOSTlpJsirbBr1QW7lICxSsVJJmcmUglovHQ==} @@ -7497,22 +7661,12 @@ packages: engines: {node: '>= 0.8.0'} dev: true - /prettier/2.5.1: - resolution: {integrity: sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==} + /prettier/2.6.1: + resolution: {integrity: sha512-8UVbTBYGwN37Bs9LERmxCPjdvPxlEowx2urIL6urHzdb3SDq4B/Z6xLFCblrSnE4iKWcS6ziJ3aOYrc1kz/E2A==} engines: {node: '>=10.13.0'} hasBin: true dev: true - /pretty-format/27.4.2: - resolution: {integrity: sha512-p0wNtJ9oLuvgOQDEIZ9zQjZffK7KtyR6Si0jnXULIDwrlNF8Cuir3AZP0hHv0jmKuNN/edOnbMjnzd4uTcmWiw==} - engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - dependencies: - '@jest/types': 27.4.2 - ansi-regex: 5.0.1 - ansi-styles: 5.2.0 - react-is: 17.0.2 - dev: true - /pretty-format/27.5.1: resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -7904,7 +8058,7 @@ packages: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} dependencies: - picomatch: 2.3.0 + picomatch: 2.3.1 /redent/3.0.0: resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} @@ -8101,9 +8255,9 @@ packages: engines: {node: '>=8.9.0'} hasBin: true dependencies: - chokidar: 3.5.2 + chokidar: 3.5.3 immutable: 4.0.0 - source-map-js: 1.0.1 + source-map-js: 1.0.2 dev: true /sax/1.2.4: @@ -8301,7 +8455,7 @@ packages: engines: {node: '>= 10'} dependencies: agent-base: 6.0.2 - debug: 4.3.3 + debug: 4.3.4 socks: 2.6.1 transitivePeerDependencies: - supports-color @@ -8315,17 +8469,13 @@ packages: smart-buffer: 4.2.0 dev: true - /source-map-js/1.0.1: - resolution: {integrity: sha512-4+TN2b3tqOCd/kaGRJ/sTYA0tR0mdXx26ipdolxcwtJVqEnqNYvlCAt1q3ypy4QMlYus+Zh34RNtYLoq2oQ4IA==} - engines: {node: '>=0.10.0'} - dev: true - /source-map-js/1.0.2: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} engines: {node: '>=0.10.0'} /source-map-resolve/0.6.0: resolution: {integrity: sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==} + deprecated: See https://github.com/lydell/source-map-resolve#deprecated dependencies: atob: 2.1.2 decode-uri-component: 0.2.0 @@ -8738,15 +8888,10 @@ packages: supports-hyperlinks: 2.2.0 dev: true - /terser/5.10.0_acorn@8.7.0: - resolution: {integrity: sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA==} + /terser/5.12.1: + resolution: {integrity: sha512-NXbs+7nisos5E+yXwAD+y7zrcTkMqb0dEJxIGtSKPdCBzopf7ni4odPul2aechpV7EXNvOudYOX2bb5tln1jbQ==} engines: {node: '>=10'} hasBin: true - peerDependencies: - acorn: ^8.5.0 - peerDependenciesMeta: - acorn: - optional: true dependencies: acorn: 8.7.0 commander: 2.20.3 @@ -8874,15 +9019,15 @@ packages: utf8-byte-length: 1.0.4 dev: true - /ts-jest/27.1.3_83f39b7ecbbd8f6012802ab3141c12c4: - resolution: {integrity: sha512-6Nlura7s6uM9BVUAoqLH7JHyMXjz8gluryjpPXxr3IxZdAXnU6FhjvVLHFtfd1vsE1p8zD1OJfskkc0jhTSnkA==} + /ts-jest/27.1.4_4dfe14e0e8266437469ae0475a5c09ac: + resolution: {integrity: sha512-qjkZlVPWVctAezwsOD1OPzbZ+k7zA5z3oxII4dGdZo5ggX/PL7kvwTM0pXTr10fAtbiVpJaL3bWd502zAhpgSQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} hasBin: true peerDependencies: '@babel/core': '>=7.0.0-beta.0 <8' '@types/jest': ^27.0.0 babel-jest: '>=27.0.0 <28' - esbuild: ~0.14.0 + esbuild: '*' jest: ^27.0.0 typescript: '>=3.8 <5.0' peerDependenciesMeta: @@ -8895,13 +9040,13 @@ packages: esbuild: optional: true dependencies: - '@types/jest': 27.4.0 + '@types/jest': 27.4.1 bs-logger: 0.2.6 - esbuild: 0.14.14 + esbuild: 0.14.27 fast-json-stable-stringify: 2.1.0 jest: 27.5.1_ts-node@10.4.0 - jest-util: 27.4.2 - json5: 2.2.0 + jest-util: 27.5.1 + json5: 2.2.1 lodash.memoize: 4.1.2 make-error: 1.3.6 semver: 7.3.5 @@ -8909,7 +9054,7 @@ packages: yargs-parser: 20.2.9 dev: true - /ts-node/10.4.0_afa64049ed426af4e84a055f796a9f2e: + /ts-node/10.4.0_44ef5af6cbbc24239b4e70b5c7b0d7a6: resolution: {integrity: sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A==} hasBin: true peerDependencies: @@ -8928,7 +9073,7 @@ packages: '@tsconfig/node12': 1.0.9 '@tsconfig/node14': 1.0.1 '@tsconfig/node16': 1.0.2 - '@types/node': 16.11.22 + '@types/node': 16.11.26 acorn: 8.7.0 acorn-walk: 8.2.0 arg: 4.1.3 @@ -8939,8 +9084,8 @@ packages: yn: 3.1.1 dev: true - /tsconfck/1.2.0_typescript@4.5.4: - resolution: {integrity: sha512-uKBM6x6i5e7Tfof5Zhll2ypgYKwWZhsxsHOoCH/7enlcHjjlcZ8FnxFrqgVFtpN6ymzZX3zoDaVGIlkh/g4x6w==} + /tsconfck/1.2.1_typescript@4.5.4: + resolution: {integrity: sha512-x28dvgpazY0+Gdpheb+D47NiaepLoueunDXlNQ6gVruu9HJbUj3M07ORgjmOQBUpPbXUAQXyfACc8Mi/jlLDVw==} engines: {node: ^12.20 || ^14.13.1 || >= 16} hasBin: true peerDependencies: @@ -9156,9 +9301,9 @@ packages: engines: {node: '>= 0.8'} dev: true - /vitepress/0.21.6: - resolution: {integrity: sha512-OzwD2cTfvoK5VKV0UWSqu4XvUOz4vWFJ4Bdi0z8GoVkTFXkfmbFawEDVXAZwzu0Hn4/VLopgmEyooc91iGKFlg==} - engines: {node: '>=12.0.0'} + /vitepress/0.22.3: + resolution: {integrity: sha512-Yfvu/rent2vp/TXIDZMutS6ft2TJPn4xngS48PYFWDEbuFI2ccUAXM481lF1qVVnCKxfh4g8e/KPvevSJdg1Bw==} + engines: {node: '>=14.0.0'} hasBin: true dependencies: '@docsearch/css': 3.0.0-alpha.42 @@ -9166,7 +9311,7 @@ packages: '@vitejs/plugin-vue': link:packages/plugin-vue prismjs: 1.25.0 vite: link:packages/vite - vue: 3.2.29 + vue: 3.2.31 transitivePeerDependencies: - '@algolia/client-search' - '@types/react' @@ -9197,25 +9342,14 @@ packages: '@vue/server-renderer': 3.2.26_vue@3.2.26 '@vue/shared': 3.2.26 - /vue/3.2.29: - resolution: {integrity: sha512-cFIwr7LkbtCRanjNvh6r7wp2yUxfxeM2yPpDQpAfaaLIGZSrUmLbNiSze9nhBJt5MrZ68Iqt0O5scwAMEVxF+Q==} + /vue/3.2.31: + resolution: {integrity: sha512-odT3W2tcffTiQCy57nOT93INw1auq5lYLLYtWpPYQQYQOOdHiqFct9Xhna6GJ+pJQaF67yZABraH47oywkJgFw==} dependencies: - '@vue/compiler-dom': 3.2.29 - '@vue/compiler-sfc': 3.2.29 - '@vue/runtime-dom': 3.2.29 - '@vue/server-renderer': 3.2.29_vue@3.2.29 - '@vue/shared': 3.2.29 - dev: true - - /vue/3.2.30: - resolution: {integrity: sha512-ZmTFWVJUX2XADkuOB8GcLTuxnBLogjJBTNVrM7WsTnjqRQ+VR8bLNrvNsbn8vj/LaP5+0WFAPrpngOYE2x+e+Q==} - dependencies: - '@vue/compiler-dom': 3.2.30 - '@vue/compiler-sfc': 3.2.30 - '@vue/runtime-dom': 3.2.30 - '@vue/server-renderer': 3.2.30_vue@3.2.30 - '@vue/shared': 3.2.30 - dev: true + '@vue/compiler-dom': 3.2.31 + '@vue/compiler-sfc': 3.2.31 + '@vue/runtime-dom': 3.2.31 + '@vue/server-renderer': 3.2.31_vue@3.2.31 + '@vue/shared': 3.2.31 /vuex/4.0.2_vue@3.2.26: resolution: {integrity: sha512-M6r8uxELjZIK8kTKDGgZTYX/ahzblnzC4isU1tpmEuOIIKmV+TRdc+H4s8ds2NuZ7wpUTdGRzJRtoj+lI+pc0Q==} @@ -9391,6 +9525,19 @@ packages: optional: true dev: true + /ws/8.4.2: + resolution: {integrity: sha512-Kbk4Nxyq7/ZWqr/tarI9yIt/+iNNFOjBXEWgTb4ydaNHBNGgvf2QHbS9fdfsndfjFlFwEd4Al+mw83YkaD10ZA==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: true + /ws/8.5.0: resolution: {integrity: sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==} engines: {node: '>=10.0.0'} diff --git a/scripts/jestGlobalSetup.cjs b/scripts/jestGlobalSetup.cjs index 9640f70c5a8291..7341cba40968d9 100644 --- a/scripts/jestGlobalSetup.cjs +++ b/scripts/jestGlobalSetup.cjs @@ -21,11 +21,21 @@ module.exports = async () => { const tempDir = path.resolve(__dirname, '../packages/temp') await fs.remove(tempDir) - await fs.copy(path.resolve(__dirname, '../packages/playground'), tempDir, { - dereference: false, - filter(file) { - file = file.replace(/\\/g, '/') - return !file.includes('__tests__') && !file.match(/dist(\/|$)/) - } - }) + await fs + .copy(path.resolve(__dirname, '../packages/playground'), tempDir, { + dereference: false, + filter(file) { + file = file.replace(/\\/g, '/') + return !file.includes('__tests__') && !file.match(/dist(\/|$)/) + } + }) + .catch(async (error) => { + if (error.code === 'EPERM' && error.syscall === 'symlink') { + throw new Error( + 'Could not create symlinks. On Windows, consider activating Developer Mode to allow non-admin users to create symlinks by following the instructions at https://docs.microsoft.com/en-us/windows/apps/get-started/enable-your-device-for-development.' + ) + } else { + throw error + } + }) } diff --git a/scripts/jestPerTestSetup.ts b/scripts/jestPerTestSetup.ts index 9c15edf9f059bf..150c02eed5b76c 100644 --- a/scripts/jestPerTestSetup.ts +++ b/scripts/jestPerTestSetup.ts @@ -4,12 +4,12 @@ import { resolve, dirname } from 'path' import sirv from 'sirv' import type { ViteDevServer, - UserConfig, + InlineConfig, PluginOption, ResolvedConfig, Logger } from 'vite' -import { createServer, build } from 'vite' +import { createServer, build, mergeConfig } from 'vite' import type { Page, ConsoleMessage } from 'playwright-chromium' import type { RollupError, RollupWatcher, RollupWatcherEvent } from 'rollup' @@ -90,9 +90,16 @@ beforeAll(async () => { } } + const testCustomConfig = resolve(dirname(testPath), 'vite.config.js') + let config: InlineConfig | undefined + if (fs.existsSync(testCustomConfig)) { + // test has custom server configuration. + config = require(testCustomConfig) + } + const serverLogs: string[] = [] - const options: UserConfig = { + const options: InlineConfig = { root: rootDir, logLevel: 'silent', server: { @@ -114,11 +121,15 @@ beforeAll(async () => { customLogger: createInMemoryLogger(serverLogs) } + setupConsoleWarnCollector(serverLogs) + global.serverLogs = serverLogs if (!isBuildTest) { process.env.VITE_INLINE = 'inline-serve' - server = await (await createServer(options)).listen() + server = await ( + await createServer(mergeConfig(options, config || {})) + ).listen() // use resolved port/base from server const base = server.config.base === '/' ? '' : server.config.base const url = @@ -135,14 +146,14 @@ beforeAll(async () => { } }) options.plugins = [resolvedPlugin()] - const rollupOutput = await build(options) + const rollupOutput = await build(mergeConfig(options, config || {})) const isWatch = !!resolvedConfig!.build.watch // in build watch,call startStaticServer after the build is complete if (isWatch) { global.watcher = rollupOutput as RollupWatcher await notifyRebuildComplete(global.watcher) } - const url = (global.viteTestUrl = await startStaticServer()) + const url = (global.viteTestUrl = await startStaticServer(config)) await page.goto(url) } } @@ -170,13 +181,15 @@ afterAll(async () => { } }) -function startStaticServer(): Promise { - // check if the test project has base config - const configFile = resolve(rootDir, 'vite.config.js') - let config: UserConfig | undefined - try { - config = require(configFile) - } catch (e) {} +function startStaticServer(config?: InlineConfig): Promise { + if (!config) { + // check if the test project has base config + const configFile = resolve(rootDir, 'vite.config.js') + try { + config = require(configFile) + } catch (e) {} + } + // fallback internal base to '' const base = (config?.base ?? '/') === '/' ? '' : config?.base ?? '' @@ -263,3 +276,11 @@ function createInMemoryLogger(logs: string[]): Logger { return logger } + +function setupConsoleWarnCollector(logs: string[]) { + const warn = console.warn + console.warn = (...args) => { + serverLogs.push(args.join(' ')) + return warn.call(console, ...args) + } +} diff --git a/scripts/release.ts b/scripts/release.ts index d536eca1f70586..5c32c13b5cf5c8 100644 --- a/scripts/release.ts +++ b/scripts/release.ts @@ -88,7 +88,7 @@ async function main(): Promise { '--commit-path', '.' ] - if (pkgName !== 'vite') changelogArgs.push('--lerna-package', 'plugin-vue') + if (pkgName !== 'vite') changelogArgs.push('--lerna-package', pkgName) await run('npx', changelogArgs, { cwd: pkgDir }) const { stdout } = await run('git', ['diff'], { stdio: 'pipe' })