diff options
author | George Hazan <ghazan@miranda.im> | 2022-11-30 17:48:47 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2022-11-30 17:48:47 +0300 |
commit | 0ece30dc7c0e34b4c5911969b8fa99c33c6d023c (patch) | |
tree | 671325d3fec09b999411e4e3ab84ef8259261818 /protocols/Telegram/tdlib/td/example/web/tdweb/src/wasm-utils.js | |
parent | 46c53ffc6809c67e4607e99951a2846c382b63b2 (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.js | 136 |
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"); +} + |