summaryrefslogtreecommitdiff
path: root/protocols/Telegram/tdlib/td/example/web/tdweb/src/wasm-utils.js
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2022-11-30 17:48:47 +0300
committerGeorge Hazan <ghazan@miranda.im>2022-11-30 17:48:47 +0300
commit0ece30dc7c0e34b4c5911969b8fa99c33c6d023c (patch)
tree671325d3fec09b999411e4e3ab84ef8259261818 /protocols/Telegram/tdlib/td/example/web/tdweb/src/wasm-utils.js
parent46c53ffc6809c67e4607e99951a2846c382b63b2 (diff)
Telegram: update for TDLIB
Diffstat (limited to 'protocols/Telegram/tdlib/td/example/web/tdweb/src/wasm-utils.js')
-rw-r--r--protocols/Telegram/tdlib/td/example/web/tdweb/src/wasm-utils.js136
1 files changed, 136 insertions, 0 deletions
diff --git a/protocols/Telegram/tdlib/td/example/web/tdweb/src/wasm-utils.js b/protocols/Telegram/tdlib/td/example/web/tdweb/src/wasm-utils.js
new file mode 100644
index 0000000000..50447d65b3
--- /dev/null
+++ b/protocols/Telegram/tdlib/td/example/web/tdweb/src/wasm-utils.js
@@ -0,0 +1,136 @@
+// 1. +++ fetchAndInstantiate() +++ //
+
+// This library function fetches the wasm module at 'url', instantiates it with
+// the given 'importObject', and returns the instantiated object instance
+
+export async function instantiateStreaming(url, importObject) {
+ let result = await WebAssembly.instantiateStreaming(fetch(url), importObject);
+ return result.instance;
+}
+export function fetchAndInstantiate(url, importObject) {
+ return fetch(url)
+ .then(response => response.arrayBuffer())
+ .then(bytes => WebAssembly.instantiate(bytes, importObject))
+ .then(results => results.instance);
+}
+
+// 2. +++ instantiateCachedURL() +++ //
+
+// This library function fetches the wasm Module at 'url', instantiates it with
+// the given 'importObject', and returns a Promise resolving to the finished
+// wasm Instance. Additionally, the function attempts to cache the compiled wasm
+// Module in IndexedDB using 'url' as the key. The entire site's wasm cache (not
+// just the given URL) is versioned by dbVersion and any change in dbVersion on
+// any call to instantiateCachedURL() will conservatively clear out the entire
+// cache to avoid stale modules.
+export function instantiateCachedURL(dbVersion, url, importObject) {
+ const dbName = 'wasm-cache';
+ const storeName = 'wasm-cache';
+
+ // This helper function Promise-ifies the operation of opening an IndexedDB
+ // database and clearing out the cache when the version changes.
+ function openDatabase() {
+ return new Promise((resolve, reject) => {
+ var request = indexedDB.open(dbName, dbVersion);
+ request.onerror = reject.bind(null, 'Error opening wasm cache database');
+ request.onsuccess = () => {
+ resolve(request.result);
+ };
+ request.onupgradeneeded = event => {
+ var db = request.result;
+ if (db.objectStoreNames.contains(storeName)) {
+ console.log(`Clearing out version ${event.oldVersion} wasm cache`);
+ db.deleteObjectStore(storeName);
+ }
+ console.log(`Creating version ${event.newVersion} wasm cache`);
+ db.createObjectStore(storeName);
+ };
+ });
+ }
+
+ // This helper function Promise-ifies the operation of looking up 'url' in the
+ // given IDBDatabase.
+ function lookupInDatabase(db) {
+ return new Promise((resolve, reject) => {
+ var store = db.transaction([storeName]).objectStore(storeName);
+ var request = store.get(url);
+ request.onerror = reject.bind(null, `Error getting wasm module ${url}`);
+ request.onsuccess = event => {
+ if (request.result) resolve(request.result);
+ else reject(`Module ${url} was not found in wasm cache`);
+ };
+ });
+ }
+
+ // This helper function fires off an async operation to store the given wasm
+ // Module in the given IDBDatabase.
+ function storeInDatabase(db, module) {
+ var store = db.transaction([storeName], 'readwrite').objectStore(storeName);
+ var request = store.put(module, url);
+ request.onerror = err => {
+ console.log(`Failed to store in wasm cache: ${err}`);
+ };
+ request.onsuccess = err => {
+ console.log(`Successfully stored ${url} in wasm cache`);
+ };
+ }
+
+ // This helper function fetches 'url', compiles it into a Module,
+ // instantiates the Module with the given import object.
+ function fetchAndInstantiate() {
+ return fetch(url)
+ .then(response => response.arrayBuffer())
+ .then(buffer => WebAssembly.instantiate(buffer, importObject));
+ }
+
+ // With all the Promise helper functions defined, we can now express the core
+ // logic of an IndexedDB cache lookup. We start by trying to open a database.
+ return openDatabase().then(
+ db => {
+ // Now see if we already have a compiled Module with key 'url' in 'db':
+ return lookupInDatabase(db).then(
+ module => {
+ // We do! Instantiate it with the given import object.
+ console.log(`Found ${url} in wasm cache`);
+ return WebAssembly.instantiate(module, importObject);
+ },
+ errMsg => {
+ // Nope! Compile from scratch and then store the compiled Module in 'db'
+ // with key 'url' for next time.
+ console.log(errMsg);
+ return fetchAndInstantiate().then(results => {
+ try {
+ storeInDatabase(db, results.module);
+ } catch (e) {
+ console.log('Failed to store module into db');
+ }
+ return results.instance;
+ });
+ }
+ );
+ },
+ errMsg => {
+ // If opening the database failed (due to permissions or quota), fall back
+ // to simply fetching and compiling the module and don't try to store the
+ // results.
+ console.log(errMsg);
+ return fetchAndInstantiate().then(results => results.instance);
+ }
+ );
+}
+
+export async function instantiateAny(version, url, importObject) {
+ console.log("instantiate");
+ try {
+ return await instantiateStreaming(url, importObject);
+ } catch (e) {
+ console.log("instantiateStreaming failed", e);
+ }
+ try {
+ return await instantiateCachedURL(version, url, importObject);
+ } catch (e) {
+ console.log("instantiateCachedURL failed", e);
+ }
+ throw new Error("can't instantiate wasm");
+}
+