Repository: mozilla/pdf.js
File: src/core/jpx.js (JavaScript)

Code before:
    } finally {
      this.#handler = null;
      this.#wasmUrl = null;
    }
  }

  static async decode(
    bytes,
    { numComponents = 4, isIndexedColormap = false, smaskInData = false } = {}
  ) {
    if (this.#instantiationFailed) {
      throw new JpxError("OpenJPEG failed to instantiate.");
    }

    let module, ptr;
    try {
      this.#modulePromise ||= OpenJPEG({
        warn,
        instantiateWasm: this.#instantiateWasm.bind(this),
      });

      module = await this.#modulePromise;
    } catch (e) {
      this.#instantiationFailed = true;
      throw e;
    }

    try {
      const size = bytes.length;
      ptr = module._malloc(size);
      module.HEAPU8.set(bytes, ptr);
      const ret = module._jp2_decode(
        ptr,
        size,
        numComponents > 0 ? numComponents : 0,
        !!isIndexedColormap,
        !!smaskInData
      );
      if (ret) {
        const { errorMessages } = module;
        if (errorMessages) {
          delete module.errorMessages;
          throw new JpxError(errorMessages);
        }
        throw new JpxError("Unknown error");
      }
      const { imageData } = module;
      module.imageData = null;

      return imageData;
    } finally {

Review comment (bug):
*Possibly a dumb question, but:* Do we still need `this.#instantiationFailed`, since it seems that `this.#modulePromise` will now correctly contain a *rejected* promise on failure which could help to simplify the code?

```diff
diff --git a/src/core/jpx.js b/src/core/jpx.js
index 0e654935e..38215d86b 100644
--- a/src/core/jpx.js
+++ b/src/core/jpx.js
@@ -29,8 +29,6 @@ class JpxImage {

   static #handler = null;

-  static #instantiationFailed = false;
-
   static #modulePromise = null;

   static #wasmUrl = null;
@@ -68,22 +66,13 @@ class JpxImage {
     bytes,
     { numComponents = 4, isIndexedColormap = false, smaskInData = false } = {}
   ) {
-    if (this.#instantiationFailed) {
-      throw new JpxError("OpenJPEG failed to instantiate.");
-    }
+    this.#modulePromise ||= OpenJPEG({
+      warn,
+      instantiateWasm: this.#instantiateWasm.bind(this),
+    });

-    let module, ptr;
-    try {
-      this.#modulePromise ||= OpenJPEG({
-        warn,
-        instantiateWasm: this.#instantiateWasm.bind(this),
-      });
-
-      module = await this.#modulePromise;
-    } catch (e) {
-      this.#instantiationFailed = true;
-      throw e;
-    }
+    const module = await this.#modulePromise;
+    let ptr;

     try {
       const size = bytes.length;
```




Code after:
      this.#wasmUrl = null;
    }
  }

  static async decode(
    bytes,
    { numComponents = 4, isIndexedColormap = false, smaskInData = false } = {}
  ) {
    this.#modulePromise ||= OpenJPEG({
      warn,
      instantiateWasm: this.#instantiateWasm.bind(this),
    });

    const module = await this.#modulePromise;
    let ptr;

    try {
      const size = bytes.length;
      ptr = module._malloc(size);
      module.HEAPU8.set(bytes, ptr);
      const ret = module._jp2_decode(
        ptr,
        size,
        numComponents > 0 ? numComponents : 0,
        !!isIndexedColormap,
        !!smaskInData
      );
      if (ret) {
        const { errorMessages } = module;
        if (errorMessages) {
          delete module.errorMessages;
          throw new JpxError(errorMessages);
        }
        throw new JpxError("Unknown error");
      }
      const { imageData } = module;
      module.imageData = null;

      return imageData;
    } finally {
      if (ptr) {
        module._free(ptr);
      }
    }
  }

  static cleanup() {
    this.#modulePromise = null;
  }

  static parseImageProperties(stream) {