@@ -4,6 +4,9 @@ const chalk = require('chalk');
44const vm = require ( 'vm' ) ;
55const sourceMapSupport = require ( 'source-map-support' ) ;
66
7+ const httpRegex = / ^ h t t p s ? : \/ \/ / ;
8+ const protocolRelativeRegex = / ^ \/ \/ / ;
9+
710module . exports = class Sandbox {
811 constructor ( globals ) {
912 this . globals = globals ;
@@ -14,6 +17,7 @@ module.exports = class Sandbox {
1417
1518 buildSandbox ( ) {
1619 let console = this . buildWrappedConsole ( ) ;
20+ let fetch = this . buildFetch ( ) ;
1721 let URL = require ( 'url' ) ;
1822 let globals = this . globals ;
1923
@@ -28,6 +32,7 @@ module.exports = class Sandbox {
2832 // Convince jQuery not to assume it's in a browser
2933 module : { exports : { } } ,
3034 } ,
35+ fetch ,
3136 globals
3237 ) ;
3338
@@ -53,6 +58,89 @@ module.exports = class Sandbox {
5358 return wrappedConsole ;
5459 }
5560
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+
56144 runScript ( script ) {
57145 script . runInContext ( this . context ) ;
58146 }
0 commit comments