@@ -15,38 +15,99 @@ var fs = inquire("fs");
15
15
* @returns {undefined }
16
16
*/
17
17
18
+ /**
19
+ * Options as used by {@link util.fetch}.
20
+ * @typedef {Object }
21
+ * @property {boolean } [binary=false] Whether expecting a binary response or not
22
+ */
23
+
18
24
/**
19
25
* Fetches the contents of a file.
20
26
* @memberof util
21
- * @param {string } path File path or url
22
- * @param {FetchCallback } [callback] Callback function
23
- * @returns { Promise<string> } A Promise if ` callback` has been omitted, otherwise `undefined`
24
- * @property { function(string, FetchCallback=):Promise<string> } xhr XHR/browser fetch with an identical signature
27
+ * @param {string } filename File path or url
28
+ * @param {FetchOptions } options Fetch options
29
+ * @param { FetchCallback } callback Callback function
30
+ * @returns { undefined }
25
31
*/
26
- function fetch ( path , callback ) {
32
+ function fetch ( filename , options , callback ) {
33
+ if ( typeof options === "function" ) {
34
+ callback = options ;
35
+ options = { } ;
36
+ } else if ( ! options )
37
+ options = { } ;
38
+
27
39
if ( ! callback )
28
- return asPromise ( fetch , this , path ) ; // eslint-disable-line no-invalid-this
40
+ return asPromise ( fetch , this , filename , options ) ; // eslint-disable-line no-invalid-this
41
+
42
+ // if a node-like filesystem is present, try it first but fall back to XHR if nothing is found.
29
43
if ( fs && fs . readFile )
30
- return fs . readFile ( path , "utf8" , function fetchReadFileCallback ( err , contents ) {
44
+ return fs . readFile ( filename , function fetchReadFileCallback ( err , contents ) {
31
45
return err && typeof XMLHttpRequest !== "undefined"
32
- ? fetch . xhr ( path , callback )
33
- : callback ( err , contents ) ;
46
+ ? fetch . xhr ( filename , options , callback )
47
+ : err
48
+ ? callback ( err )
49
+ : callback ( null , options . binary ? contents : contents . toString ( "utf8" ) ) ;
34
50
} ) ;
35
- return fetch . xhr ( path , callback ) ;
51
+
52
+ // use the XHR version otherwise.
53
+ return fetch . xhr ( filename , options , callback ) ;
36
54
}
37
55
38
- fetch . xhr = function fetch_xhr ( path , callback ) {
56
+ /**
57
+ * Fetches the contents of a file.
58
+ * @name util.fetch
59
+ * @function
60
+ * @param {string } path File path or url
61
+ * @param {FetchCallback } callback Callback function
62
+ * @returns {undefined }
63
+ * @variation 2
64
+ */
65
+
66
+ /**
67
+ * Fetches the contents of a file.
68
+ * @name util.fetch
69
+ * @function
70
+ * @param {string } path File path or url
71
+ * @param {FetchOptions } [options] Fetch options
72
+ * @returns {Promise<string|Uint8Array> } Promise
73
+ * @variation 3
74
+ */
75
+
76
+ /**/
77
+ fetch . xhr = function fetch_xhr ( filename , options , callback ) {
39
78
var xhr = new XMLHttpRequest ( ) ;
40
79
xhr . onreadystatechange /* works everywhere */ = function fetchOnReadyStateChange ( ) {
41
- return xhr . readyState === 4
42
- ? xhr . status === 0 || xhr . status === 200
43
- ? callback ( null , xhr . responseText )
44
- : callback ( Error ( "status " + xhr . status ) )
45
- : undefined ;
80
+
81
+ if ( xhr . readyState !== 4 )
82
+ return undefined ;
83
+
46
84
// local cors security errors return status 0 / empty string, too. afaik this cannot be
47
85
// reliably distinguished from an actually empty file for security reasons. feel free
48
86
// to send a pull request if you are aware of a solution.
87
+ if ( xhr . status !== 0 && xhr . status !== 200 )
88
+ return callback ( Error ( "status " + xhr . status ) ) ;
89
+
90
+ // if binary data is expected, make sure that some sort of array is returned, even if
91
+ // ArrayBuffers are not supported. the binary string fallback, however, is unsafe.
92
+ if ( options . binary ) {
93
+ var buffer = xhr . response ;
94
+ if ( ! buffer ) {
95
+ buffer = [ ] ;
96
+ for ( var i = 0 ; i < xhr . responseText . length ; ++ i )
97
+ buffer . push ( xhr . responseText . charCodeAt ( i ) & 255 ) ;
98
+ }
99
+ return callback ( null , typeof Uint8Array !== "undefined" ? new Uint8Array ( buffer ) : buffer ) ;
100
+ }
101
+ return callback ( null , xhr . responseText ) ;
49
102
} ;
50
- xhr . open ( "GET" , path ) ;
103
+
104
+ if ( options . binary ) {
105
+ // ref: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Sending_and_Receiving_Binary_Data#Receiving_binary_data_in_older_browsers
106
+ if ( "overrideMimeType" in xhr )
107
+ xhr . overrideMimeType ( "text/plain; charset=x-user-defined" ) ;
108
+ xhr . responseType = "arraybuffer" ;
109
+ }
110
+
111
+ xhr . open ( "GET" , filename ) ;
51
112
xhr . send ( ) ;
52
113
} ;
0 commit comments