From efc336e60cf1331bf5f3213d296981b87b8b2a6c Mon Sep 17 00:00:00 2001 From: George Hazan Date: Sun, 4 Jun 2023 19:24:05 +0300 Subject: =?UTF-8?q?fixes=20#3537=20(Telegram:=2032-=D1=80=D0=B0=D0=B7?= =?UTF-8?q?=D1=80=D1=8F=D0=B4=D0=BD=D0=B0=D1=8F=20=D0=B2=D0=B5=D1=80=D1=81?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=BF=D0=B0=D0=B4=D0=B0=D0=B5=D1=82=20=D0=B2=20?= =?UTF-8?q?64-=D1=80=D0=B0=D0=B7=D1=80=D1=8F=D0=B4=D0=BD=D0=BE=D0=B9=20Win?= =?UTF-8?q?dows)=20+=20update=20to=20the=20fresh=20TDLIB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tdlib/td/example/web/tdweb/src/wasm-utils.js | 136 +++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 protocols/Telegram/tdlib/td/example/web/tdweb/src/wasm-utils.js (limited to 'protocols/Telegram/tdlib/td/example/web/tdweb/src/wasm-utils.js') 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"); +} + -- cgit v1.2.3