Repository: vercel/next.js
Pull request: test: extend production-browser-sourcemaps test

To test the change in  https://github.com/vercel/next.js/pull/89915

Changed files:
filename: test/production/production-browser-sourcemaps/app/layout.js
patch: @@ -0,0 +1,8 @@
+export default function Root({ children }) {
+  return (
+    <html>
+      <head></head>
+      <body>{children}</body>
+    </html>
+  )
+}

filename: test/production/production-browser-sourcemaps/app/page.js
patch: @@ -0,0 +1,3 @@
+export default function page() {
+  return <div>hello</div>
+}

filename: test/production/production-browser-sourcemaps/index.test.ts
patch: @@ -4,24 +4,51 @@ import { getBuildManifest } from 'next-test-utils'
 import { recursiveReadDir } from 'next/dist/lib/recursive-readdir'
 import { nextTestSetup } from 'e2e-utils'
 
-function extractSourceMappingURL(jsContent): string | null {
+function extractSourceMappingURL(jsContent: string): string | null {
   // Matches both //# and //@ sourceMappingURL=...
   const match = jsContent.match(/\/\/[#@] sourceMappingURL=([^\s]+)/)
   return match ? match[1] : null
 }
 
-async function sourceMapExistsForFile(jsFilePath) {
+async function validateSourceMapForChunk(
+  dir: string,
+  file: string,
+  {
+    polyfillFiles,
+    productionBrowserSourceMaps,
+  }: { polyfillFiles: Set<string>; productionBrowserSourceMaps: boolean }
+) {
+  const jsFilePath = path.join(dir, file)
   const jsContent = await fs.readFile(jsFilePath, 'utf8')
   const sourceMappingURL = extractSourceMappingURL(jsContent)
   if (!sourceMappingURL) {
-    if (/^__turbopack_load_page_chunks__\(["']/.test(jsContent)) {
+    if (
+      /^__turbopack_load_page_chunks__\(["']/.test(jsContent) ||
+      (!process.env.IS_TURBOPACK_TEST && jsContent.length < 300)
+    ) {
       // There is no sourcemap in these loader chunks, ignore
-      return undefined
+      return
     }
-    return false
+    if (await fs.pathExists(jsFilePath + '.map')) {
+      // sourcemap file exists, but without sourceMappingURL comment
+      // currently the case for polyfills chunk
+      if (!productionBrowserSourceMaps) {
+        throw new Error(`Source map file exists for ${jsFilePath}.`)
+      }
+    }
+    if (polyfillFiles.has(file)) {
+      // polyfill files might not have sourcemaps, ignore
+      return
+    }
+    if (productionBrowserSourceMaps) {
+      throw new Error(`Source map missing for ${jsFilePath}.`)
+    }
+    return
   }
   const mapPath = path.join(path.dirname(jsFilePath), sourceMappingURL)
-  return await fs.pathExists(mapPath)
+  if ((await fs.pathExists(mapPath)) !== productionBrowserSourceMaps) {
+    throw new Error(`Source map presence mismatch for ${jsFilePath}.`)
+  }
 }
 
 describe('Production browser sourcemaps', () => {
@@ -43,32 +70,34 @@ describe('Production browser sourcemaps', () => {
       it('check sourcemaps for all browser files', async () => {
         const buildManifest = getBuildManifest(next.testDir)
 
-        // These currently don't have sourcemaps
-        let polyfillFiles = new Set(
-          buildManifest.polyfillFiles.map((f) => '/' + path.basename(f))
+        let polyfillFiles = new Set<string>(
+          buildManifest.polyfillFiles.map(
+            (f: string) => '/' + path.relative(path.join('static', 'chunks'), f)
+          )
         )
 
         const staticDir = path.join(next.testDir, '.next', 'static', 'chunks')
         const browserFiles = await recursiveReadDir(staticDir)
-        const jsFiles = browserFiles.filter(
-          (file) => file.endsWith('.js') && !polyfillFiles.has(file)
-        )
+        const jsFiles = browserFiles.filter((file) => file.endsWith('.js'))
         expect(jsFiles).not.toBeEmpty()
 
         for (const file of jsFiles) {
-          const jsPath = path.join(staticDir, file)
-          expect(await sourceMapExistsForFile(jsPath)).toBeOneOf([
+          await validateSourceMapForChunk(staticDir, file, {
+            polyfillFiles,
             productionBrowserSourceMaps,
-            undefined,
-          ])
+          })
         }
 
         for (let page of ['/ssr', '/static']) {
           const jsFiles = buildManifest.pages[page]
           for (const file of jsFiles) {
-            const jsPath = path.join(next.testDir, '.next', file)
-            expect(await sourceMapExistsForFile(jsPath)).toBe(
-              productionBrowserSourceMaps
+            await validateSourceMapForChunk(
+              path.join(next.testDir, '.next'),
+              file,
+              {
+                polyfillFiles,
+                productionBrowserSourceMaps,
+              }
             )
           }
         }