From 5fd29acf7f503dbb04b24abd22ec8b8b26c72603 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Mon, 25 Nov 2024 12:19:25 +0900 Subject: [PATCH 01/11] wip: ensure ";" between statements --- .../node/ssr/__tests__/ssrTransform.spec.ts | 110 +++++++++--------- packages/vite/src/node/ssr/ssrTransform.ts | 14 +++ 2 files changed, 69 insertions(+), 55 deletions(-) diff --git a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts index fa8bd6e52a302c..85f16ffcc6b327 100644 --- a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts +++ b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts @@ -121,7 +121,7 @@ test('export * from', async () => { ).toMatchInlineSnapshot(` "const __vite_ssr_import_0__ = await __vite_ssr_import__("vue"); __vite_ssr_exportAll__(__vite_ssr_import_0__); - + ; const __vite_ssr_import_1__ = await __vite_ssr_import__("react"); __vite_ssr_exportAll__(__vite_ssr_import_1__); " @@ -153,8 +153,8 @@ test('export as arbitrary module namespace identifier', async () => { `const something = "Something";export { something as "arbitrary string" };`, ), ).toMatchInlineSnapshot(` - "const something = "Something"; - Object.defineProperty(__vite_ssr_exports__, "arbitrary string", { enumerable: true, configurable: true, get(){ return something }});" + "const something = "Something"; + Object.defineProperty(__vite_ssr_exports__, "arbitrary string", { enumerable: true, configurable: true, get(){ return something }});" `) }) @@ -399,15 +399,15 @@ test('should handle default export variants', async () => { // default anonymous functions expect(await ssrTransformSimpleCode(`export default function() {}\n`)) .toMatchInlineSnapshot(` - "__vite_ssr_exports__.default = function() {} - " - `) + "__vite_ssr_exports__.default = function() {} + " + `) // default anonymous class expect(await ssrTransformSimpleCode(`export default class {}\n`)) .toMatchInlineSnapshot(` - "__vite_ssr_exports__.default = class {} - " - `) + "__vite_ssr_exports__.default = class {} + " + `) // default named functions expect( await ssrTransformSimpleCode( @@ -541,7 +541,7 @@ test('overwrite bindings', async () => { const a = { inject: __vite_ssr_import_0__.inject } const b = { test: __vite_ssr_import_0__.inject } function c() { const { test: inject } = { test: true }; console.log(inject) } - const d = __vite_ssr_import_0__.inject + const d = __vite_ssr_import_0__.inject; function f() { console.log(__vite_ssr_identity__(__vite_ssr_import_0__.inject)) } function e() { const { inject } = { inject: true } } function g() { const f = () => { const inject = true }; console.log(__vite_ssr_identity__(__vite_ssr_import_0__.inject)) } @@ -569,7 +569,7 @@ function c({ _ = bar() + foo() }) {} "const __vite_ssr_identity__ = v => v; const __vite_ssr_import_0__ = await __vite_ssr_import__("foo", {"importedNames":["foo","bar"]}); - + ; const a = ({ _ = __vite_ssr_identity__(__vite_ssr_import_0__.foo)() }) => {} function b({ _ = __vite_ssr_identity__(__vite_ssr_import_0__.bar)() }) {} function c({ _ = __vite_ssr_identity__(__vite_ssr_import_0__.bar)() + __vite_ssr_identity__(__vite_ssr_import_0__.foo)() }) {} @@ -591,7 +591,7 @@ const a = () => { ).toMatchInlineSnapshot(` "const __vite_ssr_import_0__ = await __vite_ssr_import__("foo", {"importedNames":["n"]}); - + ; const a = () => { const { type: n = 'bar' } = {} console.log(n) @@ -614,7 +614,7 @@ const foo = {} ).toMatchInlineSnapshot(` "const __vite_ssr_import_0__ = await __vite_ssr_import__("foo", {"importedNames":["n","m"]}); - + ; const foo = {} { @@ -658,7 +658,7 @@ objRest() "const __vite_ssr_identity__ = v => v; const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["remove","add","get","set","rest","objRest"]}); - + ; function a() { const { @@ -666,21 +666,21 @@ objRest() a: { b: { c: [ add ] }}, d: [{ get }, set, ...rest], ...objRest - } = foo + } = foo; - remove() - add() - get() - set() - rest() + remove(); + add(); + get(); + set(); + rest(); objRest() } - __vite_ssr_identity__(__vite_ssr_import_0__.remove)() - __vite_ssr_identity__(__vite_ssr_import_0__.add)() - __vite_ssr_identity__(__vite_ssr_import_0__.get)() - __vite_ssr_identity__(__vite_ssr_import_0__.set)() - __vite_ssr_identity__(__vite_ssr_import_0__.rest)() + __vite_ssr_identity__(__vite_ssr_import_0__.remove)(); + __vite_ssr_identity__(__vite_ssr_import_0__.add)(); + __vite_ssr_identity__(__vite_ssr_import_0__.get)(); + __vite_ssr_identity__(__vite_ssr_import_0__.set)(); + __vite_ssr_identity__(__vite_ssr_import_0__.rest)(); __vite_ssr_identity__(__vite_ssr_import_0__.objRest)() " `) @@ -708,9 +708,9 @@ const obj = { ).toMatchInlineSnapshot(` "const __vite_ssr_import_0__ = await __vite_ssr_import__("foo", {"importedNames":["default"]}); + ; - - const bar = 'bar' + const bar = 'bar'; const obj = { foo() {}, @@ -740,7 +740,7 @@ class A { ).toMatchInlineSnapshot(` "const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["remove","add"]}); - + ; const add = __vite_ssr_import_0__.add; const remove = __vite_ssr_import_0__.remove; @@ -772,9 +772,9 @@ class A { ).toMatchInlineSnapshot(` "const __vite_ssr_import_0__ = await __vite_ssr_import__("foo", {"importedNames":["default"]}); + ; - - const bar = 'bar' + const bar = 'bar'; class A { foo() {} @@ -819,27 +819,27 @@ bbb() "const __vite_ssr_identity__ = v => v; const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["aaa","bbb","ccc","ddd"]}); - + ; function foobar() { - ddd() + ddd(); const aaa = () => { - bbb(ccc) + bbb(ccc); ddd() } const bbb = () => { console.log('hi') } - const ccc = 1 + const ccc = 1; function ddd() {} - aaa() - bbb() + aaa(); + bbb(); ccc() } - __vite_ssr_identity__(__vite_ssr_import_0__.aaa)() + __vite_ssr_identity__(__vite_ssr_import_0__.aaa)(); __vite_ssr_identity__(__vite_ssr_import_0__.bbb)() " `) @@ -957,7 +957,7 @@ foo()`, "#!/usr/bin/env node const __vite_ssr_identity__ = v => v; const __vite_ssr_import_0__ = await __vite_ssr_import__("foo", {"importedNames":["foo"]}); - + ; __vite_ssr_identity__(__vite_ssr_import_0__.foo)()" `) }) @@ -994,27 +994,27 @@ export class Test { expect(await ssrTransformSimpleCode(code)).toMatchInlineSnapshot(` "const __vite_ssr_identity__ = v => v; const __vite_ssr_import_0__ = await __vite_ssr_import__("foobar", {"importedNames":["foo","bar"]}); - + ; if (false) { - const foo = 'foo' + const foo = 'foo'; console.log(foo) } else if (false) { - const [bar] = ['bar'] + const [bar] = ['bar']; console.log(bar) } else { - console.log(__vite_ssr_identity__(__vite_ssr_import_0__.foo)) + console.log(__vite_ssr_identity__(__vite_ssr_import_0__.foo)); console.log(__vite_ssr_identity__(__vite_ssr_import_0__.bar)) } class Test { constructor() { if (false) { - const foo = 'foo' + const foo = 'foo'; console.log(foo) } else if (false) { - const [bar] = ['bar'] + const [bar] = ['bar']; console.log(bar) } else { - console.log(__vite_ssr_identity__(__vite_ssr_import_0__.foo)) + console.log(__vite_ssr_identity__(__vite_ssr_import_0__.foo)); console.log(__vite_ssr_identity__(__vite_ssr_import_0__.bar)) } } @@ -1037,7 +1037,7 @@ function test() { ).toMatchInlineSnapshot(` "const __vite_ssr_import_0__ = await __vite_ssr_import__("foobar", {"importedNames":["foo","bar"]}); - + ; function test() { if (true) { var foo = () => { var why = 'would' }, bar = 'someone' @@ -1064,7 +1064,7 @@ function test() { ).toMatchInlineSnapshot(` "const __vite_ssr_import_0__ = await __vite_ssr_import__("foobar", {"importedNames":["foo","bar","baz"]}); - + ; function test() { [__vite_ssr_import_0__.foo]; { @@ -1096,7 +1096,7 @@ for (const test in tests) { ).toMatchInlineSnapshot(` "const __vite_ssr_import_0__ = await __vite_ssr_import__("./test.js", {"importedNames":["test"]}); - + ; for (const test of tests) { console.log(test) @@ -1171,14 +1171,14 @@ console.log(foo + 2) ).toMatchInlineSnapshot(` "const __vite_ssr_import_0__ = await __vite_ssr_import__("./foo", {"importedNames":["foo"]}); - console.log(__vite_ssr_import_0__.foo + 1) + console.log(__vite_ssr_import_0__.foo + 1); const __vite_ssr_import_1__ = await __vite_ssr_import__("./a"); __vite_ssr_exportAll__(__vite_ssr_import_1__); - - + ; + ; const __vite_ssr_import_2__ = await __vite_ssr_import__("./b"); __vite_ssr_exportAll__(__vite_ssr_import_2__); - + ; console.log(__vite_ssr_import_0__.foo + 2) " `) @@ -1196,11 +1196,11 @@ console.log(bar) "const __vite_ssr_identity__ = v => v; const __vite_ssr_import_0__ = await __vite_ssr_import__("./foo", {"importedNames":["foo"]}); - - __vite_ssr_exports__.default = __vite_ssr_identity__(__vite_ssr_import_0__.foo)() + ; + __vite_ssr_exports__.default = __vite_ssr_identity__(__vite_ssr_import_0__.foo)(); const __vite_ssr_import_1__ = await __vite_ssr_import__("./bar"); - Object.defineProperty(__vite_ssr_exports__, "bar", { enumerable: true, configurable: true, get(){ return __vite_ssr_import_1__ }}); + Object.defineProperty(__vite_ssr_exports__, "bar", { enumerable: true, configurable: true, get(){ return __vite_ssr_import_1__ }});; console.log(bar) " `) diff --git a/packages/vite/src/node/ssr/ssrTransform.ts b/packages/vite/src/node/ssr/ssrTransform.ts index 589ba9b5cf7ff2..e781bdce7963f1 100644 --- a/packages/vite/src/node/ssr/ssrTransform.ts +++ b/packages/vite/src/node/ssr/ssrTransform.ts @@ -331,6 +331,20 @@ async function ssrTransformScript( } } + // ensure ";" between statements + ;(eswalk as any)(ast, { + enter(node: Node) { + if (node.type === 'Program' || node.type === 'BlockStatement') { + for (let i = 0; i < node.body.length - 1; i++) { + const stmt = node.body[i] as Node + if (code[stmt.end - 1] !== ';' && code[stmt.end - 1] !== '}') { + s.appendRight(stmt.end, ';') + } + } + } + }, + }) + let injectIdentityFunction = false // 3. convert references to import bindings & import.meta references walk(ast, { From b17e3a108b454c60bc18b9d965456ac13abbc926 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Mon, 25 Nov 2024 12:22:07 +0900 Subject: [PATCH 02/11] wip: use `(0, ...)` --- .../node/ssr/__tests__/ssrTransform.spec.ts | 94 ++++++++----------- packages/vite/src/node/ssr/ssrTransform.ts | 5 +- 2 files changed, 42 insertions(+), 57 deletions(-) diff --git a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts index 85f16ffcc6b327..3883648c05fced 100644 --- a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts +++ b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts @@ -26,9 +26,8 @@ test('named import', async () => { `import { ref } from 'vue';function foo() { return ref(0) }`, ), ).toMatchInlineSnapshot(` - "const __vite_ssr_identity__ = v => v; - const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["ref"]}); - function foo() { return __vite_ssr_identity__(__vite_ssr_import_0__.ref)(0) }" + "const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["ref"]}); + function foo() { return (0,__vite_ssr_import_0__.ref)(0) }" `) }) @@ -38,9 +37,8 @@ test('named import: arbitrary module namespace specifier', async () => { `import { "some thing" as ref } from 'vue';function foo() { return ref(0) }`, ), ).toMatchInlineSnapshot(` - "const __vite_ssr_identity__ = v => v; - const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["some thing"]}); - function foo() { return __vite_ssr_identity__(__vite_ssr_import_0__["some thing"])(0) }" + "const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["some thing"]}); + function foo() { return (0,__vite_ssr_import_0__["some thing"])(0) }" `) }) @@ -223,9 +221,8 @@ test('do not rewrite method definition', async () => { `import { fn } from 'vue';class A { fn() { fn() } }`, ) expect(result?.code).toMatchInlineSnapshot(` - "const __vite_ssr_identity__ = v => v; - const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["fn"]}); - class A { fn() { __vite_ssr_identity__(__vite_ssr_import_0__.fn)() } }" + "const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["fn"]}); + class A { fn() { (0,__vite_ssr_import_0__.fn)() } }" `) expect(result?.deps).toEqual(['vue']) }) @@ -451,25 +448,24 @@ test('sourcemap is correct for hoisted imports', async () => { const result = (await ssrTransform(code, null, 'input.js', code))! expect(result.code).toMatchInlineSnapshot(` - "const __vite_ssr_identity__ = v => v; - const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["foo"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["foo"]}); const __vite_ssr_import_1__ = await __vite_ssr_import__("vue2", {"importedNames":["bar"]}); - console.log(__vite_ssr_identity__(__vite_ssr_import_0__.foo), __vite_ssr_identity__(__vite_ssr_import_1__.bar)); + console.log((0,__vite_ssr_import_0__.foo), (0,__vite_ssr_import_1__.bar)); " `) const traceMap = new TraceMap(result.map as any) - expect(originalPositionFor(traceMap, { line: 2, column: 0 })).toStrictEqual({ + expect(originalPositionFor(traceMap, { line: 1, column: 0 })).toStrictEqual({ source: 'input.js', line: 5, column: 0, name: null, }) - expect(originalPositionFor(traceMap, { line: 3, column: 0 })).toStrictEqual({ + expect(originalPositionFor(traceMap, { line: 2, column: 0 })).toStrictEqual({ source: 'input.js', line: 6, column: 0, @@ -536,15 +532,14 @@ test('overwrite bindings', async () => { `function g() { const f = () => { const inject = true }; console.log(inject) }\n`, ), ).toMatchInlineSnapshot(` - "const __vite_ssr_identity__ = v => v; - const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["inject"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["inject"]}); const a = { inject: __vite_ssr_import_0__.inject } const b = { test: __vite_ssr_import_0__.inject } function c() { const { test: inject } = { test: true }; console.log(inject) } const d = __vite_ssr_import_0__.inject; - function f() { console.log(__vite_ssr_identity__(__vite_ssr_import_0__.inject)) } + function f() { console.log((0,__vite_ssr_import_0__.inject)) } function e() { const { inject } = { inject: true } } - function g() { const f = () => { const inject = true }; console.log(__vite_ssr_identity__(__vite_ssr_import_0__.inject)) } + function g() { const f = () => { const inject = true }; console.log((0,__vite_ssr_import_0__.inject)) } " `) }) @@ -566,13 +561,12 @@ function c({ _ = bar() + foo() }) {} `, ), ).toMatchInlineSnapshot(` - "const __vite_ssr_identity__ = v => v; - const __vite_ssr_import_0__ = await __vite_ssr_import__("foo", {"importedNames":["foo","bar"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__("foo", {"importedNames":["foo","bar"]}); ; - const a = ({ _ = __vite_ssr_identity__(__vite_ssr_import_0__.foo)() }) => {} - function b({ _ = __vite_ssr_identity__(__vite_ssr_import_0__.bar)() }) {} - function c({ _ = __vite_ssr_identity__(__vite_ssr_import_0__.bar)() + __vite_ssr_identity__(__vite_ssr_import_0__.foo)() }) {} + const a = ({ _ = (0,__vite_ssr_import_0__.foo)() }) => {} + function b({ _ = (0,__vite_ssr_import_0__.bar)() }) {} + function c({ _ = (0,__vite_ssr_import_0__.bar)() + (0,__vite_ssr_import_0__.foo)() }) {} " `) }) @@ -655,8 +649,7 @@ objRest() `, ), ).toMatchInlineSnapshot(` - "const __vite_ssr_identity__ = v => v; - const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["remove","add","get","set","rest","objRest"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["remove","add","get","set","rest","objRest"]}); ; @@ -676,12 +669,12 @@ objRest() objRest() } - __vite_ssr_identity__(__vite_ssr_import_0__.remove)(); - __vite_ssr_identity__(__vite_ssr_import_0__.add)(); - __vite_ssr_identity__(__vite_ssr_import_0__.get)(); - __vite_ssr_identity__(__vite_ssr_import_0__.set)(); - __vite_ssr_identity__(__vite_ssr_import_0__.rest)(); - __vite_ssr_identity__(__vite_ssr_import_0__.objRest)() + (0,__vite_ssr_import_0__.remove)(); + (0,__vite_ssr_import_0__.add)(); + (0,__vite_ssr_import_0__.get)(); + (0,__vite_ssr_import_0__.set)(); + (0,__vite_ssr_import_0__.rest)(); + (0,__vite_ssr_import_0__.objRest)() " `) }) @@ -816,8 +809,7 @@ bbb() `, ), ).toMatchInlineSnapshot(` - "const __vite_ssr_identity__ = v => v; - const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["aaa","bbb","ccc","ddd"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["aaa","bbb","ccc","ddd"]}); ; @@ -839,8 +831,8 @@ bbb() ccc() } - __vite_ssr_identity__(__vite_ssr_import_0__.aaa)(); - __vite_ssr_identity__(__vite_ssr_import_0__.bbb)() + (0,__vite_ssr_import_0__.aaa)(); + (0,__vite_ssr_import_0__.bbb)() " `) }) @@ -862,12 +854,11 @@ test('jsx', async () => { const result = await transformWithEsbuild(code, id) expect(await ssrTransformSimpleCode(result.code, '/foo.jsx')) .toMatchInlineSnapshot(` - "const __vite_ssr_identity__ = v => v; - const __vite_ssr_import_0__ = await __vite_ssr_import__("react", {"importedNames":["default"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__("react", {"importedNames":["default"]}); const __vite_ssr_import_1__ = await __vite_ssr_import__("foo", {"importedNames":["Foo","Slot"]}); - function Bar({ Slot: Slot2 = /* @__PURE__ */ __vite_ssr_import_0__.default.createElement(__vite_ssr_identity__(__vite_ssr_import_1__.Foo), null) }) { + function Bar({ Slot: Slot2 = /* @__PURE__ */ __vite_ssr_import_0__.default.createElement((0,__vite_ssr_import_1__.Foo), null) }) { return /* @__PURE__ */ __vite_ssr_import_0__.default.createElement(__vite_ssr_import_0__.default.Fragment, null, /* @__PURE__ */ __vite_ssr_import_0__.default.createElement(Slot2, null)); } " @@ -939,9 +930,8 @@ import foo from "foo"`, ), ).toMatchInlineSnapshot(` "#!/usr/bin/env node - const __vite_ssr_identity__ = v => v; const __vite_ssr_import_0__ = await __vite_ssr_import__("foo", {"importedNames":["default"]}); - console.log(__vite_ssr_identity__(__vite_ssr_import_0__.default)); + console.log((0,__vite_ssr_import_0__.default)); " `) }) @@ -955,10 +945,9 @@ foo()`, ), ).toMatchInlineSnapshot(` "#!/usr/bin/env node - const __vite_ssr_identity__ = v => v; const __vite_ssr_import_0__ = await __vite_ssr_import__("foo", {"importedNames":["foo"]}); ; - __vite_ssr_identity__(__vite_ssr_import_0__.foo)()" + (0,__vite_ssr_import_0__.foo)()" `) }) @@ -992,8 +981,7 @@ export class Test { };`.trim() expect(await ssrTransformSimpleCode(code)).toMatchInlineSnapshot(` - "const __vite_ssr_identity__ = v => v; - const __vite_ssr_import_0__ = await __vite_ssr_import__("foobar", {"importedNames":["foo","bar"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__("foobar", {"importedNames":["foo","bar"]}); ; if (false) { const foo = 'foo'; @@ -1002,8 +990,8 @@ export class Test { const [bar] = ['bar']; console.log(bar) } else { - console.log(__vite_ssr_identity__(__vite_ssr_import_0__.foo)); - console.log(__vite_ssr_identity__(__vite_ssr_import_0__.bar)) + console.log((0,__vite_ssr_import_0__.foo)); + console.log((0,__vite_ssr_import_0__.bar)) } class Test { constructor() { @@ -1014,8 +1002,8 @@ export class Test { const [bar] = ['bar']; console.log(bar) } else { - console.log(__vite_ssr_identity__(__vite_ssr_import_0__.foo)); - console.log(__vite_ssr_identity__(__vite_ssr_import_0__.bar)) + console.log((0,__vite_ssr_import_0__.foo)); + console.log((0,__vite_ssr_import_0__.bar)) } } } @@ -1126,12 +1114,11 @@ const Baz = class extends Foo {} `, ) expect(result?.code).toMatchInlineSnapshot(` - "const __vite_ssr_identity__ = v => v; - const __vite_ssr_import_0__ = await __vite_ssr_import__("./foo", {"importedNames":["default","Bar"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__("./foo", {"importedNames":["default","Bar"]}); - console.log(__vite_ssr_identity__(__vite_ssr_import_0__.default), __vite_ssr_identity__(__vite_ssr_import_0__.Bar)); + console.log((0,__vite_ssr_import_0__.default), (0,__vite_ssr_import_0__.Bar)); const obj = { foo: class Foo {}, bar: class Bar {} @@ -1193,11 +1180,10 @@ export * as bar from './bar' console.log(bar) `), ).toMatchInlineSnapshot(` - "const __vite_ssr_identity__ = v => v; - const __vite_ssr_import_0__ = await __vite_ssr_import__("./foo", {"importedNames":["foo"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__("./foo", {"importedNames":["foo"]}); ; - __vite_ssr_exports__.default = __vite_ssr_identity__(__vite_ssr_import_0__.foo)(); + __vite_ssr_exports__.default = (0,__vite_ssr_import_0__.foo)(); const __vite_ssr_import_1__ = await __vite_ssr_import__("./bar"); Object.defineProperty(__vite_ssr_exports__, "bar", { enumerable: true, configurable: true, get(){ return __vite_ssr_import_1__ }});; diff --git a/packages/vite/src/node/ssr/ssrTransform.ts b/packages/vite/src/node/ssr/ssrTransform.ts index e781bdce7963f1..5a15f31463f03d 100644 --- a/packages/vite/src/node/ssr/ssrTransform.ts +++ b/packages/vite/src/node/ssr/ssrTransform.ts @@ -345,7 +345,7 @@ async function ssrTransformScript( }, }) - let injectIdentityFunction = false + const injectIdentityFunction = false // 3. convert references to import bindings & import.meta references walk(ast, { onIdentifier(id, parent, parentStack) { @@ -379,9 +379,8 @@ async function ssrTransformScript( s.update(id.start, id.end, binding) // wrap with identity function to avoid method binding `this` // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_accessors#method_binding - s.prependRight(id.start, `${ssrIdentityFunction}(`) + s.prependRight(id.start, `(0,`) s.appendLeft(id.end, `)`) - injectIdentityFunction = true } else if ( // don't transform class name identifier !(parent.type === 'ClassExpression' && id === parent.id) From 3e8bf825daca92b115f6ddbaf8845e3b17da56b7 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Mon, 25 Nov 2024 12:32:53 +0900 Subject: [PATCH 03/11] test: test transform --- .../node/ssr/__tests__/ssrTransform.spec.ts | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts index 3883648c05fced..be5e00980ca128 100644 --- a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts +++ b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts @@ -1191,3 +1191,60 @@ console.log(bar) " `) }) + +test('inject semicolon for (0, ...) wrapper', async () => { + expect( + await ssrTransformSimpleCode(` +import { f } from './f' + +let x = 0; + +x +f() + +if (1) + x +f() + +if (1) + x +else + x +f() + + +let y = x +f() + +x /*;;*/ /*;;*/ +f() +`), + ).toMatchInlineSnapshot(` + "const __vite_ssr_import_0__ = await __vite_ssr_import__("./f", {"importedNames":["f"]}); + + ; + + let x = 0; + + x; + (0,__vite_ssr_import_0__.f)(); + + if (1) + x; + (0,__vite_ssr_import_0__.f)(); + + if (1) + x + else + x; + (0,__vite_ssr_import_0__.f)(); + + + let y = x; + (0,__vite_ssr_import_0__.f)(); + + x; /*;;*/ /*;;*/ + (0,__vite_ssr_import_0__.f)() + " + `) +}) From 7d611d368b5696a921be62b7e61e09cdcb22a89b Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Mon, 25 Nov 2024 12:34:04 +0900 Subject: [PATCH 04/11] chore: cleanup --- .../node/ssr/__tests__/ssrTransform.spec.ts | 22 ++++++++++++++++++- packages/vite/src/node/ssr/ssrTransform.ts | 8 +------ 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts index be5e00980ca128..bb9c686379b564 100644 --- a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts +++ b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts @@ -1218,6 +1218,16 @@ f() x /*;;*/ /*;;*/ f() + +function z() { + x + f() + + if (1) { + x + f() + } +} `), ).toMatchInlineSnapshot(` "const __vite_ssr_import_0__ = await __vite_ssr_import__("./f", {"importedNames":["f"]}); @@ -1244,7 +1254,17 @@ f() (0,__vite_ssr_import_0__.f)(); x; /*;;*/ /*;;*/ - (0,__vite_ssr_import_0__.f)() + (0,__vite_ssr_import_0__.f)(); + + function z() { + x; + (0,__vite_ssr_import_0__.f)(); + + if (1) { + x; + (0,__vite_ssr_import_0__.f)() + } + } " `) }) diff --git a/packages/vite/src/node/ssr/ssrTransform.ts b/packages/vite/src/node/ssr/ssrTransform.ts index 5a15f31463f03d..d784fa873e3236 100644 --- a/packages/vite/src/node/ssr/ssrTransform.ts +++ b/packages/vite/src/node/ssr/ssrTransform.ts @@ -44,7 +44,6 @@ export const ssrImportKey = `__vite_ssr_import__` export const ssrDynamicImportKey = `__vite_ssr_dynamic_import__` export const ssrExportAllKey = `__vite_ssr_exportAll__` export const ssrImportMetaKey = `__vite_ssr_import_meta__` -const ssrIdentityFunction = `__vite_ssr_identity__` const hashbangRE = /^#!.*\n/ @@ -345,7 +344,6 @@ async function ssrTransformScript( }, }) - const injectIdentityFunction = false // 3. convert references to import bindings & import.meta references walk(ast, { onIdentifier(id, parent, parentStack) { @@ -377,7 +375,7 @@ async function ssrTransformScript( } } else if (parent.type === 'CallExpression') { s.update(id.start, id.end, binding) - // wrap with identity function to avoid method binding `this` + // wrap with (0, ...) to avoid method binding `this` // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_accessors#method_binding s.prependRight(id.start, `(0,`) s.appendLeft(id.end, `)`) @@ -399,10 +397,6 @@ async function ssrTransformScript( }, }) - if (injectIdentityFunction) { - s.prependLeft(fileStartIndex, `const ${ssrIdentityFunction} = v => v;\n`) - } - let map = s.generateMap({ hires: 'boundary' }) map.sources = [path.basename(url)] // needs to use originalCode instead of code From ef59c9ee5c9e80d96c49821d52b214c903881203 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Mon, 25 Nov 2024 13:27:16 +0900 Subject: [PATCH 05/11] refactor: walk single pass --- packages/vite/src/node/ssr/ssrTransform.ts | 28 +++++++++++----------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/vite/src/node/ssr/ssrTransform.ts b/packages/vite/src/node/ssr/ssrTransform.ts index d784fa873e3236..106db75b8b325a 100644 --- a/packages/vite/src/node/ssr/ssrTransform.ts +++ b/packages/vite/src/node/ssr/ssrTransform.ts @@ -330,22 +330,17 @@ async function ssrTransformScript( } } - // ensure ";" between statements - ;(eswalk as any)(ast, { - enter(node: Node) { - if (node.type === 'Program' || node.type === 'BlockStatement') { - for (let i = 0; i < node.body.length - 1; i++) { - const stmt = node.body[i] as Node - if (code[stmt.end - 1] !== ';' && code[stmt.end - 1] !== '}') { - s.appendRight(stmt.end, ';') - } + // 3. convert references to import bindings & import.meta references + walk(ast, { + onStatements(statements) { + // ensure ";" between statements + for (let i = 0; i < statements.length - 1; i++) { + const stmt = statements[i] as Node + if (code[stmt.end - 1] !== ';' && code[stmt.end - 1] !== '}') { + s.appendRight(stmt.end, ';') } } }, - }) - - // 3. convert references to import bindings & import.meta references - walk(ast, { onIdentifier(id, parent, parentStack) { const grandparent = parentStack[1] const binding = idToImportMap.get(id.name) @@ -438,6 +433,7 @@ interface Visitors { ) => void onImportMeta: (node: Node) => void onDynamicImport: (node: Node) => void + onStatements: (statements: Node[]) => void } const isNodeInPatternWeakSet = new WeakSet<_Node>() @@ -451,7 +447,7 @@ const isNodeInPattern = (node: _Node): node is Property => */ function walk( root: Node, - { onIdentifier, onImportMeta, onDynamicImport }: Visitors, + { onIdentifier, onImportMeta, onDynamicImport, onStatements }: Visitors, ) { const parentStack: Node[] = [] const varKindStack: VariableDeclaration['kind'][] = [] @@ -505,6 +501,10 @@ function walk( return this.skip() } + if (node.type === 'Program' || node.type === 'BlockStatement') { + onStatements(node.body as Node[]) + } + // track parent stack, skip for "else-if"/"else" branches as acorn nests // the ast within "if" nodes instead of flattening them if ( From 35890117271ac7a85728b162a27e80f8d1749489 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Mon, 25 Nov 2024 13:55:02 +0900 Subject: [PATCH 06/11] fix: tweak "}" skip heuristics --- .../node/ssr/__tests__/ssrTransform.spec.ts | 106 ++++++++++++------ packages/vite/src/node/ssr/ssrTransform.ts | 8 +- 2 files changed, 79 insertions(+), 35 deletions(-) diff --git a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts index bb9c686379b564..5821083c1eab2e 100644 --- a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts +++ b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts @@ -384,7 +384,7 @@ test('should declare variable for imported super class', async () => { ).toMatchInlineSnapshot(` "const __vite_ssr_import_0__ = await __vite_ssr_import__("./dependency", {"importedNames":["Foo"]}); const Foo = __vite_ssr_import_0__.Foo; - class A extends Foo {} + class A extends Foo {}; class B extends Foo {} Object.defineProperty(__vite_ssr_exports__, "B", { enumerable: true, configurable: true, get(){ return B }}); Object.defineProperty(__vite_ssr_exports__, "default", { enumerable: true, configurable: true, value: A });" @@ -412,7 +412,7 @@ test('should handle default export variants', async () => { `foo.prototype = Object.prototype;`, ), ).toMatchInlineSnapshot(` - "function foo() {} + "function foo() {}; foo.prototype = Object.prototype; Object.defineProperty(__vite_ssr_exports__, "default", { enumerable: true, configurable: true, value: foo });" `) @@ -422,7 +422,7 @@ test('should handle default export variants', async () => { `export default class A {}\n` + `export class B extends A {}`, ), ).toMatchInlineSnapshot(` - "class A {} + "class A {}; class B extends A {} Object.defineProperty(__vite_ssr_exports__, "B", { enumerable: true, configurable: true, get(){ return B }}); Object.defineProperty(__vite_ssr_exports__, "default", { enumerable: true, configurable: true, value: A });" @@ -533,8 +533,8 @@ test('overwrite bindings', async () => { ), ).toMatchInlineSnapshot(` "const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["inject"]}); - const a = { inject: __vite_ssr_import_0__.inject } - const b = { test: __vite_ssr_import_0__.inject } + const a = { inject: __vite_ssr_import_0__.inject }; + const b = { test: __vite_ssr_import_0__.inject }; function c() { const { test: inject } = { test: true }; console.log(inject) } const d = __vite_ssr_import_0__.inject; function f() { console.log((0,__vite_ssr_import_0__.inject)) } @@ -563,8 +563,8 @@ function c({ _ = bar() + foo() }) {} ).toMatchInlineSnapshot(` "const __vite_ssr_import_0__ = await __vite_ssr_import__("foo", {"importedNames":["foo","bar"]}); - ; - const a = ({ _ = (0,__vite_ssr_import_0__.foo)() }) => {} + + const a = ({ _ = (0,__vite_ssr_import_0__.foo)() }) => {}; function b({ _ = (0,__vite_ssr_import_0__.bar)() }) {} function c({ _ = (0,__vite_ssr_import_0__.bar)() + (0,__vite_ssr_import_0__.foo)() }) {} " @@ -585,9 +585,9 @@ const a = () => { ).toMatchInlineSnapshot(` "const __vite_ssr_import_0__ = await __vite_ssr_import__("foo", {"importedNames":["n"]}); - ; + const a = () => { - const { type: n = 'bar' } = {} + const { type: n = 'bar' } = {}; console.log(n) } " @@ -608,8 +608,8 @@ const foo = {} ).toMatchInlineSnapshot(` "const __vite_ssr_import_0__ = await __vite_ssr_import__("foo", {"importedNames":["n","m"]}); - ; - const foo = {} + + const foo = {}; { const { [__vite_ssr_import_0__.n]: m } = foo @@ -651,7 +651,7 @@ objRest() ).toMatchInlineSnapshot(` "const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["remove","add","get","set","rest","objRest"]}); - ; + function a() { const { @@ -701,7 +701,7 @@ const obj = { ).toMatchInlineSnapshot(` "const __vite_ssr_import_0__ = await __vite_ssr_import__("foo", {"importedNames":["default"]}); - ; + const bar = 'bar'; @@ -733,7 +733,7 @@ class A { ).toMatchInlineSnapshot(` "const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["remove","add"]}); - ; + const add = __vite_ssr_import_0__.add; const remove = __vite_ssr_import_0__.remove; @@ -765,7 +765,7 @@ class A { ).toMatchInlineSnapshot(` "const __vite_ssr_import_0__ = await __vite_ssr_import__("foo", {"importedNames":["default"]}); - ; + const bar = 'bar'; @@ -811,7 +811,7 @@ bbb() ).toMatchInlineSnapshot(` "const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["aaa","bbb","ccc","ddd"]}); - ; + function foobar() { ddd(); @@ -819,10 +819,10 @@ bbb() const aaa = () => { bbb(ccc); ddd() - } + }; const bbb = () => { console.log('hi') - } + }; const ccc = 1; function ddd() {} @@ -878,7 +878,7 @@ export function fn1() { " function fn1() { } - Object.defineProperty(__vite_ssr_exports__, "fn1", { enumerable: true, configurable: true, get(){ return fn1 }});function fn2() { + Object.defineProperty(__vite_ssr_exports__, "fn1", { enumerable: true, configurable: true, get(){ return fn1 }});;function fn2() { } Object.defineProperty(__vite_ssr_exports__, "fn2", { enumerable: true, configurable: true, get(){ return fn2 }}); " @@ -946,7 +946,7 @@ foo()`, ).toMatchInlineSnapshot(` "#!/usr/bin/env node const __vite_ssr_import_0__ = await __vite_ssr_import__("foo", {"importedNames":["foo"]}); - ; + (0,__vite_ssr_import_0__.foo)()" `) }) @@ -982,7 +982,7 @@ export class Test { expect(await ssrTransformSimpleCode(code)).toMatchInlineSnapshot(` "const __vite_ssr_import_0__ = await __vite_ssr_import__("foobar", {"importedNames":["foo","bar"]}); - ; + if (false) { const foo = 'foo'; console.log(foo) @@ -992,7 +992,7 @@ export class Test { } else { console.log((0,__vite_ssr_import_0__.foo)); console.log((0,__vite_ssr_import_0__.bar)) - } + }; class Test { constructor() { if (false) { @@ -1007,7 +1007,7 @@ export class Test { } } } - Object.defineProperty(__vite_ssr_exports__, "Test", { enumerable: true, configurable: true, get(){ return Test }});;" + Object.defineProperty(__vite_ssr_exports__, "Test", { enumerable: true, configurable: true, get(){ return Test }});;;" `) }) @@ -1025,11 +1025,11 @@ function test() { ).toMatchInlineSnapshot(` "const __vite_ssr_import_0__ = await __vite_ssr_import__("foobar", {"importedNames":["foo","bar"]}); - ; + function test() { if (true) { var foo = () => { var why = 'would' }, bar = 'someone' - } + }; return [foo, bar] }" `) @@ -1052,14 +1052,14 @@ function test() { ).toMatchInlineSnapshot(` "const __vite_ssr_import_0__ = await __vite_ssr_import__("foobar", {"importedNames":["foo","bar","baz"]}); - ; + function test() { [__vite_ssr_import_0__.foo]; { let foo = 10; let bar = 10; } - try {} catch (baz){ baz }; + try {} catch (baz){ baz };; return __vite_ssr_import_0__.bar; }" `) @@ -1084,15 +1084,15 @@ for (const test in tests) { ).toMatchInlineSnapshot(` "const __vite_ssr_import_0__ = await __vite_ssr_import__("./test.js", {"importedNames":["test"]}); - ; + for (const test of tests) { console.log(test) - } + }; for (let test = 0; test < 10; test++) { console.log(test) - } + }; for (const test in tests) { console.log(test) @@ -1122,7 +1122,7 @@ const Baz = class extends Foo {} const obj = { foo: class Foo {}, bar: class Bar {} - } + }; const Baz = class extends __vite_ssr_import_0__.default {} " `) @@ -1162,7 +1162,7 @@ console.log(foo + 2) const __vite_ssr_import_1__ = await __vite_ssr_import__("./a"); __vite_ssr_exportAll__(__vite_ssr_import_1__); ; - ; + const __vite_ssr_import_2__ = await __vite_ssr_import__("./b"); __vite_ssr_exportAll__(__vite_ssr_import_2__); ; @@ -1182,7 +1182,7 @@ console.log(bar) ).toMatchInlineSnapshot(` "const __vite_ssr_import_0__ = await __vite_ssr_import__("./foo", {"importedNames":["foo"]}); - ; + __vite_ssr_exports__.default = (0,__vite_ssr_import_0__.foo)(); const __vite_ssr_import_1__ = await __vite_ssr_import__("./bar"); @@ -1228,11 +1228,30 @@ function z() { f() } } + +let a = {} +f() + +let b = () => {} +f() + +function c() { +} +f() + +class D { +} +f() + +{ + x +} +f() `), ).toMatchInlineSnapshot(` "const __vite_ssr_import_0__ = await __vite_ssr_import__("./f", {"importedNames":["f"]}); - ; + let x = 0; @@ -1265,6 +1284,25 @@ function z() { (0,__vite_ssr_import_0__.f)() } } + + let a = {}; + (0,__vite_ssr_import_0__.f)(); + + let b = () => {}; + (0,__vite_ssr_import_0__.f)(); + + function c() { + } + (0,__vite_ssr_import_0__.f)(); + + class D { + } + (0,__vite_ssr_import_0__.f)(); + + { + x + } + (0,__vite_ssr_import_0__.f)() " `) }) diff --git a/packages/vite/src/node/ssr/ssrTransform.ts b/packages/vite/src/node/ssr/ssrTransform.ts index 106db75b8b325a..0e5a9beaf1b976 100644 --- a/packages/vite/src/node/ssr/ssrTransform.ts +++ b/packages/vite/src/node/ssr/ssrTransform.ts @@ -336,7 +336,13 @@ async function ssrTransformScript( // ensure ";" between statements for (let i = 0; i < statements.length - 1; i++) { const stmt = statements[i] as Node - if (code[stmt.end - 1] !== ';' && code[stmt.end - 1] !== '}') { + if ( + code[stmt.end - 1] !== ';' && + stmt.type !== 'FunctionDeclaration' && + stmt.type !== 'ClassDeclaration' && + stmt.type !== 'BlockStatement' && + stmt.type !== 'ImportDeclaration' + ) { s.appendRight(stmt.end, ';') } } From b965337bd8339ff5b7c7568fb0f8e48c5b4bd1f3 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Mon, 25 Nov 2024 13:56:51 +0900 Subject: [PATCH 07/11] fix: check StaticBlock --- packages/vite/src/node/ssr/ssrTransform.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/vite/src/node/ssr/ssrTransform.ts b/packages/vite/src/node/ssr/ssrTransform.ts index 0e5a9beaf1b976..cdf7955ce2389c 100644 --- a/packages/vite/src/node/ssr/ssrTransform.ts +++ b/packages/vite/src/node/ssr/ssrTransform.ts @@ -507,7 +507,11 @@ function walk( return this.skip() } - if (node.type === 'Program' || node.type === 'BlockStatement') { + if ( + node.type === 'Program' || + node.type === 'BlockStatement' || + node.type === 'StaticBlock' + ) { onStatements(node.body as Node[]) } From 83b303f17c2cffeac0b0029f852ee4ecfa2693a5 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Mon, 25 Nov 2024 18:13:24 +0900 Subject: [PATCH 08/11] chore: add bench --- package.json | 1 + .../node/ssr/__tests__/ssrTransform.bench.ts | 64 +++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 packages/vite/src/node/ssr/__tests__/ssrTransform.bench.ts diff --git a/package.json b/package.json index dd3ab51cdf2c7e..30c5744b51d06e 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "test-build": "VITE_TEST_BUILD=1 vitest run -c vitest.config.e2e.ts", "test-unit": "vitest run", "test-docs": "pnpm run docs-build", + "bench": "vitest bench", "debug-serve": "VITE_DEBUG_SERVE=1 vitest run -c vitest.config.e2e.ts", "debug-build": "VITE_TEST_BUILD=1 VITE_PRESERVE_BUILD_ARTIFACTS=1 vitest run -c vitest.config.e2e.ts", "docs": "pnpm --filter=docs run docs", diff --git a/packages/vite/src/node/ssr/__tests__/ssrTransform.bench.ts b/packages/vite/src/node/ssr/__tests__/ssrTransform.bench.ts new file mode 100644 index 00000000000000..3a97b4ae49bd47 --- /dev/null +++ b/packages/vite/src/node/ssr/__tests__/ssrTransform.bench.ts @@ -0,0 +1,64 @@ +import { bench } from 'vitest' +import { ssrTransform } from '../ssrTransform' + +const ssrTransformSimple = async (code: string, url = '') => + ssrTransform(code, null, url, code) +const ssrTransformSimpleCode = async (code: string, url?: string) => + (await ssrTransformSimple(code, url))?.code + +bench('basic', async () => { + await ssrTransformSimpleCode(` +import { f } from './f' + +let x = 0; + +x +f() + +if (1) + x +f() + +if (1) + x +else + x +f() + + +let y = x +f() + +x /*;;*/ /*;;*/ +f() + +function z() { + x + f() + + if (1) { + x + f() + } +} + +let a = {} +f() + +let b = () => {} +f() + +function c() { +} +f() + +class D { +} +f() + +{ + x +} +f() +`) +}) From eafe491b2e431c0b3df95e4092424455926d615e Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Mon, 25 Nov 2024 19:03:37 +0900 Subject: [PATCH 09/11] wip --- .../node/ssr/__tests__/ssrTransform.bench.ts | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/packages/vite/src/node/ssr/__tests__/ssrTransform.bench.ts b/packages/vite/src/node/ssr/__tests__/ssrTransform.bench.ts index 3a97b4ae49bd47..f9e314098483a3 100644 --- a/packages/vite/src/node/ssr/__tests__/ssrTransform.bench.ts +++ b/packages/vite/src/node/ssr/__tests__/ssrTransform.bench.ts @@ -1,3 +1,4 @@ +import fs from 'node:fs' import { bench } from 'vitest' import { ssrTransform } from '../ssrTransform' @@ -6,8 +7,10 @@ const ssrTransformSimple = async (code: string, url = '') => const ssrTransformSimpleCode = async (code: string, url?: string) => (await ssrTransformSimple(code, url))?.code -bench('basic', async () => { - await ssrTransformSimpleCode(` +bench( + 'basic', + async () => { + await ssrTransformSimpleCode(` import { f } from './f' let x = 0; @@ -61,4 +64,18 @@ f() } f() `) -}) + }, + { time: 5000 }, +) + +const file = + 'packages/vite/src/node/ssr/__tests__/node_modules/.cache/_chunk-YE4AM67Y.js' +const js = fs.readFileSync(file, 'utf-8') + +bench( + 'large', + async () => { + await ssrTransformSimpleCode(js) + }, + { time: 5000 }, +) From 31a436bf95166f534e94fa7c62822895bf5d73ee Mon Sep 17 00:00:00 2001 From: sapphi-red <49056869+sapphi-red@users.noreply.github.com> Date: Tue, 26 Nov 2024 13:49:08 +0900 Subject: [PATCH 10/11] fix: add ; in switch --- .../src/node/ssr/__tests__/ssrTransform.spec.ts | 16 +++++++++++++++- packages/vite/src/node/ssr/ssrTransform.ts | 5 ++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts index 5821083c1eab2e..e8570c6d4afedf 100644 --- a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts +++ b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts @@ -1247,6 +1247,13 @@ f() x } f() + +switch (1) { + case 1: + x + f() + break +} `), ).toMatchInlineSnapshot(` "const __vite_ssr_import_0__ = await __vite_ssr_import__("./f", {"importedNames":["f"]}); @@ -1302,7 +1309,14 @@ f() { x } - (0,__vite_ssr_import_0__.f)() + (0,__vite_ssr_import_0__.f)(); + + switch (1) { + case 1: + x; + (0,__vite_ssr_import_0__.f)(); + break + } " `) }) diff --git a/packages/vite/src/node/ssr/ssrTransform.ts b/packages/vite/src/node/ssr/ssrTransform.ts index cdf7955ce2389c..3a8aa9a33eeda8 100644 --- a/packages/vite/src/node/ssr/ssrTransform.ts +++ b/packages/vite/src/node/ssr/ssrTransform.ts @@ -335,7 +335,7 @@ async function ssrTransformScript( onStatements(statements) { // ensure ";" between statements for (let i = 0; i < statements.length - 1; i++) { - const stmt = statements[i] as Node + const stmt = statements[i] if ( code[stmt.end - 1] !== ';' && stmt.type !== 'FunctionDeclaration' && @@ -507,12 +507,15 @@ function walk( return this.skip() } + // for nodes that can contain multiple statements if ( node.type === 'Program' || node.type === 'BlockStatement' || node.type === 'StaticBlock' ) { onStatements(node.body as Node[]) + } else if (node.type === 'SwitchCase') { + onStatements(node.consequent as Node[]) } // track parent stack, skip for "else-if"/"else" branches as acorn nests From 54a6bc15cb5a8398404dfe952241d0e9c6512e43 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Tue, 26 Nov 2024 14:32:53 +0900 Subject: [PATCH 11/11] chore: remove bench --- package.json | 1 - .../node/ssr/__tests__/ssrTransform.bench.ts | 81 ------------------- 2 files changed, 82 deletions(-) delete mode 100644 packages/vite/src/node/ssr/__tests__/ssrTransform.bench.ts diff --git a/package.json b/package.json index b4cd3a87b83cc8..3fcd358a893291 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,6 @@ "test-build": "VITE_TEST_BUILD=1 vitest run -c vitest.config.e2e.ts", "test-unit": "vitest run", "test-docs": "pnpm run docs-build", - "bench": "vitest bench", "debug-serve": "VITE_DEBUG_SERVE=1 vitest run -c vitest.config.e2e.ts", "debug-build": "VITE_TEST_BUILD=1 VITE_PRESERVE_BUILD_ARTIFACTS=1 vitest run -c vitest.config.e2e.ts", "docs": "pnpm --filter=docs run docs", diff --git a/packages/vite/src/node/ssr/__tests__/ssrTransform.bench.ts b/packages/vite/src/node/ssr/__tests__/ssrTransform.bench.ts deleted file mode 100644 index f9e314098483a3..00000000000000 --- a/packages/vite/src/node/ssr/__tests__/ssrTransform.bench.ts +++ /dev/null @@ -1,81 +0,0 @@ -import fs from 'node:fs' -import { bench } from 'vitest' -import { ssrTransform } from '../ssrTransform' - -const ssrTransformSimple = async (code: string, url = '') => - ssrTransform(code, null, url, code) -const ssrTransformSimpleCode = async (code: string, url?: string) => - (await ssrTransformSimple(code, url))?.code - -bench( - 'basic', - async () => { - await ssrTransformSimpleCode(` -import { f } from './f' - -let x = 0; - -x -f() - -if (1) - x -f() - -if (1) - x -else - x -f() - - -let y = x -f() - -x /*;;*/ /*;;*/ -f() - -function z() { - x - f() - - if (1) { - x - f() - } -} - -let a = {} -f() - -let b = () => {} -f() - -function c() { -} -f() - -class D { -} -f() - -{ - x -} -f() -`) - }, - { time: 5000 }, -) - -const file = - 'packages/vite/src/node/ssr/__tests__/node_modules/.cache/_chunk-YE4AM67Y.js' -const js = fs.readFileSync(file, 'utf-8') - -bench( - 'large', - async () => { - await ssrTransformSimpleCode(js) - }, - { time: 5000 }, -)