Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
emscripten-core
GitHub Repository: emscripten-core/emscripten
Path: blob/main/src/lib/libfs_shared.js
4150 views
1
/**
2
* @license
3
* Copyright 2032 The Emscripten Authors
4
* SPDX-License-Identifier: MIT
5
*/
6
7
addToLibrary({
8
$preloadPlugins__postset: () => addAtModule(makeModuleReceive('preloadPlugins')),
9
$preloadPlugins: [],
10
11
#if !MINIMAL_RUNTIME
12
// Tries to handle an input byteArray using preload plugins. Returns true if
13
// it was handled.
14
$FS_handledByPreloadPlugin__internal: true,
15
$FS_handledByPreloadPlugin__deps: ['$preloadPlugins'],
16
$FS_handledByPreloadPlugin: async (byteArray, fullname) => {
17
#if LibraryManager.has('libbrowser.js')
18
// Ensure plugins are ready.
19
if (typeof Browser != 'undefined') Browser.init();
20
#endif
21
22
for (var plugin of preloadPlugins) {
23
if (plugin['canHandle'](fullname)) {
24
#if ASSERTIONS
25
assert(plugin['handle'].constructor.name === 'AsyncFunction', 'Filesystem plugin handlers must be async functions (See #24914)')
26
#endif
27
return plugin['handle'](byteArray, fullname);
28
}
29
}
30
// In no plugin handled this file then return the original/unmodified
31
// byteArray.
32
return byteArray;
33
},
34
35
// Legacy version of FS_preloadFile that uses callback rather than async
36
$FS_createPreloadedFile__deps: ['$FS_preloadFile'],
37
$FS_createPreloadedFile: (parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish) => {
38
FS_preloadFile(parent, name, url, canRead, canWrite, dontCreateFile, canOwn, preFinish).then(onload).catch(onerror);
39
},
40
41
// Preloads a file asynchronously. You can call this before run, for example in
42
// preRun. run will be delayed until this file arrives and is set up.
43
// If you call it after run(), you may want to pause the main loop until it
44
// completes, if so, you can use the onload parameter to be notified when
45
// that happens.
46
// In addition to normally creating the file, we also asynchronously preload
47
// the browser-friendly versions of it: For an image, we preload an Image
48
// element and for an audio, and Audio. These are necessary for SDL_Image
49
// and _Mixer to find the files in preloadedImages/Audios.
50
// You can also call this with a typed array instead of a url. It will then
51
// do preloading for the Image/Audio part, as if the typed array were the
52
// result of an XHR that you did manually.
53
$FS_preloadFile__deps: [
54
'$asyncLoad',
55
'$PATH_FS',
56
'$FS_createDataFile',
57
'$getUniqueRunDependency',
58
'$addRunDependency',
59
'$removeRunDependency',
60
'$FS_handledByPreloadPlugin',
61
],
62
$FS_preloadFile: async (parent, name, url, canRead, canWrite, dontCreateFile, canOwn, preFinish) => {
63
// TODO we should allow people to just pass in a complete filename instead
64
// of parent and name being that we just join them anyways
65
var fullname = name ? PATH_FS.resolve(PATH.join2(parent, name)) : parent;
66
var dep = getUniqueRunDependency(`cp ${fullname}`); // might have several active requests for the same fullname
67
addRunDependency(dep);
68
69
try {
70
var byteArray = url;
71
if (typeof url == 'string') {
72
byteArray = await asyncLoad(url);
73
}
74
75
byteArray = await FS_handledByPreloadPlugin(byteArray, fullname);
76
preFinish?.();
77
if (!dontCreateFile) {
78
FS_createDataFile(parent, name, byteArray, canRead, canWrite, canOwn);
79
}
80
} finally {
81
removeRunDependency(dep);
82
}
83
},
84
#endif
85
86
// convert the 'r', 'r+', etc. to it's corresponding set of O_* flags
87
$FS_modeStringToFlags: (str) => {
88
var flagModes = {
89
'r': {{{ cDefs.O_RDONLY }}},
90
'r+': {{{ cDefs.O_RDWR }}},
91
'w': {{{ cDefs.O_TRUNC }}} | {{{ cDefs.O_CREAT }}} | {{{ cDefs.O_WRONLY }}},
92
'w+': {{{ cDefs.O_TRUNC }}} | {{{ cDefs.O_CREAT }}} | {{{ cDefs.O_RDWR }}},
93
'a': {{{ cDefs.O_APPEND }}} | {{{ cDefs.O_CREAT }}} | {{{ cDefs.O_WRONLY }}},
94
'a+': {{{ cDefs.O_APPEND }}} | {{{ cDefs.O_CREAT }}} | {{{ cDefs.O_RDWR }}},
95
};
96
var flags = flagModes[str];
97
if (typeof flags == 'undefined') {
98
throw new Error(`Unknown file open mode: ${str}`);
99
}
100
return flags;
101
},
102
$FS_getMode: (canRead, canWrite) => {
103
var mode = 0;
104
if (canRead) mode |= {{{ cDefs.S_IRUGO }}} | {{{ cDefs.S_IXUGO }}};
105
if (canWrite) mode |= {{{ cDefs.S_IWUGO }}};
106
return mode;
107
},
108
109
$FS_stdin_getChar_buffer: [],
110
111
// getChar has 3 particular return values:
112
// a.) the next character represented as an integer
113
// b.) undefined to signal that no data is currently available
114
// c.) null to signal an EOF
115
$FS_stdin_getChar__deps: [
116
'$FS_stdin_getChar_buffer',
117
'$intArrayFromString',
118
],
119
$FS_stdin_getChar: () => {
120
if (!FS_stdin_getChar_buffer.length) {
121
var result = null;
122
#if ENVIRONMENT_MAY_BE_NODE
123
if (ENVIRONMENT_IS_NODE) {
124
// we will read data by chunks of BUFSIZE
125
var BUFSIZE = 256;
126
var buf = Buffer.alloc(BUFSIZE);
127
var bytesRead = 0;
128
129
// For some reason we must suppress a closure warning here, even though
130
// fd definitely exists on process.stdin, and is even the proper way to
131
// get the fd of stdin,
132
// https://github.com/nodejs/help/issues/2136#issuecomment-523649904
133
// This started to happen after moving this logic out of library_tty.js,
134
// so it is related to the surrounding code in some unclear manner.
135
/** @suppress {missingProperties} */
136
var fd = process.stdin.fd;
137
138
try {
139
bytesRead = fs.readSync(fd, buf, 0, BUFSIZE);
140
} catch(e) {
141
// Cross-platform differences: on Windows, reading EOF throws an
142
// exception, but on other OSes, reading EOF returns 0. Uniformize
143
// behavior by treating the EOF exception to return 0.
144
if (e.toString().includes('EOF')) bytesRead = 0;
145
else throw e;
146
}
147
148
if (bytesRead > 0) {
149
result = buf.slice(0, bytesRead).toString('utf-8');
150
}
151
} else
152
#endif
153
#if ENVIRONMENT_MAY_BE_WEB
154
if (typeof window != 'undefined' &&
155
typeof window.prompt == 'function') {
156
// Browser.
157
result = window.prompt('Input: '); // returns null on cancel
158
if (result !== null) {
159
result += '\n';
160
}
161
} else
162
#endif
163
#if ENVIRONMENT_MAY_BE_SHELL
164
if (typeof readline == 'function') {
165
// Command line.
166
result = readline();
167
if (result) {
168
result += '\n';
169
}
170
} else
171
#endif
172
{}
173
if (!result) {
174
return null;
175
}
176
FS_stdin_getChar_buffer = intArrayFromString(result, true);
177
}
178
return FS_stdin_getChar_buffer.shift();
179
},
180
181
$FS_unlink__deps: ['$FS'],
182
$FS_unlink: 'FS.unlink',
183
184
$FS_createPath__deps: ['$FS'],
185
$FS_createPath: 'FS.createPath',
186
187
$FS_createDevice__deps: ['$FS'],
188
$FS_createDevice: 'FS.createDevice',
189
190
$FS_readFile__deps: ['$FS'],
191
$FS_readFile: 'FS.readFile',
192
});
193
194
// Normally only the FS things that the compiler sees are needed are included.
195
// FORCE_FILESYSTEM makes us always include the FS object, which lets the user
196
// call APIs on it from JS freely.
197
if (FORCE_FILESYSTEM) {
198
extraLibraryFuncs.push('$FS');
199
}
200
201