Skip to content

Expose Tether's default export, not the module namespace - #234

Draft
boo-code wants to merge 1 commit into
PrestaShop:developfrom
boo-code:fix/expose-tether-default-export-39088
Draft

Expose Tether's default export, not the module namespace#234
boo-code wants to merge 1 commit into
PrestaShop:developfrom
boo-code:fix/expose-tether-default-export-39088

Conversation

@boo-code

@boo-code boo-code commented Sep 5, 2026

Copy link
Copy Markdown
Contributor
Questions Answers
Description? tether@2.0.0 declares module: dist/js/tether.esm.js, whose last line is export default Tether, and webpack resolves the package through that field. So import 'expose-loader?exposes=Tether!tether' put the module namespace object on window.Tether: new Tether(...) threw Tether is not a constructor and Bootstrap 4 alpha's tooltips and popovers stayed broken - the password strength hint on the registration form is the reported symptom. expose-loader splits an entry on `
Type? bug fix
BC breaks? no
Deprecations? no
Fixed ticket? Fixes PrestaShop/PrestaShop#39088
Sponsor company
How to test? Open the registration form on the front office and type in the password field. Before this change the console shows Uncaught TypeError: Tether is not a constructor and the strength hint does not appear; after it, no error. Any module using a Bootstrap popover or tooltip in the classic theme is affected the same way, as reported on the thread.

Measured, in the built bundle

Same webpack config, production mode, only _dev/js/theme.js differing:

before   void 0 === i.Tether && (i.Tether = r)                       // r is the imported namespace
after    var r = n(682), i = n(799), o = r.default;
         void 0 === i.Tether && (i.Tether = o)                       // o is the class

The chain that produces it, read in the installed packages rather than assumed:

_dev/node_modules/tether/package.json      module: dist/js/tether.esm.js
        tether.esm.js last line            export default Tether;
_dev/node_modules/expose-loader 5.0.0
        dist/utils.js:22-53                splits each entry on '|' into globalName / moduleLocalName
        dist/index.js:60-73                emits ___IMPORT___.<moduleLocalName> when one is given

npx webpack --mode production exits 0 and npx eslint -c .eslintrc.js js/theme.js exits 0. assets/ is
gitignored in this repository, so the built output is not in the diff.

Why not the approach in the closed PR

classic-theme#178 (ChillCode, closed unmerged 2025-12-26) added
new webpack.ProvidePlugin({Tether: 'tether'}). ProvidePlugin injects a module-scoped variable into modules
that reference the identifier; it does not set window.Tether, which is what Bootstrap's dist build looks
for, and it would supply the same namespace object rather than the constructor. It is closed, so it blocks
nothing.

Verification limit

The bundle assignment is measured; I have not opened the registration form in a browser. The reporter
measured the same thing from the other end - Tether.default is the constructor, Tether is not - and a
second reporter (JBWModules) hit it through Bootstrap popovers in their own modules.

tether 2.0.0 declares module: dist/js/tether.esm.js, which ends with 'export default Tether', and
webpack resolves it through that field. So 'expose-loader?exposes=Tether' put the namespace object on
window.Tether: new Tether(...) threw "Tether is not a constructor" and Bootstrap 4 alpha's tooltips
and popovers - including the password strength hint on the registration form - stayed broken.

expose-loader splits an entry on '|' into globalName and moduleLocalName, so 'Tether|default' assigns
the export. Built bundles, before and after:

  before   void 0 === i.Tether && (i.Tether = r)                     // r is the namespace
  after    var o = r.default; void 0 === i.Tether && (i.Tether = o)  // o is the class

Reported on PrestaShop/PrestaShop#39088.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

JS error when filling out password in registration form: Uncaught TypeError: Tether is not a constructor

1 participant