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
72 changes: 72 additions & 0 deletions packages/vite/src/node/__tests__/plugins/esbuild.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,78 @@ describe('resolveEsbuildTranspileOptions', () => {
},
})
})

describe('destructuring workaround for safari/ios (esbuild#4436)', () => {
const workaroundNeededTargets = [
'safari10',
'safari12.1',
'safari14.0',
'ios10',
'ios12.2',
'ios14',
'ios14.4',
['chrome87', 'safari14'],
]
const workaroundNotNeededTargets = [
'safari9',
'safari14.1',
'safari14.2',
'safari15',
'safari16',
'ios9',
'ios14.5',
'ios15',
'es2020',
'chrome87',
]

test('sets supported.destructuring=true for necessary targets', () => {
for (const target of workaroundNeededTargets) {
const options = resolveEsbuildTranspileOptions(
defineResolvedConfig({
build: { target, minify: false },
}),
'es',
)
expect(options?.supported).toStrictEqual(
expect.objectContaining({
destructuring: true,
}),
)
}
})

test('does not set supported.destructuring=true for unnecessary targets', () => {
for (const target of workaroundNotNeededTargets) {
const options = resolveEsbuildTranspileOptions(
defineResolvedConfig({
build: { target, minify: false },
}),
'es',
)
expect(options?.supported).toStrictEqual(
expect.not.objectContaining({
destructuring: true,
}),
)
}
})

test('user override wins over auto-set destructuring', () => {
const options = resolveEsbuildTranspileOptions(
defineResolvedConfig({
build: { target: 'safari14', minify: false },
esbuild: { supported: { destructuring: false } },
}),
'es',
)
expect(options?.supported).toEqual({
'dynamic-import': true,
'import-meta': true,
destructuring: false,
})
})
})
})

describe('transformWithEsbuild', () => {
Expand Down
32 changes: 32 additions & 0 deletions packages/vite/src/node/plugins/esbuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,35 @@ export const buildEsbuildPlugin = (): Plugin => {
}
}

const destructuringBugRE = /^(safari|ios)(\d+)(?:\.(\d+))?$/

// Workaround for https://github.com/evanw/esbuild/issues/4436
// Safari 10 through 14.0.x and ios 10 through 14.4 have a bug related to destructuring.
// So esbuild 0.27.7+ treats those browsers as not supporting destructuring.
// However, because esbuild does not support lowering destructuring, it errors when it encounters it.
// Since it was not lowered in old Vite versions, we set `destructuring: true` to revert to the old behavior.
// This means the end users using those Safari versions will encounter the bug,
// but at least it won't cause a complete build failure.
// If the user wants to avoid that, they can use Vite v8 + plugin-legacy.
function needsDestructuringSupportedWorkaround(
target: string | string[] | false | undefined,
): boolean {
if (!target) return false
const targets = Array.isArray(target) ? target : [target]
for (const t of targets) {
const match = destructuringBugRE.exec(t)
if (!match) continue
const major = Number(match[2])
if (major < 10) continue
if (major < 14) return true
if (major > 14) continue
const minor = match[3] ? Number(match[3]) : 0
const requiredMinor = match[1] === 'safari' ? 1 : 5
if (minor < requiredMinor) return true
}
return false
}

export function resolveEsbuildTranspileOptions(
config: ResolvedConfig,
format: InternalModuleFormat,
Expand All @@ -408,6 +437,9 @@ export function resolveEsbuildTranspileOptions(
format: rollupToEsbuildFormatMap[format],
supported: {
...defaultEsbuildSupported,
...(needsDestructuringSupportedWorkaround(target)
? { destructuring: true }
: null),
...esbuildOptions.supported,
},
}
Expand Down
Loading