Open 0xdevalias opened 9 months ago
useState
(but actually it ends up being more about @swc/helpers
)Looking at module-10604.js
, we can see that it's a React component using useState
:
module-10604.js
(full source)Unpacked:
var r = require(39324),
a = require(22830),
// ..snip
l = require(70079),
// ..snip
exports.Z = l.forwardRef(function (e, t) {
var n = e.name,
// ..snip
m = e.value,
// ..snip
_ = (0, a._)((0, l.useState)(m), 2),
C = _[0],
M = _[1],
// ..snip
});
Unminified:
// ..snip
const { _: _$0 } = require(22830);
// ..snip
export const Z = l.forwardRef((e, t) => {
const {
// ..snip..
value,
// ..snip..
} = e;
const [C, M] = _$0(useState(value), 2);
// ..snip
});
While there is a smart-rename
for useState
already (Ref), it appears it may not be getting applied due to the _$0
function that's wrapping const [C, M] = _$0(useState(value), 2);
Looking through the rest of the webpack bundle code (Ref) for the 22830
module, we find it in main.js
; which after unpacking, becomes module-22830.js
:
⇒ npx @wakaru/unpacker main.js -o ./main-unpacked/
# ..snip..
⇒ npx @wakaru/unminify ./main-unpacked/* -o ./main-unminified
# ..snip..
module-22830.js
(full source)Looking at module-22830.js
, we find the following code:
// ..snip..
N(e, t) ||
(() => {
throw TypeError(
"Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."
);
})()
);
}
export default {
_: o,
_sliced_to_array: o,
};
Which after using GitHub code search:
We find a relevant looking reference in a test for next/swc
's hook_optimizer
:
Which we can see appears to be testing the output of swc
compiling some React useState
code:
// ..snip..
describe('next/swc', () => {
describe('hook_optimizer', () => {
it('should leave alone array destructuring of hooks', async () => {
const output = await swc(
trim`
import { useState } from 'react';
const [count, setCount] = useState(0);
`
)
// ..snip..
And compares it to the compiled output, which includes helper functions like:
function _array_like_to_array(arr, len) {
function _array_with_holes(arr) {
function _iterable_to_array_limit(arr, i) {
function _non_iterable_rest() {
function _sliced_to_array(arr, i) {
function _unsupported_iterable_to_array(o, minLen) {
Within that output code, we see:
// ..snip..
function _non_iterable_rest() {
throw new TypeError("Invalid attempt to destructure non-iterable instance.\\\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
// ..snip..
import { useState } from "react";
var _useState = _sliced_to_array(useState(0), 2),
count = _useState[0],
setCount = _useState[1];
Looking at the latter part of that, we can see how the _sliced_to_array(useState(0), 2)
matches the format of our original unpacked useState
code from module-10604.js
:
Unpacked:
_ = (0, a._)((0, l.useState)(m), 2),
C = _[0],
M = _[1],
Unminified:
const [C, M] = _$0(useState(value), 2);
Which means that, based on the above, the _$0
in my webpacked code is likely the swc
helper function _sliced_to_array
:
function _sliced_to_array(arr, i) {
return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
}
We can also generate this output ourselves using the swc
playground:
import { useState } from 'react';
const [count, setCount] = useState(0);
Searching the swc
GitHub repo for _sliced_to_array
, we see that it seems to be included in the @swc/helpers
package:
It seems that the issue here is less about smart-rename
's handleReactRename
not handling useState
properly; and more that wakaru
needs to add support for swc
's 'runtime helper' functions like _sliced_to_array
/ etc from @swc/helpers
; probably in a similar way to how babel
's are currently implemented:
This may in part be relevant to the following 'module detection' issue as well:
Edit: I spun the @swc/helpers
part of this out into a more focussed issue here:
Currently
smart-rename
's implementation has ahandleReactRename
function that appears to have renames for:const uContext = o.createContext(u);
const uRef = o.useRef(u);
const [e, SetE] = o.useState(0);
I figured I would use this as a bit of a meta-issue for capturing improvements that could be made to this
smart-rename
for React.Context
If not otherwise specified, the webpack code I am looking at to derive my examples is the following (Ref), after using the CLI to unpack it to
./496-unpacked
, and then unminify it to./496-unminified
:TODO
useState
(but actually it ends up being more about@swc/helpers
) (Ref)See Also
48