2020-11-06 03:33:14 +01:00
|
|
|
import {
|
|
|
|
NodePath,
|
|
|
|
PluginObj,
|
|
|
|
types as BabelTypes,
|
|
|
|
} from 'next/dist/compiled/babel/core'
|
2020-01-27 23:50:59 +01:00
|
|
|
import { SERVER_PROPS_SSG_CONFLICT } from '../../../lib/constants'
|
2021-06-30 11:43:31 +02:00
|
|
|
import { SERVER_PROPS_ID, STATIC_PROPS_ID } from '../../../shared/lib/constants'
|
2019-12-05 22:43:11 +01:00
|
|
|
|
2020-02-27 18:57:39 +01:00
|
|
|
export const EXPORT_NAME_GET_STATIC_PROPS = 'getStaticProps'
|
|
|
|
export const EXPORT_NAME_GET_STATIC_PATHS = 'getStaticPaths'
|
|
|
|
export const EXPORT_NAME_GET_SERVER_PROPS = 'getServerSideProps'
|
2019-12-05 22:43:11 +01:00
|
|
|
|
2019-12-07 04:03:55 +01:00
|
|
|
const ssgExports = new Set([
|
|
|
|
EXPORT_NAME_GET_STATIC_PROPS,
|
|
|
|
EXPORT_NAME_GET_STATIC_PATHS,
|
2020-01-27 23:50:59 +01:00
|
|
|
EXPORT_NAME_GET_SERVER_PROPS,
|
2020-02-27 18:57:39 +01:00
|
|
|
|
|
|
|
// legacy methods added so build doesn't fail from importing
|
|
|
|
// server-side only methods
|
|
|
|
`unstable_getStaticProps`,
|
|
|
|
`unstable_getStaticPaths`,
|
|
|
|
`unstable_getServerProps`,
|
|
|
|
`unstable_getServerSideProps`,
|
2019-12-07 04:03:55 +01:00
|
|
|
])
|
|
|
|
|
2019-12-07 06:52:24 +01:00
|
|
|
type PluginState = {
|
|
|
|
refs: Set<NodePath<BabelTypes.Identifier>>
|
|
|
|
isPrerender: boolean
|
2020-01-27 23:50:59 +01:00
|
|
|
isServerProps: boolean
|
2019-12-07 06:52:24 +01:00
|
|
|
done: boolean
|
|
|
|
}
|
2019-12-07 04:03:55 +01:00
|
|
|
|
|
|
|
function decorateSsgExport(
|
|
|
|
t: typeof BabelTypes,
|
|
|
|
path: NodePath<BabelTypes.Program>,
|
|
|
|
state: PluginState
|
2020-05-21 14:57:04 +02:00
|
|
|
): void {
|
2020-03-06 05:15:10 +01:00
|
|
|
const gsspName = state.isPrerender ? STATIC_PROPS_ID : SERVER_PROPS_ID
|
|
|
|
const gsspId = t.identifier(gsspName)
|
2019-12-07 04:03:55 +01:00
|
|
|
|
2020-03-06 05:15:10 +01:00
|
|
|
const addGsspExport = (
|
2020-12-29 21:10:08 +01:00
|
|
|
exportPath:
|
|
|
|
| NodePath<BabelTypes.ExportDefaultDeclaration>
|
|
|
|
| NodePath<BabelTypes.ExportNamedDeclaration>
|
2020-05-21 14:57:04 +02:00
|
|
|
): void => {
|
2020-03-06 05:15:10 +01:00
|
|
|
if (state.done) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
state.done = true
|
2019-12-07 04:03:55 +01:00
|
|
|
|
2020-06-01 23:00:22 +02:00
|
|
|
const [pageCompPath] = exportPath.replaceWithMultiple([
|
2020-03-06 05:15:10 +01:00
|
|
|
t.exportNamedDeclaration(
|
2020-02-19 17:29:30 +01:00
|
|
|
t.variableDeclaration(
|
|
|
|
// We use 'var' instead of 'let' or 'const' for ES5 support. Since
|
|
|
|
// this runs in `Program#exit`, no ES2015 transforms (preset env)
|
|
|
|
// will be ran against this code.
|
|
|
|
'var',
|
2020-03-06 05:15:10 +01:00
|
|
|
[t.variableDeclarator(gsspId, t.booleanLiteral(true))]
|
2019-12-07 04:03:55 +01:00
|
|
|
),
|
2020-03-06 05:15:10 +01:00
|
|
|
[t.exportSpecifier(gsspId, gsspId)]
|
|
|
|
),
|
2020-06-01 23:00:22 +02:00
|
|
|
exportPath.node,
|
2020-03-06 05:15:10 +01:00
|
|
|
])
|
2020-12-29 21:10:08 +01:00
|
|
|
exportPath.scope.registerDeclaration(
|
|
|
|
pageCompPath as NodePath<BabelTypes.Node>
|
|
|
|
)
|
2020-03-06 05:15:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
path.traverse({
|
2020-06-01 23:00:22 +02:00
|
|
|
ExportDefaultDeclaration(exportDefaultPath) {
|
|
|
|
addGsspExport(exportDefaultPath)
|
2019-12-07 04:03:55 +01:00
|
|
|
},
|
2020-06-01 23:00:22 +02:00
|
|
|
ExportNamedDeclaration(exportNamedPath) {
|
|
|
|
addGsspExport(exportNamedPath)
|
2020-02-13 06:25:44 +01:00
|
|
|
},
|
2019-12-07 04:03:55 +01:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-01-27 23:50:59 +01:00
|
|
|
const isDataIdentifier = (name: string, state: PluginState): boolean => {
|
|
|
|
if (ssgExports.has(name)) {
|
|
|
|
if (name === EXPORT_NAME_GET_SERVER_PROPS) {
|
|
|
|
if (state.isPrerender) {
|
|
|
|
throw new Error(SERVER_PROPS_SSG_CONFLICT)
|
|
|
|
}
|
|
|
|
state.isServerProps = true
|
|
|
|
} else {
|
|
|
|
if (state.isServerProps) {
|
|
|
|
throw new Error(SERVER_PROPS_SSG_CONFLICT)
|
|
|
|
}
|
|
|
|
state.isPrerender = true
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2019-12-05 23:22:41 +01:00
|
|
|
export default function nextTransformSsg({
|
2019-12-05 22:43:11 +01:00
|
|
|
types: t,
|
|
|
|
}: {
|
|
|
|
types: typeof BabelTypes
|
2019-12-07 04:03:55 +01:00
|
|
|
}): PluginObj<PluginState> {
|
|
|
|
function getIdentifier(
|
2020-12-29 21:10:08 +01:00
|
|
|
path:
|
|
|
|
| NodePath<BabelTypes.FunctionDeclaration>
|
|
|
|
| NodePath<BabelTypes.FunctionExpression>
|
|
|
|
| NodePath<BabelTypes.ArrowFunctionExpression>
|
2019-12-07 04:03:55 +01:00
|
|
|
): NodePath<BabelTypes.Identifier> | null {
|
|
|
|
const parentPath = path.parentPath
|
|
|
|
if (parentPath.type === 'VariableDeclarator') {
|
|
|
|
const pp = parentPath as NodePath<BabelTypes.VariableDeclarator>
|
|
|
|
const name = pp.get('id')
|
|
|
|
return name.node.type === 'Identifier'
|
|
|
|
? (name as NodePath<BabelTypes.Identifier>)
|
|
|
|
: null
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parentPath.type === 'AssignmentExpression') {
|
|
|
|
const pp = parentPath as NodePath<BabelTypes.AssignmentExpression>
|
|
|
|
const name = pp.get('left')
|
|
|
|
return name.node.type === 'Identifier'
|
|
|
|
? (name as NodePath<BabelTypes.Identifier>)
|
|
|
|
: null
|
|
|
|
}
|
|
|
|
|
|
|
|
if (path.node.type === 'ArrowFunctionExpression') {
|
|
|
|
return null
|
|
|
|
}
|
|
|
|
|
|
|
|
return path.node.id && path.node.id.type === 'Identifier'
|
|
|
|
? (path.get('id') as NodePath<BabelTypes.Identifier>)
|
|
|
|
: null
|
|
|
|
}
|
|
|
|
|
|
|
|
function isIdentifierReferenced(
|
|
|
|
ident: NodePath<BabelTypes.Identifier>
|
|
|
|
): boolean {
|
|
|
|
const b = ident.scope.getBinding(ident.node.name)
|
2020-05-15 23:14:46 +02:00
|
|
|
if (b?.referenced) {
|
|
|
|
// Functions can reference themselves, so we need to check if there's a
|
|
|
|
// binding outside the function scope or not.
|
|
|
|
if (b.path.type === 'FunctionDeclaration') {
|
|
|
|
return !b.constantViolations
|
|
|
|
.concat(b.referencePaths)
|
|
|
|
// Check that every reference is contained within the function:
|
2020-05-18 21:24:37 +02:00
|
|
|
.every((ref) => ref.findParent((p) => p === b.path))
|
2020-05-15 23:14:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
2019-12-07 04:03:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
function markFunction(
|
2020-12-29 21:10:08 +01:00
|
|
|
path:
|
|
|
|
| NodePath<BabelTypes.FunctionDeclaration>
|
|
|
|
| NodePath<BabelTypes.FunctionExpression>
|
|
|
|
| NodePath<BabelTypes.ArrowFunctionExpression>,
|
2019-12-07 04:03:55 +01:00
|
|
|
state: PluginState
|
2020-05-21 14:57:04 +02:00
|
|
|
): void {
|
2019-12-07 04:03:55 +01:00
|
|
|
const ident = getIdentifier(path)
|
2020-01-08 17:30:53 +01:00
|
|
|
if (ident?.node && isIdentifierReferenced(ident)) {
|
2019-12-07 06:52:24 +01:00
|
|
|
state.refs.add(ident)
|
2019-12-07 04:03:55 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-07 04:57:14 +01:00
|
|
|
function markImport(
|
2020-12-29 21:10:08 +01:00
|
|
|
path:
|
|
|
|
| NodePath<BabelTypes.ImportSpecifier>
|
|
|
|
| NodePath<BabelTypes.ImportDefaultSpecifier>
|
|
|
|
| NodePath<BabelTypes.ImportNamespaceSpecifier>,
|
2019-12-07 04:57:14 +01:00
|
|
|
state: PluginState
|
2020-05-21 14:57:04 +02:00
|
|
|
): void {
|
2020-12-29 21:10:08 +01:00
|
|
|
const local = path.get('local') as NodePath<BabelTypes.Identifier>
|
2019-12-07 04:57:14 +01:00
|
|
|
if (isIdentifierReferenced(local)) {
|
2019-12-07 06:52:24 +01:00
|
|
|
state.refs.add(local)
|
2019-12-07 04:57:14 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-05 22:43:11 +01:00
|
|
|
return {
|
|
|
|
visitor: {
|
|
|
|
Program: {
|
2020-05-15 22:51:29 +02:00
|
|
|
enter(path, state) {
|
2019-12-07 06:52:24 +01:00
|
|
|
state.refs = new Set<NodePath<BabelTypes.Identifier>>()
|
2019-12-07 04:03:55 +01:00
|
|
|
state.isPrerender = false
|
2020-01-27 23:50:59 +01:00
|
|
|
state.isServerProps = false
|
2019-12-07 04:03:55 +01:00
|
|
|
state.done = false
|
2020-05-15 22:51:29 +02:00
|
|
|
|
|
|
|
path.traverse(
|
|
|
|
{
|
2020-06-01 23:00:22 +02:00
|
|
|
VariableDeclarator(variablePath, variableState) {
|
|
|
|
if (variablePath.node.id.type === 'Identifier') {
|
2021-08-17 09:18:08 +02:00
|
|
|
const local = variablePath.get(
|
|
|
|
'id'
|
|
|
|
) as NodePath<BabelTypes.Identifier>
|
2020-05-20 17:57:18 +02:00
|
|
|
if (isIdentifierReferenced(local)) {
|
2020-06-01 23:00:22 +02:00
|
|
|
variableState.refs.add(local)
|
2020-05-20 17:57:18 +02:00
|
|
|
}
|
2020-06-01 23:00:22 +02:00
|
|
|
} else if (variablePath.node.id.type === 'ObjectPattern') {
|
2021-08-17 09:18:08 +02:00
|
|
|
const pattern = variablePath.get(
|
|
|
|
'id'
|
|
|
|
) as NodePath<BabelTypes.ObjectPattern>
|
2020-05-20 17:57:18 +02:00
|
|
|
|
|
|
|
const properties = pattern.get('properties')
|
|
|
|
properties.forEach((p) => {
|
|
|
|
const local = p.get(
|
|
|
|
p.node.type === 'ObjectProperty'
|
|
|
|
? 'value'
|
|
|
|
: p.node.type === 'RestElement'
|
|
|
|
? 'argument'
|
|
|
|
: (function () {
|
|
|
|
throw new Error('invariant')
|
|
|
|
})()
|
|
|
|
) as NodePath<BabelTypes.Identifier>
|
2020-05-20 19:13:31 +02:00
|
|
|
if (isIdentifierReferenced(local)) {
|
2020-06-01 23:00:22 +02:00
|
|
|
variableState.refs.add(local)
|
2020-05-20 19:13:31 +02:00
|
|
|
}
|
|
|
|
})
|
2020-06-01 23:00:22 +02:00
|
|
|
} else if (variablePath.node.id.type === 'ArrayPattern') {
|
2021-08-17 09:18:08 +02:00
|
|
|
const pattern = variablePath.get(
|
|
|
|
'id'
|
|
|
|
) as NodePath<BabelTypes.ArrayPattern>
|
2020-05-20 19:13:31 +02:00
|
|
|
|
|
|
|
const elements = pattern.get('elements')
|
|
|
|
elements.forEach((e) => {
|
|
|
|
let local: NodePath<BabelTypes.Identifier>
|
|
|
|
if (e.node?.type === 'Identifier') {
|
|
|
|
local = e as NodePath<BabelTypes.Identifier>
|
|
|
|
} else if (e.node?.type === 'RestElement') {
|
2021-08-17 09:18:08 +02:00
|
|
|
local = e.get(
|
|
|
|
'argument'
|
|
|
|
) as NodePath<BabelTypes.Identifier>
|
2020-05-20 19:13:31 +02:00
|
|
|
} else {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-05-20 17:57:18 +02:00
|
|
|
if (isIdentifierReferenced(local)) {
|
2020-06-01 23:00:22 +02:00
|
|
|
variableState.refs.add(local)
|
2020-05-20 17:57:18 +02:00
|
|
|
}
|
|
|
|
})
|
2020-05-15 22:51:29 +02:00
|
|
|
}
|
|
|
|
},
|
|
|
|
FunctionDeclaration: markFunction,
|
|
|
|
FunctionExpression: markFunction,
|
|
|
|
ArrowFunctionExpression: markFunction,
|
|
|
|
ImportSpecifier: markImport,
|
|
|
|
ImportDefaultSpecifier: markImport,
|
|
|
|
ImportNamespaceSpecifier: markImport,
|
2020-06-01 23:00:22 +02:00
|
|
|
ExportNamedDeclaration(exportNamedPath, exportNamedState) {
|
|
|
|
const specifiers = exportNamedPath.get('specifiers')
|
2020-05-15 22:51:29 +02:00
|
|
|
if (specifiers.length) {
|
2020-05-18 21:24:37 +02:00
|
|
|
specifiers.forEach((s) => {
|
2020-06-01 23:00:22 +02:00
|
|
|
if (
|
2020-11-06 03:33:14 +01:00
|
|
|
isDataIdentifier(
|
|
|
|
t.isIdentifier(s.node.exported)
|
|
|
|
? s.node.exported.name
|
|
|
|
: s.node.exported.value,
|
|
|
|
exportNamedState
|
|
|
|
)
|
2020-06-01 23:00:22 +02:00
|
|
|
) {
|
2020-05-15 22:51:29 +02:00
|
|
|
s.remove()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2020-06-01 23:00:22 +02:00
|
|
|
if (exportNamedPath.node.specifiers.length < 1) {
|
|
|
|
exportNamedPath.remove()
|
2020-05-15 22:51:29 +02:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-06-01 23:00:22 +02:00
|
|
|
const decl = exportNamedPath.get('declaration') as NodePath<
|
2020-05-15 22:51:29 +02:00
|
|
|
| BabelTypes.FunctionDeclaration
|
|
|
|
| BabelTypes.VariableDeclaration
|
|
|
|
>
|
|
|
|
if (decl == null || decl.node == null) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (decl.node.type) {
|
|
|
|
case 'FunctionDeclaration': {
|
|
|
|
const name = decl.node.id!.name
|
2020-06-01 23:00:22 +02:00
|
|
|
if (isDataIdentifier(name, exportNamedState)) {
|
|
|
|
exportNamedPath.remove()
|
2020-05-15 22:51:29 +02:00
|
|
|
}
|
|
|
|
break
|
|
|
|
}
|
|
|
|
case 'VariableDeclaration': {
|
2021-08-17 09:18:08 +02:00
|
|
|
const inner = decl.get(
|
|
|
|
'declarations'
|
|
|
|
) as NodePath<BabelTypes.VariableDeclarator>[]
|
2020-05-18 21:24:37 +02:00
|
|
|
inner.forEach((d) => {
|
2020-05-15 22:51:29 +02:00
|
|
|
if (d.node.id.type !== 'Identifier') {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
const name = d.node.id.name
|
2020-06-01 23:00:22 +02:00
|
|
|
if (isDataIdentifier(name, exportNamedState)) {
|
2020-05-15 22:51:29 +02:00
|
|
|
d.remove()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
break
|
|
|
|
}
|
|
|
|
default: {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
state
|
|
|
|
)
|
|
|
|
|
2020-01-27 23:50:59 +01:00
|
|
|
if (!state.isPrerender && !state.isServerProps) {
|
2019-12-07 07:03:29 +01:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-12-07 04:03:55 +01:00
|
|
|
const refs = state.refs
|
|
|
|
let count: number
|
|
|
|
|
|
|
|
function sweepFunction(
|
2020-12-29 21:10:08 +01:00
|
|
|
sweepPath:
|
|
|
|
| NodePath<BabelTypes.FunctionDeclaration>
|
|
|
|
| NodePath<BabelTypes.FunctionExpression>
|
|
|
|
| NodePath<BabelTypes.ArrowFunctionExpression>
|
2020-05-21 14:57:04 +02:00
|
|
|
): void {
|
2020-06-01 23:00:22 +02:00
|
|
|
const ident = getIdentifier(sweepPath)
|
2019-12-07 04:03:55 +01:00
|
|
|
if (
|
2020-01-08 17:30:53 +01:00
|
|
|
ident?.node &&
|
2019-12-07 06:52:24 +01:00
|
|
|
refs.has(ident) &&
|
2019-12-07 04:03:55 +01:00
|
|
|
!isIdentifierReferenced(ident)
|
|
|
|
) {
|
|
|
|
++count
|
2019-12-05 23:22:41 +01:00
|
|
|
|
|
|
|
if (
|
2020-06-01 23:00:22 +02:00
|
|
|
t.isAssignmentExpression(sweepPath.parentPath) ||
|
|
|
|
t.isVariableDeclarator(sweepPath.parentPath)
|
2019-12-05 23:22:41 +01:00
|
|
|
) {
|
2020-06-01 23:00:22 +02:00
|
|
|
sweepPath.parentPath.remove()
|
2019-12-07 04:03:55 +01:00
|
|
|
} else {
|
2020-06-01 23:00:22 +02:00
|
|
|
sweepPath.remove()
|
2019-12-05 23:22:41 +01:00
|
|
|
}
|
2019-12-07 04:03:55 +01:00
|
|
|
}
|
|
|
|
}
|
2019-12-06 00:05:50 +01:00
|
|
|
|
2019-12-07 04:57:14 +01:00
|
|
|
function sweepImport(
|
2020-12-29 21:10:08 +01:00
|
|
|
sweepPath:
|
|
|
|
| NodePath<BabelTypes.ImportSpecifier>
|
|
|
|
| NodePath<BabelTypes.ImportDefaultSpecifier>
|
|
|
|
| NodePath<BabelTypes.ImportNamespaceSpecifier>
|
2020-05-21 14:57:04 +02:00
|
|
|
): void {
|
2021-08-17 09:18:08 +02:00
|
|
|
const local = sweepPath.get(
|
|
|
|
'local'
|
|
|
|
) as NodePath<BabelTypes.Identifier>
|
2019-12-07 06:52:24 +01:00
|
|
|
if (refs.has(local) && !isIdentifierReferenced(local)) {
|
2019-12-07 04:57:14 +01:00
|
|
|
++count
|
2020-06-01 23:00:22 +02:00
|
|
|
sweepPath.remove()
|
2019-12-07 04:57:14 +01:00
|
|
|
if (
|
2020-06-01 23:00:22 +02:00
|
|
|
(sweepPath.parent as BabelTypes.ImportDeclaration).specifiers
|
2019-12-07 04:57:14 +01:00
|
|
|
.length === 0
|
|
|
|
) {
|
2020-06-01 23:00:22 +02:00
|
|
|
sweepPath.parentPath.remove()
|
2019-12-07 04:57:14 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-07 04:03:55 +01:00
|
|
|
do {
|
|
|
|
;(path.scope as any).crawl()
|
|
|
|
count = 0
|
2019-12-06 00:05:50 +01:00
|
|
|
|
2019-12-07 04:03:55 +01:00
|
|
|
path.traverse({
|
|
|
|
// eslint-disable-next-line no-loop-func
|
2020-06-01 23:00:22 +02:00
|
|
|
VariableDeclarator(variablePath) {
|
|
|
|
if (variablePath.node.id.type === 'Identifier') {
|
2021-08-17 09:18:08 +02:00
|
|
|
const local = variablePath.get(
|
|
|
|
'id'
|
|
|
|
) as NodePath<BabelTypes.Identifier>
|
2020-05-20 17:57:18 +02:00
|
|
|
if (refs.has(local) && !isIdentifierReferenced(local)) {
|
|
|
|
++count
|
2020-06-01 23:00:22 +02:00
|
|
|
variablePath.remove()
|
2020-05-20 17:57:18 +02:00
|
|
|
}
|
2020-06-01 23:00:22 +02:00
|
|
|
} else if (variablePath.node.id.type === 'ObjectPattern') {
|
2021-08-17 09:18:08 +02:00
|
|
|
const pattern = variablePath.get(
|
|
|
|
'id'
|
|
|
|
) as NodePath<BabelTypes.ObjectPattern>
|
2020-05-20 17:57:18 +02:00
|
|
|
|
|
|
|
const beforeCount = count
|
|
|
|
const properties = pattern.get('properties')
|
|
|
|
properties.forEach((p) => {
|
|
|
|
const local = p.get(
|
|
|
|
p.node.type === 'ObjectProperty'
|
|
|
|
? 'value'
|
|
|
|
: p.node.type === 'RestElement'
|
|
|
|
? 'argument'
|
|
|
|
: (function () {
|
|
|
|
throw new Error('invariant')
|
|
|
|
})()
|
|
|
|
) as NodePath<BabelTypes.Identifier>
|
|
|
|
|
|
|
|
if (refs.has(local) && !isIdentifierReferenced(local)) {
|
|
|
|
++count
|
|
|
|
p.remove()
|
|
|
|
}
|
|
|
|
})
|
2019-12-05 23:43:18 +01:00
|
|
|
|
2020-05-20 17:57:18 +02:00
|
|
|
if (
|
|
|
|
beforeCount !== count &&
|
|
|
|
pattern.get('properties').length < 1
|
|
|
|
) {
|
2020-06-01 23:00:22 +02:00
|
|
|
variablePath.remove()
|
2020-05-20 17:57:18 +02:00
|
|
|
}
|
2020-06-01 23:00:22 +02:00
|
|
|
} else if (variablePath.node.id.type === 'ArrayPattern') {
|
2021-08-17 09:18:08 +02:00
|
|
|
const pattern = variablePath.get(
|
|
|
|
'id'
|
|
|
|
) as NodePath<BabelTypes.ArrayPattern>
|
2020-05-20 19:13:31 +02:00
|
|
|
|
|
|
|
const beforeCount = count
|
|
|
|
const elements = pattern.get('elements')
|
|
|
|
elements.forEach((e) => {
|
|
|
|
let local: NodePath<BabelTypes.Identifier>
|
|
|
|
if (e.node?.type === 'Identifier') {
|
|
|
|
local = e as NodePath<BabelTypes.Identifier>
|
|
|
|
} else if (e.node?.type === 'RestElement') {
|
2021-08-17 09:18:08 +02:00
|
|
|
local = e.get(
|
|
|
|
'argument'
|
|
|
|
) as NodePath<BabelTypes.Identifier>
|
2020-05-20 19:13:31 +02:00
|
|
|
} else {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if (refs.has(local) && !isIdentifierReferenced(local)) {
|
|
|
|
++count
|
|
|
|
e.remove()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
if (
|
|
|
|
beforeCount !== count &&
|
|
|
|
pattern.get('elements').length < 1
|
|
|
|
) {
|
2020-06-01 23:00:22 +02:00
|
|
|
variablePath.remove()
|
2020-05-20 19:13:31 +02:00
|
|
|
}
|
2019-12-05 23:43:18 +01:00
|
|
|
}
|
2019-12-07 04:03:55 +01:00
|
|
|
},
|
|
|
|
FunctionDeclaration: sweepFunction,
|
|
|
|
FunctionExpression: sweepFunction,
|
|
|
|
ArrowFunctionExpression: sweepFunction,
|
2019-12-07 04:57:14 +01:00
|
|
|
ImportSpecifier: sweepImport,
|
|
|
|
ImportDefaultSpecifier: sweepImport,
|
|
|
|
ImportNamespaceSpecifier: sweepImport,
|
2019-12-07 04:03:55 +01:00
|
|
|
})
|
|
|
|
} while (count)
|
2019-12-05 23:43:18 +01:00
|
|
|
|
2019-12-07 07:03:29 +01:00
|
|
|
decorateSsgExport(t, path, state)
|
2019-12-07 04:03:55 +01:00
|
|
|
},
|
|
|
|
},
|
2019-12-05 22:43:11 +01:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|