[wasm] Wasm TimeZoneInfo implementation VFS (#34186)
authormonojenkins <jo.shields+jenkins@xamarin.com>
Sat, 4 Apr 2020 11:37:03 +0000 (07:37 -0400)
committerGitHub <noreply@github.com>
Sat, 4 Apr 2020 11:37:03 +0000 (13:37 +0200)
Right now WebAssembly does not have an implementation for TimeZoneInfo and instead throws exceptions.

This is an alternate implementation of https://github.com/mono/mono/pull/17617 that loads the zone information into the webassembly virtual file system using a pre-loaded file package.

__BCL Changes__
TimeZoneInfo implementation for WebAssembly to read from WASM VFS `/zoneinfo`.
- Remove `TimeZoneInfo.WebAssembly.cs` file
- Remove source dependencies on `TimeZoneInfo.WebAssembly.cs`.
- Modify TimeZoneInfo for specific WASM functionality
   - Default root directory is `zoneinfo`
   -  Add icall `mono_timezone_get_local_name` for WASM in CreateLocal
- Add icall implementation
   - ves_icall_System_TimeZoneInfo_mono_timezone_get_local_name

__WASM Runtime Build__

- Add `-s FORCE_FILESYSTEM=1` to mono wasm runtime build
   - Required so that it includes support for loading pre preload packages
   * Message when generating the zoneinfo data.
   > Remember to build the main file with  -s FORCE_FILESYSTEM=1  so that it includes support for loading this file package
- Add targets to run time zone tests.
   - make run-tzd-sample
   - make run-tzd-interp-sample
   - make run-tzd-aot-sample
- Modify `runtime-tests.js` to load and parse the zoneinfo data manually to load into the VFS.

__WASM Driver - aka `driver.c`__

- Add implementations of the following:
   - mono_timezone_get_local_name

These will be called from the managed bcl module `TimeZoneInfo.cs` module.

__packager.exe__
- Add `-s FORCE_FILESYSTEM=1`
   - Required so that it includes support for loading pre preload packages
   * Message when generating the zoneinfo data.
   > Remember to build the main file with  -s FORCE_FILESYSTEM=1  so that it includes support for

__Zone Info data and support files__

- Three files for zoneinfo VFS support.
   - `mono-webassembly-zoneinfo-fs-smd.js.metadata` - This is the separate metadata output by emscripten file-packager.  Used to parse the zoneinfo data in non browser environments.  See `runtime-tests.js`
   - `mono-webassembly-zoneinfo-fs.js` - Output by emscripten file-packager that will be referenced by browser environments to load the zoneinfo data into the VFS at `/zoneinfo`
   - `zoneinfo.data` - The binary file output by emscripten file-packager.  The file contains the actual zoneinfo data loaded into the VFS and parsed by `TimeZoneInfo`.

The packages are generated automatically and the repo is temporarily at:  https://github.com/kjpou1/mono-webassembly-zoneinfo

There are some limitations to this method where the file packages generated by the emscripten [file_packager](https://emscripten.org/docs/porting/files/packaging_files.html#packaging-using-the-file-packager-tool) only runs within a web browser.

Special consideration is needed to load the VFS with the data outside of browser.  See modification for `runtime-tests.js` where the zoneinfo data is parsed manually and loaded into the VFS.  We may need to create our own file packager to handle some of the other cases.

Co-authored-by: kjpou1 <kjpou1@users.noreply.github.com>
src/mono/mono/metadata/icall-decl.h
src/mono/mono/metadata/icall-def.h
src/mono/mono/metadata/icall.c

index 34e9e6547c89fc921a84db09b75bfe0019545edf..ee95b4009c6d5dfcd2a8ff3075caf2f60f2dc26d 100644 (file)
@@ -204,6 +204,10 @@ ICALL_EXPORT gint32 ves_icall_System_IO_Compression_DeflateStreamNative_ReadZStr
 ICALL_EXPORT gint32 ves_icall_System_IO_Compression_DeflateStreamNative_WriteZStream (gpointer stream, gpointer buffer, gint32 length);
 #endif
 
+#if defined(TARGET_WASM)
+ICALL_EXPORT void ves_icall_System_TimeZoneInfo_mono_timezone_get_local_name (MonoString result);
+#endif
+
 #if defined(ENABLE_MONODROID)
 ICALL_EXPORT gpointer ves_icall_System_Net_NetworkInformation_LinuxNetworkChange_CreateNLSocket (void);
 ICALL_EXPORT gint32 ves_icall_System_Net_NetworkInformation_LinuxNetworkChange_ReadEvents (gpointer sock, gpointer buffer, gint32 count, gint32 size);
index 05cc9bf7f15bf7bbf5a0a79de3b22d718436ffb6..5b003c65b32cc316726e3384b3a67c3edc087d01 100644 (file)
@@ -1106,6 +1106,11 @@ ICALL_TYPE(WAITH, "System.Threading.WaitHandle", WAITH_1)
 HANDLES(WAITH_1, "SignalAndWait_Internal", ves_icall_System_Threading_WaitHandle_SignalAndWait_Internal, gint32, 3, (gpointer, gpointer, gint32))
 HANDLES(WAITH_2, "Wait_internal", ves_icall_System_Threading_WaitHandle_Wait_internal, gint32, 4, (gpointer_ptr, gint32, MonoBoolean, gint32))
 
+#if defined(TARGET_WASM)
+ICALL_TYPE(TZINFO, "System.TimeZoneInfo", TZINFO_1)
+NOHANDLES(ICALL(TZINFO_1, "mono_timezone_get_local_name", ves_icall_System_TimeZoneInfo_mono_timezone_get_local_name))
+#endif
+
 ICALL_TYPE(TYPE, "System.Type", TYPE_1)
 HANDLES(TYPE_1, "internal_from_handle", ves_icall_System_Type_internal_from_handle, MonoReflectionType, 1, (MonoType_ref))
 
index 3b8bfde6e7ff84e79584ee50141014a482ebc6e2..35ab2bb34220409936e2a832faa11f1d871651b3 100644 (file)
@@ -8208,6 +8208,21 @@ ves_icall_System_IO_Compression_DeflateStreamNative_WriteZStream (gpointer strea
 }
 
 #endif
+
+#if defined(TARGET_WASM)
+G_EXTERN_C void mono_timezone_get_local_name (MonoString result);
+void
+ves_icall_System_TimeZoneInfo_mono_timezone_get_local_name (MonoString result)
+{
+       // MONO_CROSS_COMPILE returns undefined symbol "_mono_timezone_get_local_name"
+       // The icall offsets will be generated and linked at build time
+       // This is defined outside the runtime within the webassembly sdk
+#ifndef MONO_CROSS_COMPILE
+       return mono_timezone_get_local_name (result);
+#endif
+}
+#endif
+
 #endif /* ENABLE_NETCORE */
 
 #ifndef PLATFORM_NO_DRIVEINFO