Skip to content

[v8] Incorrect output when banner injected above IIFE #22167

@cmdickson

Description

@cmdickson

Describe the bug

In development mode, when a banner is added to a module starting with an IIFE, the resulting Javascript is incorrect, leading to the IIFE not being invoked.

For example, the vite-plugin-node-polyfills plugin adds a banner with the following content (note there is an explicit empty line at the end):

import __buffer_polyfill from 'vite-plugin-node-polyfills/shims/buffer'
globalThis.Buffer = globalThis.Buffer || __buffer_polyfill
import __global_polyfill from 'vite-plugin-node-polyfills/shims/global'
globalThis.global = globalThis.global || __global_polyfill
import __process_polyfill from 'vite-plugin-node-polyfills/shims/process'
globalThis.process = globalThis.process || __process_polyfill

In the output, when this banner appears at the top of a module starting with an IIFE, the newline is stripped and the IIFE is appended to the last line of the banner.

e.g.

globalThis.process = globalThis.process || __process_polyfill(function(factory) {
  "use strict";
  if (typeof define === "function" && define.amd) define(["jquery", "./version"], factory);
  else factory(jQuery);
})(function($) {
...

It appears something is stripping out newlines and comments that should be after the banner.

The workaround I am using for now is to patch the library to include a semi-colon when joining to create the banner.

The banner becomes:

import __buffer_polyfill from 'vite-plugin-node-polyfills/shims/buffer';
globalThis.Buffer = globalThis.Buffer || __buffer_polyfill;
import __global_polyfill from 'vite-plugin-node-polyfills/shims/global';
globalThis.global = globalThis.global || __global_polyfill;
import __process_polyfill from 'vite-plugin-node-polyfills/shims/process';
globalThis.process = globalThis.process || __process_polyfill;

When this patch is in place, the output is correct:

globalThis.process = globalThis.process || __process_polyfill;
//#region node_modules/jquery-ui/ui/widget.js
/*!
* jQuery UI Widget 1.14.1
* https://jqueryui.com
*
* Copyright OpenJS Foundation and other contributors
* Released under the MIT license.
* https://jquery.org/license
*/
(function(factory) {
  "use strict";
  if (typeof define === "function" && define.amd) define(["jquery", "./version"], factory);
  else factory(jQuery);
})(function($) {
...

Additional notes:

  • The issue seems to be specific to Vite 8
  • There is also a PR to update the plugin to use inject instead of banner and the output issue remains.

It doesn't seem like this is something that would be due to an issue in the plugin, but let me know if my assumption is incorrect and I will move this bug to the correct repo 😄

Reproduction

https://stackblitz.com/edit/vitejs-vite-qa2o1sjy?file=src%2Fmain.ts

Steps to reproduce

  1. Load the repro application with DevTools open to Network tab
  2. View the jquery-ui.js file loaded in the Network tab

The issue with the Javascript produced will be visible and the IIFE will not be invoked.

System Info

System:
    OS: macOS 26.3
    CPU: (10) arm64 Apple M1 Pro
    Memory: 103.86 MB / 32.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 22.13.1 - /Users/xxxx/.nvm/versions/node/v22.13.1/bin/node
    Yarn: 4.5.1 - /Users/xxxx/.nvm/versions/node/v22.13.1/bin/yarn
    npm: 10.9.2 - /Users/xxxx/.nvm/versions/node/v22.13.1/bin/npm
    bun: 1.0.15 - /Users/xxxx/.bun/bin/bun
    Deno: 2.0.5 - /opt/homebrew/bin/deno
  Browsers:
    Chrome: 146.0.7680.178
    Safari: 26.3
  npmPackages:
    @vitejs/plugin-vue: ^6.0.5 => 6.0.5 
    rollup: ^4.46.3 => 4.60.0 
    vite: ^8.0.5 => 8.0.5

Used Package Manager

yarn

Logs

No response

Validations

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions