diff --git a/packages/playground/css-sourcemap/__tests__/build.spec.ts b/packages/playground/css-sourcemap/__tests__/build.spec.ts
new file mode 100644
index 00000000000000..e36c1f52d2c1f8
--- /dev/null
+++ b/packages/playground/css-sourcemap/__tests__/build.spec.ts
@@ -0,0 +1,13 @@
+import { isBuild } from 'testUtils'
+
+if (isBuild) {
+ test('should not output sourcemap warning (#4939)', () => {
+ serverLogs.forEach((log) => {
+ expect(log).not.toMatch('Sourcemap is likely to be incorrect')
+ })
+ })
+} else {
+ test('this file only includes test for build', () => {
+ expect(true).toBe(true)
+ })
+}
diff --git a/packages/playground/css-sourcemap/__tests__/serve.spec.ts b/packages/playground/css-sourcemap/__tests__/serve.spec.ts
new file mode 100644
index 00000000000000..50c256298143ab
--- /dev/null
+++ b/packages/playground/css-sourcemap/__tests__/serve.spec.ts
@@ -0,0 +1,214 @@
+import { fromComment } from 'convert-source-map'
+import { URL } from 'url'
+import { normalizePath } from 'vite'
+import { isBuild, testDir } from 'testUtils'
+
+if (!isBuild) {
+ const root = normalizePath(testDir)
+
+ const getStyleTagContentIncluding = async (content: string) => {
+ const styles = await page.$$('style')
+ for (const style of styles) {
+ const text = await style.textContent()
+ if (text.includes(content)) {
+ return text
+ }
+ }
+ throw new Error('Not found')
+ }
+
+ const extractSourcemap = (content: string) => {
+ const lines = content.trim().split('\n')
+ return fromComment(lines[lines.length - 1]).toObject()
+ }
+
+ const formatSourcemapForSnapshot = (map: any) => {
+ const m = { ...map }
+ delete m.file
+ delete m.names
+ m.sources = m.sources.map((source) => source.replace(root, '/root'))
+ return m
+ }
+
+ test('linked css', async () => {
+ const res = await page.request.get(
+ new URL('./linked.css', page.url()).href,
+ {
+ headers: {
+ accept: 'text/css'
+ }
+ }
+ )
+ const css = await res.text()
+ const lines = css.split('\n')
+ expect(lines[lines.length - 1].includes('/*')).toBe(false) // expect no sourcemap
+ })
+
+ test('linked css with import', async () => {
+ const res = await page.request.get(
+ new URL('./linked-with-import.css', page.url()).href,
+ {
+ headers: {
+ accept: 'text/css'
+ }
+ }
+ )
+ const css = await res.text()
+ const map = extractSourcemap(css)
+ expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(`
+ Object {
+ "mappings": "AAAA;EACE,UAAU;AACZ;;ACAA;EACE,UAAU;AACZ",
+ "sources": Array [
+ "/root/be-imported.css",
+ "/root/linked-with-import.css",
+ ],
+ "sourcesContent": Array [
+ ".be-imported {
+ color: red;
+ }
+ ",
+ "@import '@/be-imported.css';
+
+ .linked-with-import {
+ color: red;
+ }
+ ",
+ ],
+ "version": 3,
+ }
+ `)
+ })
+
+ test('imported css', async () => {
+ const css = await getStyleTagContentIncluding('.imported ')
+ const map = extractSourcemap(css)
+ expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(`
+ Object {
+ "mappings": "AAAA,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACX,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACb,CAAC;",
+ "sources": Array [
+ "/root/imported.css",
+ ],
+ "sourcesContent": Array [
+ ".imported {
+ color: red;
+ }
+ ",
+ ],
+ "version": 3,
+ }
+ `)
+ })
+
+ test('imported css with import', async () => {
+ const css = await getStyleTagContentIncluding('.imported-with-import ')
+ const map = extractSourcemap(css)
+ expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(`
+ Object {
+ "mappings": "AAAA;EACE,UAAU;AACZ;;ACAA;EACE,UAAU;AACZ",
+ "sources": Array [
+ "/root/be-imported.css",
+ "/root/imported-with-import.css",
+ ],
+ "sourcesContent": Array [
+ ".be-imported {
+ color: red;
+ }
+ ",
+ "@import '@/be-imported.css';
+
+ .imported-with-import {
+ color: red;
+ }
+ ",
+ ],
+ "version": 3,
+ }
+ `)
+ })
+
+ test('imported sass', async () => {
+ const css = await getStyleTagContentIncluding('.imported-sass ')
+ const map = extractSourcemap(css)
+ expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(`
+ Object {
+ "mappings": "AACE;EACE",
+ "sources": Array [
+ "/root/imported.sass",
+ ],
+ "sourcesContent": Array [
+ ".imported
+ &-sass
+ color: red
+ ",
+ ],
+ "version": 3,
+ }
+ `)
+ })
+
+ test('imported sass module', async () => {
+ const css = await getStyleTagContentIncluding('._imported-sass-module_')
+ const map = extractSourcemap(css)
+ expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(`
+ Object {
+ "mappings": "AACE;EACE",
+ "sources": Array [
+ "/root/imported.module.sass",
+ ],
+ "sourcesContent": Array [
+ ".imported
+ &-sass-module
+ color: red
+ ",
+ ],
+ "version": 3,
+ }
+ `)
+ })
+
+ test('imported less', async () => {
+ const css = await getStyleTagContentIncluding('.imported-less ')
+ const map = extractSourcemap(css)
+ expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(`
+ Object {
+ "mappings": "AACE;EACE",
+ "sources": Array [
+ "/root/imported.less",
+ ],
+ "sourcesContent": Array [
+ ".imported {
+ &-less {
+ color: @color;
+ }
+ }
+ ",
+ ],
+ "version": 3,
+ }
+ `)
+ })
+
+ test('imported stylus', async () => {
+ const css = await getStyleTagContentIncluding('.imported-stylus ')
+ const map = extractSourcemap(css)
+ expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(`
+ Object {
+ "mappings": "AACE;EACE,cAAM",
+ "sources": Array [
+ "/root/imported.styl",
+ ],
+ "sourcesContent": Array [
+ ".imported
+ &-stylus
+ color blue-red-mixed
+ ",
+ ],
+ "version": 3,
+ }
+ `)
+ })
+} else {
+ test('this file only includes test for serve', () => {
+ expect(true).toBe(true)
+ })
+}
diff --git a/packages/playground/css-sourcemap/be-imported.css b/packages/playground/css-sourcemap/be-imported.css
new file mode 100644
index 00000000000000..a29e5f77e3cb5d
--- /dev/null
+++ b/packages/playground/css-sourcemap/be-imported.css
@@ -0,0 +1,3 @@
+.be-imported {
+ color: red;
+}
diff --git a/packages/playground/css-sourcemap/imported-with-import.css b/packages/playground/css-sourcemap/imported-with-import.css
new file mode 100644
index 00000000000000..6a1ed3c3772698
--- /dev/null
+++ b/packages/playground/css-sourcemap/imported-with-import.css
@@ -0,0 +1,5 @@
+@import '@/be-imported.css';
+
+.imported-with-import {
+ color: red;
+}
diff --git a/packages/playground/css-sourcemap/imported.css b/packages/playground/css-sourcemap/imported.css
new file mode 100644
index 00000000000000..9c9b32924962dc
--- /dev/null
+++ b/packages/playground/css-sourcemap/imported.css
@@ -0,0 +1,3 @@
+.imported {
+ color: red;
+}
diff --git a/packages/playground/css-sourcemap/imported.less b/packages/playground/css-sourcemap/imported.less
new file mode 100644
index 00000000000000..e71b15eb102441
--- /dev/null
+++ b/packages/playground/css-sourcemap/imported.less
@@ -0,0 +1,5 @@
+.imported {
+ &-less {
+ color: @color;
+ }
+}
diff --git a/packages/playground/css-sourcemap/imported.module.sass b/packages/playground/css-sourcemap/imported.module.sass
new file mode 100644
index 00000000000000..448a5e7e31f75a
--- /dev/null
+++ b/packages/playground/css-sourcemap/imported.module.sass
@@ -0,0 +1,3 @@
+.imported
+ &-sass-module
+ color: red
diff --git a/packages/playground/css-sourcemap/imported.sass b/packages/playground/css-sourcemap/imported.sass
new file mode 100644
index 00000000000000..06fa634d5dd4e9
--- /dev/null
+++ b/packages/playground/css-sourcemap/imported.sass
@@ -0,0 +1,3 @@
+.imported
+ &-sass
+ color: red
diff --git a/packages/playground/css-sourcemap/imported.styl b/packages/playground/css-sourcemap/imported.styl
new file mode 100644
index 00000000000000..83c7cf517acf4d
--- /dev/null
+++ b/packages/playground/css-sourcemap/imported.styl
@@ -0,0 +1,3 @@
+.imported
+ &-stylus
+ color blue-red-mixed
diff --git a/packages/playground/css-sourcemap/index.html b/packages/playground/css-sourcemap/index.html
new file mode 100644
index 00000000000000..2fedceb8f2be44
--- /dev/null
+++ b/packages/playground/css-sourcemap/index.html
@@ -0,0 +1,35 @@
+
+
+
+
+
CSS Sourcemap
+
+
<linked>: no import
+
<linked>: with import
+
+
<imported>: no import
+
<imported>: with import
+
+
<imported sass>
+
<imported sass> with module
+
+
<imported less> with string additionalData
+
+
<imported stylus>
+
+
+
diff --git a/packages/playground/css-sourcemap/linked-with-import.css b/packages/playground/css-sourcemap/linked-with-import.css
new file mode 100644
index 00000000000000..6f65d92441fa49
--- /dev/null
+++ b/packages/playground/css-sourcemap/linked-with-import.css
@@ -0,0 +1,5 @@
+@import '@/be-imported.css';
+
+.linked-with-import {
+ color: red;
+}
diff --git a/packages/playground/css-sourcemap/linked.css b/packages/playground/css-sourcemap/linked.css
new file mode 100644
index 00000000000000..e3b67c83872ac0
--- /dev/null
+++ b/packages/playground/css-sourcemap/linked.css
@@ -0,0 +1,3 @@
+.linked {
+ color: red;
+}
diff --git a/packages/playground/css-sourcemap/package.json b/packages/playground/css-sourcemap/package.json
new file mode 100644
index 00000000000000..c29f18d4dee0d7
--- /dev/null
+++ b/packages/playground/css-sourcemap/package.json
@@ -0,0 +1,18 @@
+{
+ "name": "test-css-sourcemap",
+ "private": true,
+ "version": "0.0.0",
+ "scripts": {
+ "dev": "vite",
+ "build": "vite build",
+ "debug": "node --inspect-brk ../../vite/bin/vite",
+ "preview": "vite preview"
+ },
+ "devDependencies": {
+ "convert-source-map": "^1.8.0",
+ "less": "^4.1.2",
+ "magic-string": "^0.25.7",
+ "sass": "^1.43.4",
+ "stylus": "^0.55.0"
+ }
+}
diff --git a/packages/playground/css-sourcemap/vite.config.js b/packages/playground/css-sourcemap/vite.config.js
new file mode 100644
index 00000000000000..2e70a4a0894406
--- /dev/null
+++ b/packages/playground/css-sourcemap/vite.config.js
@@ -0,0 +1,40 @@
+const MagicString = require('magic-string')
+
+/**
+ * @type {import('vite').UserConfig}
+ */
+module.exports = {
+ resolve: {
+ alias: {
+ '@': __dirname
+ }
+ },
+ css: {
+ preprocessorOptions: {
+ less: {
+ additionalData: '@color: red;'
+ },
+ styl: {
+ additionalData: (content, filename) => {
+ const ms = new MagicString(content, { filename })
+
+ const willBeReplaced = 'blue-red-mixed'
+ const start = content.indexOf(willBeReplaced)
+ ms.overwrite(start, start + willBeReplaced.length, 'purple')
+
+ const map = ms.generateMap({ hires: true })
+ map.file = filename
+ map.sources = [filename]
+
+ return {
+ content: ms.toString(),
+ map
+ }
+ }
+ }
+ }
+ },
+ build: {
+ sourcemap: true
+ }
+}
diff --git a/packages/playground/vue-sourcemap/Css.vue b/packages/playground/vue-sourcemap/Css.vue
new file mode 100644
index 00000000000000..19668de8d33965
--- /dev/null
+++ b/packages/playground/vue-sourcemap/Css.vue
@@ -0,0 +1,23 @@
+
+ <css>
+ <css> module
+ <css> scoped
+
+
+
+
+
+
+
diff --git a/packages/playground/vue-sourcemap/Less.vue b/packages/playground/vue-sourcemap/Less.vue
new file mode 100644
index 00000000000000..f12a3e55f2111c
--- /dev/null
+++ b/packages/playground/vue-sourcemap/Less.vue
@@ -0,0 +1,9 @@
+
+ <less> with additionalData
+
+
+
diff --git a/packages/playground/vue-sourcemap/Main.vue b/packages/playground/vue-sourcemap/Main.vue
new file mode 100644
index 00000000000000..04ddf50071ccb3
--- /dev/null
+++ b/packages/playground/vue-sourcemap/Main.vue
@@ -0,0 +1,16 @@
+
+ Vue SFC Sourcemap
+
+
+
+
+
+
+
+
diff --git a/packages/playground/vue-sourcemap/Sass.vue b/packages/playground/vue-sourcemap/Sass.vue
new file mode 100644
index 00000000000000..0fded031a52c72
--- /dev/null
+++ b/packages/playground/vue-sourcemap/Sass.vue
@@ -0,0 +1,8 @@
+
+ <sass>
+
+
+
diff --git a/packages/playground/vue-sourcemap/SassWithImport.vue b/packages/playground/vue-sourcemap/SassWithImport.vue
new file mode 100644
index 00000000000000..7a00420a00bb3a
--- /dev/null
+++ b/packages/playground/vue-sourcemap/SassWithImport.vue
@@ -0,0 +1,11 @@
+
+ <sass> with import
+ <sass> with import (imported)
+
+
+
diff --git a/packages/playground/vue-sourcemap/__tests__/build.spec.ts b/packages/playground/vue-sourcemap/__tests__/build.spec.ts
new file mode 100644
index 00000000000000..e36c1f52d2c1f8
--- /dev/null
+++ b/packages/playground/vue-sourcemap/__tests__/build.spec.ts
@@ -0,0 +1,13 @@
+import { isBuild } from 'testUtils'
+
+if (isBuild) {
+ test('should not output sourcemap warning (#4939)', () => {
+ serverLogs.forEach((log) => {
+ expect(log).not.toMatch('Sourcemap is likely to be incorrect')
+ })
+ })
+} else {
+ test('this file only includes test for build', () => {
+ expect(true).toBe(true)
+ })
+}
diff --git a/packages/playground/vue-sourcemap/__tests__/serve.spec.ts b/packages/playground/vue-sourcemap/__tests__/serve.spec.ts
new file mode 100644
index 00000000000000..193b0afb9ba73f
--- /dev/null
+++ b/packages/playground/vue-sourcemap/__tests__/serve.spec.ts
@@ -0,0 +1,283 @@
+import { fromComment } from 'convert-source-map'
+import { normalizePath } from 'vite'
+import { isBuild, testDir } from 'testUtils'
+
+if (!isBuild) {
+ const root = normalizePath(testDir)
+
+ const getStyleTagContentIncluding = async (content: string) => {
+ const styles = await page.$$('style')
+ for (const style of styles) {
+ const text = await style.textContent()
+ if (text.includes(content)) {
+ return text
+ }
+ }
+ throw new Error('Not found')
+ }
+
+ const extractSourcemap = (content: string) => {
+ const lines = content.trim().split('\n')
+ return fromComment(lines[lines.length - 1]).toObject()
+ }
+
+ const formatSourcemapForSnapshot = (map: any) => {
+ const m = { ...map }
+ delete m.file
+ delete m.names
+ m.sources = m.sources.map((source) => source.replace(root, '/root'))
+ return m
+ }
+
+ test('css', async () => {
+ const css = await getStyleTagContentIncluding('.css ')
+ const map = extractSourcemap(css)
+ expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(`
+ Object {
+ "mappings": ";AAOA;EACE,UAAU;AACZ",
+ "sources": Array [
+ "/root/Css.vue",
+ ],
+ "sourcesContent": Array [
+ "
+ <css>
+ <css> module
+ <css> scoped
+
+
+
+
+
+
+
+ ",
+ ],
+ "version": 3,
+ }
+ `)
+ })
+
+ test('css module', async () => {
+ const css = await getStyleTagContentIncluding('._css-module_')
+ const map = extractSourcemap(css)
+ expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(`
+ Object {
+ "mappings": ";AAaA;EACE,UAAU;AACZ",
+ "sources": Array [
+ "/root/Css.vue",
+ ],
+ "sourcesContent": Array [
+ "
+ <css>
+ <css> module
+ <css> scoped
+
+
+
+
+
+
+
+ ",
+ ],
+ "version": 3,
+ }
+ `)
+ })
+
+ test('css scoped', async () => {
+ const css = await getStyleTagContentIncluding('.css-scoped[data-v-')
+ const map = extractSourcemap(css)
+ expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(`
+ Object {
+ "mappings": ";AAmBA;EACE,UAAU;AACZ",
+ "sources": Array [
+ "/root/Css.vue",
+ ],
+ "sourcesContent": Array [
+ "
+ <css>
+ <css> module
+ <css> scoped
+
+
+
+
+
+
+
+ ",
+ ],
+ "version": 3,
+ }
+ `)
+ })
+
+ test('sass', async () => {
+ const css = await getStyleTagContentIncluding('.sass ')
+ const map = extractSourcemap(css)
+ expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(`
+ Object {
+ "mappings": "AAKA;EACE",
+ "sources": Array [
+ "/root/Sass.vue",
+ ],
+ "sourcesContent": Array [
+ "
+ <sass>
+
+
+
+ ",
+ ],
+ "version": 3,
+ }
+ `)
+ })
+
+ test('sass with import', async () => {
+ const css = await getStyleTagContentIncluding('.sass-with-import ')
+ const map = extractSourcemap(css)
+ expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(`
+ Object {
+ "mappings": "AAAA;EACE;;ACOF;EACE",
+ "sources": Array [
+ "/root/sassWithImportImported.sass",
+ "/root/SassWithImport.vue",
+ ],
+ "sourcesContent": Array [
+ ".sass-with-import-imported
+ color: red
+ ",
+ "
+ <sass> with import
+ <sass> with import (imported)
+
+
+
+ ",
+ ],
+ "version": 3,
+ }
+ `)
+ })
+
+ test('less with additionalData', async () => {
+ const css = await getStyleTagContentIncluding('.less ')
+ const map = extractSourcemap(css)
+ expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(`
+ Object {
+ "mappings": "AAKA;EACE",
+ "sources": Array [
+ "/root/Less.vue",
+ ],
+ "sourcesContent": Array [
+ "
+ <less> with additionalData
+
+
+
+ ",
+ ],
+ "version": 3,
+ }
+ `)
+ })
+
+ test('src imported', async () => {
+ const css = await getStyleTagContentIncluding('.src-import[data-v-')
+ const map = extractSourcemap(css)
+ expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(`
+ Object {
+ "mappings": "AAAA;EACE,UAAU;AACZ",
+ "sources": Array [
+ "/root/src-import/src-import.css",
+ ],
+ "sourcesContent": Array [
+ ".src-import {
+ color: red;
+ }
+ ",
+ ],
+ "version": 3,
+ }
+ `)
+ })
+
+ test('src imported sass', async () => {
+ const css = await getStyleTagContentIncluding('.src-import-sass[data-v-')
+ const map = extractSourcemap(css)
+ expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(`
+ Object {
+ "mappings": "AAAA;EACE;;ACCF;EACE",
+ "sources": Array [
+ "/root/src-import/src-import-imported.sass",
+ "/root/src-import/src-import.sass",
+ ],
+ "sourcesContent": Array [
+ ".src-import-sass-imported
+ color: red
+ ",
+ "@import './src-import-imported'
+
+ .src-import-sass
+ color: red
+ ",
+ ],
+ "version": 3,
+ }
+ `)
+ })
+} else {
+ test('this file only includes test for serve', () => {
+ expect(true).toBe(true)
+ })
+}
diff --git a/packages/playground/vue-sourcemap/index.html b/packages/playground/vue-sourcemap/index.html
new file mode 100644
index 00000000000000..57f325518a2c25
--- /dev/null
+++ b/packages/playground/vue-sourcemap/index.html
@@ -0,0 +1,7 @@
+
+
diff --git a/packages/playground/vue-sourcemap/package.json b/packages/playground/vue-sourcemap/package.json
new file mode 100644
index 00000000000000..5672b5e3d9d57d
--- /dev/null
+++ b/packages/playground/vue-sourcemap/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "test-vue-sourcemap",
+ "private": true,
+ "version": "0.0.0",
+ "scripts": {
+ "dev": "vite",
+ "build": "vite build",
+ "debug": "node --inspect-brk ../../vite/bin/vite",
+ "preview": "vite preview"
+ },
+ "devDependencies": {
+ "@vitejs/plugin-vue": "workspace:*",
+ "convert-source-map": "^1.8.0",
+ "less": "^4.1.2",
+ "sass": "^1.43.4"
+ },
+ "dependencies": {
+ "vue": "^3.2.31"
+ }
+}
diff --git a/packages/playground/vue-sourcemap/sassWithImportImported.sass b/packages/playground/vue-sourcemap/sassWithImportImported.sass
new file mode 100644
index 00000000000000..8092b37048cbdd
--- /dev/null
+++ b/packages/playground/vue-sourcemap/sassWithImportImported.sass
@@ -0,0 +1,2 @@
+.sass-with-import-imported
+ color: red
diff --git a/packages/playground/vue-sourcemap/src-import/SrcImport.vue b/packages/playground/vue-sourcemap/src-import/SrcImport.vue
new file mode 100644
index 00000000000000..406c6a6b45382d
--- /dev/null
+++ b/packages/playground/vue-sourcemap/src-import/SrcImport.vue
@@ -0,0 +1,8 @@
+
+ <src-import> css
+ <src-import> sass
+ <src-import> sass (imported)
+
+
+
+
diff --git a/packages/playground/vue-sourcemap/src-import/src-import-imported.sass b/packages/playground/vue-sourcemap/src-import/src-import-imported.sass
new file mode 100644
index 00000000000000..2ed87d933e58a6
--- /dev/null
+++ b/packages/playground/vue-sourcemap/src-import/src-import-imported.sass
@@ -0,0 +1,2 @@
+.src-import-sass-imported
+ color: red
diff --git a/packages/playground/vue-sourcemap/src-import/src-import.css b/packages/playground/vue-sourcemap/src-import/src-import.css
new file mode 100644
index 00000000000000..da61ff0fb6cb27
--- /dev/null
+++ b/packages/playground/vue-sourcemap/src-import/src-import.css
@@ -0,0 +1,3 @@
+.src-import {
+ color: red;
+}
diff --git a/packages/playground/vue-sourcemap/src-import/src-import.sass b/packages/playground/vue-sourcemap/src-import/src-import.sass
new file mode 100644
index 00000000000000..c7e0314fda541c
--- /dev/null
+++ b/packages/playground/vue-sourcemap/src-import/src-import.sass
@@ -0,0 +1,4 @@
+@import './src-import-imported'
+
+.src-import-sass
+ color: red
diff --git a/packages/playground/vue-sourcemap/vite.config.js b/packages/playground/vue-sourcemap/vite.config.js
new file mode 100644
index 00000000000000..045410259fe590
--- /dev/null
+++ b/packages/playground/vue-sourcemap/vite.config.js
@@ -0,0 +1,18 @@
+const vuePlugin = require('@vitejs/plugin-vue')
+
+/**
+ * @type {import('vite').UserConfig}
+ */
+module.exports = {
+ css: {
+ preprocessorOptions: {
+ less: {
+ additionalData: '@color: red;'
+ }
+ }
+ },
+ plugins: [vuePlugin()],
+ build: {
+ sourcemap: true
+ }
+}
diff --git a/packages/plugin-vue/src/index.ts b/packages/plugin-vue/src/index.ts
index fb1bce3cd61132..28a15996363285 100644
--- a/packages/plugin-vue/src/index.ts
+++ b/packages/plugin-vue/src/index.ts
@@ -235,7 +235,8 @@ export default function vuePlugin(rawOptions: Options = {}): Plugin {
descriptor,
Number(query.index),
options,
- this
+ this,
+ filename
)
}
}
diff --git a/packages/plugin-vue/src/style.ts b/packages/plugin-vue/src/style.ts
index ad9d981412f52d..c124f3ec744e4f 100644
--- a/packages/plugin-vue/src/style.ts
+++ b/packages/plugin-vue/src/style.ts
@@ -1,6 +1,8 @@
import type { SFCDescriptor } from 'vue/compiler-sfc'
-import type { TransformPluginContext } from 'rollup'
+import type { ExistingRawSourceMap, TransformPluginContext } from 'rollup'
import type { ResolvedOptions } from '.'
+import type { RawSourceMap } from 'source-map'
+import { formatPostcssSourceMap } from 'vite'
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export async function transformStyle(
@@ -8,7 +10,8 @@ export async function transformStyle(
descriptor: SFCDescriptor,
index: number,
options: ResolvedOptions,
- pluginContext: TransformPluginContext
+ pluginContext: TransformPluginContext,
+ filename: string
) {
const block = descriptor.styles[index]
// vite already handles pre-processors and CSS module so this is only
@@ -19,7 +22,14 @@ export async function transformStyle(
id: `data-v-${descriptor.id}`,
isProd: options.isProduction,
source: code,
- scoped: block.scoped
+ scoped: block.scoped,
+ postcssOptions: {
+ map: {
+ from: filename,
+ inline: false,
+ annotation: false
+ }
+ }
})
if (result.errors.length) {
@@ -36,8 +46,17 @@ export async function transformStyle(
return null
}
+ const map = result.map
+ ? formatPostcssSourceMap(
+ // version property of result.map is declared as string
+ // but actually it is a number
+ result.map as Omit as ExistingRawSourceMap,
+ filename
+ )
+ : ({ mappings: '' } as any)
+
return {
code: result.code,
- map: result.map || ({ mappings: '' } as any)
+ map: map
}
}
diff --git a/packages/vite/package.json b/packages/vite/package.json
index d6952c40cace43..a46be406815e37 100644
--- a/packages/vite/package.json
+++ b/packages/vite/package.json
@@ -109,6 +109,7 @@
"resolve.exports": "^1.1.0",
"rollup-plugin-license": "^2.6.1",
"sirv": "^2.0.2",
+ "source-map-js": "^1.0.2",
"source-map-support": "^0.5.21",
"strip-ansi": "^6.0.1",
"terser": "^5.12.1",
diff --git a/packages/vite/src/node/index.ts b/packages/vite/src/node/index.ts
index 99567735b21757..f0f217c9be03d3 100644
--- a/packages/vite/src/node/index.ts
+++ b/packages/vite/src/node/index.ts
@@ -5,6 +5,7 @@ export { build } from './build'
export { optimizeDeps } from './optimizer'
export { send } from './server/send'
export { createLogger, printHttpServerUrls } from './logger'
+export { formatPostcssSourceMap } from './plugins/css'
export { transformWithEsbuild } from './plugins/esbuild'
export { resolvePackageEntry } from './plugins/resolve'
export {
diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts
index d513c88420b6ff..db8e0a2679f74f 100644
--- a/packages/vite/src/node/plugins/css.ts
+++ b/packages/vite/src/node/plugins/css.ts
@@ -11,17 +11,19 @@ import {
isObject,
normalizePath,
processSrcSet,
- parseRequest
+ parseRequest,
+ combineSourcemaps
} from '../utils'
import type { Plugin } from '../plugin'
import type { ResolvedConfig } from '../config'
import postcssrc from 'postcss-load-config'
import type {
+ ExistingRawSourceMap,
NormalizedOutputOptions,
OutputChunk,
RenderedChunk,
RollupError,
- SourceMap
+ SourceMapInput
} from 'rollup'
import { dataToEsm } from '@rollup/pluginutils'
import colors from 'picocolors'
@@ -44,6 +46,8 @@ import type { Alias } from 'types/alias'
import type { ModuleNode } from '../server/moduleGraph'
import { transform, formatMessages } from 'esbuild'
import { addToHTMLProxyTransformResult } from './html'
+import { injectSourcesContent, getCodeWithSourcemap } from '../server/sourcemap'
+import type { RawSourceMap } from '@ampproject/remapping'
// const debug = createDebugger('vite:css')
@@ -178,7 +182,8 @@ export function cssPlugin(config: ResolvedConfig): Plugin {
const {
code: css,
modules,
- deps
+ deps,
+ map
} = await compileCSS(
id,
raw,
@@ -245,8 +250,7 @@ export function cssPlugin(config: ResolvedConfig): Plugin {
return {
code: css,
- // TODO CSS source map
- map: { mappings: '' }
+ map
}
}
}
@@ -296,12 +300,17 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin {
if (inlined) {
return `export default ${JSON.stringify(css)}`
}
+
+ const sourcemap = this.getCombinedSourcemap()
+ await injectSourcesContent(sourcemap, cleanUrl(id), config.logger)
+ const cssContent = getCodeWithSourcemap('css', css, sourcemap)
+
return [
`import { updateStyle as __vite__updateStyle, removeStyle as __vite__removeStyle } from ${JSON.stringify(
path.posix.join(config.base, CLIENT_PUBLIC_PATH)
)}`,
`const __vite__id = ${JSON.stringify(id)}`,
- `const __vite__css = ${JSON.stringify(css)}`,
+ `const __vite__css = ${JSON.stringify(cssContent)}`,
`__vite__updateStyle(__vite__id, __vite__css)`,
// css modules exports change on edit so it can't self accept
`${
@@ -590,7 +599,7 @@ async function compileCSS(
server?: ViteDevServer
): Promise<{
code: string
- map?: SourceMap
+ map?: SourceMapInput
ast?: Postcss.Result
modules?: Record
deps?: Set
@@ -612,10 +621,10 @@ async function compileCSS(
!needInlineImport &&
!hasUrl
) {
- return { code }
+ return { code, map: null }
}
- let map: SourceMap | undefined
+ let preprocessorMap: ExistingRawSourceMap | undefined
let modules: Record | undefined
const deps = new Set()
@@ -657,7 +666,12 @@ async function compileCSS(
}
code = preprocessResult.code
- map = preprocessResult.map as SourceMap
+ preprocessorMap = combineSourcemapsIfExists(
+ opts.filename,
+ preprocessResult.map,
+ preprocessResult.additionalMap
+ )
+
if (preprocessResult.deps) {
preprocessResult.deps.forEach((dep) => {
// sometimes sass registers the file itself as a dep
@@ -733,7 +747,7 @@ async function compileCSS(
if (!postcssPlugins.length) {
return {
code,
- map
+ map: preprocessorMap
}
}
@@ -742,12 +756,14 @@ async function compileCSS(
.default(postcssPlugins)
.process(code, {
...postcssOptions,
- to: id,
- from: id,
+ to: cleanUrl(id),
+ from: cleanUrl(id),
map: {
inline: false,
annotation: false,
- prev: map
+ sourcesContent: false
+ // when "prev: preprocessorMap", the result map may include duplicate filename in `postcssResult.map.sources`
+ // prev: preprocessorMap,
}
})
@@ -791,15 +807,61 @@ async function compileCSS(
}
}
+ const rawPostcssMap = postcssResult.map.toJSON()
+
+ const postcssMap = formatPostcssSourceMap(
+ // version property of rawPostcssMap is declared as string
+ // but actually it is a number
+ rawPostcssMap as Omit as ExistingRawSourceMap,
+ cleanUrl(id)
+ )
+
return {
ast: postcssResult,
code: postcssResult.css,
- map: postcssResult.map as any,
+ map: combineSourcemapsIfExists(cleanUrl(id), postcssMap, preprocessorMap),
modules,
deps
}
}
+export function formatPostcssSourceMap(
+ rawMap: ExistingRawSourceMap,
+ file: string
+): ExistingRawSourceMap {
+ const inputFileDir = path.dirname(file)
+ const sources = rawMap.sources
+ // remove from sources, to prevent source map to be combined incorrectly
+ .filter((source) => source !== '')
+ .map((source) => {
+ const cleanSource = cleanUrl(decodeURIComponent(source))
+ return normalizePath(path.resolve(inputFileDir, cleanSource))
+ })
+
+ return {
+ file,
+ mappings: rawMap.mappings,
+ names: rawMap.names,
+ sources,
+ version: rawMap.version
+ }
+}
+
+function combineSourcemapsIfExists(
+ filename: string,
+ map1: ExistingRawSourceMap | undefined,
+ map2: ExistingRawSourceMap | undefined
+): ExistingRawSourceMap | undefined {
+ return map1 && map2
+ ? (combineSourcemaps(filename, [
+ // type of version property of ExistingRawSourceMap is number
+ // but it is always 3
+ map1 as RawSourceMap,
+ map2 as RawSourceMap
+ ]) as ExistingRawSourceMap)
+ : map1
+}
+
interface PostCSSConfigResult {
options: Postcss.ProcessOptions
plugins: Postcss.Plugin[]
@@ -998,9 +1060,18 @@ AtImportHoistPlugin.postcss = true
// Preprocessor support. This logic is largely replicated from @vue/compiler-sfc
+type PreprocessorAdditionalDataResult =
+ | string
+ | { content: string; map?: ExistingRawSourceMap }
+
type PreprocessorAdditionalData =
| string
- | ((source: string, filename: string) => string | Promise)
+ | ((
+ source: string,
+ filename: string
+ ) =>
+ | PreprocessorAdditionalDataResult
+ | Promise)
type StylePreprocessorOptions = {
[key: string]: any
@@ -1027,7 +1098,8 @@ type SassStylePreprocessor = (
export interface StylePreprocessorResults {
code: string
- map?: object
+ map?: ExistingRawSourceMap | undefined
+ additionalMap?: ExistingRawSourceMap | undefined
errors: RollupError[]
deps: string[]
}
@@ -1092,12 +1164,20 @@ const scss: SassStylePreprocessor = async (
: importer.push(options.importer)
}
+ const { content: data, map: additionalMap } = await getSource(
+ source,
+ options.filename,
+ options.additionalData
+ )
const finalOptions: Sass.Options = {
...options,
- data: await getSource(source, options.filename, options.additionalData),
+ data,
file: options.filename,
outFile: options.filename,
- importer
+ importer,
+ sourceMap: true,
+ omitSourceMapUrl: true,
+ sourceMapRoot: path.dirname(options.filename)
}
try {
@@ -1111,9 +1191,14 @@ const scss: SassStylePreprocessor = async (
})
})
const deps = result.stats.includedFiles
+ const map: ExistingRawSourceMap | undefined = result.map
+ ? JSON.parse(result.map.toString())
+ : undefined
return {
code: result.css.toString(),
+ map,
+ additionalMap,
errors: [],
deps
}
@@ -1203,13 +1288,21 @@ const less: StylePreprocessor = async (source, root, options, resolvers) => {
options.alias,
resolvers
)
- source = await getSource(source, options.filename, options.additionalData)
+ const { content, map: additionalMap } = await getSource(
+ source,
+ options.filename,
+ options.additionalData
+ )
let result: Less.RenderOutput | undefined
try {
- result = await nodeLess.render(source, {
+ result = await nodeLess.render(content, {
...options,
- plugins: [viteResolverPlugin, ...(options.plugins || [])]
+ plugins: [viteResolverPlugin, ...(options.plugins || [])],
+ sourceMap: {
+ outputSourceFiles: true,
+ sourceMapFileInline: false
+ }
})
} catch (e) {
const error = e as Less.RenderError
@@ -1222,8 +1315,14 @@ const less: StylePreprocessor = async (source, root, options, resolvers) => {
}
return { code: '', errors: [normalizedError], deps: [] }
}
+
+ const map: ExistingRawSourceMap = JSON.parse(result.map)
+ delete map.sourcesContent
+
return {
code: result.css.toString(),
+ map,
+ additionalMap,
deps: result.imports,
errors: []
}
@@ -1305,7 +1404,7 @@ const styl: StylePreprocessor = async (source, root, options) => {
const nodeStylus = loadPreprocessor(PreprocessLang.stylus, root)
// Get source with preprocessor options.additionalData. Make sure a new line separator
// is added to avoid any render error, as added stylus content may not have semi-colon separators
- source = await getSource(
+ const { content, map: additionalMap } = await getSource(
source,
options.filename,
options.additionalData,
@@ -1317,32 +1416,77 @@ const styl: StylePreprocessor = async (source, root, options) => {
path.resolve(dep)
)
try {
- const ref = nodeStylus(source, options)
-
- // if (map) ref.set('sourcemap', { inline: false, comment: false })
+ const ref = nodeStylus(content, options)
+ ref.set('sourcemap', {
+ comment: false,
+ inline: false,
+ basePath: root
+ })
const result = ref.render()
// Concat imports deps with computed deps
const deps = [...ref.deps(), ...importsDeps]
- return { code: result, errors: [], deps }
+ // @ts-expect-error sourcemap exists
+ const map: ExistingRawSourceMap = ref.sourcemap
+
+ return {
+ code: result,
+ map: formatStylusSourceMap(map, root),
+ additionalMap,
+ errors: [],
+ deps
+ }
} catch (e) {
return { code: '', errors: [e], deps: [] }
}
}
-function getSource(
+function formatStylusSourceMap(
+ mapBefore: ExistingRawSourceMap,
+ root: string
+): ExistingRawSourceMap {
+ const map = { ...mapBefore }
+
+ const resolveFromRoot = (p: string) => normalizePath(path.resolve(root, p))
+
+ if (map.file) {
+ map.file = resolveFromRoot(map.file)
+ }
+ map.sources = map.sources.map(resolveFromRoot)
+
+ return map
+}
+
+async function getSource(
source: string,
filename: string,
additionalData?: PreprocessorAdditionalData,
sep: string = ''
-): string | Promise {
- if (!additionalData) return source
+): Promise<{ content: string; map?: ExistingRawSourceMap }> {
+ if (!additionalData) return { content: source }
+
if (typeof additionalData === 'function') {
- return additionalData(source, filename)
+ const newContent = await additionalData(source, filename)
+ if (typeof newContent === 'string') {
+ return { content: newContent }
+ }
+ return newContent
+ }
+
+ const ms = new MagicString(source)
+ ms.appendLeft(0, sep)
+ ms.appendLeft(0, additionalData)
+
+ const map = ms.generateMap({ hires: true })
+ map.file = filename
+ map.sources = [filename]
+
+ return {
+ content: ms.toString(),
+ map
}
- return additionalData + sep + source
}
const preProcessors = Object.freeze({
diff --git a/packages/vite/src/node/server/pluginContainer.ts b/packages/vite/src/node/server/pluginContainer.ts
index 2f9c171de5d2e5..2aab3e03097c99 100644
--- a/packages/vite/src/node/server/pluginContainer.ts
+++ b/packages/vite/src/node/server/pluginContainer.ts
@@ -51,7 +51,7 @@ import type {
import * as acorn from 'acorn'
import type { RawSourceMap } from '@ampproject/remapping'
import { TraceMap, originalPositionFor } from '@jridgewell/trace-mapping'
-import { combineSourcemaps } from '../utils'
+import { cleanUrl, combineSourcemaps } from '../utils'
import MagicString from 'magic-string'
import type { FSWatcher } from 'chokidar'
import {
@@ -419,7 +419,7 @@ export async function createPluginContainer(
if (!combinedMap) {
combinedMap = m as SourceMap
} else {
- combinedMap = combineSourcemaps(this.filename, [
+ combinedMap = combineSourcemaps(cleanUrl(this.filename), [
{
...(m as RawSourceMap),
sourcesContent: combinedMap.sourcesContent
diff --git a/packages/vite/src/node/server/send.ts b/packages/vite/src/node/server/send.ts
index 58c63e4c9f39f2..a52d17d17458ba 100644
--- a/packages/vite/src/node/server/send.ts
+++ b/packages/vite/src/node/server/send.ts
@@ -1,8 +1,7 @@
import type { IncomingMessage, OutgoingHttpHeaders, ServerResponse } from 'http'
import getEtag from 'etag'
import type { SourceMap } from 'rollup'
-
-const isDebug = process.env.DEBUG
+import { getCodeWithSourcemap } from './sourcemap'
const alias: Record = {
js: 'application/javascript',
@@ -54,25 +53,12 @@ export function send(
// inject source map reference
if (map && map.mappings) {
- if (isDebug) {
- content += `\n/*${JSON.stringify(map, null, 2).replace(
- /\*\//g,
- '*\\/'
- )}*/\n`
+ if (type === 'js' || type === 'css') {
+ content = getCodeWithSourcemap(type, content.toString(), map)
}
- content += genSourceMapString(map)
}
res.statusCode = 200
res.end(content)
return
}
-
-function genSourceMapString(map: SourceMap | string | undefined) {
- if (typeof map !== 'string') {
- map = JSON.stringify(map)
- }
- return `\n//# sourceMappingURL=data:application/json;base64,${Buffer.from(
- map
- ).toString('base64')}`
-}
diff --git a/packages/vite/src/node/server/sourcemap.ts b/packages/vite/src/node/server/sourcemap.ts
index c6fc3b1f2579bf..68684a3c2d6f2a 100644
--- a/packages/vite/src/node/server/sourcemap.ts
+++ b/packages/vite/src/node/server/sourcemap.ts
@@ -2,6 +2,7 @@ import path from 'path'
import { promises as fs } from 'fs'
import type { Logger } from '../logger'
import { createDebugger } from '../utils'
+import type { SourceMap } from 'rollup'
const isDebug = !!process.env.DEBUG
const debug = createDebugger('vite:sourcemap', {
@@ -57,3 +58,28 @@ export async function injectSourcesContent(
isDebug && debug(`Missing sources:\n ` + missingSources.join(`\n `))
}
}
+
+function genSourceMapUrl(map: SourceMap | string | undefined) {
+ if (typeof map !== 'string') {
+ map = JSON.stringify(map)
+ }
+ return `data:application/json;base64,${Buffer.from(map).toString('base64')}`
+}
+
+export function getCodeWithSourcemap(
+ type: 'js' | 'css',
+ code: string,
+ map: SourceMap | null
+) {
+ if (isDebug) {
+ code += `\n/*${JSON.stringify(map, null, 2).replace(/\*\//g, '*\\/')}*/\n`
+ }
+
+ if (type === 'js') {
+ code += `\n//# sourceMappingURL=${genSourceMapUrl(map ?? undefined)}`
+ } else if (type === 'css') {
+ code += `\n/*# sourceMappingURL=${genSourceMapUrl(map ?? undefined)} */`
+ }
+
+ return code
+}
diff --git a/packages/vite/src/node/utils.ts b/packages/vite/src/node/utils.ts
index cca8df5750ec49..4e0f230fd7edfd 100644
--- a/packages/vite/src/node/utils.ts
+++ b/packages/vite/src/node/utils.ts
@@ -575,6 +575,26 @@ export async function processSrcSet(
}, '')
}
+function escapeToLinuxLikePath(path: string) {
+ if (/^[A-Z]:/.test(path)) {
+ return path.replace(/^([A-Z]):\//, '/windows/$1/')
+ }
+ if (/^\/[^/]/.test(path)) {
+ return `/linux${path}`
+ }
+ return path
+}
+
+function unescapeToLinuxLikePath(path: string) {
+ if (path.startsWith('/linux/')) {
+ return path.slice('/linux'.length)
+ }
+ if (path.startsWith('/windows/')) {
+ return path.replace(/^\/windows\/([A-Z])\//, '$1:/')
+ }
+ return path
+}
+
// based on https://github.com/sveltejs/svelte/blob/abf11bb02b2afbd3e4cac509a0f70e318c306364/src/compiler/utils/mapped_code.ts#L221
const nullSourceMap: RawSourceMap = {
names: [],
@@ -593,6 +613,18 @@ export function combineSourcemaps(
return { ...nullSourceMap }
}
+ // hack for parse broken with normalized absolute paths on windows (C:/path/to/something).
+ // escape them to linux like paths
+ sourcemapList.forEach((sourcemap) => {
+ sourcemap.sources = sourcemap.sources.map((source) =>
+ source ? escapeToLinuxLikePath(source) : null
+ )
+ if (sourcemap.sourceRoot) {
+ sourcemap.sourceRoot = escapeToLinuxLikePath(sourcemap.sourceRoot)
+ }
+ })
+ const escapedFilename = escapeToLinuxLikePath(filename)
+
// We don't declare type here so we can convert/fake/map as RawSourceMap
let map //: SourceMap
let mapIndex = 1
@@ -604,10 +636,10 @@ export function combineSourcemaps(
map = remapping(
sourcemapList[0],
function loader(sourcefile) {
- if (sourcefile === filename && sourcemapList[mapIndex]) {
+ if (sourcefile === escapedFilename && sourcemapList[mapIndex]) {
return sourcemapList[mapIndex++]
} else {
- return { ...nullSourceMap }
+ return null
}
},
true
@@ -617,6 +649,12 @@ export function combineSourcemaps(
delete map.file
}
+ // unescape the previous hack
+ map.sources = map.sources.map((source) =>
+ source ? unescapeToLinuxLikePath(source) : source
+ )
+ map.file = filename
+
return map as RawSourceMap
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index d8246238955fc1..5cbee016154079 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -150,6 +150,20 @@ importers:
packages/playground/css-codesplit-cjs:
specifiers: {}
+ packages/playground/css-sourcemap:
+ specifiers:
+ convert-source-map: ^1.8.0
+ less: ^4.1.2
+ magic-string: ^0.25.7
+ sass: ^1.43.4
+ stylus: ^0.55.0
+ devDependencies:
+ convert-source-map: 1.8.0
+ less: 4.1.2
+ magic-string: 0.25.7
+ sass: 1.45.1
+ stylus: 0.55.0
+
packages/playground/css/css-dep:
specifiers: {}
@@ -686,6 +700,21 @@ importers:
devDependencies:
'@vitejs/plugin-vue': link:../../plugin-vue
+ packages/playground/vue-sourcemap:
+ specifiers:
+ '@vitejs/plugin-vue': workspace:*
+ convert-source-map: ^1.8.0
+ less: ^4.1.2
+ sass: ^1.43.4
+ vue: ^3.2.31
+ dependencies:
+ vue: 3.2.31
+ devDependencies:
+ '@vitejs/plugin-vue': link:../../plugin-vue
+ convert-source-map: 1.8.0
+ less: 4.1.2
+ sass: 1.45.1
+
packages/playground/wasm:
specifiers: {}
@@ -829,6 +858,7 @@ importers:
rollup: ^2.59.0
rollup-plugin-license: ^2.6.1
sirv: ^2.0.2
+ source-map-js: ^1.0.2
source-map-support: ^0.5.21
strip-ansi: ^6.0.1
terser: ^5.12.1
@@ -901,6 +931,7 @@ importers:
resolve.exports: 1.1.0
rollup-plugin-license: 2.6.1_rollup@2.62.0
sirv: 2.0.2
+ source-map-js: 1.0.2
source-map-support: 0.5.21
strip-ansi: 6.0.1
terser: 5.12.1
@@ -2148,9 +2179,9 @@ packages:
chalk: 4.1.2
dev: true
- /@jridgewell/resolve-uri/3.0.3:
- resolution: {integrity: sha512-fuIOnc81C5iRNevb/XPiM8Khp9bVjreydRQ37rt0C/dY0PAW1DRvEM3WrKX/5rStS5lbgwS0FCgqSndh9tvK5w==}
- engines: {node: '>=10.0.0'}
+ /@jridgewell/resolve-uri/3.0.5:
+ resolution: {integrity: sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==}
+ engines: {node: '>=6.0.0'}
/@jridgewell/sourcemap-codec/1.4.10:
resolution: {integrity: sha512-Ht8wIW5v165atIX1p+JvKR5ONzUyF4Ac8DZIQ5kZs9zrb6M8SJNXpx1zn04rn65VjBMygRoMXcyYwNK0fT7bEg==}
@@ -2158,7 +2189,7 @@ packages:
/@jridgewell/trace-mapping/0.3.2:
resolution: {integrity: sha512-9KzzH4kMjA2XmBRHfqG2/Vtl7s92l6uNDd0wW7frDE+EUvQFGqNXhWp0UGJjSkt3v2AYjzOZn1QO9XaTNJIt1Q==}
dependencies:
- '@jridgewell/resolve-uri': 3.0.3
+ '@jridgewell/resolve-uri': 3.0.5
'@jridgewell/sourcemap-codec': 1.4.10
/@jridgewell/trace-mapping/0.3.4:
@@ -2830,6 +2861,15 @@ packages:
source-map: 0.6.1
dev: true
+ /@vue/compiler-core/3.2.31:
+ resolution: {integrity: sha512-aKno00qoA4o+V/kR6i/pE+aP+esng5siNAVQ422TkBNM6qA4veXiZbSe8OTXHXquEi/f6Akc+nLfB4JGfe4/WQ==}
+ dependencies:
+ '@babel/parser': 7.17.0
+ '@vue/shared': 3.2.31
+ estree-walker: 2.0.2
+ source-map: 0.6.1
+ dev: false
+
/@vue/compiler-dom/3.2.26:
resolution: {integrity: sha512-smBfaOW6mQDxcT3p9TKT6mE22vjxjJL50GFVJiI0chXYGU/xzC05QRGrW3HHVuJrmLTLx5zBhsZ2dIATERbarg==}
dependencies:
@@ -2843,6 +2883,13 @@ packages:
'@vue/shared': 3.2.31
dev: true
+ /@vue/compiler-dom/3.2.31:
+ resolution: {integrity: sha512-60zIlFfzIDf3u91cqfqy9KhCKIJgPeqxgveH2L+87RcGU/alT6BRrk5JtUso0OibH3O7NXuNOQ0cDc9beT0wrg==}
+ dependencies:
+ '@vue/compiler-core': 3.2.31
+ '@vue/shared': 3.2.31
+ dev: false
+
/@vue/compiler-sfc/3.2.26:
resolution: {integrity: sha512-ePpnfktV90UcLdsDQUh2JdiTuhV0Skv2iYXxfNMOK/F3Q+2BO0AulcVcfoksOpTJGmhhfosWfMyEaEf0UaWpIw==}
dependencies:
@@ -2872,6 +2919,21 @@ packages:
source-map: 0.6.1
dev: true
+ /@vue/compiler-sfc/3.2.31:
+ resolution: {integrity: sha512-748adc9msSPGzXgibHiO6T7RWgfnDcVQD+VVwYgSsyyY8Ans64tALHZANrKtOzvkwznV/F4H7OAod/jIlp/dkQ==}
+ dependencies:
+ '@babel/parser': 7.17.0
+ '@vue/compiler-core': 3.2.31
+ '@vue/compiler-dom': 3.2.31
+ '@vue/compiler-ssr': 3.2.31
+ '@vue/reactivity-transform': 3.2.31
+ '@vue/shared': 3.2.31
+ estree-walker: 2.0.2
+ magic-string: 0.25.7
+ postcss: 8.4.6
+ source-map: 0.6.1
+ dev: false
+
/@vue/compiler-ssr/3.2.26:
resolution: {integrity: sha512-2mywLX0ODc4Zn8qBoA2PDCsLEZfpUGZcyoFRLSOjyGGK6wDy2/5kyDOWtf0S0UvtoyVq95OTSGIALjZ4k2q/ag==}
dependencies:
@@ -2885,6 +2947,13 @@ packages:
'@vue/shared': 3.2.31
dev: true
+ /@vue/compiler-ssr/3.2.31:
+ resolution: {integrity: sha512-mjN0rqig+A8TVDnsGPYJM5dpbjlXeHUm2oZHZwGyMYiGT/F4fhJf/cXy8QpjnLQK4Y9Et4GWzHn9PS8AHUnSkw==}
+ dependencies:
+ '@vue/compiler-dom': 3.2.31
+ '@vue/shared': 3.2.31
+ dev: false
+
/@vue/devtools-api/6.0.0-beta.21.1:
resolution: {integrity: sha512-FqC4s3pm35qGVeXRGOjTsRzlkJjrBLriDS9YXbflHLsfA9FrcKzIyWnLXoNm+/7930E8rRakXuAc2QkC50swAw==}
dev: false
@@ -2908,6 +2977,16 @@ packages:
magic-string: 0.25.7
dev: true
+ /@vue/reactivity-transform/3.2.31:
+ resolution: {integrity: sha512-uS4l4z/W7wXdI+Va5pgVxBJ345wyGFKvpPYtdSgvfJfX/x2Ymm6ophQlXXB6acqGHtXuBqNyyO3zVp9b1r0MOA==}
+ dependencies:
+ '@babel/parser': 7.17.0
+ '@vue/compiler-core': 3.2.31
+ '@vue/shared': 3.2.31
+ estree-walker: 2.0.2
+ magic-string: 0.25.7
+ dev: false
+
/@vue/reactivity/3.2.26:
resolution: {integrity: sha512-h38bxCZLW6oFJVDlCcAiUKFnXI8xP8d+eO0pcDxx+7dQfSPje2AO6M9S9QO6MrxQB7fGP0DH0dYQ8ksf6hrXKQ==}
dependencies:
@@ -2919,6 +2998,12 @@ packages:
'@vue/shared': 3.2.31
dev: true
+ /@vue/reactivity/3.2.31:
+ resolution: {integrity: sha512-HVr0l211gbhpEKYr2hYe7hRsV91uIVGFYNHj73njbARVGHQvIojkImKMaZNDdoDZOIkMsBc9a1sMqR+WZwfSCw==}
+ dependencies:
+ '@vue/shared': 3.2.31
+ dev: false
+
/@vue/runtime-core/3.2.26:
resolution: {integrity: sha512-BcYi7qZ9Nn+CJDJrHQ6Zsmxei2hDW0L6AB4vPvUQGBm2fZyC0GXd/4nVbyA2ubmuhctD5RbYY8L+5GUJszv9mQ==}
dependencies:
@@ -2932,6 +3017,13 @@ packages:
'@vue/shared': 3.2.31
dev: true
+ /@vue/runtime-core/3.2.31:
+ resolution: {integrity: sha512-Kcog5XmSY7VHFEMuk4+Gap8gUssYMZ2+w+cmGI6OpZWYOEIcbE0TPzzPHi+8XTzAgx1w/ZxDFcXhZeXN5eKWsA==}
+ dependencies:
+ '@vue/reactivity': 3.2.31
+ '@vue/shared': 3.2.31
+ dev: false
+
/@vue/runtime-dom/3.2.26:
resolution: {integrity: sha512-dY56UIiZI+gjc4e8JQBwAifljyexfVCkIAu/WX8snh8vSOt/gMSEGwPRcl2UpYpBYeyExV8WCbgvwWRNt9cHhQ==}
dependencies:
@@ -2947,6 +3039,14 @@ packages:
csstype: 2.6.19
dev: true
+ /@vue/runtime-dom/3.2.31:
+ resolution: {integrity: sha512-N+o0sICVLScUjfLG7u9u5XCjvmsexAiPt17GNnaWHJUfsKed5e85/A3SWgKxzlxx2SW/Hw7RQxzxbXez9PtY3g==}
+ dependencies:
+ '@vue/runtime-core': 3.2.31
+ '@vue/shared': 3.2.31
+ csstype: 2.6.19
+ dev: false
+
/@vue/server-renderer/3.2.26_vue@3.2.26:
resolution: {integrity: sha512-Jp5SggDUvvUYSBIvYEhy76t4nr1vapY/FIFloWmQzn7UxqaHrrBpbxrqPcTrSgGrcaglj0VBp22BKJNre4aA1w==}
peerDependencies:
@@ -2966,6 +3066,16 @@ packages:
vue: 3.2.31
dev: true
+ /@vue/server-renderer/3.2.31_vue@3.2.31:
+ resolution: {integrity: sha512-8CN3Zj2HyR2LQQBHZ61HexF5NReqngLT3oahyiVRfSSvak+oAvVmu8iNLSu6XR77Ili2AOpnAt1y8ywjjqtmkg==}
+ peerDependencies:
+ vue: 3.2.31
+ dependencies:
+ '@vue/compiler-ssr': 3.2.31
+ '@vue/shared': 3.2.31
+ vue: 3.2.31
+ dev: false
+
/@vue/shared/3.2.26:
resolution: {integrity: sha512-vPV6Cq+NIWbH5pZu+V+2QHE9y1qfuTq49uNWw4f7FDEeZaDU2H2cx5jcUZOAKW7qTrUS4k6qZPbMy1x4N96nbA==}
@@ -2973,6 +3083,10 @@ packages:
resolution: {integrity: sha512-ymN2pj6zEjiKJZbrf98UM2pfDd6F2H7ksKw7NDt/ZZ1fh5Ei39X5tABugtT03ZRlWd9imccoK0hE8hpjpU7irQ==}
dev: true
+ /@vue/shared/3.2.31:
+ resolution: {integrity: sha512-ymN2pj6zEjiKJZbrf98UM2pfDd6F2H7ksKw7NDt/ZZ1fh5Ei39X5tABugtT03ZRlWd9imccoK0hE8hpjpU7irQ==}
+ dev: false
+
/@wessberg/stringutil/1.0.19:
resolution: {integrity: sha512-9AZHVXWlpN8Cn9k5BC/O0Dzb9E9xfEMXzYrNunwvkUTvuK7xgQPVRZpLo+jWCOZ5r8oBa8NIrHuPEu1hzbb6bg==}
engines: {node: '>=8.0.0'}
@@ -5046,6 +5160,19 @@ packages:
peerDependenciesMeta:
debug:
optional: true
+ dev: false
+
+ /follow-redirects/1.14.6_debug@4.3.3:
+ resolution: {integrity: sha512-fhUl5EwSJbbl8AR+uYL2KQDxLkdSjZGR36xy46AO7cOMTrCMON6Sa28FmAnC2tRTDbd/Uuzz3aJBv7EBN7JH8A==}
+ engines: {node: '>=4.0'}
+ peerDependencies:
+ debug: '*'
+ peerDependenciesMeta:
+ debug:
+ optional: true
+ dependencies:
+ debug: 4.3.3
+ dev: true
/form-data/3.0.1:
resolution: {integrity: sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==}
@@ -5446,7 +5573,7 @@ packages:
engines: {node: '>=8.0.0'}
dependencies:
eventemitter3: 4.0.7
- follow-redirects: 1.14.6
+ follow-redirects: 1.14.6_debug@4.3.3
requires-port: 1.0.0
transitivePeerDependencies:
- debug
@@ -6808,6 +6935,7 @@ packages:
resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==}
engines: {node: '>=4'}
hasBin: true
+ requiresBuild: true
dev: true
/mime/3.0.0:
@@ -8234,9 +8362,9 @@ packages:
engines: {node: '>=8.9.0'}
hasBin: true
dependencies:
- chokidar: 3.5.2
+ chokidar: 3.5.3
immutable: 4.0.0
- source-map-js: 1.0.1
+ source-map-js: 1.0.2
dev: true
/sax/1.2.4:
@@ -8448,17 +8576,13 @@ packages:
smart-buffer: 4.2.0
dev: true
- /source-map-js/1.0.1:
- resolution: {integrity: sha512-4+TN2b3tqOCd/kaGRJ/sTYA0tR0mdXx26ipdolxcwtJVqEnqNYvlCAt1q3ypy4QMlYus+Zh34RNtYLoq2oQ4IA==}
- engines: {node: '>=0.10.0'}
- dev: true
-
/source-map-js/1.0.2:
resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
engines: {node: '>=0.10.0'}
/source-map-resolve/0.6.0:
resolution: {integrity: sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==}
+ deprecated: See https://github.com/lydell/source-map-resolve#deprecated
dependencies:
atob: 2.1.2
decode-uri-component: 0.2.0
@@ -9335,6 +9459,16 @@ packages:
'@vue/shared': 3.2.31
dev: true
+ /vue/3.2.31:
+ resolution: {integrity: sha512-odT3W2tcffTiQCy57nOT93INw1auq5lYLLYtWpPYQQYQOOdHiqFct9Xhna6GJ+pJQaF67yZABraH47oywkJgFw==}
+ dependencies:
+ '@vue/compiler-dom': 3.2.31
+ '@vue/compiler-sfc': 3.2.31
+ '@vue/runtime-dom': 3.2.31
+ '@vue/server-renderer': 3.2.31_vue@3.2.31
+ '@vue/shared': 3.2.31
+ dev: false
+
/vuex/4.0.2_vue@3.2.26:
resolution: {integrity: sha512-M6r8uxELjZIK8kTKDGgZTYX/ahzblnzC4isU1tpmEuOIIKmV+TRdc+H4s8ds2NuZ7wpUTdGRzJRtoj+lI+pc0Q==}
peerDependencies:
diff --git a/scripts/jestPerTestSetup.ts b/scripts/jestPerTestSetup.ts
index 9c15edf9f059bf..312d254a3b11d2 100644
--- a/scripts/jestPerTestSetup.ts
+++ b/scripts/jestPerTestSetup.ts
@@ -114,6 +114,8 @@ beforeAll(async () => {
customLogger: createInMemoryLogger(serverLogs)
}
+ setupConsoleWarnCollector(serverLogs)
+
global.serverLogs = serverLogs
if (!isBuildTest) {
@@ -263,3 +265,11 @@ function createInMemoryLogger(logs: string[]): Logger {
return logger
}
+
+function setupConsoleWarnCollector(logs: string[]) {
+ const warn = console.warn
+ console.warn = (...args) => {
+ serverLogs.push(args.join(' '))
+ return warn.call(console, ...args)
+ }
+}