From 5b097e3bc11a24650ed49ad0018df3121484be03 Mon Sep 17 00:00:00 2001 From: "Ghislain B." Date: Thu, 31 Oct 2024 10:04:15 -0400 Subject: [PATCH 1/7] fix(json): don't `json.stringify` arrays, fixes #18533 --- packages/vite/src/node/plugins/json.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vite/src/node/plugins/json.ts b/packages/vite/src/node/plugins/json.ts index 261250ba0227f5..d032d31373c6be 100644 --- a/packages/vite/src/node/plugins/json.ts +++ b/packages/vite/src/node/plugins/json.ts @@ -51,7 +51,7 @@ export function jsonPlugin( if (options.stringify !== false) { if (options.namedExports) { const parsed = JSON.parse(json) - if (typeof parsed === 'object' && parsed != null) { + if (typeof parsed === 'object' && parsed != null && !Array.isArray(parsed)) { const keys = Object.keys(parsed) let code = '' From cb2bbd6e712f548ff459f112c5bda241a3523440 Mon Sep 17 00:00:00 2001 From: "Ghislain B." Date: Thu, 31 Oct 2024 10:09:45 -0400 Subject: [PATCH 2/7] chore: fix linting --- packages/vite/src/node/plugins/json.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/vite/src/node/plugins/json.ts b/packages/vite/src/node/plugins/json.ts index d032d31373c6be..9c6142031145a1 100644 --- a/packages/vite/src/node/plugins/json.ts +++ b/packages/vite/src/node/plugins/json.ts @@ -51,7 +51,11 @@ export function jsonPlugin( if (options.stringify !== false) { if (options.namedExports) { const parsed = JSON.parse(json) - if (typeof parsed === 'object' && parsed != null && !Array.isArray(parsed)) { + if ( + typeof parsed === 'object' && + parsed != null && + !Array.isArray(parsed) + ) { const keys = Object.keys(parsed) let code = '' From a7713af41da46d63de15f9837187b7eb537bbaa9 Mon Sep 17 00:00:00 2001 From: "Ghislain B." Date: Thu, 31 Oct 2024 14:21:20 -0400 Subject: [PATCH 3/7] chore: refactor with proposed fast-path --- packages/vite/src/node/plugins/json.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/vite/src/node/plugins/json.ts b/packages/vite/src/node/plugins/json.ts index 9c6142031145a1..4836ef28c69689 100644 --- a/packages/vite/src/node/plugins/json.ts +++ b/packages/vite/src/node/plugins/json.ts @@ -48,14 +48,10 @@ export function jsonPlugin( json = stripBomTag(json) try { - if (options.stringify !== false) { + if (options.stringify !== false && /^\s*\{/.test(json)) { if (options.namedExports) { const parsed = JSON.parse(json) - if ( - typeof parsed === 'object' && - parsed != null && - !Array.isArray(parsed) - ) { + if (typeof parsed === 'object' && parsed != null) { const keys = Object.keys(parsed) let code = '' From 41ebe7248ff8477561d9b3415be67b662f715c60 Mon Sep 17 00:00:00 2001 From: ghiscoding Date: Thu, 31 Oct 2024 20:08:39 -0400 Subject: [PATCH 4/7] chore: add unit test for json array --- .../vite/src/node/__tests__/plugins/json.spec.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/packages/vite/src/node/__tests__/plugins/json.spec.ts b/packages/vite/src/node/__tests__/plugins/json.spec.ts index 18438a007f2bec..6d9063e917cf31 100644 --- a/packages/vite/src/node/__tests__/plugins/json.spec.ts +++ b/packages/vite/src/node/__tests__/plugins/json.spec.ts @@ -35,6 +35,22 @@ describe('transform', () => { return (plugin.transform! as Function)(input, 'test.json').code } + test("namedExports: true, stringify: 'auto' should not transformed an array input", () => { + const actualSmall = transform( + '[{"a":1,"b":2}]', + { namedExports: true, stringify: 'auto' }, + false, + ) + expect(actualSmall).toMatchInlineSnapshot(` +"export default [ + { + a: 1, + b: 2 + } +];" + `) + }) + test('namedExports: true, stringify: false', () => { const actual = transform( '{"a":1,\n"🫠": "",\n"const": false}', From 95b98f1f2d505a59c8aae4248c344919cb3833c2 Mon Sep 17 00:00:00 2001 From: ghiscoding Date: Thu, 31 Oct 2024 23:01:30 -0400 Subject: [PATCH 5/7] chore: refactor as per suggestion and add extra test --- packages/vite/src/node/__tests__/plugins/json.spec.ts | 11 +++++++++++ packages/vite/src/node/plugins/json.ts | 4 ++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/vite/src/node/__tests__/plugins/json.spec.ts b/packages/vite/src/node/__tests__/plugins/json.spec.ts index 6d9063e917cf31..cde30624472dfd 100644 --- a/packages/vite/src/node/__tests__/plugins/json.spec.ts +++ b/packages/vite/src/node/__tests__/plugins/json.spec.ts @@ -51,6 +51,17 @@ describe('transform', () => { `) }) + test('namedExports: true, stringify: true should not transformed an array input', () => { + const actualSmall = transform( + '[{"a":1,"b":2}]', + { namedExports: true, stringify: true }, + false, + ) + expect(actualSmall).toMatchInlineSnapshot( + `"export default JSON.parse("[{\\"a\\":1,\\"b\\":2}]")"`, + ) + }) + test('namedExports: true, stringify: false', () => { const actual = transform( '{"a":1,\n"🫠": "",\n"const": false}', diff --git a/packages/vite/src/node/plugins/json.ts b/packages/vite/src/node/plugins/json.ts index 4836ef28c69689..4f826f2950715b 100644 --- a/packages/vite/src/node/plugins/json.ts +++ b/packages/vite/src/node/plugins/json.ts @@ -48,8 +48,8 @@ export function jsonPlugin( json = stripBomTag(json) try { - if (options.stringify !== false && /^\s*\{/.test(json)) { - if (options.namedExports) { + if (options.stringify !== false) { + if (options.namedExports && /^\s*\{/.test(json)) { const parsed = JSON.parse(json) if (typeof parsed === 'object' && parsed != null) { const keys = Object.keys(parsed) From 4f3770e3d950d680eba2ea4b873ec8d19196b304 Mon Sep 17 00:00:00 2001 From: ghiscoding Date: Thu, 31 Oct 2024 23:09:10 -0400 Subject: [PATCH 6/7] chore: refactor again as per suggestion --- packages/vite/src/node/plugins/json.ts | 34 ++++++++++++-------------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/packages/vite/src/node/plugins/json.ts b/packages/vite/src/node/plugins/json.ts index 4f826f2950715b..f0d66b6ca2089f 100644 --- a/packages/vite/src/node/plugins/json.ts +++ b/packages/vite/src/node/plugins/json.ts @@ -51,26 +51,24 @@ export function jsonPlugin( if (options.stringify !== false) { if (options.namedExports && /^\s*\{/.test(json)) { const parsed = JSON.parse(json) - if (typeof parsed === 'object' && parsed != null) { - const keys = Object.keys(parsed) - - let code = '' - let defaultObjectCode = '{\n' - for (const key of keys) { - if (key === makeLegalIdentifier(key)) { - code += `export const ${key} = ${serializeValue(parsed[key])};\n` - defaultObjectCode += ` ${key},\n` - } else { - defaultObjectCode += ` ${JSON.stringify(key)}: ${serializeValue(parsed[key])},\n` - } + const keys = Object.keys(parsed) + + let code = '' + let defaultObjectCode = '{\n' + for (const key of keys) { + if (key === makeLegalIdentifier(key)) { + code += `export const ${key} = ${serializeValue(parsed[key])};\n` + defaultObjectCode += ` ${key},\n` + } else { + defaultObjectCode += ` ${JSON.stringify(key)}: ${serializeValue(parsed[key])},\n` } - defaultObjectCode += '}' + } + defaultObjectCode += '}' - code += `export default ${defaultObjectCode};\n` - return { - code, - map: { mappings: '' }, - } + code += `export default ${defaultObjectCode};\n` + return { + code, + map: { mappings: '' }, } } From 0036f238d73ef5e1bcdef4236e0fb4b5e378bcdd Mon Sep 17 00:00:00 2001 From: bluwy Date: Fri, 1 Nov 2024 11:49:24 +0800 Subject: [PATCH 7/7] refactor: hoist regex --- packages/vite/src/node/plugins/json.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/vite/src/node/plugins/json.ts b/packages/vite/src/node/plugins/json.ts index f0d66b6ca2089f..3ba18f5bb60b29 100644 --- a/packages/vite/src/node/plugins/json.ts +++ b/packages/vite/src/node/plugins/json.ts @@ -29,6 +29,8 @@ export interface JsonOptions { // Custom json filter for vite const jsonExtRE = /\.json(?:$|\?)(?!commonjs-(?:proxy|external))/ +const jsonObjRE = /^\s*\{/ + const jsonLangs = `\\.(?:json|json5)(?:$|\\?)` const jsonLangRE = new RegExp(jsonLangs) export const isJSONRequest = (request: string): boolean => @@ -49,7 +51,7 @@ export function jsonPlugin( try { if (options.stringify !== false) { - if (options.namedExports && /^\s*\{/.test(json)) { + if (options.namedExports && jsonObjRE.test(json)) { const parsed = JSON.parse(json) const keys = Object.keys(parsed)