Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ See docs/process.md for more on how version tagging works.

5.0.3 (in development)
----------------------
- The low level FS.write API now only accepts TypedArray. The higher level
writeFile and createDataFile file still also accept string and Array.
(#26413)
- Warn on usage of the deprecated `EMSCRIPTEN` macro (`__EMSCRIPTEN__` should
be used instead). (#26381)
- The `-sRELOCATABLE` setting was effectively removed (moved to legacy
Expand Down
2 changes: 1 addition & 1 deletion src/lib/libcore.js
Original file line number Diff line number Diff line change
Expand Up @@ -2193,7 +2193,7 @@ addToLibrary({
#endif
FS.createPath('/', PATH.dirname(name), true, true);
// canOwn this data in the filesystem, it is a slice of wasm memory that will never change
FS.createDataFile(name, null, HEAP8.subarray(content, content + len), true, true, true);
FS.createDataFile(name, null, HEAP8.subarray(content, content + len), true, true, /*canOwn=*/true);
} while ({{{ makeGetValue('ptr', '0', '*') }}});
#if RUNTIME_DEBUG
dbg('done preloading data files');
Expand Down
27 changes: 14 additions & 13 deletions src/lib/libfs.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
var LibraryFS = {
$FS__deps: ['$randomFill', '$PATH', '$PATH_FS', '$TTY', '$MEMFS',
'$FS_modeStringToFlags',
'$FS_fileDataToTypedArray',
'$FS_getMode',
'$intArrayFromString',
#if LibraryManager.has('libidbfs.js')
Expand Down Expand Up @@ -1253,9 +1254,13 @@ FS.staticInit();`;
#endif
return bytesRead;
},
/**
* @param {TypedArray} buffer
*/
write(stream, buffer, offset, length, position, canOwn) {
#if ASSERTIONS
assert(offset >= 0);
assert(buffer.subarray, 'FS.write expects a TypedArray');
#endif
if (length < 0 || position < 0) {
throw new FS.ErrnoError({{{ cDefs.EINVAL }}});
Expand Down Expand Up @@ -1346,17 +1351,14 @@ FS.staticInit();`;
FS.close(stream);
return buf;
},
/**
* @param {TypedArray|Array|string} data
*/
writeFile(path, data, opts = {}) {
opts.flags = opts.flags || {{{ cDefs.O_TRUNC | cDefs.O_CREAT | cDefs.O_WRONLY }}};
var stream = FS.open(path, opts.flags, opts.mode);
if (typeof data == 'string') {
data = new Uint8Array(intArrayFromString(data, true));
}
if (ArrayBuffer.isView(data)) {
FS.write(stream, data, 0, data.byteLength, undefined, opts.canOwn);
} else {
abort('Unsupported data type');
}
data = FS_fileDataToTypedArray(data);
FS.write(stream, data, 0, data.byteLength, undefined, opts.canOwn);
FS.close(stream);
},

Expand Down Expand Up @@ -1604,6 +1606,9 @@ FS.staticInit();`;
var mode = FS_getMode(canRead, canWrite);
return FS.create(path, mode);
},
/**
* @param {TypedArray|Array|string=} data
*/
createDataFile(parent, name, data, canRead, canWrite, canOwn) {
var path = name;
if (parent) {
Expand All @@ -1613,11 +1618,7 @@ FS.staticInit();`;
var mode = FS_getMode(canRead, canWrite);
var node = FS.create(path, mode);
if (data) {
if (typeof data == 'string') {
var arr = new Array(data.length);
for (var i = 0, len = data.length; i < len; ++i) arr[i] = data.charCodeAt(i);
data = arr;
}
data = FS_fileDataToTypedArray(data);
// make sure we can write to the file
FS.chmod(node, mode | {{{ cDefs.S_IWUGO }}});
var stream = FS.open(node, {{{ cDefs.O_TRUNC | cDefs.O_CREAT | cDefs.O_WRONLY }}});
Expand Down
10 changes: 10 additions & 0 deletions src/lib/libfs_shared.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,16 @@ addToLibrary({
return mode;
},

$FS_fileDataToTypedArray: (data) => {
if (typeof data == 'string') {
data = intArrayFromString(data, true);
}
if (!data.subarray) {
data = new Uint8Array(data);
}
return data;
},

$FS_stdin_getChar_buffer: [],

// getChar has 3 particular return values:
Expand Down
57 changes: 25 additions & 32 deletions src/lib/libmemfs.js
Original file line number Diff line number Diff line change
Expand Up @@ -248,16 +248,23 @@ addToLibrary({
return size;
},

// Writes the byte range (buffer[offset], buffer[offset+length]) to offset 'position' into the file pointed by 'stream'
// canOwn: A boolean that tells if this function can take ownership of the passed in buffer from the subbuffer portion
// that the typed array view 'buffer' points to. The underlying ArrayBuffer can be larger than that, but
// canOwn=true will not take ownership of the portion outside the bytes addressed by the view. This means that
// with canOwn=true, creating a copy of the bytes is avoided, but the caller shouldn't touch the passed in range
// of bytes anymore since their contents now represent file data inside the filesystem.
/**
* Writes the byte range (buffer[offset], buffer[offset+length]) to offset
* 'position' into the file pointed by 'stream'.
* @param {TypedArray} buffer
* @param {boolean=} canOwn - A boolean that tells if this function can
* take ownership of the passed in buffer from the subbuffer portion
* that the typed array view 'buffer' points to. The underlying
* ArrayBuffer can be larger than that, but canOwn=true will not take
* ownership of the portion outside the bytes addressed by the view.
* This means that with canOwn=true, creating a copy of the bytes is
* avoided, but the caller shouldn't touch the passed in range of
* bytes anymore since their contents now represent file data inside
* the filesystem.
*/
write(stream, buffer, offset, length, position, canOwn) {
#if ASSERTIONS
// The data buffer should be a typed array view
assert(!(buffer instanceof ArrayBuffer));
assert(buffer.subarray, 'FS.write expects a TypedArray');
#endif
#if ALLOW_MEMORY_GROWTH
// If the buffer is located in main memory (HEAP), and if
Expand All @@ -273,35 +280,21 @@ addToLibrary({
var node = stream.node;
node.mtime = node.ctime = Date.now();

if (buffer.subarray) { // This write is from a typed array to a typed array?
if (canOwn) {
if (canOwn) {
#if ASSERTIONS
assert(position === 0, 'canOwn must imply no weird position inside the file');
assert(position === 0, 'canOwn must imply no weird position inside the file');
#endif
node.contents = buffer.subarray(offset, offset + length);
node.usedBytes = length;
return length;
} else if (node.usedBytes === 0 && position === 0) { // If this is a simple first write to an empty file, do a fast set since we don't need to care about old data.
node.contents = buffer.slice(offset, offset + length);
node.usedBytes = length;
return length;
} else if (position + length <= node.usedBytes) { // Writing to an already allocated and used subrange of the file?
node.contents.set(buffer.subarray(offset, offset + length), position);
return length;
}
}

// Appending to an existing file and we need to reallocate, or source data did not come as a typed array.
MEMFS.expandFileStorage(node, position+length);
if (buffer.subarray) {
node.contents = buffer.subarray(offset, offset + length);
node.usedBytes = length;
} else if (node.usedBytes === 0 && position === 0) { // If this is a simple first write to an empty file, do a fast set since we don't need to care about old data.
node.contents = buffer.slice(offset, offset + length);
node.usedBytes = length;
} else {
MEMFS.expandFileStorage(node, position+length);
// Use typed array write which is available.
node.contents.set(buffer.subarray(offset, offset + length), position);
} else {
for (var i = 0; i < length; i++) {
node.contents[position + i] = buffer[offset + i]; // Or fall back to manual write if not.
}
node.usedBytes = Math.max(node.usedBytes, position + length);
}
node.usedBytes = Math.max(node.usedBytes, position + length);
return length;
},

Expand Down
11 changes: 4 additions & 7 deletions src/lib/libwasmfs.js
Original file line number Diff line number Diff line change
Expand Up @@ -509,20 +509,17 @@ addToLibrary({
return FS_mknod(path, mode, 0);
},

$FS_writeFile__deps: ['_wasmfs_write_file', '$stackSave', '$stackRestore', 'malloc', 'free'],
$FS_writeFile__deps: ['$FS_fileDataToTypedArray', '_wasmfs_write_file', '$stackSave', '$stackRestore', 'malloc', 'free'],
$FS_writeFile: (path, data) => {
var sp = stackSave();
var pathBuffer = stringToUTF8OnStack(path);
var len = typeof data == 'string' ? lengthBytesUTF8(data) + 1 : data.length;
data = FS_fileDataToTypedArray(data);
var len = data.length;
var dataBuffer = _malloc(len);
#if ASSERTIONS
assert(dataBuffer);
#endif
if (typeof data == 'string') {
len = stringToUTF8(data, dataBuffer, len);
} else {
HEAPU8.set(data, dataBuffer);
}
HEAPU8.set(data, dataBuffer);
var ret = __wasmfs_write_file(pathBuffer, dataBuffer, len);
_free(dataBuffer);
stackRestore(sp);
Expand Down
8 changes: 4 additions & 4 deletions test/codesize/test_codesize_cxx_ctors1.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"a.out.js": 19334,
"a.out.js.gz": 8012,
"a.out.js": 19214,
"a.out.js.gz": 7982,
"a.out.nodebug.wasm": 132865,
"a.out.nodebug.wasm.gz": 49889,
"total": 152199,
"total_gz": 57901,
"total": 152079,
"total_gz": 57871,
"sent": [
"__cxa_throw",
"_abort_js",
Expand Down
8 changes: 4 additions & 4 deletions test/codesize/test_codesize_cxx_ctors2.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"a.out.js": 19311,
"a.out.js.gz": 7998,
"a.out.js": 19191,
"a.out.js.gz": 7968,
"a.out.nodebug.wasm": 132285,
"a.out.nodebug.wasm.gz": 49542,
"total": 151596,
"total_gz": 57540,
"total": 151476,
"total_gz": 57510,
"sent": [
"__cxa_throw",
"_abort_js",
Expand Down
8 changes: 4 additions & 4 deletions test/codesize/test_codesize_cxx_except.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"a.out.js": 22995,
"a.out.js.gz": 8989,
"a.out.js": 22875,
"a.out.js.gz": 8959,
"a.out.nodebug.wasm": 172743,
"a.out.nodebug.wasm.gz": 57374,
"total": 195738,
"total_gz": 66363,
"total": 195618,
"total_gz": 66333,
"sent": [
"__cxa_begin_catch",
"__cxa_end_catch",
Expand Down
8 changes: 4 additions & 4 deletions test/codesize/test_codesize_cxx_except_wasm.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"a.out.js": 19145,
"a.out.js.gz": 7934,
"a.out.js": 19025,
"a.out.js.gz": 7906,
"a.out.nodebug.wasm": 148138,
"a.out.nodebug.wasm.gz": 55261,
"total": 167283,
"total_gz": 63195,
"total": 167163,
"total_gz": 63167,
"sent": [
"_abort_js",
"_tzset_js",
Expand Down
8 changes: 4 additions & 4 deletions test/codesize/test_codesize_cxx_except_wasm_legacy.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"a.out.js": 19219,
"a.out.js.gz": 7954,
"a.out.js": 19099,
"a.out.js.gz": 7926,
"a.out.nodebug.wasm": 145944,
"a.out.nodebug.wasm.gz": 54887,
"total": 165163,
"total_gz": 62841,
"total": 165043,
"total_gz": 62813,
"sent": [
"_abort_js",
"_tzset_js",
Expand Down
8 changes: 4 additions & 4 deletions test/codesize/test_codesize_cxx_lto.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"a.out.js": 18682,
"a.out.js.gz": 7697,
"a.out.js": 18562,
"a.out.js.gz": 7670,
"a.out.nodebug.wasm": 102126,
"a.out.nodebug.wasm.gz": 39426,
"total": 120808,
"total_gz": 47123,
"total": 120688,
"total_gz": 47096,
"sent": [
"a (emscripten_resize_heap)",
"b (_setitimer_js)",
Expand Down
8 changes: 4 additions & 4 deletions test/codesize/test_codesize_cxx_mangle.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"a.out.js": 23045,
"a.out.js.gz": 9008,
"a.out.js": 22925,
"a.out.js.gz": 8978,
"a.out.nodebug.wasm": 239177,
"a.out.nodebug.wasm.gz": 79774,
"total": 262222,
"total_gz": 88782,
"total": 262102,
"total_gz": 88752,
"sent": [
"__cxa_begin_catch",
"__cxa_end_catch",
Expand Down
8 changes: 4 additions & 4 deletions test/codesize/test_codesize_cxx_noexcept.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"a.out.js": 19334,
"a.out.js.gz": 8012,
"a.out.js": 19214,
"a.out.js.gz": 7982,
"a.out.nodebug.wasm": 134872,
"a.out.nodebug.wasm.gz": 50724,
"total": 154206,
"total_gz": 58736,
"total": 154086,
"total_gz": 58706,
"sent": [
"__cxa_throw",
"_abort_js",
Expand Down
Loading