From 6a406db60a2c4d795b0cfcea0910bfab79af7281 Mon Sep 17 00:00:00 2001
From: Johannes Loher <johannes.loher@fg4f.de>
Date: Sun, 12 Sep 2021 17:48:14 +0200
Subject: [PATCH] fix issues

---
 .vscode/extensions.json                      |  14 +-
 .vscode/settings.json                        |  16 +-
 .yarn/sdks/eslint/bin/eslint.js              |   2 +-
 .yarn/sdks/eslint/lib/api.js                 |   2 +-
 .yarn/sdks/eslint/package.json               |   8 +-
 .yarn/sdks/integrations.yml                  |   4 +-
 .yarn/sdks/prettier/index.js                 |  14 +-
 .yarn/sdks/prettier/package.json             |   8 +-
 .yarn/sdks/typescript/bin/tsc                |   2 +-
 .yarn/sdks/typescript/bin/tsserver           |   2 +-
 .yarn/sdks/typescript/lib/tsc.js             |   2 +-
 .yarn/sdks/typescript/lib/tsserver.js        |  84 +++++++---
 .yarn/sdks/typescript/lib/tsserverlibrary.js | 157 +++++++++++++++++++
 .yarn/sdks/typescript/lib/typescript.js      |   2 +-
 .yarn/sdks/typescript/package.json           |   8 +-
 src/module/fonts.ts                          |  32 ----
 src/module/hooks/setup.ts                    |   4 +-
 src/module/migrations.ts                     |   3 +-
 src/module/migrations/migrationHelpers.ts    |  21 ++-
 src/module/rolls/check-evaluation.ts         |  21 ++-
 src/module/rolls/check-factory.ts            |   2 +-
 src/module/rolls/check.ts                    |   4 +-
 tsconfig.json                                |   1 +
 23 files changed, 295 insertions(+), 118 deletions(-)
 create mode 100644 .yarn/sdks/typescript/lib/tsserverlibrary.js

diff --git a/.vscode/extensions.json b/.vscode/extensions.json
index 7281d215..7856d457 100644
--- a/.vscode/extensions.json
+++ b/.vscode/extensions.json
@@ -1,9 +1,9 @@
 {
-    "recommendations": [
-        "dbaeumer.vscode-eslint",
-        "esbenp.prettier-vscode",
-        "gruntfuggly.todo-tree",
-        "eg2.vscode-npm-script",
-        "arcanis.vscode-zipfs"
-    ]
+  "recommendations": [
+    "dbaeumer.vscode-eslint",
+    "esbenp.prettier-vscode",
+    "gruntfuggly.todo-tree",
+    "eg2.vscode-npm-script",
+    "arcanis.vscode-zipfs"
+  ]
 }
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 4b06d0d6..62787842 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,10 +1,10 @@
 {
-    "search.exclude": {
-        "**/.yarn": true,
-        "**/.pnp.*": true
-    },
-    "eslint.nodePath": ".yarn/sdks",
-    "prettier.prettierPath": ".yarn/sdks/prettier/index.js",
-    "typescript.tsdk": ".yarn/sdks/typescript/lib",
-    "typescript.enablePromptUseWorkspaceTsdk": true
+  "search.exclude": {
+    "**/.yarn": true,
+    "**/.pnp.*": true
+  },
+  "eslint.nodePath": ".yarn/sdks",
+  "prettier.prettierPath": ".yarn/sdks/prettier/index.js",
+  "typescript.tsdk": ".yarn/sdks/typescript/lib",
+  "typescript.enablePromptUseWorkspaceTsdk": true
 }
diff --git a/.yarn/sdks/eslint/bin/eslint.js b/.yarn/sdks/eslint/bin/eslint.js
index 4e7554dc..4d327a49 100755
--- a/.yarn/sdks/eslint/bin/eslint.js
+++ b/.yarn/sdks/eslint/bin/eslint.js
@@ -4,7 +4,7 @@ const {existsSync} = require(`fs`);
 const {createRequire, createRequireFromPath} = require(`module`);
 const {resolve} = require(`path`);
 
-const relPnpApiPath = "../../../../.pnp.js";
+const relPnpApiPath = "../../../../.pnp.cjs";
 
 const absPnpApiPath = resolve(__dirname, relPnpApiPath);
 const absRequire = (createRequire || createRequireFromPath)(absPnpApiPath);
diff --git a/.yarn/sdks/eslint/lib/api.js b/.yarn/sdks/eslint/lib/api.js
index ac3c9fc0..97a05244 100644
--- a/.yarn/sdks/eslint/lib/api.js
+++ b/.yarn/sdks/eslint/lib/api.js
@@ -4,7 +4,7 @@ const {existsSync} = require(`fs`);
 const {createRequire, createRequireFromPath} = require(`module`);
 const {resolve} = require(`path`);
 
-const relPnpApiPath = "../../../../.pnp.js";
+const relPnpApiPath = "../../../../.pnp.cjs";
 
 const absPnpApiPath = resolve(__dirname, relPnpApiPath);
 const absRequire = (createRequire || createRequireFromPath)(absPnpApiPath);
diff --git a/.yarn/sdks/eslint/package.json b/.yarn/sdks/eslint/package.json
index e425c68c..744a7732 100644
--- a/.yarn/sdks/eslint/package.json
+++ b/.yarn/sdks/eslint/package.json
@@ -1,6 +1,6 @@
 {
-    "name": "eslint",
-    "version": "7.19.0-pnpify",
-    "main": "./lib/api.js",
-    "type": "commonjs"
+  "name": "eslint",
+  "version": "7.32.0-sdk",
+  "main": "./lib/api.js",
+  "type": "commonjs"
 }
diff --git a/.yarn/sdks/integrations.yml b/.yarn/sdks/integrations.yml
index 76ed42ba..aa9d0d0a 100644
--- a/.yarn/sdks/integrations.yml
+++ b/.yarn/sdks/integrations.yml
@@ -1,5 +1,5 @@
-# This file is automatically generated by PnPify.
-# Manual changes will be lost!
+# This file is automatically generated by @yarnpkg/sdks.
+# Manual changes might be lost!
 
 integrations:
   - vscode
diff --git a/.yarn/sdks/prettier/index.js b/.yarn/sdks/prettier/index.js
index 80134e18..f6882d80 100755
--- a/.yarn/sdks/prettier/index.js
+++ b/.yarn/sdks/prettier/index.js
@@ -2,9 +2,9 @@
 
 const {existsSync} = require(`fs`);
 const {createRequire, createRequireFromPath} = require(`module`);
-const {resolve, dirname} = require(`path`);
+const {resolve} = require(`path`);
 
-const relPnpApiPath = "../../../.pnp.js";
+const relPnpApiPath = "../../../.pnp.cjs";
 
 const absPnpApiPath = resolve(__dirname, relPnpApiPath);
 const absRequire = (createRequire || createRequireFromPath)(absPnpApiPath);
@@ -14,16 +14,6 @@ if (existsSync(absPnpApiPath)) {
     // Setup the environment to be able to require prettier/index.js
     require(absPnpApiPath).setup();
   }
-
-  const pnpifyResolution = require.resolve(`@yarnpkg/pnpify`, {paths: [dirname(absPnpApiPath)]});
-  if (typeof global[`__yarnpkg_sdk_is_using_pnpify__`] === `undefined`) {
-    Object.defineProperty(global, `__yarnpkg_sdk_is_using_pnpify__`, {configurable: true, value: true});
-
-    process.env.NODE_OPTIONS += ` -r ${pnpifyResolution}`;
-
-    // Apply PnPify to the current process
-    absRequire(pnpifyResolution).patchFs();
-  }
 }
 
 // Defer to the real prettier/index.js your application uses
diff --git a/.yarn/sdks/prettier/package.json b/.yarn/sdks/prettier/package.json
index ab2cedc4..97caaf2a 100644
--- a/.yarn/sdks/prettier/package.json
+++ b/.yarn/sdks/prettier/package.json
@@ -1,6 +1,6 @@
 {
-    "name": "prettier",
-    "version": "2.2.1-pnpify",
-    "main": "./index.js",
-    "type": "commonjs"
+  "name": "prettier",
+  "version": "2.4.0-sdk",
+  "main": "./index.js",
+  "type": "commonjs"
 }
diff --git a/.yarn/sdks/typescript/bin/tsc b/.yarn/sdks/typescript/bin/tsc
index 06e51d0d..5608e574 100755
--- a/.yarn/sdks/typescript/bin/tsc
+++ b/.yarn/sdks/typescript/bin/tsc
@@ -4,7 +4,7 @@ const {existsSync} = require(`fs`);
 const {createRequire, createRequireFromPath} = require(`module`);
 const {resolve} = require(`path`);
 
-const relPnpApiPath = "../../../../.pnp.js";
+const relPnpApiPath = "../../../../.pnp.cjs";
 
 const absPnpApiPath = resolve(__dirname, relPnpApiPath);
 const absRequire = (createRequire || createRequireFromPath)(absPnpApiPath);
diff --git a/.yarn/sdks/typescript/bin/tsserver b/.yarn/sdks/typescript/bin/tsserver
index 2d03f3d9..cd7d557d 100755
--- a/.yarn/sdks/typescript/bin/tsserver
+++ b/.yarn/sdks/typescript/bin/tsserver
@@ -4,7 +4,7 @@ const {existsSync} = require(`fs`);
 const {createRequire, createRequireFromPath} = require(`module`);
 const {resolve} = require(`path`);
 
-const relPnpApiPath = "../../../../.pnp.js";
+const relPnpApiPath = "../../../../.pnp.cjs";
 
 const absPnpApiPath = resolve(__dirname, relPnpApiPath);
 const absRequire = (createRequire || createRequireFromPath)(absPnpApiPath);
diff --git a/.yarn/sdks/typescript/lib/tsc.js b/.yarn/sdks/typescript/lib/tsc.js
index e030711c..16042d01 100644
--- a/.yarn/sdks/typescript/lib/tsc.js
+++ b/.yarn/sdks/typescript/lib/tsc.js
@@ -4,7 +4,7 @@ const {existsSync} = require(`fs`);
 const {createRequire, createRequireFromPath} = require(`module`);
 const {resolve} = require(`path`);
 
-const relPnpApiPath = "../../../../.pnp.js";
+const relPnpApiPath = "../../../../.pnp.cjs";
 
 const absPnpApiPath = resolve(__dirname, relPnpApiPath);
 const absRequire = (createRequire || createRequireFromPath)(absPnpApiPath);
diff --git a/.yarn/sdks/typescript/lib/tsserver.js b/.yarn/sdks/typescript/lib/tsserver.js
index 1d6dfb61..4d90f387 100644
--- a/.yarn/sdks/typescript/lib/tsserver.js
+++ b/.yarn/sdks/typescript/lib/tsserver.js
@@ -4,15 +4,22 @@ const {existsSync} = require(`fs`);
 const {createRequire, createRequireFromPath} = require(`module`);
 const {resolve} = require(`path`);
 
-const relPnpApiPath = "../../../../.pnp.js";
+const relPnpApiPath = "../../../../.pnp.cjs";
 
 const absPnpApiPath = resolve(__dirname, relPnpApiPath);
 const absRequire = (createRequire || createRequireFromPath)(absPnpApiPath);
 
 const moduleWrapper = tsserver => {
+  if (!process.versions.pnp) {
+    return tsserver;
+  }
+
   const {isAbsolute} = require(`path`);
   const pnpApi = require(`pnpapi`);
 
+  const isVirtual = str => str.match(/\/(\$\$virtual|__virtual__)\//);
+  const normalize = str => str.replace(/\\/g, `/`).replace(/^\/?/, `/`);
+
   const dependencyTreeRoots = new Set(pnpApi.getDependencyTreeRoots().map(locator => {
     return `${locator.name}@${locator.reference}`;
   }));
@@ -23,9 +30,9 @@ const moduleWrapper = tsserver => {
 
   function toEditorPath(str) {
     // We add the `zip:` prefix to both `.zip/` paths and virtual paths
-    if (isAbsolute(str) && !str.match(/^\^zip:/) && (str.match(/\.zip\//) || str.match(/\$\$virtual\//))) {
+    if (isAbsolute(str) && !str.match(/^\^zip:/) && (str.match(/\.zip\//) || isVirtual(str))) {
       // We also take the opportunity to turn virtual paths into physical ones;
-      // this makes is much easier to work with workspaces that list peer
+      // this makes it much easier to work with workspaces that list peer
       // dependencies, since otherwise Ctrl+Click would bring us to the virtual
       // file instances instead of the real ones.
       //
@@ -34,26 +41,49 @@ const moduleWrapper = tsserver => {
       // with peer dep (otherwise jumping into react-dom would show resolution
       // errors on react).
       //
-      const resolved = pnpApi.resolveVirtual(str);
+      const resolved = isVirtual(str) ? pnpApi.resolveVirtual(str) : str;
       if (resolved) {
         const locator = pnpApi.findPackageLocator(resolved);
         if (locator && dependencyTreeRoots.has(`${locator.name}@${locator.reference}`)) {
-         str = resolved;
+          str = resolved;
         }
       }
 
-      str = str.replace(/\\/g, `/`)
-      str = str.replace(/^\/?/, `/`);
+      str = normalize(str);
 
-      // Absolute VSCode `Uri.fsPath`s need to start with a slash.
-      // VSCode only adds it automatically for supported schemes,
-      // so we have to do it manually for the `zip` scheme.
-      // The path needs to start with a caret otherwise VSCode doesn't handle the protocol
-      //
-      // Ref: https://github.com/microsoft/vscode/issues/105014#issuecomment-686760910
-      //
       if (str.match(/\.zip\//)) {
-        str = `${isVSCode ? `^` : ``}zip:${str}`;
+        switch (hostInfo) {
+          // Absolute VSCode `Uri.fsPath`s need to start with a slash.
+          // VSCode only adds it automatically for supported schemes,
+          // so we have to do it manually for the `zip` scheme.
+          // The path needs to start with a caret otherwise VSCode doesn't handle the protocol
+          //
+          // Ref: https://github.com/microsoft/vscode/issues/105014#issuecomment-686760910
+          //
+          case `vscode`: {
+            str = `^zip:${str}`;
+          } break;
+
+          // To make "go to definition" work,
+          // We have to resolve the actual file system path from virtual path
+          // and convert scheme to supported by [vim-rzip](https://github.com/lbrayner/vim-rzip)
+          case `coc-nvim`: {
+            str = normalize(resolved).replace(/\.zip\//, `.zip::`);
+            str = resolve(`zipfile:${str}`);
+          } break;
+
+          // Support neovim native LSP and [typescript-language-server](https://github.com/theia-ide/typescript-language-server)
+          // We have to resolve the actual file system path from virtual path,
+          // everything else is up to neovim
+          case `neovim`: {
+            str = normalize(resolved).replace(/\.zip\//, `.zip::`);
+            str = `zipfile:${str}`;
+          } break;
+
+          default: {
+            str = `zip:${str}`;
+          } break;
+        }
       }
     }
 
@@ -66,15 +96,29 @@ const moduleWrapper = tsserver => {
       : str.replace(/^\^?zip:/, ``);
   }
 
+  // Force enable 'allowLocalPluginLoads'
+  // TypeScript tries to resolve plugins using a path relative to itself
+  // which doesn't work when using the global cache
+  // https://github.com/microsoft/TypeScript/blob/1b57a0395e0bff191581c9606aab92832001de62/src/server/project.ts#L2238
+  // VSCode doesn't want to enable 'allowLocalPluginLoads' due to security concerns but
+  // TypeScript already does local loads and if this code is running the user trusts the workspace
+  // https://github.com/microsoft/vscode/issues/45856
+  const ConfiguredProject = tsserver.server.ConfiguredProject;
+  const {enablePluginsWithOptions: originalEnablePluginsWithOptions} = ConfiguredProject.prototype;
+  ConfiguredProject.prototype.enablePluginsWithOptions = function() {
+    this.projectService.allowLocalPluginLoads = true;
+    return originalEnablePluginsWithOptions.apply(this, arguments);
+  };
+
   // And here is the point where we hijack the VSCode <-> TS communications
   // by adding ourselves in the middle. We locate everything that looks
   // like an absolute path of ours and normalize it.
 
   const Session = tsserver.server.Session;
   const {onMessage: originalOnMessage, send: originalSend} = Session.prototype;
-  let isVSCode = false;
+  let hostInfo = `unknown`;
 
-  return Object.assign(Session.prototype, {
+  Object.assign(Session.prototype, {
     onMessage(/** @type {string} */ message) {
       const parsedMessage = JSON.parse(message)
 
@@ -82,9 +126,9 @@ const moduleWrapper = tsserver => {
         parsedMessage != null &&
         typeof parsedMessage === `object` &&
         parsedMessage.arguments &&
-        parsedMessage.arguments.hostInfo === `vscode`
+        typeof parsedMessage.arguments.hostInfo === `string`
       ) {
-        isVSCode = true;
+        hostInfo = parsedMessage.arguments.hostInfo;
       }
 
       return originalOnMessage.call(this, JSON.stringify(parsedMessage, (key, value) => {
@@ -98,6 +142,8 @@ const moduleWrapper = tsserver => {
       })));
     }
   });
+
+  return tsserver;
 };
 
 if (existsSync(absPnpApiPath)) {
diff --git a/.yarn/sdks/typescript/lib/tsserverlibrary.js b/.yarn/sdks/typescript/lib/tsserverlibrary.js
new file mode 100644
index 00000000..c3de4ff5
--- /dev/null
+++ b/.yarn/sdks/typescript/lib/tsserverlibrary.js
@@ -0,0 +1,157 @@
+#!/usr/bin/env node
+
+const {existsSync} = require(`fs`);
+const {createRequire, createRequireFromPath} = require(`module`);
+const {resolve} = require(`path`);
+
+const relPnpApiPath = "../../../../.pnp.cjs";
+
+const absPnpApiPath = resolve(__dirname, relPnpApiPath);
+const absRequire = (createRequire || createRequireFromPath)(absPnpApiPath);
+
+const moduleWrapper = tsserver => {
+  if (!process.versions.pnp) {
+    return tsserver;
+  }
+
+  const {isAbsolute} = require(`path`);
+  const pnpApi = require(`pnpapi`);
+
+  const isVirtual = str => str.match(/\/(\$\$virtual|__virtual__)\//);
+  const normalize = str => str.replace(/\\/g, `/`).replace(/^\/?/, `/`);
+
+  const dependencyTreeRoots = new Set(pnpApi.getDependencyTreeRoots().map(locator => {
+    return `${locator.name}@${locator.reference}`;
+  }));
+
+  // VSCode sends the zip paths to TS using the "zip://" prefix, that TS
+  // doesn't understand. This layer makes sure to remove the protocol
+  // before forwarding it to TS, and to add it back on all returned paths.
+
+  function toEditorPath(str) {
+    // We add the `zip:` prefix to both `.zip/` paths and virtual paths
+    if (isAbsolute(str) && !str.match(/^\^zip:/) && (str.match(/\.zip\//) || isVirtual(str))) {
+      // We also take the opportunity to turn virtual paths into physical ones;
+      // this makes it much easier to work with workspaces that list peer
+      // dependencies, since otherwise Ctrl+Click would bring us to the virtual
+      // file instances instead of the real ones.
+      //
+      // We only do this to modules owned by the the dependency tree roots.
+      // This avoids breaking the resolution when jumping inside a vendor
+      // with peer dep (otherwise jumping into react-dom would show resolution
+      // errors on react).
+      //
+      const resolved = isVirtual(str) ? pnpApi.resolveVirtual(str) : str;
+      if (resolved) {
+        const locator = pnpApi.findPackageLocator(resolved);
+        if (locator && dependencyTreeRoots.has(`${locator.name}@${locator.reference}`)) {
+          str = resolved;
+        }
+      }
+
+      str = normalize(str);
+
+      if (str.match(/\.zip\//)) {
+        switch (hostInfo) {
+          // Absolute VSCode `Uri.fsPath`s need to start with a slash.
+          // VSCode only adds it automatically for supported schemes,
+          // so we have to do it manually for the `zip` scheme.
+          // The path needs to start with a caret otherwise VSCode doesn't handle the protocol
+          //
+          // Ref: https://github.com/microsoft/vscode/issues/105014#issuecomment-686760910
+          //
+          case `vscode`: {
+            str = `^zip:${str}`;
+          } break;
+
+          // To make "go to definition" work,
+          // We have to resolve the actual file system path from virtual path
+          // and convert scheme to supported by [vim-rzip](https://github.com/lbrayner/vim-rzip)
+          case `coc-nvim`: {
+            str = normalize(resolved).replace(/\.zip\//, `.zip::`);
+            str = resolve(`zipfile:${str}`);
+          } break;
+
+          // Support neovim native LSP and [typescript-language-server](https://github.com/theia-ide/typescript-language-server)
+          // We have to resolve the actual file system path from virtual path,
+          // everything else is up to neovim
+          case `neovim`: {
+            str = normalize(resolved).replace(/\.zip\//, `.zip::`);
+            str = `zipfile:${str}`;
+          } break;
+
+          default: {
+            str = `zip:${str}`;
+          } break;
+        }
+      }
+    }
+
+    return str;
+  }
+
+  function fromEditorPath(str) {
+    return process.platform === `win32`
+      ? str.replace(/^\^?zip:\//, ``)
+      : str.replace(/^\^?zip:/, ``);
+  }
+
+  // Force enable 'allowLocalPluginLoads'
+  // TypeScript tries to resolve plugins using a path relative to itself
+  // which doesn't work when using the global cache
+  // https://github.com/microsoft/TypeScript/blob/1b57a0395e0bff191581c9606aab92832001de62/src/server/project.ts#L2238
+  // VSCode doesn't want to enable 'allowLocalPluginLoads' due to security concerns but
+  // TypeScript already does local loads and if this code is running the user trusts the workspace
+  // https://github.com/microsoft/vscode/issues/45856
+  const ConfiguredProject = tsserver.server.ConfiguredProject;
+  const {enablePluginsWithOptions: originalEnablePluginsWithOptions} = ConfiguredProject.prototype;
+  ConfiguredProject.prototype.enablePluginsWithOptions = function() {
+    this.projectService.allowLocalPluginLoads = true;
+    return originalEnablePluginsWithOptions.apply(this, arguments);
+  };
+
+  // And here is the point where we hijack the VSCode <-> TS communications
+  // by adding ourselves in the middle. We locate everything that looks
+  // like an absolute path of ours and normalize it.
+
+  const Session = tsserver.server.Session;
+  const {onMessage: originalOnMessage, send: originalSend} = Session.prototype;
+  let hostInfo = `unknown`;
+
+  Object.assign(Session.prototype, {
+    onMessage(/** @type {string} */ message) {
+      const parsedMessage = JSON.parse(message)
+
+      if (
+        parsedMessage != null &&
+        typeof parsedMessage === `object` &&
+        parsedMessage.arguments &&
+        typeof parsedMessage.arguments.hostInfo === `string`
+      ) {
+        hostInfo = parsedMessage.arguments.hostInfo;
+      }
+
+      return originalOnMessage.call(this, JSON.stringify(parsedMessage, (key, value) => {
+        return typeof value === `string` ? fromEditorPath(value) : value;
+      }));
+    },
+
+    send(/** @type {any} */ msg) {
+      return originalSend.call(this, JSON.parse(JSON.stringify(msg, (key, value) => {
+        return typeof value === `string` ? toEditorPath(value) : value;
+      })));
+    }
+  });
+
+  return tsserver;
+};
+
+if (existsSync(absPnpApiPath)) {
+  if (!process.versions.pnp) {
+    // Setup the environment to be able to require typescript/lib/tsserverlibrary.js
+    require(absPnpApiPath).setup();
+  }
+}
+
+// Defer to the real typescript/lib/tsserverlibrary.js your application uses
+module.exports = moduleWrapper(absRequire(`typescript/lib/tsserverlibrary.js`));
diff --git a/.yarn/sdks/typescript/lib/typescript.js b/.yarn/sdks/typescript/lib/typescript.js
index 7e3c852f..cbdbf150 100644
--- a/.yarn/sdks/typescript/lib/typescript.js
+++ b/.yarn/sdks/typescript/lib/typescript.js
@@ -4,7 +4,7 @@ const {existsSync} = require(`fs`);
 const {createRequire, createRequireFromPath} = require(`module`);
 const {resolve} = require(`path`);
 
-const relPnpApiPath = "../../../../.pnp.js";
+const relPnpApiPath = "../../../../.pnp.cjs";
 
 const absPnpApiPath = resolve(__dirname, relPnpApiPath);
 const absRequire = (createRequire || createRequireFromPath)(absPnpApiPath);
diff --git a/.yarn/sdks/typescript/package.json b/.yarn/sdks/typescript/package.json
index db217567..1a105129 100644
--- a/.yarn/sdks/typescript/package.json
+++ b/.yarn/sdks/typescript/package.json
@@ -1,6 +1,6 @@
 {
-    "name": "typescript",
-    "version": "4.1.5-pnpify",
-    "main": "./lib/typescript.js",
-    "type": "commonjs"
+  "name": "typescript",
+  "version": "4.4.3-sdk",
+  "main": "./lib/typescript.js",
+  "type": "commonjs"
 }
diff --git a/src/module/fonts.ts b/src/module/fonts.ts
index a95d0e55..75c52bdc 100644
--- a/src/module/fonts.ts
+++ b/src/module/fonts.ts
@@ -2,38 +2,6 @@
 //
 // SPDX-License-Identifier: MIT
 
-type CSSOMString = string;
-type FontFaceLoadStatus = "unloaded" | "loading" | "loaded" | "error";
-type FontFaceSetStatus = "loading" | "loaded";
-
-interface FontFace {
-    family: CSSOMString;
-    style: CSSOMString;
-    weight: CSSOMString;
-    stretch: CSSOMString;
-    unicodeRange: CSSOMString;
-    variant: CSSOMString;
-    featureSettings: CSSOMString;
-    variationSettings: CSSOMString;
-    display: CSSOMString;
-    readonly status: FontFaceLoadStatus;
-    readonly loaded: Promise<FontFace>;
-    load(): Promise<FontFace>;
-}
-
-interface FontFaceSet {
-    readonly status: FontFaceSetStatus;
-    readonly ready: Promise<FontFaceSet>;
-    check(font: string, text?: string): boolean;
-    load(font: string, text?: string): Promise<FontFace[]>;
-}
-
-declare global {
-    interface Document {
-        fonts: FontFaceSet;
-    }
-}
-
 const fonts = ["Lora", "Wood Stamp"];
 
 export async function preloadFonts(): Promise<FontFace[][]> {
diff --git a/src/module/hooks/setup.ts b/src/module/hooks/setup.ts
index b5bf2748..d9105954 100644
--- a/src/module/hooks/setup.ts
+++ b/src/module/hooks/setup.ts
@@ -21,11 +21,11 @@ function localizeAndSortConfigObjects() {
     const noSort = ["attributes", "traits", "combatValues", "creatureSizeCategories"];
 
     const localizeObject = <T extends { [s: string]: string }>(obj: T, sort = true): T => {
-        const localized = Object.entries(obj).map(([key, value]) => {
+        const localized = Object.entries(obj).map(([key, value]): [string, string] => {
             return [key, getGame().i18n.localize(value)];
         });
         if (sort) localized.sort((a, b) => a[1].localeCompare(b[1]));
-        return Object.fromEntries(localized);
+        return Object.fromEntries(localized) as T;
     };
 
     DS4.i18n = Object.fromEntries(
diff --git a/src/module/migrations.ts b/src/module/migrations.ts
index 9dfb122a..63d97697 100644
--- a/src/module/migrations.ts
+++ b/src/module/migrations.ts
@@ -58,8 +58,7 @@ async function migrateFromTo(oldMigrationVersion: number, targetMigrationVersion
                     }),
                     { permanent: true },
                 );
-                err.message = `Failed ds4 system migration: ${err.message}`;
-                logger.error(err);
+                logger.error("Failed ds4 system migration:", err);
                 return;
             }
         }
diff --git a/src/module/migrations/migrationHelpers.ts b/src/module/migrations/migrationHelpers.ts
index 2f94d93d..ca2bcdf9 100644
--- a/src/module/migrations/migrationHelpers.ts
+++ b/src/module/migrations/migrationHelpers.ts
@@ -20,8 +20,7 @@ export async function migrateItems(getItemUpdateData: ItemUpdateDataGetter): Pro
                 await item.update(updateData), { enforceTypes: false };
             }
         } catch (err) {
-            err.message = `Error during migration of Item document ${item.name} (${item.id}), continuing anyways.`;
-            logger.error(err);
+            logger.error(`Error during migration of Item document ${item.name} (${item.id}), continuing anyways.`, err);
         }
     }
 }
@@ -39,8 +38,10 @@ export async function migrateActors(getActorUpdateData: ActorUpdateDataGetter):
                 await actor.update(updateData);
             }
         } catch (err) {
-            err.message = `Error during migration of Actor document ${actor.name} (${actor.id}), continuing anyways.`;
-            logger.error(err);
+            logger.error(
+                `Error during migration of Actor document ${actor.name} (${actor.id}), continuing anyways.`,
+                err,
+            );
         }
     }
 }
@@ -60,8 +61,10 @@ export async function migrateScenes(getSceneUpdateData: SceneUpdateDataGetter):
                 );
             }
         } catch (err) {
-            err.message = `Error during migration of Scene document ${scene.name} (${scene.id}), continuing anyways.`;
-            logger.error(err);
+            logger.error(
+                `Error during migration of Scene document ${scene.name} (${scene.id}), continuing anyways.`,
+                err,
+            );
         }
     }
 }
@@ -170,8 +173,10 @@ export function getCompendiumMigrator(
                         ));
                 }
             } catch (err) {
-                err.message = `Error during migration of document ${doc.name} (${doc.id}) in compendium ${compendium.collection}, continuing anyways.`;
-                logger.error(err);
+                logger.error(
+                    `Error during migration of document ${doc.name} (${doc.id}) in compendium ${compendium.collection}, continuing anyways.`,
+                    err,
+                );
             }
         }
 
diff --git a/src/module/rolls/check-evaluation.ts b/src/module/rolls/check-evaluation.ts
index 8017bd37..2ee1e461 100644
--- a/src/module/rolls/check-evaluation.ts
+++ b/src/module/rolls/check-evaluation.ts
@@ -65,7 +65,7 @@ function assignSubChecksToDice(
 
 function findIndexOfSmallestNonCoup(dice: number[], maximumCoupResult: number): number {
     return dice
-        .map((die, index) => [die, index])
+        .map((die, index): [number, number] => [die, index])
         .filter((indexedDie) => indexedDie[0] > maximumCoupResult)
         .reduce(
             (smallestIndexedDie, indexedDie) =>
@@ -77,14 +77,25 @@ function findIndexOfSmallestNonCoup(dice: number[], maximumCoupResult: number):
 function shouldUseCoupForLastSubCheck(
     indexOfSmallestNonCoup: number,
     indexOfFirstCoup: number,
-    dice: number[],
+    dice: readonly number[],
     checkTargetNumberForLastSubCheck: number,
 ) {
+    if (indexOfFirstCoup !== -1 && indexOfSmallestNonCoup === -1) {
+        return true;
+    }
+    const smallestNonCoup = dice[indexOfSmallestNonCoup];
+    if (
+        !Number.isInteger(indexOfFirstCoup) ||
+        indexOfFirstCoup < -1 ||
+        !Number.isInteger(indexOfSmallestNonCoup) ||
+        smallestNonCoup === undefined
+    ) {
+        throw new Error("Received an invalid value for the parameter indexOfSmallestNonCoup or indexOfFirstCoup,");
+    }
     return (
         indexOfFirstCoup !== -1 &&
-        (indexOfSmallestNonCoup === -1 ||
-            (dice[indexOfSmallestNonCoup] > checkTargetNumberForLastSubCheck &&
-                dice[indexOfSmallestNonCoup] + checkTargetNumberForLastSubCheck > 20))
+        smallestNonCoup > checkTargetNumberForLastSubCheck &&
+        smallestNonCoup + checkTargetNumberForLastSubCheck > 20
     );
 }
 
diff --git a/src/module/rolls/check-factory.ts b/src/module/rolls/check-factory.ts
index 45895d8a..07f5ee1b 100644
--- a/src/module/rolls/check-factory.ts
+++ b/src/module/rolls/check-factory.ts
@@ -144,7 +144,7 @@ async function askGmModifier(
                                 }),
                             );
                         } else {
-                            const innerForm = html[0].querySelector("form");
+                            const innerForm = html[0]?.querySelector("form");
                             if (!innerForm) {
                                 throw new Error(
                                     getGame().i18n.format("DS4.ErrorCouldNotFindHtmlElement", { htmlElement: "form" }),
diff --git a/src/module/rolls/check.ts b/src/module/rolls/check.ts
index 2074cdc9..9dcf8d0c 100644
--- a/src/module/rolls/check.ts
+++ b/src/module/rolls/check.ts
@@ -104,8 +104,8 @@ export class DS4Check extends DiceTerm {
             canFumble: this.canFumble,
         });
         this.results = results;
-        this.coup = results[0].success ?? false;
-        this.fumble = results[0].failure ?? false;
+        this.coup = results[0]?.success ?? false;
+        this.fumble = results[0]?.failure ?? false;
     }
 
     /**
diff --git a/tsconfig.json b/tsconfig.json
index 55672c07..8bdb6920 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -7,6 +7,7 @@
         "moduleResolution": "node",
         "forceConsistentCasingInFileNames": true,
         "strict": true,
+        "noUncheckedIndexedAccess": true,
         "sourceMap": true
     },
     "include": ["src"]