From 945beee7efff52decf353a022ba85a6aebf386e7 Mon Sep 17 00:00:00 2001 From: Larry Ewing Date: Mon, 20 Jul 2020 11:40:17 -0500 Subject: [PATCH] [wasm] Include data archives and timezone data by default (#39586) * Add data archive loading to the generic loading logic --- eng/testing/tests.mobile.targets | 2 +- src/mono/wasm/runtime-test.js | 23 ---------- src/mono/wasm/runtime/library_mono.js | 52 +++++++++++++--------- .../mobile.tasks/WasmAppBuilder/WasmAppBuilder.cs | 2 +- 4 files changed, 33 insertions(+), 46 deletions(-) diff --git a/eng/testing/tests.mobile.targets b/eng/testing/tests.mobile.targets index 266a6d3..284ae30 100644 --- a/eng/testing/tests.mobile.targets +++ b/eng/testing/tests.mobile.targets @@ -14,7 +14,7 @@ - $HARNESS_RUNNER wasm test --engine=$(JSEngine) $(JSEngineArgs) --js-file=runtime.js -v --output-directory=$XHARNESS_OUT -- --enable-zoneinfo --run WasmTestRunner.dll $(AssemblyName).dll + $HARNESS_RUNNER wasm test --engine=$(JSEngine) $(JSEngineArgs) --js-file=runtime.js -v --output-directory=$XHARNESS_OUT -- --run WasmTestRunner.dll $(AssemblyName).dll diff --git a/src/mono/wasm/runtime-test.js b/src/mono/wasm/runtime-test.js index b63c8fc..a2a66b6 100644 --- a/src/mono/wasm/runtime-test.js +++ b/src/mono/wasm/runtime-test.js @@ -130,9 +130,6 @@ while (true) { } else if (args [0] == "--disable-on-demand-gc") { enable_gc = false; args = args.slice (1); - } else if (args [0] == "--enable-zoneinfo") { - enable_zoneinfo = true; - args = args.slice (1); } else { break; } @@ -173,26 +170,6 @@ var Module = { if (!enable_gc) { Module.ccall ('mono_wasm_enable_on_demand_gc', 'void', ['number'], [0]); } - if (enable_zoneinfo) { - // The timezone file is generated by https://github.com/dotnet/blazor/tree/master/src/TimeZoneData. - // The file format of the TZ file look like so - // - // [4-byte magic number] - // [4 - byte length of manifest] - // [json manifest] - // [data bytes] - // - // The json manifest is an array that looks like so: - // - // [...["America/Fort_Nelson",2249],["America/Glace_Bay",2206]..] - // - // where the first token in each array is the relative path of the file on disk, and the second is the - // length of the file. The starting offset of a file can be calculated using the lengths of all files - // that appear prior to it. - var zonedata = new Uint8Array(read ("dotnet.timezones.blat", "binary")); - MONO.mono_wasm_load_data (zonedata, "/usr/share/zoneinfo"); - } - config.loaded_cb = function () { App.init (); diff --git a/src/mono/wasm/runtime/library_mono.js b/src/mono/wasm/runtime/library_mono.js index b1be6e6..f47c0f8 100644 --- a/src/mono/wasm/runtime/library_mono.js +++ b/src/mono/wasm/runtime/library_mono.js @@ -619,7 +619,6 @@ var MonoSupportLib = { : virtualName; if (fileName.startsWith("/")) fileName = fileName.substr(1); - if (parentDirectory) { if (ctx.tracing) console.log ("MONO_WASM: Creating directory '" + parentDirectory + "'"); @@ -634,11 +633,12 @@ var MonoSupportLib = { if (ctx.tracing) console.log ("MONO_WASM: Creating file '" + fileName + "' in directory '" + parentDirectory + "'"); - var fileRet = ctx.createDataFile ( - parentDirectory, fileName, - bytes, true /* canRead */, true /* canWrite */, true /* canOwn */ - ); - + if (!this.mono_wasm_load_data_archive (bytes, parentDirectory)) { + var fileRet = ctx.createDataFile ( + parentDirectory, fileName, + bytes, true /* canRead */, true /* canWrite */, true /* canOwn */ + ); + } break; default: @@ -1110,16 +1110,30 @@ var MonoSupportLib = { return className.replace(/\//g, '.').replace(/`\d+/g, ''); }, - mono_wasm_load_data: function (data, prefix) { + mono_wasm_load_data_archive: function (data, prefix) { + if (data.length < 8) + return false; + var dataview = new DataView(data.buffer); var magic = dataview.getUint32(0, true); // get magic number if (magic != 0x626c6174) { - throw new Error ("File is of wrong type"); + return false; } var manifestSize = dataview.getUint32(4, true); - var manifestContent = Module.UTF8ArrayToString(data, 8, manifestSize); - var manifest = JSON.parse(manifestContent); + if (manifestSize == 0 || data.length < manifestSize + 8) + return false; + + var manifest; + try { + manifestContent = Module.UTF8ArrayToString(data, 8, manifestSize); + manifest = JSON.parse(manifestContent); + if (!(manifest instanceof Array)) + return false; + } catch (exc) { + return false; + } + data = data.slice(manifestSize+8); // Create the folder structure @@ -1127,18 +1141,13 @@ var MonoSupportLib = { // /usr/share/zoneinfo/Africa // /usr/share/zoneinfo/Asia // .. - var p = prefix.slice(1).split('/'); - p.forEach((v, i) => { - FS.mkdir(v); - Module['FS_createPath']("/" + p.slice(0, i).join('/'), v, true, true); - }) + var folders = new Set() manifest.filter(m => { - m = m[0].split('/') - if (m!= null) { - if (m.length > 2) folders.add(m.slice(0,m.length-1).join('/')); - folders.add(m[0]); - } + var file = m[0]; + var last = file.lastIndexOf ("/"); + var directory = file.slice (0, last); + folders.add(directory); }); folders.forEach(folder => { Module['FS_createPath'](prefix, folder, true, true); @@ -1148,9 +1157,10 @@ var MonoSupportLib = { var name = row[0]; var length = row[1]; var bytes = data.slice(0, length); - Module['FS_createDataFile'](`${prefix}/${name}`, null, bytes, true, true); + Module['FS_createDataFile'](prefix, name, bytes, true, true); data = data.slice(length); } + return true; } }, diff --git a/tools-local/tasks/mobile.tasks/WasmAppBuilder/WasmAppBuilder.cs b/tools-local/tasks/mobile.tasks/WasmAppBuilder/WasmAppBuilder.cs index 9a5d51c..668d4ef 100644 --- a/tools-local/tasks/mobile.tasks/WasmAppBuilder/WasmAppBuilder.cs +++ b/tools-local/tasks/mobile.tasks/WasmAppBuilder/WasmAppBuilder.cs @@ -121,7 +121,7 @@ public class WasmAppBuilder : Task var sEnableRemote = enableRemote ? "true" : "false"; sw.WriteLine($"\t\t{{ behavior: \"icu\", name: \"icudt.dat\", load_remote: {sEnableRemote} }},"); - + sw.WriteLine($"\t\t{{ behavior: \"vfs\", name: \"dotnet.timezones.blat\", virtual_path: \"/usr/share/zoneinfo/\" }}"); sw.WriteLine ("\t],"); if (enableRemote) { -- 2.7.4