Skip to content
Closed
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
1 change: 1 addition & 0 deletions packages/wp-build/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Bug Fixes

- Preserve the non-enumerable `__esModule` marker on `window.wp.*` IIFE globals so that external webpack consumers (e.g. WooCommerce) can still default-import `@wordpress/*` packages exposed as webpack externals.
- Remove the incorrect `#wpwrap` background from wp-admin critical CSS to prevent a black flash before hydration; rely on the existing `body` background instead ([#78493](https://github.com/WordPress/gutenberg/pull/78493)).

## 0.15.0 (2026-05-27)
Expand Down
10 changes: 7 additions & 3 deletions packages/wp-build/lib/build.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -585,10 +585,14 @@ async function bundlePackage( packageName, options = {} ) {
}
if ( globalName ) {
// esbuild marks the getters non-configurable, so we can't rewrite
// them in place; replacing the whole namespace with a shallow
// copy is the simplest way to materialize each value once.
// them in place; replacing the whole namespace with a shallow copy
// is the simplest way to materialize each value once.
//
// Seed the copy with a non-enumerable `__esModule` flag so that
// bundlers treat it as an ESM module, triggering interop
// conventions for default exports.
footerParts.push(
`if(${ globalName }&&typeof ${ globalName }==='object'){${ globalName }=Object.assign({},${ globalName });}`
`if(${ globalName }&&typeof ${ globalName }==='object'){${ globalName }=Object.assign(Object.defineProperty({},'__esModule',{value:true,writable:true}),${ globalName });}`
);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think that all we need to do is that instead of Object.assign({}, ...) we do Object.assign({ __esModule: true }, ...). That covers everything, the patch doesn't need to be that complicated.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good call, that's much cleaner — pre-seeding the target also makes the writable concern moot in the common case. One tweak: a plain { __esModule: true } literal defines the property as enumerable, but esbuild's __toCommonJS (and webpack's own __webpack_require__.r) mark it non-enumerable, so the literal would leak __esModule into Object.keys(), spread, and downstream Object.assign. Keeping it non-enumerable is still a one-liner:

`if(${ globalName }&&typeof ${ globalName }==='object'){${ globalName }=Object.assign(Object.defineProperty({},'__esModule',{value:true,writable:true}),${ globalName });}`

That drops both the conditional and the two-branch split. I kept writable: true as a cheap guard so a future esbuild change emitting an enumerable __esModule wouldn't trip a strict-mode write when Object.assign copies it — happy to drop it if you'd rather keep it minimal. Pushed in be32a3d.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yes, it's great that Object.defineProperty returns the object 🙂

}
if ( footerParts.length ) {
Expand Down
Loading