diff --git a/eslint.config.js b/eslint.config.js index d3432066a717..624d9673c406 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -13,6 +13,7 @@ export default antfu( 'test/core/src/self', 'test/workspaces/results.json', 'test/reporters/fixtures/with-syntax-error.test.js', + 'test/network-imports/public/slash@3.0.0.js', 'examples/**/mockServiceWorker.js', ], }, diff --git a/package.json b/package.json index 5882e0f1dc24..6d899091f737 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "test:run": "vitest run -r test/core", "test:all": "CI=true pnpm -r --stream run test --allowOnly", "test:ci": "CI=true pnpm -r --stream --filter !test-browser --filter !test-esm --filter !test-browser run test --allowOnly", - "test:ci:vm-threads": "CI=true pnpm -r --stream --filter !test-coverage --filter !test-single-thread --filter !test-browser --filter !test-esm --filter !test-browser --filter !example-react-testing-lib-msw run test --allowOnly --pool vmThreads", + "test:ci:vm-threads": "CI=true pnpm -r --stream --filter !test-coverage --filter !test-single-thread --filter !test-browser --filter !test-esm --filter !test-network-imports --filter !test-browser --filter !example-react-testing-lib-msw run test --allowOnly --pool vmThreads", "test:ci:no-threads": "CI=true pnpm -r --stream --filter !test-vm-threads --filter !test-coverage --filter !test-watch --filter !test-bail --filter !test-esm --filter !test-browser run test --allowOnly --pool forks", "typecheck": "tsc -p tsconfig.check.json --noEmit", "typecheck:why": "tsc -p tsconfig.check.json --noEmit --explainFiles > explainTypes.txt", diff --git a/packages/vite-node/src/externalize.ts b/packages/vite-node/src/externalize.ts index 2a579bea6287..e306bbba9a22 100644 --- a/packages/vite-node/src/externalize.ts +++ b/packages/vite-node/src/externalize.ts @@ -95,8 +95,9 @@ async function _shouldExternalize( return id // data: should be processed by native import, - // since it is a feature of ESM - if (id.startsWith('data:')) + // since it is a feature of ESM. + // also externalize network imports since nodejs allows it when --experimental-network-imports + if (id.startsWith('data:') || /^(https?:)?\/\//.test(id)) return id id = patchWindowsImportPath(id) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 42547a1957c1..afbdedaabc19 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1793,6 +1793,12 @@ importers: specifier: workspace:* version: link:../../packages/vitest + test/network-imports: + devDependencies: + vitest: + specifier: workspace:* + version: link:../../packages/vitest + test/path-resolution: devDependencies: '@edge-runtime/vm': diff --git a/test/network-imports/package.json b/test/network-imports/package.json new file mode 100644 index 000000000000..a8463ad9787e --- /dev/null +++ b/test/network-imports/package.json @@ -0,0 +1,11 @@ +{ + "name": "@vitest/test-network-imports", + "type": "module", + "private": true, + "scripts": { + "test": "vitest" + }, + "devDependencies": { + "vitest": "workspace:*" + } +} diff --git a/test/network-imports/public/slash@3.0.0.js b/test/network-imports/public/slash@3.0.0.js new file mode 100644 index 000000000000..a20adf9eb5bd --- /dev/null +++ b/test/network-imports/public/slash@3.0.0.js @@ -0,0 +1,5 @@ +/* eslint-disable */ +// copied from https://esm.sh/v133/slash@3.0.0/es2022/slash.mjs to reduce network issues in CI + +/* esm.sh - esbuild bundle(slash@3.0.0) es2022 production */ +var a=Object.create;var d=Object.defineProperty;var m=Object.getOwnPropertyDescriptor;var x=Object.getOwnPropertyNames;var g=Object.getPrototypeOf,p=Object.prototype.hasOwnProperty;var A=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),E=(e,t)=>{for(var r in t)d(e,r,{get:t[r],enumerable:!0})},u=(e,t,r,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of x(t))!p.call(e,n)&&n!==r&&d(e,n,{get:()=>t[n],enumerable:!(i=m(t,n))||i.enumerable});return e},o=(e,t,r)=>(u(e,t,"default"),r&&u(r,t,"default")),c=(e,t,r)=>(r=e!=null?a(g(e)):{},u(t||!e||!e.__esModule?d(r,"default",{value:e,enumerable:!0}):r,e));var f=A((h,_)=>{"use strict";_.exports=e=>{let t=/^\\\\\?\\/.test(e),r=/[^\u0000-\u0080]+/.test(e);return t||r?e:e.replace(/\\/g,"/")}});var s={};E(s,{default:()=>P});var L=c(f());o(s,c(f()));var{default:l,...N}=L,P=l!==void 0?l:N;export{P as default}; diff --git a/test/network-imports/test/basic.test.ts b/test/network-imports/test/basic.test.ts new file mode 100644 index 000000000000..21862089a4c9 --- /dev/null +++ b/test/network-imports/test/basic.test.ts @@ -0,0 +1,11 @@ +import { expect, test } from 'vitest' + +// @ts-expect-error network imports +import slash from 'http://localhost:9602/slash@3.0.0.js' + +// test without local server +// import slash from 'https://esm.sh/slash@3.0.0' + +test('network imports', () => { + expect(slash('foo\\bar')).toBe('foo/bar') +}) diff --git a/test/network-imports/vitest.config.ts b/test/network-imports/vitest.config.ts new file mode 100644 index 000000000000..d4fdcc4e457e --- /dev/null +++ b/test/network-imports/vitest.config.ts @@ -0,0 +1,24 @@ +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + poolOptions: { + threads: { + execArgv: ['--experimental-network-imports'], + }, + forks: { + execArgv: ['--experimental-network-imports'], + }, + // not supported? + // FAIL test/basic.test.ts [ test/basic.test.ts ] + // Error: ENOENT: no such file or directory, open 'http://localhost:9602/slash@3.0.0.js' + // ❯ Object.openSync node:fs:596:3 + // ❯ readFileSync node:fs:464:35 + vmThreads: { + execArgv: ['--experimental-network-imports'], + }, + }, + // let vite serve public/slash@3.0.0.js + api: 9602, + }, +})