@@ -4,6 +4,9 @@ const chalk = require('chalk');
4
4
const vm = require ( 'vm' ) ;
5
5
const sourceMapSupport = require ( 'source-map-support' ) ;
6
6
7
+ const httpRegex = / ^ h t t p s ? : \/ \/ / ;
8
+ const protocolRelativeRegex = / ^ \/ \/ / ;
9
+
7
10
module . exports = class Sandbox {
8
11
constructor ( globals ) {
9
12
this . globals = globals ;
@@ -14,6 +17,7 @@ module.exports = class Sandbox {
14
17
15
18
buildSandbox ( ) {
16
19
let console = this . buildWrappedConsole ( ) ;
20
+ let fetch = this . buildFetch ( ) ;
17
21
let URL = require ( 'url' ) ;
18
22
let globals = this . globals ;
19
23
@@ -28,6 +32,7 @@ module.exports = class Sandbox {
28
32
// Convince jQuery not to assume it's in a browser
29
33
module : { exports : { } } ,
30
34
} ,
35
+ fetch ,
31
36
globals
32
37
) ;
33
38
@@ -53,6 +58,89 @@ module.exports = class Sandbox {
53
58
return wrappedConsole ;
54
59
}
55
60
61
+ buildFetch ( ) {
62
+ let globals ;
63
+
64
+ if ( globalThis . fetch ) {
65
+ globals = {
66
+ fetch : globalThis . fetch ,
67
+ Request : globalThis . Request ,
68
+ Response : globalThis . Response ,
69
+ Headers : globalThis . Headers ,
70
+ AbortController : globalThis . AbortController ,
71
+ } ;
72
+ } else {
73
+ let nodeFetch = require ( 'node-fetch' ) ;
74
+ let {
75
+ AbortController,
76
+ abortableFetch,
77
+ } = require ( 'abortcontroller-polyfill/dist/cjs-ponyfill' ) ;
78
+ let { fetch, Request } = abortableFetch ( {
79
+ fetch : nodeFetch ,
80
+ Request : nodeFetch . Request ,
81
+ } ) ;
82
+
83
+ globals = {
84
+ fetch,
85
+ Request,
86
+ Response : nodeFetch . Response ,
87
+ Headers : nodeFetch . Headers ,
88
+ AbortController,
89
+ } ;
90
+ }
91
+
92
+ let originalFetch = globals . fetch ;
93
+ globals . fetch = function __fastbootFetch ( input , init ) {
94
+ input = globals . fetch . __fastbootBuildAbsoluteURL ( input ) ;
95
+ return originalFetch ( input , init ) ;
96
+ } ;
97
+
98
+ globals . fetch . __fastbootBuildAbsoluteURL = function __fastbootBuildAbsoluteURL ( input ) {
99
+ if ( input && input . href ) {
100
+ // WHATWG URL or Node.js Url Object
101
+ input = input . href ;
102
+ }
103
+
104
+ if ( typeof input !== 'string' ) {
105
+ return input ;
106
+ }
107
+
108
+ if ( protocolRelativeRegex . test ( input ) ) {
109
+ let request = globals . fetch . __fastbootRequest ;
110
+ let [ protocol ] = globals . fetch . __fastbootParseRequest ( input , request ) ;
111
+ input = `${ protocol } //${ input } ` ;
112
+ } else if ( ! httpRegex . test ( input ) ) {
113
+ let request = globals . fetch . __fastbootRequest ;
114
+ let [ protocol , host ] = globals . fetch . __fastbootParseRequest ( input , request ) ;
115
+ input = `${ protocol } //${ host } ${ input } ` ;
116
+ }
117
+
118
+ return input ;
119
+ } ;
120
+
121
+ globals . fetch . __fastbootParseRequest = function __fastbootParseRequest ( url , request ) {
122
+ if ( ! request ) {
123
+ throw new Error (
124
+ `Using fetch with relative URL ${ url } , but application instance has not been initialized yet.`
125
+ ) ;
126
+ }
127
+
128
+ // Old Prember version is not sending protocol
129
+ const protocol = request . protocol === 'undefined:' ? 'http:' : request . protocol ;
130
+ return [ protocol , request . host ] ;
131
+ } ;
132
+
133
+ let OriginalRequest = globals . Request ;
134
+ globals . Request = class __FastBootRequest extends OriginalRequest {
135
+ constructor ( input , init ) {
136
+ input = globals . fetch . __fastbootBuildAbsoluteURL ( input ) ;
137
+ super ( input , init ) ;
138
+ }
139
+ } ;
140
+
141
+ return globals ;
142
+ }
143
+
56
144
runScript ( script ) {
57
145
script . runInContext ( this . context ) ;
58
146
}
0 commit comments