Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: define process variable and using import.meta.env together did not work #3944

Merged
merged 4 commits into from Aug 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 4 additions & 2 deletions packages/vite-node/src/client.ts
Expand Up @@ -6,7 +6,7 @@ import { fileURLToPath, pathToFileURL } from 'node:url'
import vm from 'node:vm'
import { resolve } from 'pathe'
import createDebug from 'debug'
import { VALID_ID_PREFIX, cleanUrl, isInternalRequest, isNodeBuiltin, isPrimitive, normalizeModuleId, normalizeRequestId, slash, toFilePath } from './utils'
import { VALID_ID_PREFIX, cleanUrl, createImportMetaEnvProxy, isInternalRequest, isNodeBuiltin, isPrimitive, normalizeModuleId, normalizeRequestId, slash, toFilePath } from './utils'
import type { HotContext, ModuleCache, ViteNodeRunnerOptions } from './types'
import { extractSourceMap } from './source-map'

Expand All @@ -32,6 +32,8 @@ const clientStub = {
removeStyle: () => {},
}

const env = createImportMetaEnvProxy()

export const DEFAULT_REQUEST_STUBS: Record<string, Record<string, unknown>> = {
'/@vite/client': clientStub,
'@vite/client': clientStub,
Expand Down Expand Up @@ -299,7 +301,7 @@ export class ViteNodeRunner {
const modulePath = cleanUrl(moduleId)
// disambiguate the `<UNIT>:/` on windows: see nodejs/node#31710
const href = pathToFileURL(modulePath).href
const meta = { url: href }
const meta = { url: href, env }
const exports = Object.create(null)
Object.defineProperty(exports, Symbol.toStringTag, {
value: 'Module',
Expand Down
29 changes: 29 additions & 0 deletions packages/vite-node/src/utils.ts
Expand Up @@ -199,3 +199,32 @@ function traverseBetweenDirs(
longerDir = dirname(longerDir)
}
}

export function createImportMetaEnvProxy() {
// packages/vitest/src/node/plugins/index.ts:146
const booleanKeys = [
'DEV',
'PROD',
'SSR',
]
return new Proxy(process.env, {
get(_, key) {
if (typeof key !== 'string')
return undefined
if (booleanKeys.includes(key))
return !!process.env[key]
return process.env[key]
},
set(_, key, value) {
if (typeof key !== 'string')
return true

if (booleanKeys.includes(key))
process.env[key] = value ? '1' : ''
else
process.env[key] = value

return true
},
})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this implementation I have a question: if you set import.meta.env.SSR = false will it be false or true? Since process.env casts a value to a string, I would assume that process.env.SSR === 'false' which will be true when casted back to boolean

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's correct now.

}
2 changes: 1 addition & 1 deletion packages/vitest/src/node/plugins/ssrReplacer.ts
Expand Up @@ -23,7 +23,7 @@ export function SsrReplacerPlugin(): Plugin {
const startIndex = env.index!
const endIndex = startIndex + env[0].length

s.overwrite(startIndex, endIndex, 'process.env')
s.overwrite(startIndex, endIndex, '__vite_ssr_import_meta__.env')
}

if (s) {
Expand Down
15 changes: 15 additions & 0 deletions test/core/test/env.test.ts
Expand Up @@ -47,3 +47,18 @@ test('custom env', () => {
test('ignores import.meta.env in string literals', () => {
expect('import.meta.env').toBe('import' + '.meta.env')
})

test('define process and using import.meta.env together', () => {
const process = {}
expect(process).toMatchObject({})
expect(import.meta.env.MODE).toEqual('test')
})

test('PROD, DEV, SSR should be boolean', () => {
expect(typeof import.meta.env.PROD).toEqual('boolean')
expect(typeof import.meta.env.DEV).toEqual('boolean')
expect(typeof import.meta.env.SSR).toEqual('boolean')

import.meta.env.SSR = false
expect(import.meta.env.SSR).toEqual(false)
})