66 */
77
88/* @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' ;
149import { listenToRuntimeErrors } from './listenToRuntimeErrors' ;
15- import { iframeStyle , overlayStyle } from './styles' ;
10+ import { iframeStyle } from './styles' ;
1611import { applyStyles } from './utils/dom/css' ;
1712
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+
1818import type { ErrorRecord } from './listenToRuntimeErrors' ;
1919
2020type RuntimeReportingOptions = { |
@@ -25,8 +25,8 @@ type RuntimeReportingOptions = {|
2525
2626let iframe : null | HTMLIFrameElement = null ;
2727let isLoadingIframe : boolean = false ;
28+ var isIframeReady : boolean = false ;
2829
29- let renderedElement : null | Element < any > = null ;
3030let currentBuildError : null | string = null ;
3131let currentRuntimeErrorRecords : Array < ErrorRecord > = [ ] ;
3232let currentRuntimeErrorOptions : null | RuntimeReportingOptions = null ;
@@ -88,15 +88,14 @@ export function stopReportingRuntimeErrors() {
8888}
8989
9090function update ( ) {
91- renderedElement = render ( ) ;
9291 // Loading iframe can be either sync or async depending on the browser.
9392 if ( isLoadingIframe ) {
9493 // Iframe is loading.
9594 // First render will happen soon--don't need to do anything.
9695 return ;
9796 }
98- if ( iframe ) {
99- // Iframe has already loaded .
97+ if ( isIframeReady ) {
98+ // Iframe is ready .
10099 // Just update it.
101100 updateIframeContent ( ) ;
102101 return ;
@@ -108,58 +107,46 @@ function update() {
108107 loadingIframe . onload = function ( ) {
109108 const iframeDocument = loadingIframe . contentDocument ;
110109 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.
119110 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 ) ;
122117 }
123118 } ;
124119 const appDocument = window . document ;
125120 appDocument . body . appendChild ( loadingIframe ) ;
126121}
127122
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.' ) ;
143126 }
144- return null ;
145- }
146127
147- function updateIframeContent ( ) {
148- if ( iframe === null ) {
128+ if ( ! iframe ) {
149129 throw new Error ( 'Iframe has not been created yet.' ) ;
150130 }
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 ) {
158140 window . document . body . removeChild ( iframe ) ;
159- ReactDOM . unmountComponentAtNode ( iframeRoot ) ;
160141 iframe = null ;
161- return ;
142+ isIframeReady = false ;
162143 }
163- // Update the overlay
164- ReactDOM . render ( renderedElement , iframeRoot ) ;
165144}
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