Skip to content

Commit fceff60

Browse files
authored
fix(ssr)!: don't access Object variable in ssr transformed code (#19996)
1 parent 494f854 commit fceff60

File tree

9 files changed

+62
-38
lines changed

9 files changed

+62
-38
lines changed

packages/vite/src/module-runner/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ export const ssrModuleExportsKey = `__vite_ssr_exports__`
33
export const ssrImportKey = `__vite_ssr_import__`
44
export const ssrDynamicImportKey = `__vite_ssr_dynamic_import__`
55
export const ssrExportAllKey = `__vite_ssr_exportAll__`
6+
export const ssrExportNameKey = `__vite_ssr_exportName__`
67
export const ssrImportMetaKey = `__vite_ssr_import_meta__`

packages/vite/src/module-runner/esmEvaluator.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
import {
66
ssrDynamicImportKey,
77
ssrExportAllKey,
8+
ssrExportNameKey,
89
ssrImportKey,
910
ssrImportMetaKey,
1011
ssrModuleExportsKey,
@@ -25,6 +26,7 @@ export class ESModulesEvaluator implements ModuleEvaluator {
2526
ssrImportKey,
2627
ssrDynamicImportKey,
2728
ssrExportAllKey,
29+
ssrExportNameKey,
2830
// source map should already be inlined by Vite
2931
'"use strict";' + code,
3032
)
@@ -35,6 +37,7 @@ export class ESModulesEvaluator implements ModuleEvaluator {
3537
context[ssrImportKey],
3638
context[ssrDynamicImportKey],
3739
context[ssrExportAllKey],
40+
context[ssrExportNameKey],
3841
)
3942

4043
Object.seal(context[ssrModuleExportsKey])

packages/vite/src/module-runner/runner.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import {
2525
import {
2626
ssrDynamicImportKey,
2727
ssrExportAllKey,
28+
ssrExportNameKey,
2829
ssrImportKey,
2930
ssrImportMetaKey,
3031
ssrModuleExportsKey,
@@ -405,6 +406,12 @@ export class ModuleRunner {
405406
[ssrDynamicImportKey]: dynamicRequest,
406407
[ssrModuleExportsKey]: exports,
407408
[ssrExportAllKey]: (obj: any) => exportAll(exports, obj),
409+
[ssrExportNameKey]: (name, getter) =>
410+
Object.defineProperty(exports, name, {
411+
enumerable: true,
412+
configurable: true,
413+
get: getter,
414+
}),
408415
[ssrImportMetaKey]: meta,
409416
}
410417

packages/vite/src/module-runner/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import type { EvaluatedModuleNode, EvaluatedModules } from './evaluatedModules'
1515
import type {
1616
ssrDynamicImportKey,
1717
ssrExportAllKey,
18+
ssrExportNameKey,
1819
ssrImportKey,
1920
ssrImportMetaKey,
2021
ssrModuleExportsKey,
@@ -38,6 +39,7 @@ export interface ModuleRunnerContext {
3839
options?: ImportCallOptions,
3940
) => Promise<any>
4041
[ssrExportAllKey]: (obj: any) => void
42+
[ssrExportNameKey]: (name: string, getter: () => unknown) => void
4143
[ssrImportMetaKey]: ModuleRunnerImportMeta
4244
}
4345

packages/vite/src/node/ssr/__tests__/ssrLoadModule.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ test('json', async () => {
235235
null,
236236
'/test.json',
237237
)
238-
expect(json?.code.length).toMatchInlineSnapshot(`225`)
238+
expect(json?.code.length).toMatchInlineSnapshot(`165`)
239239
})
240240

241241
test('file url', async () => {

packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts

Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ test('export function declaration', async () => {
6767
await ssrTransformSimpleCode(`export function foo() {}`),
6868
).toMatchInlineSnapshot(
6969
`
70-
"Object.defineProperty(__vite_ssr_exports__, "foo", { enumerable: true, configurable: true, get(){ try { return foo } catch {} }});
70+
"__vite_ssr_exportName__("foo", () => { try { return foo } catch {} });
7171
function foo() {}"
7272
`,
7373
)
@@ -78,7 +78,7 @@ test('export class declaration', async () => {
7878
await ssrTransformSimpleCode(`export class foo {}`),
7979
).toMatchInlineSnapshot(
8080
`
81-
"Object.defineProperty(__vite_ssr_exports__, "foo", { enumerable: true, configurable: true, get(){ try { return foo } catch {} }});
81+
"__vite_ssr_exportName__("foo", () => { try { return foo } catch {} });
8282
class foo {}"
8383
`,
8484
)
@@ -89,8 +89,8 @@ test('export var declaration', async () => {
8989
await ssrTransformSimpleCode(`export const a = 1, b = 2`),
9090
).toMatchInlineSnapshot(
9191
`
92-
"Object.defineProperty(__vite_ssr_exports__, "a", { enumerable: true, configurable: true, get(){ try { return a } catch {} }});
93-
Object.defineProperty(__vite_ssr_exports__, "b", { enumerable: true, configurable: true, get(){ try { return b } catch {} }});
92+
"__vite_ssr_exportName__("a", () => { try { return a } catch {} });
93+
__vite_ssr_exportName__("b", () => { try { return b } catch {} });
9494
const a = 1, b = 2"
9595
`,
9696
)
@@ -101,8 +101,8 @@ test('export named', async () => {
101101
await ssrTransformSimpleCode(`const a = 1, b = 2; export { a, b as c }`),
102102
).toMatchInlineSnapshot(
103103
`
104-
"Object.defineProperty(__vite_ssr_exports__, "a", { enumerable: true, configurable: true, get(){ try { return a } catch {} }});
105-
Object.defineProperty(__vite_ssr_exports__, "c", { enumerable: true, configurable: true, get(){ try { return b } catch {} }});
104+
"__vite_ssr_exportName__("a", () => { try { return a } catch {} });
105+
__vite_ssr_exportName__("c", () => { try { return b } catch {} });
106106
const a = 1, b = 2; "
107107
`,
108108
)
@@ -113,8 +113,8 @@ test('export named from', async () => {
113113
await ssrTransformSimpleCode(`export { ref, computed as c } from 'vue'`),
114114
).toMatchInlineSnapshot(
115115
`
116-
"Object.defineProperty(__vite_ssr_exports__, "ref", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_import_0__.ref } catch {} }});
117-
Object.defineProperty(__vite_ssr_exports__, "c", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_import_0__.computed } catch {} }});
116+
"__vite_ssr_exportName__("ref", () => { try { return __vite_ssr_import_0__.ref } catch {} });
117+
__vite_ssr_exportName__("c", () => { try { return __vite_ssr_import_0__.computed } catch {} });
118118
const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["ref","computed"]});
119119
"
120120
`,
@@ -128,7 +128,7 @@ test('named exports of imported binding', async () => {
128128
),
129129
).toMatchInlineSnapshot(
130130
`
131-
"Object.defineProperty(__vite_ssr_exports__, "createApp", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_import_0__.createApp } catch {} }});
131+
"__vite_ssr_exportName__("createApp", () => { try { return __vite_ssr_import_0__.createApp } catch {} });
132132
const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["createApp"]});
133133
"
134134
`,
@@ -155,7 +155,7 @@ test('export * as from', async () => {
155155
await ssrTransformSimpleCode(`export * as foo from 'vue'`),
156156
).toMatchInlineSnapshot(
157157
`
158-
"Object.defineProperty(__vite_ssr_exports__, "foo", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_import_0__ } catch {} }});
158+
"__vite_ssr_exportName__("foo", () => { try { return __vite_ssr_import_0__ } catch {} });
159159
const __vite_ssr_import_0__ = await __vite_ssr_import__("vue");
160160
"
161161
`,
@@ -169,7 +169,7 @@ import * as foo from 'foo'
169169
export * as foo from 'foo'
170170
`),
171171
).toMatchInlineSnapshot(`
172-
"Object.defineProperty(__vite_ssr_exports__, "foo", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_import_1__ } catch {} }});
172+
"__vite_ssr_exportName__("foo", () => { try { return __vite_ssr_import_1__ } catch {} });
173173
const __vite_ssr_import_0__ = await __vite_ssr_import__("foo");
174174
const __vite_ssr_import_1__ = await __vite_ssr_import__("foo");
175175
@@ -183,7 +183,7 @@ import { foo } from 'foo'
183183
export { foo } from 'foo'
184184
`),
185185
).toMatchInlineSnapshot(`
186-
"Object.defineProperty(__vite_ssr_exports__, "foo", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_import_1__.foo } catch {} }});
186+
"__vite_ssr_exportName__("foo", () => { try { return __vite_ssr_import_1__.foo } catch {} });
187187
const __vite_ssr_import_0__ = await __vite_ssr_import__("foo", {"importedNames":["foo"]});
188188
const __vite_ssr_import_1__ = await __vite_ssr_import__("foo", {"importedNames":["foo"]});
189189
@@ -197,7 +197,7 @@ import { foo } from 'foo'
197197
export { foo as foo } from 'foo'
198198
`),
199199
).toMatchInlineSnapshot(`
200-
"Object.defineProperty(__vite_ssr_exports__, "foo", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_import_1__.foo } catch {} }});
200+
"__vite_ssr_exportName__("foo", () => { try { return __vite_ssr_import_1__.foo } catch {} });
201201
const __vite_ssr_import_0__ = await __vite_ssr_import__("foo", {"importedNames":["foo"]});
202202
const __vite_ssr_import_1__ = await __vite_ssr_import__("foo", {"importedNames":["foo"]});
203203
@@ -211,7 +211,7 @@ test('export * as from arbitrary module namespace identifier', async () => {
211211
await ssrTransformSimpleCode(`export * as "arbitrary string" from 'vue'`),
212212
).toMatchInlineSnapshot(
213213
`
214-
"Object.defineProperty(__vite_ssr_exports__, "arbitrary string", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_import_0__ } catch {} }});
214+
"__vite_ssr_exportName__("arbitrary string", () => { try { return __vite_ssr_import_0__ } catch {} });
215215
const __vite_ssr_import_0__ = await __vite_ssr_import__("vue");
216216
"
217217
`,
@@ -225,7 +225,7 @@ test('export as arbitrary module namespace identifier', async () => {
225225
),
226226
).toMatchInlineSnapshot(
227227
`
228-
"Object.defineProperty(__vite_ssr_exports__, "arbitrary string", { enumerable: true, configurable: true, get(){ try { return something } catch {} }});
228+
"__vite_ssr_exportName__("arbitrary string", () => { try { return something } catch {} });
229229
const something = "Something";"
230230
`,
231231
)
@@ -238,7 +238,7 @@ test('export as from arbitrary module namespace identifier', async () => {
238238
),
239239
).toMatchInlineSnapshot(
240240
`
241-
"Object.defineProperty(__vite_ssr_exports__, "arbitrary string", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_import_0__["arbitrary string2"] } catch {} }});
241+
"__vite_ssr_exportName__("arbitrary string", () => { try { return __vite_ssr_import_0__["arbitrary string2"] } catch {} });
242242
const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["arbitrary string2"]});
243243
"
244244
`,
@@ -248,7 +248,7 @@ test('export as from arbitrary module namespace identifier', async () => {
248248
test('export default', async () => {
249249
expect(await ssrTransformSimpleCode(`export default {}`))
250250
.toMatchInlineSnapshot(`
251-
"Object.defineProperty(__vite_ssr_exports__, "default", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_export_default__ } catch {} }});
251+
"__vite_ssr_exportName__("default", () => { try { return __vite_ssr_export_default__ } catch {} });
252252
const __vite_ssr_export_default__ = {}"
253253
`)
254254
})
@@ -306,7 +306,7 @@ test('dynamic import', async () => {
306306
)
307307
expect(result?.code).toMatchInlineSnapshot(
308308
`
309-
"Object.defineProperty(__vite_ssr_exports__, "i", { enumerable: true, configurable: true, get(){ try { return i } catch {} }});
309+
"__vite_ssr_exportName__("i", () => { try { return i } catch {} });
310310
const i = () => __vite_ssr_dynamic_import__('./foo')"
311311
`,
312312
)
@@ -506,8 +506,8 @@ test('should declare variable for imported super class', async () => {
506506
`export class B extends Foo {}`,
507507
),
508508
).toMatchInlineSnapshot(`
509-
"Object.defineProperty(__vite_ssr_exports__, "default", { enumerable: true, configurable: true, get(){ try { return A } catch {} }});
510-
Object.defineProperty(__vite_ssr_exports__, "B", { enumerable: true, configurable: true, get(){ try { return B } catch {} }});
509+
"__vite_ssr_exportName__("default", () => { try { return A } catch {} });
510+
__vite_ssr_exportName__("B", () => { try { return B } catch {} });
511511
const __vite_ssr_import_0__ = await __vite_ssr_import__("./dependency", {"importedNames":["Foo"]});
512512
const Foo = __vite_ssr_import_0__.Foo;
513513
class A extends Foo {};
@@ -520,14 +520,14 @@ test('should handle default export variants', async () => {
520520
// default anonymous functions
521521
expect(await ssrTransformSimpleCode(`export default function() {}\n`))
522522
.toMatchInlineSnapshot(`
523-
"Object.defineProperty(__vite_ssr_exports__, "default", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_export_default__ } catch {} }});
523+
"__vite_ssr_exportName__("default", () => { try { return __vite_ssr_export_default__ } catch {} });
524524
const __vite_ssr_export_default__ = function() {}
525525
"
526526
`)
527527
// default anonymous class
528528
expect(await ssrTransformSimpleCode(`export default class {}\n`))
529529
.toMatchInlineSnapshot(`
530-
"Object.defineProperty(__vite_ssr_exports__, "default", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_export_default__ } catch {} }});
530+
"__vite_ssr_exportName__("default", () => { try { return __vite_ssr_export_default__ } catch {} });
531531
const __vite_ssr_export_default__ = class {}
532532
"
533533
`)
@@ -538,7 +538,7 @@ test('should handle default export variants', async () => {
538538
`foo.prototype = Object.prototype;`,
539539
),
540540
).toMatchInlineSnapshot(`
541-
"Object.defineProperty(__vite_ssr_exports__, "default", { enumerable: true, configurable: true, get(){ try { return foo } catch {} }});
541+
"__vite_ssr_exportName__("default", () => { try { return foo } catch {} });
542542
function foo() {};
543543
foo.prototype = Object.prototype;"
544544
`)
@@ -548,8 +548,8 @@ test('should handle default export variants', async () => {
548548
`export default class A {}\n` + `export class B extends A {}`,
549549
),
550550
).toMatchInlineSnapshot(`
551-
"Object.defineProperty(__vite_ssr_exports__, "default", { enumerable: true, configurable: true, get(){ try { return A } catch {} }});
552-
Object.defineProperty(__vite_ssr_exports__, "B", { enumerable: true, configurable: true, get(){ try { return B } catch {} }});
551+
"__vite_ssr_exportName__("default", () => { try { return A } catch {} });
552+
__vite_ssr_exportName__("B", () => { try { return B } catch {} });
553553
class A {};
554554
class B extends A {}"
555555
`)
@@ -1001,8 +1001,8 @@ export function fn1() {
10011001
`,
10021002
),
10031003
).toMatchInlineSnapshot(`
1004-
"Object.defineProperty(__vite_ssr_exports__, "fn1", { enumerable: true, configurable: true, get(){ try { return fn1 } catch {} }});
1005-
Object.defineProperty(__vite_ssr_exports__, "fn2", { enumerable: true, configurable: true, get(){ try { return fn2 } catch {} }});
1004+
"__vite_ssr_exportName__("fn1", () => { try { return fn1 } catch {} });
1005+
__vite_ssr_exportName__("fn2", () => { try { return fn2 } catch {} });
10061006
10071007
function fn1() {
10081008
};function fn2() {
@@ -1024,15 +1024,15 @@ export default (function getRandom() {
10241024
`.trim()
10251025

10261026
expect(await ssrTransformSimpleCode(code)).toMatchInlineSnapshot(`
1027-
"Object.defineProperty(__vite_ssr_exports__, "default", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_export_default__ } catch {} }});
1027+
"__vite_ssr_exportName__("default", () => { try { return __vite_ssr_export_default__ } catch {} });
10281028
const __vite_ssr_export_default__ = (function getRandom() {
10291029
return Math.random();
10301030
});"
10311031
`)
10321032

10331033
expect(await ssrTransformSimpleCode(`export default (class A {});`))
10341034
.toMatchInlineSnapshot(`
1035-
"Object.defineProperty(__vite_ssr_exports__, "default", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_export_default__ } catch {} }});
1035+
"__vite_ssr_exportName__("default", () => { try { return __vite_ssr_export_default__ } catch {} });
10361036
const __vite_ssr_export_default__ = (class A {});"
10371037
`)
10381038
})
@@ -1110,7 +1110,7 @@ export class Test {
11101110
};`.trim()
11111111

11121112
expect(await ssrTransformSimpleCode(code)).toMatchInlineSnapshot(`
1113-
"Object.defineProperty(__vite_ssr_exports__, "Test", { enumerable: true, configurable: true, get(){ try { return Test } catch {} }});
1113+
"__vite_ssr_exportName__("Test", () => { try { return Test } catch {} });
11141114
const __vite_ssr_import_0__ = await __vite_ssr_import__("foobar", {"importedNames":["foo","bar"]});
11151115
11161116
if (false) {
@@ -1309,8 +1309,8 @@ export * as bar from './bar'
13091309
console.log(bar)
13101310
`),
13111311
).toMatchInlineSnapshot(`
1312-
"Object.defineProperty(__vite_ssr_exports__, "default", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_export_default__ } catch {} }});
1313-
Object.defineProperty(__vite_ssr_exports__, "bar", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_import_1__ } catch {} }});
1312+
"__vite_ssr_exportName__("default", () => { try { return __vite_ssr_export_default__ } catch {} });
1313+
__vite_ssr_exportName__("bar", () => { try { return __vite_ssr_import_1__ } catch {} });
13141314
const __vite_ssr_import_0__ = await __vite_ssr_import__("./foo", {"importedNames":["foo"]});
13151315
const __vite_ssr_import_1__ = await __vite_ssr_import__("./bar");
13161316
;
@@ -1585,9 +1585,9 @@ import("e")
15851585
export * as A from "a";
15861586
`)
15871587
expect(result?.code).toMatchInlineSnapshot(`
1588-
"Object.defineProperty(__vite_ssr_exports__, "b", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_import_1__.b } catch {} }});
1589-
Object.defineProperty(__vite_ssr_exports__, "d", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_import_3__ } catch {} }});
1590-
Object.defineProperty(__vite_ssr_exports__, "A", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_import_4__ } catch {} }});
1588+
"__vite_ssr_exportName__("b", () => { try { return __vite_ssr_import_1__.b } catch {} });
1589+
__vite_ssr_exportName__("d", () => { try { return __vite_ssr_import_3__ } catch {} });
1590+
__vite_ssr_exportName__("A", () => { try { return __vite_ssr_import_4__ } catch {} });
15911591
const __vite_ssr_import_0__ = await __vite_ssr_import__("a", {"importedNames":["default"]});
15921592
const __vite_ssr_import_1__ = await __vite_ssr_import__("b", {"importedNames":["b"]});
15931593
const __vite_ssr_import_2__ = await __vite_ssr_import__("c");
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
const Object = "my-object";
2+
export { Object };

packages/vite/src/node/ssr/runtime/__tests__/server-runtime.spec.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,15 @@ describe('module runner initialization', async () => {
390390
`,
391391
)
392392
})
393+
394+
it(`handle Object variable`, async ({ runner }) => {
395+
const mod = await runner.import('/fixtures/top-level-object.js')
396+
expect(mod).toMatchInlineSnapshot(`
397+
{
398+
"Object": "my-object",
399+
}
400+
`)
401+
})
393402
})
394403

395404
describe('optimize-deps', async () => {

packages/vite/src/node/ssr/ssrTransform.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ export const ssrModuleExportsKey = `__vite_ssr_exports__`
4343
export const ssrImportKey = `__vite_ssr_import__`
4444
export const ssrDynamicImportKey = `__vite_ssr_dynamic_import__`
4545
export const ssrExportAllKey = `__vite_ssr_exportAll__`
46+
export const ssrExportNameKey = `__vite_ssr_exportName__`
4647
export const ssrImportMetaKey = `__vite_ssr_import_meta__`
4748

4849
const hashbangRE = /^#!.*\n/
@@ -156,8 +157,7 @@ async function ssrTransformScript(
156157
// wrap with try/catch to fallback to `undefined` for backward compat.
157158
s.appendLeft(
158159
fileStartIndex,
159-
`Object.defineProperty(${ssrModuleExportsKey}, ${JSON.stringify(name)}, ` +
160-
`{ enumerable: true, configurable: true, get(){ try { return ${local} } catch {} }});\n`,
160+
`${ssrExportNameKey}(${JSON.stringify(name)}, () => { try { return ${local} } catch {} });\n`,
161161
)
162162
}
163163

0 commit comments

Comments
 (0)