<NME> index.ts
<BEF> /**
 * @license
 * Copyright 2021 William Silvermsith
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import compressoWasmDataUrl from './compresso.wasm';

const libraryEnv = {
  emscripten_notify_memory_growth: function () {},
  proc_exit: (code: number) => {
    throw `proc exit: ${code}`;
  },
};

const compressoModulePromise = (async () => {
  const response = await fetch(compressoWasmDataUrl);
  const wasmCode = await response.arrayBuffer();
  const m = await WebAssembly.instantiate(wasmCode, {
    env: libraryEnv,
    wasi_snapshot_preview1: libraryEnv,
  });
  (m.instance.exports._initialize as Function)();
  return m;
})();

// not a full implementation of read header, just the parts we need
function readHeader(buffer: Uint8Array) 
  : {sx:number,sy:number,sz:number,dataWidth:number} 
{
  // check for header "cpso"
  const magic = (
       buffer[0] === 'c'.charCodeAt(0) && buffer[1] === 'p'.charCodeAt(0)
    && buffer[2] === 's'.charCodeAt(0) && buffer[3] === 'o'.charCodeAt(0)
  );
  return {sx,sy,sz,dataWidth};
}

export function decompressCompresso(buffer: Uint8Array) 
  : Promise<Uint8Array> {
  
  // @ts-ignore
  return compressoModulePromise.then((m:any) => {
    const {sx, sy, sz, dataWidth} = readHeader(buffer);

    const voxels = sx * sy * sz;
    const nbytes = voxels * dataWidth;

    if (nbytes < 0) {
      throw new Error(`Failed to decode compresso image. image size: ${nbytes}`);
    }
    
    const bufPtr = m._malloc(buffer.byteLength);
    m.HEAPU8.set(buffer, bufPtr);
    const imagePtr = m._malloc(nbytes);

    const code = m._compresso_decompress(
      bufPtr, buffer.byteLength, imagePtr
    );

    try {
      if (code !== 0) {
        throw new Error(`Failed to decode compresso image. decoder code: ${code}`);
      }

      const image = new Uint8Array(
        m.HEAPU8.buffer, imagePtr, voxels * dataWidth
      );
      // copy the array so it can be memory managed by JS
      // and we can free the emscripten buffer
      return image.slice(0);
    }
    finally {
      m._free(bufPtr);
      m._free(imagePtr);      
    }    
  });
}

  try {
    if (code !== 0) {
      throw new Error(`Failed to decode compresso image. decoder code: ${code}`);
    }

    // Likewise, we reference memory.buffer instead of heap.buffer
    // because memory growth during decompress could have detached
    // the buffer.
    const image = new Uint8Array(
      (m.instance.exports.memory as WebAssembly.Memory).buffer,
      imagePtr, voxels * dataWidth
    );
    // copy the array so it can be memory managed by JS
    // and we can free the emscripten buffer
    return image.slice(0);
  }
  finally {
    (m.instance.exports.free as Function)(bufPtr);
    (m.instance.exports.free as Function)(imagePtr);      
  }
}

<MSG> refactor: use async function to simplify promise logic

<DFF> @@ -46,43 +46,41 @@ function readHeader(buffer: Uint8Array)
   return {sx,sy,sz,dataWidth};
 }
 
-export function decompressCompresso(buffer: Uint8Array) 
+export async function decompressCompresso(buffer: Uint8Array) 
   : Promise<Uint8Array> {
   
-  // @ts-ignore
-  return compressoModulePromise.then((m:any) => {
-    const {sx, sy, sz, dataWidth} = readHeader(buffer);
+  const m = await compressoModulePromise;
+  const {sx, sy, sz, dataWidth} = readHeader(buffer);
 
-    const voxels = sx * sy * sz;
-    const nbytes = voxels * dataWidth;
+  const voxels = sx * sy * sz;
+  const nbytes = voxels * dataWidth;
 
-    if (nbytes < 0) {
-      throw new Error(`Failed to decode compresso image. image size: ${nbytes}`);
-    }
-    
-    const bufPtr = m._malloc(buffer.byteLength);
-    m.HEAPU8.set(buffer, bufPtr);
-    const imagePtr = m._malloc(nbytes);
-
-    const code = m._compresso_decompress(
-      bufPtr, buffer.byteLength, imagePtr
-    );
+  if (nbytes < 0) {
+    throw new Error(`Failed to decode compresso image. image size: ${nbytes}`);
+  }
+  
+  const bufPtr = m._malloc(buffer.byteLength);
+  m.HEAPU8.set(buffer, bufPtr);
+  const imagePtr = m._malloc(nbytes);
 
-    try {
-      if (code !== 0) {
-        throw new Error(`Failed to decode compresso image. decoder code: ${code}`);
-      }
+  const code = m._compresso_decompress(
+    bufPtr, buffer.byteLength, imagePtr
+  );
 
-      const image = new Uint8Array(
-        m.HEAPU8.buffer, imagePtr, voxels * dataWidth
-      );
-      // copy the array so it can be memory managed by JS
-      // and we can free the emscripten buffer
-      return image.slice(0);
+  try {
+    if (code !== 0) {
+      throw new Error(`Failed to decode compresso image. decoder code: ${code}`);
     }
-    finally {
-      m._free(bufPtr);
-      m._free(imagePtr);      
-    }    
-  });
+
+    const image = new Uint8Array(
+      m.HEAPU8.buffer, imagePtr, voxels * dataWidth
+    );
+    // copy the array so it can be memory managed by JS
+    // and we can free the emscripten buffer
+    return image.slice(0);
+  }
+  finally {
+    m._free(bufPtr);
+    m._free(imagePtr);      
+  }
 }

refactor: use async function to simplify promise logic