pionxzh / wakaru

🔪📦 Javascript decompiler for modern frontend
https://wakaru.vercel.app/
MIT License
296 stars 17 forks source link

Multiple exports of "X" found, only the last one will be kept #53

Closed 0xdevalias closed 10 months ago

0xdevalias commented 10 months ago

Attempting to unpack/unminify some webpacked code (Ref):

⇒ cd ./unpacked/_next/static/chunks

⇒ npx @wakaru/unpacker pages/_app.js -o ./pages/_app-unpacked/
Generated 213 modules from pages/_app.js to pages/_app-unpacked (24,049ms)

⇒ npx @wakaru/unminify ./pages/_app-unpacked/* -o ./pages/_app-unminified
# ..snip..

I got a bunch of warnings(?) similar to the following while attempting to unminify; though it's not clear if these warnings relate to the module listed before them, or after them:

• Transforming pages/_app-unminified/pages/_app-unpacked/module-10538.js (361.8ms)
Multiple exports of "default" found, only the last one will be kept
• Transforming pages/_app-unminified/pages/_app-unpacked/module-10608.js (64.1ms)

.. snip..

• Transforming pages/_app-unminified/pages/_app-unpacked/module-138.js (153.3ms)
Multiple exports of "getUserCacheKey" found, only the last one will be kept
• Transforming pages/_app-unminified/pages/_app-unpacked/module-13957.js (290.8ms)

etc

The 'multiple exports' log seems to happen in unminify's replaceWithExportDeclaration:

https://github.com/pionxzh/wakaru/blob/e2ff1ba7e455b1f31a869e1bcefb9bab3fa71964/packages/unminify/src/transformations/un-esm.ts#L401-L407

The 'Transforming' log seems to happen in unminify's CLI, and appears after the call to runDefaultTransformation (which calls runTransformations, which uses transformationMap, which includes unEsm, which contains transformAST, which calls transformExport, which calls replaceWithExportDeclaration)

This implies that the warning before the module applies to that module..

Full list of the different warnings + modules that caused them ``` Multiple exports of "default" found, only the last one will be kept • Transforming pages/_app-unminified/pages/_app-unpacked/module-10608.js (64.1ms) Multiple exports of "getUserCacheKey" found, only the last one will be kept • Transforming pages/_app-unminified/pages/_app-unpacked/module-13957.js (290.8ms) Multiple exports of "default" found, only the last one will be kept • Transforming pages/_app-unminified/pages/_app-unpacked/module-16861.js (163.4ms) Multiple exports of "default" found, only the last one will be kept • Transforming pages/_app-unminified/pages/_app-unpacked/module-18458.js (212.8ms) Multiple exports of "default" found, only the last one will be kept • Transforming pages/_app-unminified/pages/_app-unpacked/module-21121.js (147.7ms) Multiple exports of "default" found, only the last one will be kept • Transforming pages/_app-unminified/pages/_app-unpacked/module-21508.js (55.2ms) Multiple exports of "Base64" found, only the last one will be kept • Transforming pages/_app-unminified/pages/_app-unpacked/module-27046.js (283.1ms) Multiple exports of "default" found, only the last one will be kept • Transforming pages/_app-unminified/pages/_app-unpacked/module-36386.js (97.5ms) Multiple exports of "checkCookies" found, only the last one will be kept • Transforming pages/_app-unminified/pages/_app-unpacked/module-44544.js (892.6ms) Multiple exports of "STORAGE_PREFIX" found, only the last one will be kept • Transforming pages/_app-unminified/pages/_app-unpacked/module-49787.js (94.5ms) Multiple exports of "default" found, only the last one will be kept • Transforming pages/_app-unminified/pages/_app-unpacked/module-50201.js (2,190.6ms) Multiple exports of "ExceptionEndpoint" found, only the last one will be kept • Transforming pages/_app-unminified/pages/_app-unpacked/module-5421.js (1,131.6ms) Multiple exports of "StatsigInvalidArgumentError" found, only the last one will be kept • Transforming pages/_app-unminified/pages/_app-unpacked/module-5502.js (238.5ms) Multiple exports of "default" found, only the last one will be kept • Transforming pages/_app-unminified/pages/_app-unpacked/module-60925.js (160.4ms) Multiple exports of "default" found, only the last one will be kept • Transforming pages/_app-unminified/pages/_app-unpacked/module-65860.js (93.2ms) Multiple exports of "default" found, only the last one will be kept • Transforming pages/_app-unminified/pages/_app-unpacked/module-6631.js (202.8ms) Multiple exports of "default" found, only the last one will be kept • Transforming pages/_app-unminified/pages/_app-unpacked/module-67523.js (105.4ms) Multiple exports of "default" found, only the last one will be kept • Transforming pages/_app-unminified/pages/_app-unpacked/module-67860.js (75.8ms) Multiple exports of "default" found, only the last one will be kept • Transforming pages/_app-unminified/pages/_app-unpacked/module-69270.js (89.2ms) Multiple exports of "default" found, only the last one will be kept • Transforming pages/_app-unminified/pages/_app-unpacked/module-70479.js (123.6ms) Multiple exports of "default" found, only the last one will be kept • Transforming pages/_app-unminified/pages/_app-unpacked/module-71083.js (576.5ms) Multiple exports of "default" found, only the last one will be kept • Transforming pages/_app-unminified/pages/_app-unpacked/module-74861.js (51.2ms) Multiple exports of "default" found, only the last one will be kept • Transforming pages/_app-unminified/pages/_app-unpacked/module-76226.js (123.2ms) Multiple exports of "default" found, only the last one will be kept • Transforming pages/_app-unminified/pages/_app-unpacked/module-77415.js (107.2ms) Multiple exports of "UnsupportedStrategy" found, only the last one will be kept • Transforming pages/_app-unminified/pages/_app-unpacked/module-80456.js (2,691.6ms) Multiple exports of "default" found, only the last one will be kept • Transforming pages/_app-unminified/pages/_app-unpacked/module-84019.js (130.3ms) Multiple exports of "default" found, only the last one will be kept • Transforming pages/_app-unminified/pages/_app-unpacked/module-8629.js (83.7ms) Multiple exports of "default" found, only the last one will be kept • Transforming pages/_app-unminified/pages/_app-unpacked/module-91921.js (75ms) Multiple exports of "default" found, only the last one will be kept • Transforming pages/_app-unminified/pages/_app-unpacked/module-94355.js (54.4ms) Multiple exports of "default" found, only the last one will be kept • Transforming pages/_app-unminified/pages/_app-unpacked/module-98421.js (65.1ms) Multiple exports of "difference" found, only the last one will be kept • Transforming pages/_app-unminified/pages/_app-unpacked/module-98480.js (80.3ms) ```

I haven't yet looked through the individual modules that caused warnings, but I wanted to open this issue as a placeholder for adding any more info about them that seems relevant as I do.

0xdevalias commented 10 months ago
Multiple exports of "default" found, only the last one will be kept
• Transforming pages/_app-unminified/pages/_app-unpacked/module-10608.js (64.1ms)

This is the code within module-10608.js that is triggering the warning:

function B() {
  throw TypeError(
    "Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."
  );
}
(module.exports = B),
  (module.exports.__esModule = !0),
  (module.exports.default = module.exports);

Other modules with similar patterns to this:


Multiple exports of "getUserCacheKey" found, only the last one will be kept
• Transforming pages/_app-unminified/pages/_app-unpacked/module-13957.js (290.8ms)

module-13957.js has the following:

"use strict";;
Object.defineProperty(exports, "__esModule", { value: !0 }),
  (exports.getUserCacheKey = exports.getHashValue = exports.SimpleHash = void 0);

// ..snip..

(exports.SimpleHash = J), (exports.getHashValue = X), (exports.getUserCacheKey = Q);

pages/_app-unminified/pages/_app-unpacked/module-27046.js

"use strict";;
Object.defineProperty(exports, "__esModule", { value: !0 }),
  (exports.Base64 = void 0),
  (exports.Base64 = {
      // ..snip..
      return exports.Base64._encodeBinary(G);
    },
  });

pages/_app-unminified/pages/_app-unpacked/module-5502.js

// ..snip..

Object.defineProperty(exports, "__esModule", { value: !0 }),
  (exports.StatsigInvalidArgumentError = exports.StatsigUninitializedError = void 0);

// ..snip..

exports.StatsigInvalidArgumentError = V;

Multiple exports of "STORAGE_PREFIX" found, only the last one will be kept
• Transforming pages/_app-unminified/pages/_app-unpacked/module-49787.js (94.5ms)

This seems incorrect? (Edit: This warning wasn't incorrect, I was looking at the wrong file, see this comment for details: https://github.com/pionxzh/wakaru/issues/53#issuecomment-1822275814 )

export const OVERRIDES_STORE_KEY =
  "STATSIG_LOCAL_STORAGE_INTERNAL_STORE_OVERRIDES_V3";
export const STICKY_DEVICE_EXPERIMENTS_KEY =
  "STATSIG_LOCAL_STORAGE_STICKY_DEVICE_EXPERIMENTS";
export const INTERNAL_STORE_KEY = "STATSIG_LOCAL_STORAGE_INTERNAL_STORE_V4";
export const STATSIG_STABLE_ID_KEY = "STATSIG_LOCAL_STORAGE_STABLE_ID";
export const STATSIG_LOCAL_STORAGE_LOGGING_REQUEST_KEY =
  "STATSIG_LOCAL_STORAGE_LOGGING_REQUEST";

export const LOCAL_STORAGE_KEYS = {
  STATSIG_LOCAL_STORAGE_STABLE_ID: true,
  STATSIG_LOCAL_STORAGE_INTERNAL_STORE_V4: true,
  STATSIG_LOCAL_STORAGE_STICKY_DEVICE_EXPERIMENTS: true,
  STATSIG_LOCAL_STORAGE_INTERNAL_STORE_OVERRIDES_V3: true,
  STATSIG_LOCAL_STORAGE_LOGGING_REQUEST: true,
};

export const STORAGE_PREFIX = "STATSIG_LOCAL_STORAGE";

I didn't look too closely at these remaining ones, some of them may fit into similar patterns as above, but they also might be unique cases:

Multiple exports of "checkCookies" found, only the last one will be kept
• Transforming pages/_app-unminified/pages/_app-unpacked/module-44544.js (892.6ms)

Multiple exports of "default" found, only the last one will be kept
• Transforming pages/_app-unminified/pages/_app-unpacked/module-50201.js (2,190.6ms)

Multiple exports of "ExceptionEndpoint" found, only the last one will be kept
• Transforming pages/_app-unminified/pages/_app-unpacked/module-5421.js (1,131.6ms)

Multiple exports of "default" found, only the last one will be kept
• Transforming pages/_app-unminified/pages/_app-unpacked/module-6631.js (202.8ms)

Multiple exports of "default" found, only the last one will be kept
• Transforming pages/_app-unminified/pages/_app-unpacked/module-69270.js (89.2ms)

Multiple exports of "default" found, only the last one will be kept
• Transforming pages/_app-unminified/pages/_app-unpacked/module-71083.js (576.5ms)

Multiple exports of "default" found, only the last one will be kept
• Transforming pages/_app-unminified/pages/_app-unpacked/module-74861.js (51.2ms)

Multiple exports of "default" found, only the last one will be kept
• Transforming pages/_app-unminified/pages/_app-unpacked/module-76226.js (123.2ms)

Multiple exports of "default" found, only the last one will be kept
• Transforming pages/_app-unminified/pages/_app-unpacked/module-77415.js (107.2ms)

Multiple exports of "UnsupportedStrategy" found, only the last one will be kept
• Transforming pages/_app-unminified/pages/_app-unpacked/module-80456.js (2,691.6ms)
pionxzh commented 10 months ago

This is kind of expected because some bundlers will assign void 0 to the exports.[target] first, transforming them can be unsafe. But it would be good if we could detect this pattern and silence the warnings as they can be considered safe.

pionxzh commented 10 months ago

Why the example of STORAGE_PREFIX is incorrect to you?

0xdevalias commented 10 months ago

But it would be good if we could detect this pattern and silence the warnings as they can be considered safe.

@pionxzh Yeah, that was sort of my thoughts in collecting/grouping all of the warnings; as it seems like a lot of them follow a general pattern that would probably be safe to silence the warning for.


Why the example of STORAGE_PREFIX is incorrect to you?

@pionxzh I originally thought that I was looking at/provided the unpacked (but not unminimised) code above, because it didn't seem to have any duplicate identifiers; but seems that was actually the unminimised code (just checked again).

Looking at the actual unpacked code, it seems to be another case of the void 0 duplicate pattern:

module-49787.js Unpacked: ```js "use strict"; Object.defineProperty(exports, "__esModule", { value: !0 }), (exports.STORAGE_PREFIX = exports.LOCAL_STORAGE_KEYS = exports.STATSIG_LOCAL_STORAGE_LOGGING_REQUEST_KEY = exports.STATSIG_STABLE_ID_KEY = exports.INTERNAL_STORE_KEY = exports.STICKY_DEVICE_EXPERIMENTS_KEY = exports.OVERRIDES_STORE_KEY = void 0), (exports.OVERRIDES_STORE_KEY = "STATSIG_LOCAL_STORAGE_INTERNAL_STORE_OVERRIDES_V3"), (exports.STICKY_DEVICE_EXPERIMENTS_KEY = "STATSIG_LOCAL_STORAGE_STICKY_DEVICE_EXPERIMENTS"), (exports.INTERNAL_STORE_KEY = "STATSIG_LOCAL_STORAGE_INTERNAL_STORE_V4"), (exports.STATSIG_STABLE_ID_KEY = "STATSIG_LOCAL_STORAGE_STABLE_ID"), (exports.STATSIG_LOCAL_STORAGE_LOGGING_REQUEST_KEY = "STATSIG_LOCAL_STORAGE_LOGGING_REQUEST"), (exports.LOCAL_STORAGE_KEYS = { STATSIG_LOCAL_STORAGE_STABLE_ID: !0, STATSIG_LOCAL_STORAGE_INTERNAL_STORE_V4: !0, STATSIG_LOCAL_STORAGE_STICKY_DEVICE_EXPERIMENTS: !0, STATSIG_LOCAL_STORAGE_INTERNAL_STORE_OVERRIDES_V3: !0, STATSIG_LOCAL_STORAGE_LOGGING_REQUEST: !0, }), (exports.STORAGE_PREFIX = "STATSIG_LOCAL_STORAGE"); ``` Unminimised: ```js export const OVERRIDES_STORE_KEY = "STATSIG_LOCAL_STORAGE_INTERNAL_STORE_OVERRIDES_V3"; export const STICKY_DEVICE_EXPERIMENTS_KEY = "STATSIG_LOCAL_STORAGE_STICKY_DEVICE_EXPERIMENTS"; export const INTERNAL_STORE_KEY = "STATSIG_LOCAL_STORAGE_INTERNAL_STORE_V4"; export const STATSIG_STABLE_ID_KEY = "STATSIG_LOCAL_STORAGE_STABLE_ID"; export const STATSIG_LOCAL_STORAGE_LOGGING_REQUEST_KEY = "STATSIG_LOCAL_STORAGE_LOGGING_REQUEST"; export const LOCAL_STORAGE_KEYS = { STATSIG_LOCAL_STORAGE_STABLE_ID: true, STATSIG_LOCAL_STORAGE_INTERNAL_STORE_V4: true, STATSIG_LOCAL_STORAGE_STICKY_DEVICE_EXPERIMENTS: true, STATSIG_LOCAL_STORAGE_INTERNAL_STORE_OVERRIDES_V3: true, STATSIG_LOCAL_STORAGE_LOGGING_REQUEST: true, }; export const STORAGE_PREFIX = "STATSIG_LOCAL_STORAGE"; ```
pionxzh commented 10 months ago

Reopen, there are still some false alerts that can be improved.

pionxzh commented 10 months ago

No more alerts for this multiple exports generated on the sample with unminify v0.6