webpack/webpack

Module concatenation causes Terser bailout conditions

已關閉

#17,626 建立於 2023年8月24日

 (9 則留言) (0 個反應) (0 位負責人)JavaScript (9,356 個分叉)batch import
enhancementhelp wanted

倉庫指標

星標
 (65,766 顆星)
PR 合併指標
 (平均合併 1天 5小時) (30 天內合併 180 個 PR)

描述

Bug report

I have created a simple 5-line reproduction case here: https://gist.github.com/laverdet/1b8537f56dca2d990fe63decf66a2cc6

When we export hoistable function declarations which consume concatenated modules Webpack creates bailout conditions in Terser.

If you run this example with npm i && npx webpack && cat dist/344.js we can see the output:

// [runtime noise omitted]
const e={title:"main",aaaaaaaaaaaaaaaaaaaa:"bbbbbbbbbbbb"};function s(){console.log(e.title)}

If instead you you comment out line 2, and uncomment line 3 in async.js we get this output instead:

// [runtime noise omitted]
const c=()=>{console.log("main")}

What is the current behavior?

The code that Webpack generates cannot be optimized well because Terser assumes that as soon as the function is referenced it may be invoked. Therefore it would be incorrect to inline the object keys since the hoisted function would throw if invoked before the object is defined.

If the current behavior is a bug, please provide the steps to reproduce.

This deopt is a bug because we know from the es-262 specification that the default export of payload.js will be evaluated fully before any other module can reference the function defined in async.js.

What is the expected behavior?

If concatenated modules were injected before the export runtime invocation (sorry I don't know what you call this internally) then the code could be optimized. You can observe this effect pretty easily at the Terser REPL by pasting the two examples in:

https://try.terser.org/

const a = { aaaaaaaaaaaaaaaaa: 'a' };
globalThis.foo = function() {
  console.log(a.aaaaaaaaaaaaaaaaa);
}

output: const o="a";globalThis.foo=function(){console.log(o)};

globalThis.foo = function() {
  console.log(a.aaaaaaaaaaaaaaaaa);
}
const a = { aaaaaaaaaaaaaaaaa: 'a' };

output: globalThis.foo=function(){console.log(a.aaaaaaaaaaaaaaaaa)};const a={aaaaaaaaaaaaaaaaa:"a"};

Other relevant information: webpack version: 5.88.2 Node.js version: main [996f3904bc] Operating System: macOS 13.3.1(a)

貢獻者指南