Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 1.8k
Expand file tree
/
Copy pathhoist-non-react-statics.ts
More file actions
Latest commit
154 lines (137 loc) · 4.58 KB
/
Copy pathhoist-non-react-statics.ts
File metadata and controls
154 lines (137 loc) · 4.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/**
* Inlined implementation of hoist-non-react-statics
* Original library: https://github.com/mridgway/hoist-non-react-statics
* License: BSD-3-Clause
* Copyright 2015, Yahoo! Inc.
*
* This is an inlined version to avoid ESM compatibility issues with the original package.
*/
importtype*asReactfrom'react';
/**
* React statics that should not be hoisted
*/
constREACT_STATICS={
childContextTypes: true,
contextType: true,
contextTypes: true,
defaultProps: true,
displayName: true,
getDefaultProps: true,
getDerivedStateFromError: true,
getDerivedStateFromProps: true,
mixins: true,
propTypes: true,
type: true,
}asconst;
/**
* Known JavaScript function statics that should not be hoisted
*/
constKNOWN_STATICS={
name: true,
length: true,
prototype: true,
caller: true,
callee: true,
arguments: true,
arity: true,
}asconst;
/**
* Statics specific to ForwardRef components
*/
constFORWARD_REF_STATICS={
$$typeof: true,
render: true,
defaultProps: true,
displayName: true,
propTypes: true,
}asconst;
/**
* Statics specific to Memo components
*/
constMEMO_STATICS={
$$typeof: true,
compare: true,
defaultProps: true,
displayName: true,
propTypes: true,
type: true,
}asconst;
/**
* Inlined react-is utilities
* We only need to detect ForwardRef and Memo types
*/
constForwardRefType=Symbol.for('react.forward_ref');
constMemoType=Symbol.for('react.memo');
/**
* Map of React component types to their specific statics
*/
constTYPE_STATICS: Record<symbol,Record<string,boolean>>={};
TYPE_STATICS[ForwardRefType]=FORWARD_REF_STATICS;
TYPE_STATICS[MemoType]=MEMO_STATICS;
/**
* Get the appropriate statics object for a given component
*/
functiongetStatics(component: React.ComponentType<unknown>): Record<string,boolean>{
constcomponentType=(componentas{$$typeof?: symbol}).$$typeof;
return(componentType&&TYPE_STATICS[componentType])||REACT_STATICS;
}
constdefineProperty=Object.defineProperty.bind(Object);
constgetOwnPropertyNames=Object.getOwnPropertyNames.bind(Object);
constgetOwnPropertySymbols=Object.getOwnPropertySymbols?.bind(Object);
constgetOwnPropertyDescriptor=Object.getOwnPropertyDescriptor.bind(Object);
constgetPrototypeOf=Object.getPrototypeOf.bind(Object);
constobjectPrototype=Object.prototype;
/**
* Copies non-react specific statics from a child component to a parent component.
* Similar to Object.assign, but copies all static properties from source to target,
* excluding React-specific statics and known JavaScript statics.
*
* @param targetComponent - The component to copy statics to
* @param sourceComponent - The component to copy statics from
* @param excludelist - An optional object of keys to exclude from hoisting
* @returns The target component with hoisted statics
*/
exportfunctionhoistNonReactStatics<
// eslint-disable-next-line @typescript-eslint/no-explicit-any
TextendsReact.ComponentType<any>,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
SextendsReact.ComponentType<any>,
CextendsRecord<string,boolean>=Record<string,never>,
>(targetComponent: T,sourceComponent: S,excludelist?: C): T{
if(typeofsourceComponent!=='string'){
// Don't hoist over string (html) components
if(objectPrototype){
constinheritedComponent=getPrototypeOf(sourceComponent);
if(inheritedComponent&&inheritedComponent!==objectPrototype){
hoistNonReactStatics(targetComponent,inheritedComponent,excludelist);
}
}
letkeys: (string|symbol)[]=getOwnPropertyNames(sourceComponent);
if(getOwnPropertySymbols){
keys=keys.concat(getOwnPropertySymbols(sourceComponent));
}
consttargetStatics=getStatics(targetComponent);
constsourceStatics=getStatics(sourceComponent);
for(constkeyofkeys){
// Use key directly - String(key) throws for Symbols if minified to '' + key (#18966)
if(
!KNOWN_STATICS[keyaskeyoftypeofKNOWN_STATICS]&&
!excludelist?.[keyaskeyofC]&&
!sourceStatics?.[keyasstring]&&
!targetStatics?.[keyasstring]&&
!getOwnPropertyDescriptor(targetComponent,key)// Don't overwrite existing properties
){
constdescriptor=getOwnPropertyDescriptor(sourceComponent,key);
if(descriptor){
try{
// Avoid failures from read-only properties
defineProperty(targetComponent,key,descriptor);
}catch{
// Silently ignore errors
}
}
}
}
}
returntargetComponent;
}