Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ export const swc: PresetProperty<'swc'> = (config: Record<string, any>): Record<
safari: 15,
firefox: 91,
},
bugfixes: config?.env?.bugfixes ?? false,
// Transpiles the broken syntax to the closest non-broken modern syntax.
// E.g. it won't transpile parameter destructuring in Safari
// which would break how we detect if the mount context property is used in the play function.
bugfixes: config?.env?.bugfixes ?? true,
},
};
};
Expand Down
1 change: 1 addition & 0 deletions code/core/src/core-server/presets/common-preset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ export const babel = async (_: unknown, options: Options) => {
[
'@babel/preset-env',
{
bugfixes: true,
targets: {
// This is the same browser supports that we use to bundle our manager and preview code.
chrome: 100,
Expand Down
1 change: 1 addition & 0 deletions code/frameworks/nextjs/src/babel/preset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ export default (api: any, options: NextBabelPresetOptions = {}): BabelPreset =>
// In production/development this option is set to `false` so that webpack can handle import/export with tree-shaking
modules: 'auto',
exclude: ['transform-typeof-symbol'],
bugfixes: true,
targets: {
chrome: 100,
safari: 15,
Expand Down
1 change: 1 addition & 0 deletions code/frameworks/nextjs/src/preset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ export const babel: PresetProperty<'babel'> = async (baseConfig: TransformOption
[
'next/dist/compiled/babel/preset-env',
{
bugfixes: true,
targets: {
chrome: 100,
safari: 15,
Expand Down
4 changes: 4 additions & 0 deletions code/frameworks/nextjs/src/swc/next-swc-loader-patch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ async function loaderTransform(this: any, parentTrace: any, source?: string, inp
// modules.
sourceFileName: filename,
};
// Transpiles the broken syntax to the closest non-broken modern syntax.
// E.g. it won't transpile parameter destructuring in Safari
// which would break how we detect if the mount context property is used in the play function.
programmaticOptions.env.bugfixes = true;
Comment on lines +116 to +119

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, locate and examine the file in question
cat -n code/frameworks/nextjs/src/swc/next-swc-loader-patch.ts | head -150

Repository: storybookjs/storybook

Length of output: 6244


🏁 Script executed:

# Search for getLoaderSWCOptions function definition
rg -nP -A 30 'export (const|function) getLoaderSWCOptions' --type=ts --type=js

Repository: storybookjs/storybook

Length of output: 47


🏁 Script executed:

# Also check for any type definitions or interfaces for programmaticOptions
rg -nP 'interface.*SWCOptions|type.*SWCOptions|programmaticOptions.*=' --type=ts --type=js code/frameworks/nextjs/src/swc/

Repository: storybookjs/storybook

Length of output: 547


🏁 Script executed:

# Check the Next.js version in dependencies
rg '"next"' code/frameworks/nextjs/package.json

Repository: storybookjs/storybook

Length of output: 144


🏁 Script executed:

# Search for any SWC options type definitions or documentation in the repo
rg -A 10 'env.*bugfixes|env:.*{' --type=ts --type=js code/frameworks/nextjs/

Repository: storybookjs/storybook

Length of output: 170


🏁 Script executed:

# Look for other places where getLoaderSWCOptions is used or where env is accessed on SWC options
rg 'getLoaderSWCOptions|\.env\.' --type=ts --type=js code/frameworks/nextjs/ -B 2 -A 2

Repository: storybookjs/storybook

Length of output: 4659


🏁 Script executed:

# Check if there's a Next.js patch or version check
cat code/frameworks/nextjs/package.json

Repository: storybookjs/storybook

Length of output: 4745


🏁 Script executed:

# Search for tests related to next-swc-loader-patch
fd -e test.ts -e test.js -e spec.ts -e spec.js -e .test.ts code/frameworks/nextjs/ | head -20

Repository: storybookjs/storybook

Length of output: 462


🏁 Script executed:

# Search for any usage/reference to swcOptions or env in the context of SWC
rg -A 5 -B 5 'swcOptions' code/frameworks/nextjs/src/ --type=ts --type=js

Repository: storybookjs/storybook

Length of output: 1879


🏁 Script executed:

# Check if there are any comments or documentation about the structure
rg -A 10 'getLoaderSWCOptions' code/frameworks/nextjs/ --type=ts --type=js

Repository: storybookjs/storybook

Length of output: 1956


🏁 Script executed:

# Look for version checks or compatibility handling
rg 'getNextjsVersion|version' code/frameworks/nextjs/src/utils.ts -A 5 -B 5

Repository: storybookjs/storybook

Length of output: 1440


🏁 Script executed:

# Search for test files in the nextjs framework
fd . code/frameworks/nextjs --type f -name "*.test.*" -o -name "*.spec.*"

Repository: storybookjs/storybook

Length of output: 295


🏁 Script executed:

# Look for any imports or type definitions related to swc in the repo
rg 'type.*SWC|interface.*SWC' code/frameworks/nextjs --type=ts

Repository: storybookjs/storybook

Length of output: 156


🏁 Script executed:

# Check if there are any comments or patterns in how swcOptions is used in other parts of the codebase
rg -B 10 -A 10 'programmaticOptions\.env|swcOptions\.env' --type=ts --type=js

Repository: storybookjs/storybook

Length of output: 1988


🏁 Script executed:

# Search in broader Storybook codebase for SWC patterns
rg 'env.*bugfixes|bugfixes.*true' --type=ts --type=js

Repository: storybookjs/storybook

Length of output: 489


🏁 Script executed:

# Get more context around the builder-webpack5 pattern
rg -B 15 -A 5 'bugfixes: config' code/builders/builder-webpack5/src/presets/custom-webpack-preset.ts

Repository: storybookjs/storybook

Length of output: 807


🏁 Script executed:

# Check the file that was mentioned in the original review as context
cat -n code/builders/builder-webpack5/src/presets/custom-webpack-preset.ts | sed -n '1,50p'

Repository: storybookjs/storybook

Length of output: 2216


🏁 Script executed:

# Search for any historical issues or comments about env property
rg -i 'env.*property|env.*undefined|env.*null' code/frameworks/nextjs/ --type=ts --type=js

Repository: storybookjs/storybook

Length of output: 47


Verify that programmaticOptions.env exists before assignment.

The code directly assigns programmaticOptions.env.bugfixes = true without verifying that the env property exists. If getLoaderSWCOptions returns an object without an env property, this will throw a TypeError.

Compare this to the defensive pattern used in the same codebase (code/builders/builder-webpack5/src/presets/custom-webpack-preset.ts), which uses identical logic but with a defensive approach:

env: {
  ...(config?.env ?? {}),
  bugfixes: config?.env?.bugfixes ?? true,
},

Additionally, the code already demonstrates defensive checking patterns elsewhere (lines 128–133 verify programmaticOptions.jsc before nested access). Apply the same defensive approach here:

programmaticOptions.env = programmaticOptions.env || {};
programmaticOptions.env.bugfixes = true;
🤖 Prompt for AI Agents
In @code/frameworks/nextjs/src/swc/next-swc-loader-patch.ts around lines 116 -
119, Ensure programmaticOptions.env exists before setting bugfixes: when you see
the direct assignment to programmaticOptions.env.bugfixes change it to first
ensure programmaticOptions.env is an object (create an empty object if
undefined) and then set programmaticOptions.env.bugfixes = true (or only set it
when undefined if you prefer to preserve an explicit existing value); update the
code around the programmaticOptions.env.bugfixes assignment to follow this
defensive pattern.


if (!programmaticOptions.inputSourceMap) {
delete programmaticOptions.inputSourceMap;
Expand Down
Loading