6
6
*/
7
7
8
8
/* @flow */
9
- import React from 'react' ;
10
- import type { Element } from 'react' ;
11
- import ReactDOM from 'react-dom' ;
12
- import CompileErrorContainer from './containers/CompileErrorContainer' ;
13
- import RuntimeErrorContainer from './containers/RuntimeErrorContainer' ;
14
9
import { listenToRuntimeErrors } from './listenToRuntimeErrors' ;
15
- import { iframeStyle , overlayStyle } from './styles' ;
10
+ import { iframeStyle } from './styles' ;
16
11
import { applyStyles } from './utils/dom/css' ;
17
12
13
+ // Importing iframe-bundle generated in the pre build step as
14
+ // a text using webpack raw-loader. See webpack.config.js file.
15
+ // $FlowFixMe
16
+ import iframeScript from 'iframeScript' ;
17
+
18
18
import type { ErrorRecord } from './listenToRuntimeErrors' ;
19
19
20
20
type RuntimeReportingOptions = { |
@@ -25,8 +25,8 @@ type RuntimeReportingOptions = {|
25
25
26
26
let iframe : null | HTMLIFrameElement = null ;
27
27
let isLoadingIframe : boolean = false ;
28
+ var isIframeReady : boolean = false ;
28
29
29
- let renderedElement : null | Element < any > = null ;
30
30
let currentBuildError : null | string = null ;
31
31
let currentRuntimeErrorRecords : Array < ErrorRecord > = [ ] ;
32
32
let currentRuntimeErrorOptions : null | RuntimeReportingOptions = null ;
@@ -88,15 +88,14 @@ export function stopReportingRuntimeErrors() {
88
88
}
89
89
90
90
function update ( ) {
91
- renderedElement = render ( ) ;
92
91
// Loading iframe can be either sync or async depending on the browser.
93
92
if ( isLoadingIframe ) {
94
93
// Iframe is loading.
95
94
// First render will happen soon--don't need to do anything.
96
95
return ;
97
96
}
98
- if ( iframe ) {
99
- // Iframe has already loaded .
97
+ if ( isIframeReady ) {
98
+ // Iframe is ready .
100
99
// Just update it.
101
100
updateIframeContent ( ) ;
102
101
return ;
@@ -108,58 +107,46 @@ function update() {
108
107
loadingIframe . onload = function ( ) {
109
108
const iframeDocument = loadingIframe . contentDocument ;
110
109
if ( iframeDocument != null && iframeDocument . body != null ) {
111
- iframeDocument . body . style . margin = '0' ;
112
- // Keep popup within body boundaries for iOS Safari
113
- iframeDocument . body . style [ 'max-width' ] = '100vw' ;
114
- const iframeRoot = iframeDocument . createElement ( 'div' ) ;
115
- applyStyles ( iframeRoot , overlayStyle ) ;
116
- iframeDocument . body . appendChild ( iframeRoot ) ;
117
-
118
- // Ready! Now we can update the UI.
119
110
iframe = loadingIframe ;
120
- isLoadingIframe = false ;
121
- updateIframeContent ( ) ;
111
+ const script = loadingIframe . contentWindow . document . createElement (
112
+ 'script'
113
+ ) ;
114
+ script . type = 'text/javascript' ;
115
+ script . innerHTML = iframeScript ;
116
+ iframeDocument . body . appendChild ( script ) ;
122
117
}
123
118
} ;
124
119
const appDocument = window . document ;
125
120
appDocument . body . appendChild ( loadingIframe ) ;
126
121
}
127
122
128
- function render ( ) {
129
- if ( currentBuildError ) {
130
- return < CompileErrorContainer error = { currentBuildError } /> ;
131
- }
132
- if ( currentRuntimeErrorRecords . length > 0 ) {
133
- if ( ! currentRuntimeErrorOptions ) {
134
- throw new Error ( 'Expected options to be injected.' ) ;
135
- }
136
- return (
137
- < RuntimeErrorContainer
138
- errorRecords = { currentRuntimeErrorRecords }
139
- close = { dismissRuntimeErrors }
140
- launchEditorEndpoint = { currentRuntimeErrorOptions . launchEditorEndpoint }
141
- />
142
- ) ;
123
+ function updateIframeContent ( ) {
124
+ if ( ! currentRuntimeErrorOptions ) {
125
+ throw new Error ( 'Expected options to be injected.' ) ;
143
126
}
144
- return null ;
145
- }
146
127
147
- function updateIframeContent ( ) {
148
- if ( iframe === null ) {
128
+ if ( ! iframe ) {
149
129
throw new Error ( 'Iframe has not been created yet.' ) ;
150
130
}
151
- const iframeBody = iframe . contentDocument . body ;
152
- if ( ! iframeBody ) {
153
- throw new Error ( 'Expected iframe to have a body.' ) ;
154
- }
155
- const iframeRoot = iframeBody . firstChild ;
156
- if ( renderedElement === null ) {
157
- // Destroy iframe and force it to be recreated on next error
131
+
132
+ const isRendered = iframe . contentWindow . updateContent ( {
133
+ currentBuildError,
134
+ currentRuntimeErrorRecords,
135
+ dismissRuntimeErrors,
136
+ launchEditorEndpoint : currentRuntimeErrorOptions . launchEditorEndpoint ,
137
+ } ) ;
138
+
139
+ if ( ! isRendered ) {
158
140
window . document . body . removeChild ( iframe ) ;
159
- ReactDOM . unmountComponentAtNode ( iframeRoot ) ;
160
141
iframe = null ;
161
- return ;
142
+ isIframeReady = false ;
162
143
}
163
- // Update the overlay
164
- ReactDOM . render ( renderedElement , iframeRoot ) ;
165
144
}
145
+
146
+ window . __REACT_ERROR_OVERLAY_GLOBAL_HOOK__ =
147
+ window . __REACT_ERROR_OVERLAY_GLOBAL_HOOK__ || { } ;
148
+ window . __REACT_ERROR_OVERLAY_GLOBAL_HOOK__ . iframeReady = function iframeReady ( ) {
149
+ isIframeReady = true ;
150
+ isLoadingIframe = false ;
151
+ updateIframeContent ( ) ;
152
+ } ;
0 commit comments