1
- const BrowserInterface = require ( './browser-interface' ) ;
2
- const {
1
+ import { BrowserInterface } from './browser-interface' ;
2
+ import {
3
3
CrossDomainError ,
4
4
HttpError ,
5
5
LoadTimeoutError ,
6
6
RedirectError ,
7
7
UrlVerifyError ,
8
8
UnknownError ,
9
9
XFrameDenyError ,
10
- } = require ( './errors' ) ;
10
+ UrlError ,
11
+ } from './errors' ;
12
+ import { Viewport , NullableViewport } from './types' ;
11
13
12
14
const defaultLoadTimeout = 60 * 1000 ;
13
15
14
- class BrowserInterfaceIframe extends BrowserInterface {
16
+ type VerifyMethod = (
17
+ rawUrl : string ,
18
+ contentWindow : Window ,
19
+ contentDocument : Document
20
+ ) => Promise < boolean > ;
21
+
22
+ type BrowserInterfaceIframeOptions = {
23
+ requestGetParameters ?: { [ key : string ] : string } ;
24
+ loadTimeout ?: number ;
25
+ verifyPage : VerifyMethod ;
26
+ allowScripts ?: boolean ;
27
+ } ;
28
+
29
+ export class BrowserInterfaceIframe extends BrowserInterface {
30
+ private requestGetParameters : { [ key : string ] : string } ;
31
+ private loadTimeout : number ;
32
+ private verifyPage : VerifyMethod ;
33
+
34
+ private currentUrl : string | null ;
35
+ private currentSize : NullableViewport ;
36
+
37
+ private wrapperDiv : HTMLDivElement ;
38
+ private iframe : HTMLIFrameElement ;
39
+
15
40
constructor ( {
16
41
requestGetParameters,
17
42
loadTimeout,
18
43
verifyPage,
19
44
allowScripts,
20
- } = { } ) {
45
+ } : BrowserInterfaceIframeOptions ) {
21
46
super ( ) ;
22
47
23
48
this . requestGetParameters = requestGetParameters || { } ;
@@ -27,12 +52,8 @@ class BrowserInterfaceIframe extends BrowserInterface {
27
52
// Default 'allowScripts' to true if not specified.
28
53
allowScripts = allowScripts !== false ;
29
54
30
- if ( ! verifyPage ) {
31
- throw new Error ( 'You must specify a page verification callback' ) ;
32
- }
33
-
34
55
this . currentUrl = null ;
35
- this . currentSize = { width : undefined , height : undefined } ;
56
+ this . currentSize = { width : null , height : null } ;
36
57
37
58
// Create a wrapper div to keep the iframe invisible.
38
59
this . wrapperDiv = document . createElement ( 'div' ) ;
@@ -56,24 +77,21 @@ class BrowserInterfaceIframe extends BrowserInterface {
56
77
this . wrapperDiv . append ( this . iframe ) ;
57
78
}
58
79
59
- cleanup ( ) {
80
+ async cleanup ( ) {
60
81
this . iframe . remove ( ) ;
61
82
this . wrapperDiv . remove ( ) ;
62
83
}
63
84
64
- /**
65
- * Wrapper for window.fetch. Overload this to change CSS or HTML fetching
66
- * behaviour.
67
- *
68
- * @param {string } url URL to fetch.
69
- * @param {Object } options Fetch options.
70
- * @param {string } _role 'css' or 'html' indicating what kind of thing is being fetched.
71
- */
72
- async fetch ( url , options , _role ) {
85
+ async fetch ( url : string , options : RequestInit , _role : 'css' | 'html' ) {
73
86
return window . fetch ( url , options ) ;
74
87
}
75
88
76
- async runInPage ( pageUrl , viewport , method , ...args ) {
89
+ async runInPage < ReturnType > (
90
+ pageUrl : string ,
91
+ viewport : Viewport | null ,
92
+ method : Function ,
93
+ ...args : any [ ]
94
+ ) : Promise < ReturnType > {
77
95
await this . loadPage ( pageUrl ) ;
78
96
79
97
if ( viewport ) {
@@ -85,7 +103,7 @@ class BrowserInterfaceIframe extends BrowserInterface {
85
103
return method ( { innerWindow : this . iframe . contentWindow , args } ) ;
86
104
}
87
105
88
- addGetParameters ( rawUrl ) {
106
+ addGetParameters ( rawUrl : string ) : string {
89
107
const urlObject = new URL ( rawUrl ) ;
90
108
for ( const key of Object . keys ( this . requestGetParameters ) ) {
91
109
urlObject . searchParams . append (
@@ -97,7 +115,7 @@ class BrowserInterfaceIframe extends BrowserInterface {
97
115
return urlObject . toString ( ) ;
98
116
}
99
117
100
- async diagnoseUrlError ( url ) {
118
+ async diagnoseUrlError ( url : string ) : Promise < UrlError | null > {
101
119
try {
102
120
const response = await this . fetch (
103
121
url ,
@@ -127,18 +145,18 @@ class BrowserInterfaceIframe extends BrowserInterface {
127
145
}
128
146
}
129
147
130
- sameOrigin ( url ) {
148
+ sameOrigin ( url : string ) : boolean {
131
149
return new URL ( url ) . origin === window . location . origin ;
132
150
}
133
151
134
- async loadPage ( rawUrl ) {
152
+ async loadPage ( rawUrl : string ) : Promise < void > {
135
153
if ( rawUrl === this . currentUrl ) {
136
154
return ;
137
155
}
138
156
139
157
const fullUrl = this . addGetParameters ( rawUrl ) ;
140
158
141
- await new Promise ( ( resolve , rawReject ) => {
159
+ return new Promise ( ( resolve , rawReject ) => {
142
160
// Track all URL errors.
143
161
const reject = ( err ) => {
144
162
this . trackUrlError ( rawUrl , err ) ;
@@ -153,18 +171,21 @@ class BrowserInterfaceIframe extends BrowserInterface {
153
171
154
172
// Set a timeout.
155
173
const timeoutId = setTimeout ( ( ) => {
156
- this . iframe . onload = undefined ;
174
+ this . iframe . onload = null ;
157
175
reject ( new LoadTimeoutError ( { url : fullUrl } ) ) ;
158
176
} , this . loadTimeout ) ;
159
177
160
178
// Catch load event.
161
179
this . iframe . onload = async ( ) => {
162
180
try {
163
- this . iframe . onload = undefined ;
181
+ this . iframe . onload = null ;
164
182
clearTimeout ( timeoutId ) ;
165
183
166
184
// Verify the inner document is readable.
167
- if ( ! this . iframe . contentDocument ) {
185
+ if (
186
+ ! this . iframe . contentDocument ||
187
+ ! this . iframe . contentWindow
188
+ ) {
168
189
throw (
169
190
( await this . diagnoseUrlError ( fullUrl ) ) ||
170
191
new CrossDomainError ( { url : fullUrl } )
@@ -195,7 +216,7 @@ class BrowserInterfaceIframe extends BrowserInterface {
195
216
} ) ;
196
217
}
197
218
198
- async resize ( { width, height } ) {
219
+ async resize ( { width, height } : Viewport ) {
199
220
if (
200
221
this . currentSize . width === width &&
201
222
this . currentSize . height === height
@@ -205,13 +226,11 @@ class BrowserInterfaceIframe extends BrowserInterface {
205
226
206
227
return new Promise ( ( resolve ) => {
207
228
// Set iframe size.
208
- this . iframe . width = width ;
209
- this . iframe . height = height ;
229
+ this . iframe . width = width . toString ( ) ;
230
+ this . iframe . height = height . toString ( ) ;
210
231
211
232
// Bounce to browser main loop to allow resize to complete.
212
233
setTimeout ( resolve , 1 ) ;
213
234
} ) ;
214
235
}
215
236
}
216
-
217
- module . exports = BrowserInterfaceIframe ;
0 commit comments