From 785a9f9a1f9842f8e4c45d83acac935c8707ed80 Mon Sep 17 00:00:00 2001
From: Balearica <admin@scribeocr.com>
Date: Fri, 23 Jun 2023 16:50:50 -0700
Subject: [PATCH 01/16] Fixed so 'debug' output does not force recognition per
 #788 (#789)

---
 src/worker-script/index.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/worker-script/index.js b/src/worker-script/index.js
index 9a2bc924..ae0dae00 100644
--- a/src/worker-script/index.js
+++ b/src/worker-script/index.js
@@ -266,7 +266,7 @@ const processOutput = (output) => {
   if (params.tessjs_create_tsv === '1') workingOutput.tsv = true;
   if (params.tessjs_create_unlv === '1') workingOutput.unlv = true;
 
-  const nonRecOutputs = ['imageColor', 'imageGrey', 'imageBinary', 'layoutBlocks'];
+  const nonRecOutputs = ['imageColor', 'imageGrey', 'imageBinary', 'layoutBlocks', 'debug'];
   let recOutputCount = 0;
   for (const prop of Object.keys(output)) {
     workingOutput[prop] = output[prop];

From 296afbcba624df26805b669b104780f7883ab4cf Mon Sep 17 00:00:00 2001
From: Simple7575 <76493343+Simple7575@users.noreply.github.com>
Date: Thu, 29 Jun 2023 21:27:45 +0400
Subject: [PATCH 02/16] Update api.md (#791)

Mistake in docs fixed Worker.readFile() -> Worker.removeFile()
---
 docs/api.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/api.md b/docs/api.md
index 08c8bcfd..379ef089 100644
--- a/docs/api.md
+++ b/docs/api.md
@@ -122,7 +122,7 @@ Worker.readText() reads a text file to the path specified in MEMFS, it is useful
 <a name="worker-removeFile"></a>
 ### Worker.removeFile(path, jobId): Promise
 
-Worker.readFile() remove a file in MEMFS, it is useful when you want to free the memory.
+Worker.removeFile() remove a file in MEMFS, it is useful when you want to free the memory.
 
 **Arguments:**
 

From 50afb32e4ba723e2ed7a89d91814cd7fa3e68027 Mon Sep 17 00:00:00 2001
From: Balearica <admin@scribeocr.com>
Date: Thu, 29 Jun 2023 13:14:21 -0700
Subject: [PATCH 03/16] Update local-installation.md

---
 docs/local-installation.md | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/docs/local-installation.md b/docs/local-installation.md
index bd034877..c2708ee9 100644
--- a/docs/local-installation.md
+++ b/docs/local-installation.md
@@ -33,8 +33,8 @@ A string specifying the location of the `worker.js` file.
 A string specifying the location of the tesseract language files, with default value 'https://tessdata.projectnaptha.com/4.0.0'. Language file URLs are calculated according to the formula `langPath + langCode + '.traineddata.gz'`.
 
 ### corePath
-A string specifying the location of the [tesseract.js-core library](https://github.com/naptha/tesseract.js-core), with default value 'https://cdn.jsdelivr.net/npm/tesseract.js-core@v4.0.3'.
+A string specifying the location of the [tesseract.js-core](https://github.com/naptha/tesseract.js-core) files, with default value 'https://cdn.jsdelivr.net/npm/tesseract.js-core@v4.0.3'.
 
-When `corePath` is a directory rather than specific `.js` file (e.g. `https://cdn.jsdelivr.net/npm/tesseract.js-core@v4.0.3`), Tesseract.js loads either `tesseract-core-simd.wasm.js` or `tesseract-core.wasm.js` depending on whether the users' device supports SIMD (see [https://webassembly.org/roadmap/](https://webassembly.org/roadmap/)).  Therefore, if self-hosting it is important that both these files are in the location you specify for `corePath`.  Having multiple files is necessary as the SIMD-enabled version is *significantly* faster (for the LSTM model [the default]), however is not yet supported on all devices. 
+`corePath` should be set to a directory containing both `tesseract-core-simd.wasm.js` and `tesseract-core.wasm.js`.  Tesseract.js will load either `tesseract-core-simd.wasm.js` or `tesseract-core.wasm.js` from the directory depending on whether the users' device supports SIMD (see [https://webassembly.org/roadmap/](https://webassembly.org/roadmap/)).
 
-When `corePath` is set to a specific `.js` file (e.g. `https://cdn.jsdelivr.net/npm/tesseract.js-core@v4.0.3/tesseract-core.wasm.js`), it will load that file regardless of whether the users' device supports SIMD or not.  This behavior exists to preserve backwards compatibility--specifying a directory that contains both files is strongly recommended.  Specifying a single file will either result in much slower performance (if `tesseract-core.wasm.js` is specified) or failure to run on certain devices (if `tesseract-core-simd.wasm.js` is specified). 
+To avoid breaking old code, when `corePath` is set to a specific `.js` file (e.g. `https://cdn.jsdelivr.net/npm/tesseract.js-core@v4.0.3/tesseract-core.wasm.js`), it will load that file regardless of whether the users' device supports SIMD or not.  This behavior only exists to preserve backwards compatibility—setting `corePath` to a specific `.js` file is strongly discouraged.  Doing so will either result in much slower performance (if `tesseract-core.wasm.js` is specified) or failure to run on certain devices (if `tesseract-core-simd.wasm.js` is specified).

From 67b982eff16a59b579cc4914c787556ac2b00040 Mon Sep 17 00:00:00 2001
From: Balearica <admin@scribeocr.com>
Date: Tue, 25 Jul 2023 20:52:31 -0700
Subject: [PATCH 04/16] Create performance.md

---
 docs/performance.md | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)
 create mode 100644 docs/performance.md

diff --git a/docs/performance.md b/docs/performance.md
new file mode 100644
index 00000000..1f95e0b8
--- /dev/null
+++ b/docs/performance.md
@@ -0,0 +1,39 @@
+# Overview
+This guide contains tips and strategies for getting the fastest performance from Tesseract.js.  While some of the tips below involve avoiding pitfalls and should be universally implemented, other strategies (changing the language data or recognition model) may harm recognition quality.  Therefore, whether these strategies are appropriate depends on the application, and users should always benchmark performance and quality before changing important settings from their defaults. 
+
+# Reducing Setup Time
+Within certain applications, the majority of runtime may be attributable to setup steps (`createWorker`, `worker.initialize`, and `worker.loadLanguage`) rather than recognition (`worker.recognize`).  Implementing the strategies in this section should reduce the time spent on these steps. 
+
+Notably, the time spent on setup for first-time users may not be apparent to developers, as Tesseract.js caches language data after it is downloaded for the first time. To experience Tesseract.js as a first-time user, set `cacheMethod: 'none'` in the [createWorker options](./api.md#createworkeroptions-worker).  Be sure to remove this setting before publishing your app.
+### Reuse Workers
+When recognizing multiple images, some users will create/load/destroy a new worker for each image.  This is never the correct option.  If the images are being recognized one after the other, all of the extra `createWorker`/`worker.initialize`/`worker.loadLanguage` steps are wasted runtime, as `worker.recognize` could be run with the same `worker`.  Workers do not break after one use. 
+
+Alternatively, if images are being recognized in parallel, then creating a new worker for each recognition job is likely to cause crashes due to resource limitations.  As each Tesseract.js worker uses a high amount of memory, code should never be able to create an arbitrary number of `workers`.  Instead, schedulers should be used to create a specific pool for workers (say, 4 workers), and then jobs assigned through the scheduler.
+### Set Up Workers Ahead of Time
+Rather than waiting until the last minute to load code and data, you can set up a worker ahead of time.  Doing so greatly reduces runtime the first time a user run recognition.  This requires managing workers rather than using `Tesseract.recognize`, which is explained [here](./intro.md).  An example where a worker is prepared ahead of time can be found [here](../examples/browser/basic-efficient.html).
+
+The appropriate time to load Tesseract.js workers and data is application-specific.  For example, if you have an web app where only 5% of users need OCR, it likely does not make sense to download ~15MB in code and data upon a page load.  You could consider instead loading Tesseract.js when a user indicates they want to perform OCR, but before they select a specific image.
+
+### Do Not Disable Language Data Caching
+Language data is, by far, the largest download required to run Tesseract.js.  The default `eng.traineddata` file is 10.4MB compressed.  The default `chi_sim.traineddata` file is 19.2MB compressed.
+
+To avoid downloading language data multiple times, Tesseract.js caches `.traineddata` files.  In past versions of Tesseract.js, this caching behavior contained bugs, so some users disabled it (setting `cacheMethod: 'none'` or `cacheMethod: 'refresh'`).  As these bugs were fixed in [v4.0.6](https://github.com/naptha/tesseract.js/releases/tag/v4.0.6), it is now recommended that users use the default `cacheMethod` value (i.e. just ignore the `cacheMethod` argument). 
+
+### Consider Using Smaller Language Data 
+The default language data used by Tesseract.js includes data for both Tesseract engines (LSTM [the default model] and Legacy), and is optimized for quality rather than speed.  Both the inclusion of multiple models and the focus on quality increase the size of the language data.  Setting a non-default `langData` path may result in significantly smaller files being downloaded.  
+
+For example, by changing `langPath` from the default (`https://tessdata.projectnaptha.com/4.0.0`) to `https://tessdata.projectnaptha.com/4.0.0_fast` the size of the compressed English language data is reduced from 10.9MB to 2.0MB.  Note that this language data (1) only supports the default LSTM model and (2) is optimized for size/speed rather than quality, so users should switch only after testing whether this data works for their application. 
+
+# Reducing Recognition Runtime
+
+### Use the Latest Version of Tesseract.js
+Old versions of Tesseract.js are significantly slower.  Notably, v2 (now depreciated) takes 10x longer to recognize certain images compared to the latest version.
+
+### Consider Using the Legacy Model
+In general, the LSTM (default) recognition model provides the best quality.  However, the Legacy model generally runs faster, and depending on your application, may provide sufficient recognition quality.  If runtime is a significant concern, consider experimenting with the Legacy model (by setting `oem` to `”0”` within `worker.initialize`).  As a rule of thumb, the Legacy model is usually viable when the input data is high-quality (high-definition screenshots, document scans, etc.).  
+
+### Consider Using "Fast" Language Data
+By default, Tesseract.js uses language data that is optimized for quality rather than speed.  You can also experiment with using language data that is optimized for speed by setting `langPath` to `https://tessdata.projectnaptha.com/4.0.0_fast`.
+
+### Do Not Set `corePath` to a Single `.js` file
+If you set the `corePath` argument, be sure to set it to a directory that contains both `tesseract-core.wasm.js` or `tesseract-core-simd.wasm.js`.  Tesseract.js needs to be able to pick between both files—setting `corePath` to a specific `.js` file will significantly degrade performance or compatibility.  See [this comment](https://github.com/naptha/tesseract.js/issues/735#issuecomment-1519157646) for explanation.

From 6f90bc9cd9851102f5f6ac736dc7906147f0e0d3 Mon Sep 17 00:00:00 2001
From: Balearica <admin@scribeocr.com>
Date: Tue, 25 Jul 2023 21:11:40 -0700
Subject: [PATCH 05/16] Updated scheduler examples per #801 (#803)

---
 examples/browser/basic-efficient.html | 11 +++---
 examples/browser/basic-scheduler.html | 49 +++++++++++++++++++++++++++
 examples/node/scheduler.js            |  5 ++-
 3 files changed, 57 insertions(+), 8 deletions(-)
 create mode 100644 examples/browser/basic-scheduler.html

diff --git a/examples/browser/basic-efficient.html b/examples/browser/basic-efficient.html
index 88a11735..4d278f31 100644
--- a/examples/browser/basic-efficient.html
+++ b/examples/browser/basic-efficient.html
@@ -4,7 +4,7 @@
     <script src="/dist/tesseract.dev.js"></script>
   </head>
   <body>
-    <input type="file" id="uploader">
+    <input type="file" id="uploader" multiple>
     <script type="module">
 
       // This is a basic example more efficient than "basic.html".
@@ -22,10 +22,11 @@
 
       const recognize = async function(evt){
         const files = evt.target.files;
-
-        const ret = await worker.recognize(files[0]);
-        console.log(ret.data.text);
-
+        
+        for (let i=0; i<files.length; i++) {
+          const ret = await worker.recognize(files[i]);
+          console.log(ret.data.text);
+        }
       }
       const elm = document.getElementById('uploader');
       elm.addEventListener('change', recognize);
diff --git a/examples/browser/basic-scheduler.html b/examples/browser/basic-scheduler.html
new file mode 100644
index 00000000..35b7e78f
--- /dev/null
+++ b/examples/browser/basic-scheduler.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML>
+<html>
+  <head>
+    <script src="/dist/tesseract.dev.js"></script>
+  </head>
+  <body>
+    <input type="file" id="uploader" multiple>
+    <script type="module">
+
+      // This example builds on "basic-efficient.html".
+      // Rather than using a single worker, a scheduler manages a pool of multiple workers. 
+      // While performance is similar for a single file, this parallel processing results in significantly
+      // faster speeds when used with multiple files.
+
+      const scheduler = Tesseract.createScheduler();
+
+      // Creates worker and adds to scheduler
+      const workerGen = async () => {
+        const worker = await Tesseract.createWorker({
+          corePath: '../../node_modules/tesseract.js-core',
+          workerPath: "/dist/worker.dev.js",
+          logger: function(m){console.log(m);}
+        });
+        await worker.loadLanguage('eng');
+        await worker.initialize('eng');
+        scheduler.addWorker(worker);
+      }
+
+      const workerN = 4;
+      (async () => {
+        const resArr = Array(workerN);
+        for (let i=0; i<workerN; i++) {
+          resArr[i] = await workerGen();
+        }
+      })();
+
+      const recognize = async function(evt){
+        const files = evt.target.files;
+
+        for (let i=0; i<files.length; i++) {
+          scheduler.addJob('recognize', files[i]).then((x) => console.log(x.data.text))
+        }
+      }
+
+      const elm = document.getElementById('uploader');
+      elm.addEventListener('change', recognize);
+    </script>
+  </body>
+</html>
diff --git a/examples/node/scheduler.js b/examples/node/scheduler.js
index 0087158a..43afb87c 100755
--- a/examples/node/scheduler.js
+++ b/examples/node/scheduler.js
@@ -4,8 +4,7 @@ const scheduler = createScheduler();
 
 // Creates worker and adds to scheduler
 const workerGen = async () => {
-  const worker = createWorker({cachePath: "."});
-  await worker.load();
+  const worker = await createWorker({cachePath: "."});
   await worker.loadLanguage('eng');
   await worker.initialize('eng');
   scheduler.addWorker(worker);
@@ -15,7 +14,7 @@ const workerN = 4;
 (async () => {
   const resArr = Array(workerN);
   for (let i=0; i<workerN; i++) {
-    resArr[i] = workerGen();
+    resArr[i] = await workerGen();
   }
   await Promise.all(resArr);
   /** Add 4 recognition jobs */

From 861e28833d8c2e6bb3332ef2d616e1ab61583521 Mon Sep 17 00:00:00 2001
From: Jake W <delight.wjk@gmail.com>
Date: Fri, 4 Aug 2023 04:06:01 +0800
Subject: [PATCH 06/16] Update api.md (#805)

Fixed typo
---
 docs/api.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/api.md b/docs/api.md
index 379ef089..5a5579a7 100644
--- a/docs/api.md
+++ b/docs/api.md
@@ -63,7 +63,7 @@ const worker = await createWorker({
 A Worker helps you to do the OCR related tasks, it takes few steps to setup Worker before it is fully functional. The full flow is:
 
 - FS functions // optional
-- loadLanguauge
+- loadLanguage
 - initialize
 - setParameters // optional
 - recognize or detect

From 4a63a8e28cebf740baeb4d44c9a72d27f3fc71dc Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 3 Aug 2023 13:06:50 -0700
Subject: [PATCH 07/16] Bump word-wrap from 1.2.3 to 1.2.4 (#798)

Bumps [word-wrap](https://github.com/jonschlinkert/word-wrap) from 1.2.3 to 1.2.4.
- [Release notes](https://github.com/jonschlinkert/word-wrap/releases)
- [Commits](https://github.com/jonschlinkert/word-wrap/compare/1.2.3...1.2.4)

---
updated-dependencies:
- dependency-name: word-wrap
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 package-lock.json | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index a29adcfa..f0331d63 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9472,9 +9472,9 @@
       "dev": true
     },
     "node_modules/word-wrap": {
-      "version": "1.2.3",
-      "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
-      "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+      "version": "1.2.4",
+      "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz",
+      "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==",
       "dev": true,
       "engines": {
         "node": ">=0.10.0"
@@ -16633,9 +16633,9 @@
       "dev": true
     },
     "word-wrap": {
-      "version": "1.2.3",
-      "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
-      "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+      "version": "1.2.4",
+      "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz",
+      "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==",
       "dev": true
     },
     "workerpool": {

From 96b9b8b5002802b47a7a580a8cb66b26968e8045 Mon Sep 17 00:00:00 2001
From: Balearica <admin@scribeocr.com>
Date: Wed, 23 Aug 2023 18:27:52 -0700
Subject: [PATCH 08/16] Removed non-existent option from types per #808 (#810)

---
 src/index.d.ts | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/index.d.ts b/src/index.d.ts
index 43025f29..58598e8d 100644
--- a/src/index.d.ts
+++ b/src/index.d.ts
@@ -65,7 +65,6 @@ declare namespace Tesseract {
     errorHandler: (arg: any) => void
   }
   interface WorkerParams {
-    tessedit_ocr_engine_mode: OEM
     tessedit_pageseg_mode: PSM
     tessedit_char_whitelist: string
     preserve_interword_spaces: string

From 3c20cb448da24a92c08307b9e6639c1c0b56e33f Mon Sep 17 00:00:00 2001
From: Balearica <admin@scribeocr.com>
Date: Wed, 23 Aug 2023 22:41:07 -0700
Subject: [PATCH 09/16] Update faq.md

---
 docs/faq.md | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/docs/faq.md b/docs/faq.md
index 5f448247..901cfdbb 100644
--- a/docs/faq.md
+++ b/docs/faq.md
@@ -7,6 +7,15 @@ Tesseract.js is the JavaScript/Webassembly port of the Tesseract OCR engine.  We
 
 If you encounter a Tesseract bug you would like to see fixed you should confirm the behavior is the same in the [main (CLI) version](https://github.com/tesseract-ocr/tesseract) of Tesseract and then open a Git Issue in that repository.    
 
+# Recognizing Text
+## Are PDF files supported? 
+Tesseract.js does not support .pdf directly—a separate library must be used to convert the .pdf files to images before Tesseract can recognize them.  If you are an end user and want to use Tesseract.js to OCR a .pdf file, consider using [scribeocr.com](https://scribeocr.com/), a project that uses Tesseract.js and supports .pdf files.  If you are a developer who wants to use Tesseract.js with .pdf files, you can use either of the libraries below to convert from .pdf to images. 
+1. [PDF.js](https://github.com/mozilla/pdf.js/) (Apache-2.0 license)
+2. [muPDF](https://github.com/ArtifexSoftware/mupdf) (AGPL-3.0 license)
+
+## What configuration settings should I use? 
+Default settings should provide optimal results for most users.  If you do want to experiment with configuration settings, Tesseract does include many settings to change—the vast majority are documented in the [main Tesseract project](https://github.com/tesseract-ocr/tesseract) and not here.  As noted above (“what is the scope of this project”), the core recognition engine is inherited from the main Tesseract project—all of the configuration settings in Tesseract work identically in Tesseract.js.  Therefore, for specific questions about configuring recognition settings (e.g. “how can I make noise removal more/less aggressive” or “what settings work best for license plates”) you are more likely to find an answer in the Tesseract documentation/discussion versus only looking in this repo.  
+
 # Trained Data
 ## How does tesseract.js download and keep \*.traineddata?
 

From 8fce83963657a9546c3c3afba74d0bec2225b3fd Mon Sep 17 00:00:00 2001
From: Omar Boulbaze <yokariig@gmail.com>
Date: Fri, 25 Aug 2023 17:41:39 -0400
Subject: [PATCH 10/16] Update api.md (#575)

---
 docs/api.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/api.md b/docs/api.md
index 5a5579a7..2129a4c8 100644
--- a/docs/api.md
+++ b/docs/api.md
@@ -154,7 +154,7 @@ Worker.FS() is a generic FS function to do anything you want, you can check [HER
 (async () => {
   await worker.FS('writeFile', ['tmp.txt', 'Hi\nTesseract.js\n']);
   // equal to:
-  // await worker.readText('tmp.txt', 'Hi\nTesseract.js\n');
+  // await worker.writeText('tmp.txt', 'Hi\nTesseract.js\n');
 })();
 ```
 

From 2c2e014ea9e2eb05f2e7b68e8c975fee082fbb1e Mon Sep 17 00:00:00 2001
From: Balearica <admin@scribeocr.com>
Date: Sun, 27 Aug 2023 11:46:39 -0700
Subject: [PATCH 11/16] Edited logging to fix memory bug per #812 (#814)

---
 src/worker-script/index.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/worker-script/index.js b/src/worker-script/index.js
index ae0dae00..35412424 100644
--- a/src/worker-script/index.js
+++ b/src/worker-script/index.js
@@ -58,7 +58,7 @@ const load = async ({ workerId, jobId, payload: { options: { corePath, logging }
 };
 
 const FS = async ({ workerId, payload: { method, args } }, res) => {
-  log(`[${workerId}]: FS.${method} with args ${args}`);
+  log(`[${workerId}]: FS.${method}`);
   res.resolve(TessModule.FS[method](...args));
 };
 

From 79cacaab956adee07ef38fa376a3800770190c06 Mon Sep 17 00:00:00 2001
From: Balearica <admin@scribeocr.com>
Date: Sun, 27 Aug 2023 18:31:35 -0700
Subject: [PATCH 12/16] Minor edits to reduce memory use (#815)

---
 src/worker-script/index.js | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/src/worker-script/index.js b/src/worker-script/index.js
index 35412424..c251cb39 100644
--- a/src/worker-script/index.js
+++ b/src/worker-script/index.js
@@ -120,7 +120,7 @@ res) => {
           if (!resp.ok) {
             throw Error(`Network error while fetching ${fetchUrl}. Response code: ${resp.status}`);
           }
-          data = await resp.arrayBuffer();
+          data = new Uint8Array(await resp.arrayBuffer());
 
         // langPath is a local file, read .traineddata from local filesystem
         // (adapter.readCache is a generic file read function in Node.js version)
@@ -132,8 +132,6 @@ res) => {
       }
     }
 
-    data = new Uint8Array(data);
-
     // Check for gzip magic numbers (1F and 8B in hex)
     const isGzip = (data[0] === 31 && data[1] === 139) || (data[1] === 31 && data[0] === 139);
 
@@ -160,8 +158,7 @@ res) => {
         log(err.toString());
       }
     }
-
-    return Promise.resolve(data);
+    return Promise.resolve();
   };
 
   res.progress({ workerId, status: 'loading language traineddata', progress: 0 });
@@ -445,8 +442,14 @@ const terminate = async (_, res) => {
  */
 exports.dispatchHandlers = (packet, send) => {
   const res = (status, data) => {
+    // Return only the necessary info to avoid sending unnecessarily large messages
+    const packetRes = {
+      jobId: packet.jobId,
+      workerId: packet.workerId,
+      action: packet.action,
+    };
     send({
-      ...packet,
+      ...packetRes,
       status,
       data,
     });

From bb973ea2b8175c69e7ab4df587244f970dcbbb8a Mon Sep 17 00:00:00 2001
From: Balearica <admin@scribeocr.com>
Date: Sun, 27 Aug 2023 20:45:32 -0700
Subject: [PATCH 13/16] Added warning message when trying to set init-only
 params per #808 (#816)

---
 src/worker-script/index.js | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/src/worker-script/index.js b/src/worker-script/index.js
index c251cb39..d5c3c672 100644
--- a/src/worker-script/index.js
+++ b/src/worker-script/index.js
@@ -172,6 +172,22 @@ res) => {
 };
 
 const setParameters = async ({ payload: { params: _params } }, res) => {
+  // A small number of parameters can only be set at initialization.
+  // These can only be set using (1) the `oem` argument of `initialize` (for setting the oem)
+  // or (2) the `config` argument of `initialize` (for all other settings).
+  // Attempting to set these using this function will have no impact so a warning is printed.
+  // This list is generated by searching the Tesseract codebase for parameters
+  // defined with `[type]_INIT_MEMBER` rather than `[type]_MEMBER`.
+  const initParamNames = ['ambigs_debug_level', 'user_words_suffix', 'user_patterns_suffix', 'user_patterns_suffix',
+    'load_system_dawg', 'load_freq_dawg', 'load_unambig_dawg', 'load_punc_dawg', 'load_number_dawg', 'load_bigram_dawg',
+    'tessedit_ocr_engine_mode', 'tessedit_init_config_only', 'language_model_ngram_on', 'language_model_use_sigmoidal_certainty'];
+
+  const initParamStr = Object.keys(_params)
+    .filter((k) => initParamNames.includes(k))
+    .join(', ');
+
+  if (initParamStr.length > 0) console.log(`Attempted to set parameters that can only be set during initialization: ${initParamStr}`);
+
   Object.keys(_params)
     .filter((k) => !k.startsWith('tessjs_'))
     .forEach((key) => {

From d0df3d126cc80885c2f6c18e7c6053de2977b657 Mon Sep 17 00:00:00 2001
From: Balearica <admin@scribeocr.com>
Date: Sun, 27 Aug 2023 20:58:29 -0700
Subject: [PATCH 14/16] Edited browser benchmark to report memory use per #813
 (#817)

---
 benchmarks/browser/speed-benchmark.html | 19 ++++++++++++++++++-
 scripts/server.js                       | 10 +++++++++-
 2 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/benchmarks/browser/speed-benchmark.html b/benchmarks/browser/speed-benchmark.html
index b34c7445..93b62fe7 100644
--- a/benchmarks/browser/speed-benchmark.html
+++ b/benchmarks/browser/speed-benchmark.html
@@ -16,7 +16,18 @@
         const worker = await createWorker();
         await worker.loadLanguage('eng');
         await worker.initialize('eng');
-        
+
+        // The performance.measureUserAgentSpecificMemory function only runs under specific circumstances for security reasons.
+        // See: https://developer.mozilla.org/en-US/docs/Web/API/Performance/measureUserAgentSpecificMemory#security_requirements
+        // Launching a server using `npm start` and accessing via localhost on the same system should meet these conditions.
+        const debugMemory = true;
+        if (debugMemory && crossOriginIsolated) {
+          console.log("Memory utilization after initialization:");
+          console.log(await performance.measureUserAgentSpecificMemory());
+        } else {
+          console.log("Unable to run `performance.measureUserAgentSpecificMemory`: not crossOriginIsolated.")
+        }
+
         const fileArr = ["../data/meditations.jpg", "../data/tyger.jpg", "../data/testocr.png"];
         let timeTotal = 0;
         for (let file of fileArr) {
@@ -29,6 +40,12 @@
             timeTotal += timeDif;
             document.getElementById('message').innerHTML += "\n" + file + " [x10] runtime: " + timeDif + "s";
         }
+
+        if (debugMemory && crossOriginIsolated) {
+          console.log("Memory utilization after recognition:");
+          console.log(await performance.measureUserAgentSpecificMemory());
+        }
+
         document.getElementById('message').innerHTML += "\nTotal runtime: " + timeTotal + "s";
 
       })();
diff --git a/scripts/server.js b/scripts/server.js
index 95e2d549..8e857f5f 100644
--- a/scripts/server.js
+++ b/scripts/server.js
@@ -9,9 +9,17 @@ const compiler = webpack(webpackConfig);
 const app = express();
 
 app.use(cors());
-app.use('/', express.static(path.resolve(__dirname, '..')));
 app.use(middleware(compiler, { publicPath: '/dist', writeToDisk: true }));
 
+// These headers are required to measure memory within the benchmark code.
+// If they are problematic within other contexts they can be removed.
+app.use(express.static(path.resolve(__dirname, '..'), {
+  setHeaders: (res) => {
+    res.set('Cross-Origin-Opener-Policy', 'same-origin');
+    res.set('Cross-Origin-Embedder-Policy', 'require-corp');
+  }
+}));
+
 module.exports = app.listen(3000, () => {
   console.log('Server is running on the port no. 3000');
 });

From 58e59d16b0f1717df7558ed59cd4f5c894c51dd4 Mon Sep 17 00:00:00 2001
From: Balearica <admin@scribeocr.com>
Date: Sun, 27 Aug 2023 21:16:56 -0700
Subject: [PATCH 15/16] Edited benchmark to use local version of worker code

---
 benchmarks/browser/speed-benchmark.html | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/benchmarks/browser/speed-benchmark.html b/benchmarks/browser/speed-benchmark.html
index 93b62fe7..e2e51fe3 100644
--- a/benchmarks/browser/speed-benchmark.html
+++ b/benchmarks/browser/speed-benchmark.html
@@ -13,7 +13,10 @@
       const { createWorker } = Tesseract;
       
       (async () => {
-        const worker = await createWorker();
+        const worker = await createWorker({
+          // corePath: '/tesseract-core-simd.wasm.js',
+          workerPath: "/dist/worker.dev.js"
+        });
         await worker.loadLanguage('eng');
         await worker.initialize('eng');
 

From 71b227f2e0246d3caa0b424281a2966847bb816f Mon Sep 17 00:00:00 2001
From: Balearica <admin@scribeocr.com>
Date: Sun, 27 Aug 2023 21:23:18 -0700
Subject: [PATCH 16/16] 4.1.2

---
 package-lock.json | 4 ++--
 package.json      | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index f0331d63..0b7507e1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "tesseract.js",
-  "version": "4.1.1",
+  "version": "4.1.2",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
       "name": "tesseract.js",
-      "version": "4.1.1",
+      "version": "4.1.2",
       "hasInstallScript": true,
       "license": "Apache-2.0",
       "dependencies": {
diff --git a/package.json b/package.json
index f15fb84f..c6358d04 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "tesseract.js",
-  "version": "4.1.1",
+  "version": "4.1.2",
   "description": "Pure Javascript Multilingual OCR",
   "main": "src/index.js",
   "types": "src/index.d.ts",
