@@ -39,6 +39,16 @@ export interface SvgPortalNode<C extends Component<any> = Component<any>> extend
39
39
type AnyPortalNode < C extends Component < any > = Component < any > > = HtmlPortalNode < C > | SvgPortalNode < C > ;
40
40
41
41
42
+ const validateElementType = ( domElement : Element , elementType : ANY_ELEMENT_TYPE ) => {
43
+ if ( elementType === ELEMENT_TYPE_HTML ) {
44
+ return domElement instanceof HTMLElement ;
45
+ }
46
+ if ( elementType === ELEMENT_TYPE_SVG ) {
47
+ return domElement instanceof SVGElement ;
48
+ }
49
+ throw new Error ( `Unrecognized element type "${ elementType } " for validateElementType.` ) ;
50
+ } ;
51
+
42
52
// This is the internal implementation: the public entry points set elementType to an appropriate value
43
53
const createPortalNode = < C extends Component < any > > ( elementType : ANY_ELEMENT_TYPE ) : AnyPortalNode < C > => {
44
54
let initialProps = { } as ComponentProps < C > ;
@@ -52,7 +62,7 @@ const createPortalNode = <C extends Component<any>>(elementType: ANY_ELEMENT_TYP
52
62
} else if ( elementType === ELEMENT_TYPE_SVG ) {
53
63
element = document . createElementNS ( SVG_NAMESPACE , 'g' ) ;
54
64
} else {
55
- throw new Error ( `Invalid element type "${ elementType } " for createPortalNode: must be "html" or "svg".` )
65
+ throw new Error ( `Invalid element type "${ elementType } " for createPortalNode: must be "html" or "svg".` ) ;
56
66
}
57
67
58
68
const portalNode : AnyPortalNode < C > = {
@@ -74,9 +84,8 @@ const createPortalNode = <C extends Component<any>>(elementType: ANY_ELEMENT_TYP
74
84
// To support SVG and other non-html elements, the portalNode's elementType needs to match
75
85
// the elementType it's being rendered into
76
86
if ( newParent !== parent ) {
77
- if ( ( elementType === ELEMENT_TYPE_HTML && ! ( newParent instanceof HTMLElement ) ) ||
78
- ( elementType === ELEMENT_TYPE_SVG && ! ( newParent instanceof SVGElement ) ) ) {
79
- throw new Error ( `Invalid element type for portal: "${ elementType } " portalNodes must be used with ${ elementType } elements.` )
87
+ if ( ! validateElementType ( newParent , elementType ) ) {
88
+ throw new Error ( `Invalid element type for portal: "${ elementType } " portalNodes must be used with ${ elementType } elements, but OutPortal is within <${ newParent . tagName } >.` ) ;
80
89
}
81
90
}
82
91
@@ -141,11 +150,10 @@ class InPortal extends React.PureComponent<InPortalProps, { nodeProps: {} }> {
141
150
142
151
// To support SVG and other non-html elements, every element that gets rendered
143
152
// into the InPortal needs to match the portalNode's elementType.
144
- // Non-elements like text and comments are fine with any portal type .
153
+ // Non-elements like Text aren't checkable .
145
154
childNodes . forEach ( ( childNode ) => {
146
155
if ( childNode instanceof Element ) {
147
- if ( ( elementType === ELEMENT_TYPE_HTML && ! ( childNode instanceof HTMLElement ) ) ||
148
- ( elementType === ELEMENT_TYPE_SVG && ! ( childNode instanceof SVGElement ) ) ) {
156
+ if ( ! validateElementType ( childNode , elementType ) ) {
149
157
throw new Error ( `Invalid content for portal: "${ elementType } " portalNodes must be used with ${ elementType } elements, but InPortal received <${ childNode . tagName } >.` ) ;
150
158
}
151
159
}
0 commit comments