Repository: playcanvas/engine
Pull request #4210 (2022-04-22 15:51:27)

Add layer check between Camera and Element when testing for input.
Fixes https://github.com/playcanvas/engine/issues/4180

Add layer check between Camera and Element when testing for input, with performance-friendly implementation using a new `layersSet` property in Camera.

Tested against https://launch.playcanvas.com/1383836?debug=true and works as expected.

I confirm I have read the [contributing guidelines](https://github.com/playcanvas/engine/blob/master/.github/CONTRIBUTING.md) and signed the [Contributor License Agreement](https://docs.google.com/a/playcanvas.com/forms/d/1Ih69zQfJG-QDLIEpHr6CsaAs6fPORNOVnMv5nuo0cjk/viewform).


yaustar: Given this going to be a more expensive for a less common use case, can we put this on a toggle? Eg on the screen component 
mvaligursky: > Given this going to be a more expensive for a less common use case, can we put this on a toggle? Eg on the screen component

I'm not sure that is required. The solution using a Set is very cheap. And considering most elements are only on a single layer, this is an O(1) solution.
jpauloruschel: > > Given this going to be a more expensive for a less common use case, can we put this on a toggle? Eg on the screen component
> 
> I'm not sure that is required. The solution using a Set is very cheap. And considering most elements are only on a single layer, this is an O(1) solution.

I agree with Martin here - I believe the `Set` approach is more than fast enough.

Patch:
diff --git a/package-lock.json b/package-lock.json
index 35c2485b8..f9adbcc2b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,9 +9,9 @@
       "version": "1.56.0-dev",
       "license": "MIT",
       "devDependencies": {
-        "@babel/core": "^7.18.9",
+        "@babel/core": "^7.18.10",
         "@babel/eslint-parser": "^7.18.9",
-        "@babel/preset-env": "^7.18.9",
+        "@babel/preset-env": "^7.18.10",
         "@playcanvas/canvas-mock": "^1.0.1",
         "@playcanvas/eslint-config": "^1.2.0",
         "@playcanvas/jsdoc-template": "^1.0.27",
@@ -20,7 +20,7 @@
         "@rollup/pluginutils": "^4.2.1",
         "c8": "^7.12.0",
         "chai": "^4.3.6",
-        "eslint": "^8.21.0",
+        "eslint": "^8.22.0",
         "jsdoc": "^3.6.11",
         "jsdoc-tsimport-plugin": "^1.0.5",
         "karma": "^6.4.0",
@@ -28,7 +28,7 @@
         "karma-mocha": "2.0.1",
         "karma-spec-reporter": "^0.0.34",
         "mocha": "^10.0.0",
-        "rollup": "^2.77.2",
+        "rollup": "^2.78.0",
         "rollup-plugin-dts": "^4.2.2",
         "rollup-plugin-jscc": "2.0.0",
         "rollup-plugin-terser": "7.0.2",
@@ -74,21 +74,21 @@
       }
     },
     "node_modules/@babel/core": {
-      "version": "7.18.9",
-      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.9.tgz",
-      "integrity": "sha512-1LIb1eL8APMy91/IMW+31ckrfBM4yCoLaVzoDhZUKSM4cu1L1nIidyxkCgzPAgrC5WEz36IPEr/eSeSF9pIn+g==",
+      "version": "7.18.10",
+      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.10.tgz",
+      "integrity": "sha512-JQM6k6ENcBFKVtWvLavlvi/mPcpYZ3+R+2EySDEMSMbp7Mn4FexlbbJVrx2R7Ijhr01T8gyqrOaABWIOgxeUyw==",
       "dev": true,
       "dependencies": {
         "@ampproject/remapping": "^2.1.0",
         "@babel/code-frame": "^7.18.6",
-        "@babel/generator": "^7.18.9",
+        "@babel/generator": "^7.18.10",
         "@babel/helper-compilation-targets": "^7.18.9",
         "@babel/helper-module-transforms": "^7.18.9",
         "@babel/helpers": "^7.18.9",
-        "@babel/parser": "^7.18.9",
-        "@babel/template": "^7.18.6",
-        "@babel/traverse": "^7.18.9",
-        "@babel/types": "^7.18.9",
+        "@babel/parser": "^7.18.10",
+        "@babel/template": "^7.18.10",
+        "@babel/traverse": "^7.18.10",
+        "@babel/types": "^7.18.10",
         "convert-source-map": "^1.7.0",
         "debug": "^4.1.0",
         "gensync": "^1.0.0-beta.2",
@@ -122,12 +122,12 @@
       }
     },
     "node_modules/@babel/generator": {
-      "version": "7.18.9",
-      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.9.tgz",
-      "integrity": "sha512-wt5Naw6lJrL1/SGkipMiFxJjtyczUWTP38deiP1PO60HsBjDeKk08CGC3S8iVuvf0FmTdgKwU1KIXzSKL1G0Ug==",
+      "version": "7.18.12",
+      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.12.tgz",
+      "integrity": "sha512-dfQ8ebCN98SvyL7IxNMCUtZQSq5R7kxgN+r8qYTGDmmSion1hX2C0zq2yo1bsCDhXixokv1SAWTZUMYbO/V5zg==",
       "dev": true,
       "dependencies": {
-        "@babel/types": "^7.18.9",
+        "@babel/types": "^7.18.10",
         "@jridgewell/gen-mapping": "^0.3.2",
         "jsesc": "^2.5.1"
       },
@@ -230,15 +230,13 @@
       }
     },
     "node_modules/@babel/helper-define-polyfill-provider": {
-      "version": "0.3.1",
-      "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz",
-      "integrity": "sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==",
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.2.tgz",
+      "integrity": "sha512-r9QJJ+uDWrd+94BSPcP6/de67ygLtvVy6cK4luE6MOuDsZIdoaPBnfSpbO/+LTifjPckbKXRuI9BB/Z2/y3iTg==",
       "dev": true,
       "dependencies": {
-        "@babel/helper-compilation-targets": "^7.13.0",
-        "@babel/helper-module-imports": "^7.12.13",
-        "@babel/helper-plugin-utils": "^7.13.0",
-        "@babel/traverse": "^7.13.0",
+        "@babel/helper-compilation-targets": "^7.17.7",
+        "@babel/helper-plugin-utils": "^7.16.7",
         "debug": "^4.1.1",
         "lodash.debounce": "^4.0.8",
         "resolve": "^1.14.2",
@@ -428,6 +426,15 @@
         "node": ">=6.9.0"
       }
     },
+    "node_modules/@babel/helper-string-parser": {
+      "version": "7.18.10",
+      "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz",
+      "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
     "node_modules/@babel/helper-validator-identifier": {
       "version": "7.18.6",
       "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz",
@@ -490,9 +497,9 @@
       }
     },
     "node_modules/@babel/parser": {
-      "version": "7.18.9",
-      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.9.tgz",
-      "integrity": "sha512-9uJveS9eY9DJ0t64YbIBZICtJy8a5QrDEVdiLCG97fVLpDTpGX7t8mMSb6OWw6Lrnjqj4O8zwjELX3dhoMgiBg==",
+      "version": "7.18.11",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.11.tgz",
+      "integrity": "sha512-9JKn5vN+hDt0Hdqn1PiJ2guflwP+B6Ga8qbDuoF0PzzVhrzsKIJo8yGqVk6CmMHiMei9w1C1Bp9IMJSIK+HPIQ==",
       "dev": true,
       "bin": {
         "parser": "bin/babel-parser.js"
@@ -534,14 +541,14 @@
       }
     },
     "node_modules/@babel/plugin-proposal-async-generator-functions": {
-      "version": "7.18.6",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.18.6.tgz",
-      "integrity": "sha512-WAz4R9bvozx4qwf74M+sfqPMKfSqwM0phxPTR6iJIi8robgzXwkEgmeJG1gEKhm6sDqT/U9aV3lfcqybIpev8w==",
+      "version": "7.18.10",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.18.10.tgz",
+      "integrity": "sha512-1mFuY2TOsR1hxbjCo4QL+qlIjV07p4H4EUYw2J/WCqsvFV6V9X9z9YhXbWndc/4fw+hYGlDT7egYxliMp5O6Ew==",
       "dev": true,
       "dependencies": {
-        "@babel/helper-environment-visitor": "^7.18.6",
-        "@babel/helper-plugin-utils": "^7.18.6",
-        "@babel/helper-remap-async-to-generator": "^7.18.6",
+        "@babel/helper-environment-visitor": "^7.18.9",
+        "@babel/helper-plugin-utils": "^7.18.9",
+        "@babel/helper-remap-async-to-generator": "^7.18.9",
         "@babel/plugin-syntax-async-generators": "^7.8.4"
       },
       "engines": {
@@ -1452,12 +1459,12 @@
       }
     },
     "node_modules/@babel/plugin-transform-unicode-escapes": {
-      "version": "7.18.6",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.6.tgz",
-      "integrity": "sha512-XNRwQUXYMP7VLuy54cr/KS/WeL3AZeORhrmeZ7iewgu+X2eBqmpaLI/hzqr9ZxCeUoq0ASK4GUzSM0BDhZkLFw==",
+      "version": "7.18.10",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz",
+      "integrity": "sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==",
       "dev": true,
       "dependencies": {
-        "@babel/helper-plugin-utils": "^7.18.6"
+        "@babel/helper-plugin-utils": "^7.18.9"
       },
       "engines": {
         "node": ">=6.9.0"
@@ -1483,9 +1490,9 @@
       }
     },
     "node_modules/@babel/preset-env": {
-      "version": "7.18.9",
-      "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.18.9.tgz",
-      "integrity": "sha512-75pt/q95cMIHWssYtyfjVlvI+QEZQThQbKvR9xH+F/Agtw/s4Wfc2V9Bwd/P39VtixB7oWxGdH4GteTTwYJWMg==",
+      "version": "7.18.10",
+      "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.18.10.tgz",
+      "integrity": "sha512-wVxs1yjFdW3Z/XkNfXKoblxoHgbtUF7/l3PvvP4m02Qz9TZ6uZGxRVYjSQeR87oQmHco9zWitW5J82DJ7sCjvA==",
       "dev": true,
       "dependencies": {
         "@babel/compat-data": "^7.18.8",
@@ -1494,7 +1501,7 @@
         "@babel/helper-validator-option": "^7.18.6",
         "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6",
         "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.9",
-        "@babel/plugin-proposal-async-generator-functions": "^7.18.6",
+        "@babel/plugin-proposal-async-generator-functions": "^7.18.10",
         "@babel/plugin-proposal-class-properties": "^7.18.6",
         "@babel/plugin-proposal-class-static-block": "^7.18.6",
         "@babel/plugin-proposal-dynamic-import": "^7.18.6",
@@ -1554,13 +1561,13 @@
         "@babel/plugin-transform-sticky-regex": "^7.18.6",
         "@babel/plugin-transform-template-literals": "^7.18.9",
         "@babel/plugin-transform-typeof-symbol": "^7.18.9",
-        "@babel/plugin-transform-unicode-escapes": "^7.18.6",
+        "@babel/plugin-transform-unicode-escapes": "^7.18.10",
         "@babel/plugin-transform-unicode-regex": "^7.18.6",
         "@babel/preset-modules": "^0.1.5",
-        "@babel/types": "^7.18.9",
-        "babel-plugin-polyfill-corejs2": "^0.3.1",
-        "babel-plugin-polyfill-corejs3": "^0.5.2",
-        "babel-plugin-polyfill-regenerator": "^0.3.1",
+        "@babel/types": "^7.18.10",
+        "babel-plugin-polyfill-corejs2": "^0.3.2",
+        "babel-plugin-polyfill-corejs3": "^0.5.3",
+        "babel-plugin-polyfill-regenerator": "^0.4.0",
         "core-js-compat": "^3.22.1",
         "semver": "^6.3.0"
       },
@@ -1600,33 +1607,33 @@
       }
     },
     "node_modules/@babel/template": {
-      "version": "7.18.6",
-      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.6.tgz",
-      "integrity": "sha512-JoDWzPe+wgBsTTgdnIma3iHNFC7YVJoPssVBDjiHfNlyt4YcunDtcDOUmfVDfCK5MfdsaIoX9PkijPhjH3nYUw==",
+      "version": "7.18.10",
+      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz",
+      "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==",
       "dev": true,
       "dependencies": {
         "@babel/code-frame": "^7.18.6",
-        "@babel/parser": "^7.18.6",
-        "@babel/types": "^7.18.6"
+        "@babel/parser": "^7.18.10",
+        "@babel/types": "^7.18.10"
       },
       "engines": {
         "node": ">=6.9.0"
       }
     },
     "node_modules/@babel/traverse": {
-      "version": "7.18.9",
-      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.9.tgz",
-      "integrity": "sha512-LcPAnujXGwBgv3/WHv01pHtb2tihcyW1XuL9wd7jqh1Z8AQkTd+QVjMrMijrln0T7ED3UXLIy36P9Ao7W75rYg==",
+      "version": "7.18.11",
+      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.11.tgz",
+      "integrity": "sha512-TG9PiM2R/cWCAy6BPJKeHzNbu4lPzOSZpeMfeNErskGpTJx6trEvFaVCbDvpcxwy49BKWmEPwiW8mrysNiDvIQ==",
       "dev": true,
       "dependencies": {
         "@babel/code-frame": "^7.18.6",
-        "@babel/generator": "^7.18.9",
+        "@babel/generator": "^7.18.10",
         "@babel/helper-environment-visitor": "^7.18.9",
         "@babel/helper-function-name": "^7.18.9",
         "@babel/helper-hoist-variables": "^7.18.6",
         "@babel/helper-split-export-declaration": "^7.18.6",
-        "@babel/parser": "^7.18.9",
-        "@babel/types": "^7.18.9",
+        "@babel/parser": "^7.18.11",
+        "@babel/types": "^7.18.10",
         "debug": "^4.1.0",
         "globals": "^11.1.0"
       },
@@ -1635,11 +1642,12 @@
       }
     },
     "node_modules/@babel/types": {
-      "version": "7.18.9",
-      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.9.tgz",
-      "integrity": "sha512-WwMLAg2MvJmt/rKEVQBBhIVffMmnilX4oe0sRe7iPOHIGsqpruFHHdrfj4O1CMMtgMtCU4oPafZjDPCRgO57Wg==",
+      "version": "7.18.10",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.10.tgz",
+      "integrity": "sha512-MJvnbEiiNkpjo+LknnmRrqbY1GPUUggjv+wQVjetM/AONoupqRALB7I6jGqNUAZsKcRIEu2J6FRFvsczljjsaQ==",
       "dev": true,
       "dependencies": {
+        "@babel/helper-string-parser": "^7.18.10",
         "@babel/helper-validator-identifier": "^7.18.6",
         "to-fast-properties": "^2.0.0"
       },
@@ -2296,13 +2304,13 @@
       }
     },
     "node_modules/babel-plugin-polyfill-corejs2": {
-      "version": "0.3.1",
-      "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz",
-      "integrity": "sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==",
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.2.tgz",
+      "integrity": "sha512-LPnodUl3lS0/4wN3Rb+m+UK8s7lj2jcLRrjho4gLw+OJs+I4bvGXshINesY5xx/apM+biTnQ9reDI8yj+0M5+Q==",
       "dev": true,
       "dependencies": {
-        "@babel/compat-data": "^7.13.11",
-        "@babel/helper-define-polyfill-provider": "^0.3.1",
+        "@babel/compat-data": "^7.17.7",
+        "@babel/helper-define-polyfill-provider": "^0.3.2",
         "semver": "^6.1.1"
       },
       "peerDependencies": {
@@ -2310,12 +2318,12 @@
       }
     },
     "node_modules/babel-plugin-polyfill-corejs3": {
-      "version": "0.5.2",
-      "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz",
-      "integrity": "sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==",
+      "version": "0.5.3",
+      "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.3.tgz",
+      "integrity": "sha512-zKsXDh0XjnrUEW0mxIHLfjBfnXSMr5Q/goMe/fxpQnLm07mcOZiIZHBNWCMx60HmdvjxfXcalac0tfFg0wqxyw==",
       "dev": true,
       "dependencies": {
-        "@babel/helper-define-polyfill-provider": "^0.3.1",
+        "@babel/helper-define-polyfill-provider": "^0.3.2",
         "core-js-compat": "^3.21.0"
       },
       "peerDependencies": {
@@ -2323,12 +2331,12 @@
       }
     },
     "node_modules/babel-plugin-polyfill-regenerator": {
-      "version": "0.3.1",
-      "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz",
-      "integrity": "sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==",
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.0.tgz",
+      "integrity": "sha512-RW1cnryiADFeHmfLS+WW/G431p1PsW5qdRdz0SDRi7TKcUgc7Oh/uXkT7MZ/+tGsT1BkczEAmD5XjUyJ5SWDTw==",
       "dev": true,
       "dependencies": {
-        "@babel/helper-define-polyfill-provider": "^0.3.1"
+        "@babel/helper-define-polyfill-provider": "^0.3.2"
       },
       "peerDependencies": {
         "@babel/core": "^7.0.0-0"
@@ -2466,9 +2474,9 @@
       "dev": true
     },
     "node_modules/browserslist": {
-      "version": "4.21.2",
-      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.2.tgz",
-      "integrity": "sha512-MonuOgAtUB46uP5CezYbRaYKBNt2LxP0yX+Pmj4LkcDFGkn9Cbpi83d9sCjwQDErXsIJSzY5oKGDbgOlF/LPAA==",
+      "version": "4.21.3",
+      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz",
+      "integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==",
       "dev": true,
       "funding": [
         {
@@ -2481,10 +2489,10 @@
         }
       ],
       "dependencies": {
-        "caniuse-lite": "^1.0.30001366",
-        "electron-to-chromium": "^1.4.188",
+        "caniuse-lite": "^1.0.30001370",
+        "electron-to-chromium": "^1.4.202",
         "node-releases": "^2.0.6",
-        "update-browserslist-db": "^1.0.4"
+        "update-browserslist-db": "^1.0.5"
       },
       "bin": {
         "browserslist": "cli.js"
@@ -2569,9 +2577,9 @@
       }
     },
     "node_modules/caniuse-lite": {
-      "version": "1.0.30001368",
-      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001368.tgz",
-      "integrity": "sha512-wgfRYa9DenEomLG/SdWgQxpIyvdtH3NW8Vq+tB6AwR9e56iOIcu1im5F/wNdDf04XlKHXqIx4N8Jo0PemeBenQ==",
+      "version": "1.0.30001378",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001378.tgz",
+      "integrity": "sha512-JVQnfoO7FK7WvU4ZkBRbPjaot4+YqxogSDosHv0Hv5mWpUESmN+UubMU6L/hGz8QlQ2aY5U0vR6MOs6j/CXpNA==",
       "dev": true,
       "funding": [
         {
@@ -3043,12 +3051,12 @@
       }
     },
     "node_modules/core-js-compat": {
-      "version": "3.23.5",
-      "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.23.5.tgz",
-      "integrity": "sha512-fHYozIFIxd+91IIbXJgWd/igXIc8Mf9is0fusswjnGIWVG96y2cwyUdlCkGOw6rMLHKAxg7xtCIVaHsyOUnJIg==",
+      "version": "3.24.1",
+      "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.24.1.tgz",
+      "integrity": "sha512-XhdNAGeRnTpp8xbD+sR/HFDK9CbeeeqXT6TuofXh3urqEevzkWmLRgrVoykodsw8okqo2pu1BOmuCKrHx63zdw==",
       "dev": true,
       "dependencies": {
-        "browserslist": "^4.21.2",
+        "browserslist": "^4.21.3",
         "semver": "7.0.0"
       },
       "funding": {
@@ -3271,9 +3279,9 @@
       "dev": true
     },
     "node_modules/electron-to-chromium": {
-      "version": "1.4.198",
-      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.198.tgz",
-      "integrity": "sha512-jwqQPdKGeAslcq8L+1SZZgL6uDiIDmTe9Gq4brsdWAH27y7MJ2g9Ue6MyST3ogmSM49EAQP7bype1V5hsuNrmQ==",
+      "version": "1.4.222",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.222.tgz",
+      "integrity": "sha512-gEM2awN5HZknWdLbngk4uQCVfhucFAfFzuchP3wM3NN6eow1eDU0dFy2kts43FB20ZfhVFF0jmFSTb1h5OhyIg==",
       "dev": true
     },
     "node_modules/emoji-regex": {
@@ -3361,9 +3369,9 @@
       }
     },
     "node_modules/eslint": {
-      "version": "8.21.0",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.21.0.tgz",
-      "integrity": "sha512-/XJ1+Qurf1T9G2M5IHrsjp+xrGT73RZf23xA1z5wB1ZzzEAWSZKvRwhWxTFp1rvkvCfwcvAUNAP31bhKTTGfDA==",
+      "version": "8.22.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.22.0.tgz",
+      "integrity": "sha512-ci4t0sz6vSRKdmkOGmprBo6fmI4PrphDFMy5JEq/fNS0gQkJM3rLmrqcp8ipMcdobH3KtUP40KniAE9W19S4wA==",
       "dev": true,
       "dependencies": {
         "@eslint/eslintrc": "^1.3.0",
@@ -4363,9 +4371,9 @@
       }
     },
     "node_modules/is-core-module": {
-      "version": "2.9.0",
-      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz",
-      "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==",
+      "version": "2.10.0",
+      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz",
+      "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==",
       "dev": true,
       "dependencies": {
         "has": "^1.0.3"
@@ -6038,9 +6046,9 @@
       }
     },
     "node_modules/rollup": {
-      "version": "2.77.2",
-      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.77.2.tgz",
-      "integrity": "sha512-m/4YzYgLcpMQbxX3NmAqDvwLATZzxt8bIegO78FZLl+lAgKJBd1DRAOeEiZcKOIOPjxE6ewHWHNgGEalFXuz1g==",
+      "version": "2.78.0",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.78.0.tgz",
+      "integrity": "sha512-4+YfbQC9QEVvKTanHhIAFVUFSRsezvQF8vFOJwtGfb9Bb+r014S+qryr9PSmw8x6sMnPkmFBGAvIFVQxvJxjtg==",
       "dev": true,
       "bin": {
         "rollup": "dist/bin/rollup"
@@ -7348,21 +7356,21 @@
       "dev": true
     },
     "@babel/core": {
-      "version": "7.18.9",
-      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.9.tgz",
-      "integrity": "sha512-1LIb1eL8APMy91/IMW+31ckrfBM4yCoLaVzoDhZUKSM4cu1L1nIidyxkCgzPAgrC5WEz36IPEr/eSeSF9pIn+g==",
+      "version": "7.18.10",
+      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.10.tgz",
+      "integrity": "sha512-JQM6k6ENcBFKVtWvLavlvi/mPcpYZ3+R+2EySDEMSMbp7Mn4FexlbbJVrx2R7Ijhr01T8gyqrOaABWIOgxeUyw==",
       "dev": true,
       "requires": {
         "@ampproject/remapping": "^2.1.0",
         "@babel/code-frame": "^7.18.6",
-        "@babel/generator": "^7.18.9",
+        "@babel/generator": "^7.18.10",
         "@babel/helper-compilation-targets": "^7.18.9",
         "@babel/helper-module-transforms": "^7.18.9",
         "@babel/helpers": "^7.18.9",
-        "@babel/parser": "^7.18.9",
-        "@babel/template": "^7.18.6",
-        "@babel/traverse": "^7.18.9",
-        "@babel/types": "^7.18.9",
+        "@babel/parser": "^7.18.10",
+        "@babel/template": "^7.18.10",
+        "@babel/traverse": "^7.18.10",
+        "@babel/types": "^7.18.10",
         "convert-source-map": "^1.7.0",
         "debug": "^4.1.0",
         "gensync": "^1.0.0-beta.2",
@@ -7382,12 +7390,12 @@
       }
     },
     "@babel/generator": {
-      "version": "7.18.9",
-      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.9.tgz",
-      "integrity": "sha512-wt5Naw6lJrL1/SGkipMiFxJjtyczUWTP38deiP1PO60HsBjDeKk08CGC3S8iVuvf0FmTdgKwU1KIXzSKL1G0Ug==",
+      "version": "7.18.12",
+      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.12.tgz",
+      "integrity": "sha512-dfQ8ebCN98SvyL7IxNMCUtZQSq5R7kxgN+r8qYTGDmmSion1hX2C0zq2yo1bsCDhXixokv1SAWTZUMYbO/V5zg==",
       "dev": true,
       "requires": {
-        "@babel/types": "^7.18.9",
+        "@babel/types": "^7.18.10",
         "@jridgewell/gen-mapping": "^0.3.2",
         "jsesc": "^2.5.1"
       },
@@ -7462,15 +7470,13 @@
       }
     },
     "@babel/helper-define-polyfill-provider": {
-      "version": "0.3.1",
-      "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz",
-      "integrity": "sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==",
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.2.tgz",
+      "integrity": "sha512-r9QJJ+uDWrd+94BSPcP6/de67ygLtvVy6cK4luE6MOuDsZIdoaPBnfSpbO/+LTifjPckbKXRuI9BB/Z2/y3iTg==",
       "dev": true,
       "requires": {
-        "@babel/helper-compilation-targets": "^7.13.0",
-        "@babel/helper-module-imports": "^7.12.13",
-        "@babel/helper-plugin-utils": "^7.13.0",
-        "@babel/traverse": "^7.13.0",
+        "@babel/helper-compilation-targets": "^7.17.7",
+        "@babel/helper-plugin-utils": "^7.16.7",
         "debug": "^4.1.1",
         "lodash.debounce": "^4.0.8",
         "resolve": "^1.14.2",
@@ -7612,6 +7618,12 @@
         "@babel/types": "^7.18.6"
       }
     },
+    "@babel/helper-string-parser": {
+      "version": "7.18.10",
+      "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz",
+      "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==",
+      "dev": true
+    },
     "@babel/helper-validator-identifier": {
       "version": "7.18.6",
       "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz",
@@ -7659,9 +7671,9 @@
       }
     },
     "@babel/parser": {
-      "version": "7.18.9",
-      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.9.tgz",
-      "integrity": "sha512-9uJveS9eY9DJ0t64YbIBZICtJy8a5QrDEVdiLCG97fVLpDTpGX7t8mMSb6OWw6Lrnjqj4O8zwjELX3dhoMgiBg==",
+      "version": "7.18.11",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.11.tgz",
+      "integrity": "sha512-9JKn5vN+hDt0Hdqn1PiJ2guflwP+B6Ga8qbDuoF0PzzVhrzsKIJo8yGqVk6CmMHiMei9w1C1Bp9IMJSIK+HPIQ==",
       "dev": true
     },
     "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
@@ -7685,14 +7697,14 @@
       }
     },
     "@babel/plugin-proposal-async-generator-functions": {
-      "version": "7.18.6",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.18.6.tgz",
-      "integrity": "sha512-WAz4R9bvozx4qwf74M+sfqPMKfSqwM0phxPTR6iJIi8robgzXwkEgmeJG1gEKhm6sDqT/U9aV3lfcqybIpev8w==",
+      "version": "7.18.10",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.18.10.tgz",
+      "integrity": "sha512-1mFuY2TOsR1hxbjCo4QL+qlIjV07p4H4EUYw2J/WCqsvFV6V9X9z9YhXbWndc/4fw+hYGlDT7egYxliMp5O6Ew==",
       "dev": true,
       "requires": {
-        "@babel/helper-environment-visitor": "^7.18.6",
-        "@babel/helper-plugin-utils": "^7.18.6",
-        "@babel/helper-remap-async-to-generator": "^7.18.6",
+        "@babel/helper-environment-visitor": "^7.18.9",
+        "@babel/helper-plugin-utils": "^7.18.9",
+        "@babel/helper-remap-async-to-generator": "^7.18.9",
         "@babel/plugin-syntax-async-generators": "^7.8.4"
       }
     },
@@ -8276,12 +8288,12 @@
       }
     },
     "@babel/plugin-transform-unicode-escapes": {
-      "version": "7.18.6",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.6.tgz",
-      "integrity": "sha512-XNRwQUXYMP7VLuy54cr/KS/WeL3AZeORhrmeZ7iewgu+X2eBqmpaLI/hzqr9ZxCeUoq0ASK4GUzSM0BDhZkLFw==",
+      "version": "7.18.10",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz",
+      "integrity": "sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==",
       "dev": true,
       "requires": {
-        "@babel/helper-plugin-utils": "^7.18.6"
+        "@babel/helper-plugin-utils": "^7.18.9"
       }
     },
     "@babel/plugin-transform-unicode-regex": {
@@ -8295,9 +8307,9 @@
       }
     },
     "@babel/preset-env": {
-      "version": "7.18.9",
-      "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.18.9.tgz",
-      "integrity": "sha512-75pt/q95cMIHWssYtyfjVlvI+QEZQThQbKvR9xH+F/Agtw/s4Wfc2V9Bwd/P39VtixB7oWxGdH4GteTTwYJWMg==",
+      "version": "7.18.10",
+      "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.18.10.tgz",
+      "integrity": "sha512-wVxs1yjFdW3Z/XkNfXKoblxoHgbtUF7/l3PvvP4m02Qz9TZ6uZGxRVYjSQeR87oQmHco9zWitW5J82DJ7sCjvA==",
       "dev": true,
       "requires": {
         "@babel/compat-data": "^7.18.8",
@@ -8306,7 +8318,7 @@
         "@babel/helper-validator-option": "^7.18.6",
         "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6",
         "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.9",
-        "@babel/plugin-proposal-async-generator-functions": "^7.18.6",
+        "@babel/plugin-proposal-async-generator-functions": "^7.18.10",
         "@babel/plugin-proposal-class-properties": "^7.18.6",
         "@babel/plugin-proposal-class-static-block": "^7.18.6",
         "@babel/plugin-proposal-dynamic-import": "^7.18.6",
@@ -8366,13 +8378,13 @@
         "@babel/plugin-transform-sticky-regex": "^7.18.6",
         "@babel/plugin-transform-template-literals": "^7.18.9",
         "@babel/plugin-transform-typeof-symbol": "^7.18.9",
-        "@babel/plugin-transform-unicode-escapes": "^7.18.6",
+        "@babel/plugin-transform-unicode-escapes": "^7.18.10",
         "@babel/plugin-transform-unicode-regex": "^7.18.6",
         "@babel/preset-modules": "^0.1.5",
-        "@babel/types": "^7.18.9",
-        "babel-plugin-polyfill-corejs2": "^0.3.1",
-        "babel-plugin-polyfill-corejs3": "^0.5.2",
-        "babel-plugin-polyfill-regenerator": "^0.3.1",
+        "@babel/types": "^7.18.10",
+        "babel-plugin-polyfill-corejs2": "^0.3.2",
+        "babel-plugin-polyfill-corejs3": "^0.5.3",
+        "babel-plugin-polyfill-regenerator": "^0.4.0",
         "core-js-compat": "^3.22.1",
         "semver": "^6.3.0"
       }
@@ -8400,40 +8412,41 @@
       }
     },
     "@babel/template": {
-      "version": "7.18.6",
-      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.6.tgz",
-      "integrity": "sha512-JoDWzPe+wgBsTTgdnIma3iHNFC7YVJoPssVBDjiHfNlyt4YcunDtcDOUmfVDfCK5MfdsaIoX9PkijPhjH3nYUw==",
+      "version": "7.18.10",
+      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz",
+      "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==",
       "dev": true,
       "requires": {
         "@babel/code-frame": "^7.18.6",
-        "@babel/parser": "^7.18.6",
-        "@babel/types": "^7.18.6"
+        "@babel/parser": "^7.18.10",
+        "@babel/types": "^7.18.10"
       }
     },
     "@babel/traverse": {
-      "version": "7.18.9",
-      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.9.tgz",
-      "integrity": "sha512-LcPAnujXGwBgv3/WHv01pHtb2tihcyW1XuL9wd7jqh1Z8AQkTd+QVjMrMijrln0T7ED3UXLIy36P9Ao7W75rYg==",
+      "version": "7.18.11",
+      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.11.tgz",
+      "integrity": "sha512-TG9PiM2R/cWCAy6BPJKeHzNbu4lPzOSZpeMfeNErskGpTJx6trEvFaVCbDvpcxwy49BKWmEPwiW8mrysNiDvIQ==",
       "dev": true,
       "requires": {
         "@babel/code-frame": "^7.18.6",
-        "@babel/generator": "^7.18.9",
+        "@babel/generator": "^7.18.10",
         "@babel/helper-environment-visitor": "^7.18.9",
         "@babel/helper-function-name": "^7.18.9",
         "@babel/helper-hoist-variables": "^7.18.6",
         "@babel/helper-split-export-declaration": "^7.18.6",
-        "@babel/parser": "^7.18.9",
-        "@babel/types": "^7.18.9",
+        "@babel/parser": "^7.18.11",
+        "@babel/types": "^7.18.10",
         "debug": "^4.1.0",
         "globals": "^11.1.0"
       }
     },
     "@babel/types": {
-      "version": "7.18.9",
-      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.9.tgz",
-      "integrity": "sha512-WwMLAg2MvJmt/rKEVQBBhIVffMmnilX4oe0sRe7iPOHIGsqpruFHHdrfj4O1CMMtgMtCU4oPafZjDPCRgO57Wg==",
+      "version": "7.18.10",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.10.tgz",
+      "integrity": "sha512-MJvnbEiiNkpjo+LknnmRrqbY1GPUUggjv+wQVjetM/AONoupqRALB7I6jGqNUAZsKcRIEu2J6FRFvsczljjsaQ==",
       "dev": true,
       "requires": {
+        "@babel/helper-string-parser": "^7.18.10",
         "@babel/helper-validator-identifier": "^7.18.6",
         "to-fast-properties": "^2.0.0"
       }
@@ -8957,33 +8970,33 @@
       }
     },
     "babel-plugin-polyfill-corejs2": {
-      "version": "0.3.1",
-      "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz",
-      "integrity": "sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==",
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.2.tgz",
+      "integrity": "sha512-LPnodUl3lS0/4wN3Rb+m+UK8s7lj2jcLRrjho4gLw+OJs+I4bvGXshINesY5xx/apM+biTnQ9reDI8yj+0M5+Q==",
       "dev": true,
       "requires": {
-        "@babel/compat-data": "^7.13.11",
-        "@babel/helper-define-polyfill-provider": "^0.3.1",
+        "@babel/compat-data": "^7.17.7",
+        "@babel/helper-define-polyfill-provider": "^0.3.2",
         "semver": "^6.1.1"
       }
     },
     "babel-plugin-polyfill-corejs3": {
-      "version": "0.5.2",
-      "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz",
-      "integrity": "sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==",
+      "version": "0.5.3",
+      "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.3.tgz",
+      "integrity": "sha512-zKsXDh0XjnrUEW0mxIHLfjBfnXSMr5Q/goMe/fxpQnLm07mcOZiIZHBNWCMx60HmdvjxfXcalac0tfFg0wqxyw==",
       "dev": true,
       "requires": {
-        "@babel/helper-define-polyfill-provider": "^0.3.1",
+        "@babel/helper-define-polyfill-provider": "^0.3.2",
         "core-js-compat": "^3.21.0"
       }
     },
     "babel-plugin-polyfill-regenerator": {
-      "version": "0.3.1",
-      "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz",
-      "integrity": "sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==",
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.0.tgz",
+      "integrity": "sha512-RW1cnryiADFeHmfLS+WW/G431p1PsW5qdRdz0SDRi7TKcUgc7Oh/uXkT7MZ/+tGsT1BkczEAmD5XjUyJ5SWDTw==",
       "dev": true,
       "requires": {
-        "@babel/helper-define-polyfill-provider": "^0.3.1"
+        "@babel/helper-define-polyfill-provider": "^0.3.2"
       }
     },
     "balanced-match": {
@@ -9097,15 +9110,15 @@
       "dev": true
     },
     "browserslist": {
-      "version": "4.21.2",
-      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.2.tgz",
-      "integrity": "sha512-MonuOgAtUB46uP5CezYbRaYKBNt2LxP0yX+Pmj4LkcDFGkn9Cbpi83d9sCjwQDErXsIJSzY5oKGDbgOlF/LPAA==",
+      "version": "4.21.3",
+      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz",
+      "integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==",
       "dev": true,
       "requires": {
-        "caniuse-lite": "^1.0.30001366",
-        "electron-to-chromium": "^1.4.188",
+        "caniuse-lite": "^1.0.30001370",
+        "electron-to-chromium": "^1.4.202",
         "node-releases": "^2.0.6",
-        "update-browserslist-db": "^1.0.4"
+        "update-browserslist-db": "^1.0.5"
       }
     },
     "buffer-from": {
@@ -9163,9 +9176,9 @@
       "dev": true
     },
     "caniuse-lite": {
-      "version": "1.0.30001368",
-      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001368.tgz",
-      "integrity": "sha512-wgfRYa9DenEomLG/SdWgQxpIyvdtH3NW8Vq+tB6AwR9e56iOIcu1im5F/wNdDf04XlKHXqIx4N8Jo0PemeBenQ==",
+      "version": "1.0.30001378",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001378.tgz",
+      "integrity": "sha512-JVQnfoO7FK7WvU4ZkBRbPjaot4+YqxogSDosHv0Hv5mWpUESmN+UubMU6L/hGz8QlQ2aY5U0vR6MOs6j/CXpNA==",
       "dev": true
     },
     "catharsis": {
@@ -9527,12 +9540,12 @@
       "dev": true
     },
     "core-js-compat": {
-      "version": "3.23.5",
-      "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.23.5.tgz",
-      "integrity": "sha512-fHYozIFIxd+91IIbXJgWd/igXIc8Mf9is0fusswjnGIWVG96y2cwyUdlCkGOw6rMLHKAxg7xtCIVaHsyOUnJIg==",
+      "version": "3.24.1",
+      "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.24.1.tgz",
+      "integrity": "sha512-XhdNAGeRnTpp8xbD+sR/HFDK9CbeeeqXT6TuofXh3urqEevzkWmLRgrVoykodsw8okqo2pu1BOmuCKrHx63zdw==",
       "dev": true,
       "requires": {
-        "browserslist": "^4.21.2",
+        "browserslist": "^4.21.3",
         "semver": "7.0.0"
       },
       "dependencies": {
@@ -9696,9 +9709,9 @@
       "dev": true
     },
     "electron-to-chromium": {
-      "version": "1.4.198",
-      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.198.tgz",
-      "integrity": "sha512-jwqQPdKGeAslcq8L+1SZZgL6uDiIDmTe9Gq4brsdWAH27y7MJ2g9Ue6MyST3ogmSM49EAQP7bype1V5hsuNrmQ==",
+      "version": "1.4.222",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.222.tgz",
+      "integrity": "sha512-gEM2awN5HZknWdLbngk4uQCVfhucFAfFzuchP3wM3NN6eow1eDU0dFy2kts43FB20ZfhVFF0jmFSTb1h5OhyIg==",
       "dev": true
     },
     "emoji-regex": {
@@ -9768,9 +9781,9 @@
       "dev": true
     },
     "eslint": {
-      "version": "8.21.0",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.21.0.tgz",
-      "integrity": "sha512-/XJ1+Qurf1T9G2M5IHrsjp+xrGT73RZf23xA1z5wB1ZzzEAWSZKvRwhWxTFp1rvkvCfwcvAUNAP31bhKTTGfDA==",
+      "version": "8.22.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.22.0.tgz",
+      "integrity": "sha512-ci4t0sz6vSRKdmkOGmprBo6fmI4PrphDFMy5JEq/fNS0gQkJM3rLmrqcp8ipMcdobH3KtUP40KniAE9W19S4wA==",
       "dev": true,
       "requires": {
         "@eslint/eslintrc": "^1.3.0",
@@ -10514,9 +10527,9 @@
       }
     },
     "is-core-module": {
-      "version": "2.9.0",
-      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz",
-      "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==",
+      "version": "2.10.0",
+      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz",
+      "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==",
       "dev": true,
       "requires": {
         "has": "^1.0.3"
@@ -11776,9 +11789,9 @@
       }
     },
     "rollup": {
-      "version": "2.77.2",
-      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.77.2.tgz",
-      "integrity": "sha512-m/4YzYgLcpMQbxX3NmAqDvwLATZzxt8bIegO78FZLl+lAgKJBd1DRAOeEiZcKOIOPjxE6ewHWHNgGEalFXuz1g==",
+      "version": "2.78.0",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.78.0.tgz",
+      "integrity": "sha512-4+YfbQC9QEVvKTanHhIAFVUFSRsezvQF8vFOJwtGfb9Bb+r014S+qryr9PSmw8x6sMnPkmFBGAvIFVQxvJxjtg==",
       "dev": true,
       "requires": {
         "fsevents": "~2.3.2"
diff --git a/package.json b/package.json
index f16a5dbc9..6581c6389 100644
--- a/package.json
+++ b/package.json
@@ -75,9 +75,9 @@
     "README-zh.md"
   ],
   "devDependencies": {
-    "@babel/core": "^7.18.9",
+    "@babel/core": "^7.18.10",
     "@babel/eslint-parser": "^7.18.9",
-    "@babel/preset-env": "^7.18.9",
+    "@babel/preset-env": "^7.18.10",
     "@playcanvas/canvas-mock": "^1.0.1",
     "@playcanvas/eslint-config": "^1.2.0",
     "@playcanvas/jsdoc-template": "^1.0.27",
@@ -86,7 +86,7 @@
     "@rollup/pluginutils": "^4.2.1",
     "c8": "^7.12.0",
     "chai": "^4.3.6",
-    "eslint": "^8.21.0",
+    "eslint": "^8.22.0",
     "jsdoc": "^3.6.11",
     "jsdoc-tsimport-plugin": "^1.0.5",
     "karma": "^6.4.0",
@@ -94,7 +94,7 @@
     "karma-mocha": "2.0.1",
     "karma-spec-reporter": "^0.0.34",
     "mocha": "^10.0.0",
-    "rollup": "^2.77.2",
+    "rollup": "^2.78.0",
     "rollup-plugin-dts": "^4.2.2",
     "rollup-plugin-jscc": "2.0.0",
     "rollup-plugin-terser": "7.0.2",
diff --git a/src/asset/asset-list-loader.js b/src/asset/asset-list-loader.js
index 2b734e8d6..18d7b31e4 100644
--- a/src/asset/asset-list-loader.js
+++ b/src/asset/asset-list-loader.js
@@ -127,7 +127,7 @@ class AssetListLoader extends EventHandler {
             }
         });
         if (!loadingAssets && this._waitingAssets.size === 0) {
-            this.fire("load", Array.from(this._assets));
+            this._loadingComplete();
         }
     }
 
diff --git a/src/framework/components/camera/component.js b/src/framework/components/camera/component.js
index 42d7e58e2..ac9af8092 100644
--- a/src/framework/components/camera/component.js
+++ b/src/framework/components/camera/component.js
@@ -347,6 +347,10 @@ class CameraComponent extends Component {
         return this._camera.layers;
     }
 
+    get layersSet() {
+        return this._camera.layersSet;
+    }
+
     /**
      * The post effects queue for this camera. Use this to add or remove post effects from the camera.
      *
diff --git a/src/graphics/program-lib/chunks/lit/frag/refractionDynamic.js b/src/graphics/program-lib/chunks/lit/frag/refractionDynamic.js
index 61eaf6c45..9f9247b1d 100644
--- a/src/graphics/program-lib/chunks/lit/frag/refractionDynamic.js
+++ b/src/graphics/program-lib/chunks/lit/frag/refractionDynamic.js
@@ -53,6 +53,6 @@ void addRefraction() {
 
     // Apply fresnel effect on refraction
     vec3 fresnel = vec3(1.0) - getFresnel(dot(dViewDirW, dNormalW), dSpecularity);
-    dDiffuseLight = mix(dDiffuseLight, refraction * dAlbedo * transmittance * fresnel, dTransmission);
+    dDiffuseLight = mix(dDiffuseLight, refraction * transmittance * fresnel, dTransmission);
 }
 `;
diff --git a/src/graphics/program-lib/programs/basic.js b/src/graphics/program-lib/programs/basic.js
index ca7f550ae..5950bd33d 100644
--- a/src/graphics/program-lib/programs/basic.js
+++ b/src/graphics/program-lib/programs/basic.js
@@ -1,6 +1,5 @@
 import {
-    SEMANTIC_BLENDINDICES, SEMANTIC_BLENDWEIGHT, SEMANTIC_COLOR, SEMANTIC_POSITION, SEMANTIC_TEXCOORD0,
-    DEVICETYPE_WEBGPU
+    SEMANTIC_BLENDINDICES, SEMANTIC_BLENDWEIGHT, SEMANTIC_COLOR, SEMANTIC_POSITION, SEMANTIC_TEXCOORD0
 } from '../../constants.js';
 import { shaderChunks } from '../chunks/chunks.js';
 
@@ -8,10 +7,7 @@ import {
     SHADER_DEPTH, SHADER_PICK
 } from '../../../scene/constants.js';
 
-import { begin, end, fogCode, precisionCode, skinCode, versionCode } from './common.js';
-
-// Spector integration
-const shaderNameCode = '#define SHADER_NAME BasicMaterial\n';
+import { vertexIntro, fragmentIntro, begin, end, fogCode, skinCode } from './common.js';
 
 const basic = {
     generateKey: function (options) {
@@ -49,13 +45,7 @@ const basic = {
         }
 
         // GENERATE VERTEX SHADER
-        let code = versionCode(device) + shaderNameCode;
-
-        if (device.deviceType === DEVICETYPE_WEBGPU) {
-            code += shaderChunks.webgpuVS;
-        } else if (device.webgl2) {
-            code += shaderChunks.gles3VS;
-        }
+        let code = vertexIntro(device, 'BasicShader', options.pass);
 
         // VERTEX SHADER DECLARATIONS
         code += shaderChunks.transformDeclVS;
@@ -109,14 +99,7 @@ const basic = {
         const vshader = code;
 
         // GENERATE FRAGMENT SHADER
-        code = versionCode(device) + precisionCode(device);
-        code += shaderNameCode;
-
-        if (device.deviceType === DEVICETYPE_WEBGPU) {
-            code += shaderChunks.webgpuPS;
-        } else if (device.webgl2) {
-            code += shaderChunks.gles3PS;
-        }
+        code = fragmentIntro(device, 'BasicMaterial', options.pass);
 
         // FRAGMENT SHADER DECLARATIONS
         if (options.vertexColors) {
diff --git a/src/graphics/program-lib/programs/common.js b/src/graphics/program-lib/programs/common.js
index f03497104..6a724d357 100644
--- a/src/graphics/program-lib/programs/common.js
+++ b/src/graphics/program-lib/programs/common.js
@@ -1,11 +1,12 @@
 import {
-    DEVICETYPE_WEBGPU
+    DEVICETYPE_WEBGPU, DEVICETYPE_WEBGL
 } from '../../../graphics/constants.js';
 
 import {
     GAMMA_SRGB, GAMMA_SRGBFAST, GAMMA_SRGBHDR,
     TONEMAP_ACES, TONEMAP_ACES2, TONEMAP_FILMIC, TONEMAP_HEJL, TONEMAP_LINEAR
 } from '../../../scene/constants.js';
+import { ShaderPass } from '../../../scene/shader-pass.js';
 
 import { shaderChunks } from '../chunks/chunks.js';
 
@@ -55,18 +56,36 @@ function skinCode(device, chunks) {
     return "#define BONE_LIMIT " + device.getBoneLimit() + "\n" + chunks.skinConstVS;
 }
 
-function precisionCode(device) {
+function precisionCode(device, forcePrecision, shadowPrecision) {
 
-    // temporarily ignore precision for WebGPU
-    if (device.deviceType === DEVICETYPE_WEBGPU) {
-        return '';
-    }
+    let code = '';
+
+    if (device.deviceType === DEVICETYPE_WEBGL) {
+
+        if (forcePrecision && forcePrecision !== 'highp' && forcePrecision !== 'mediump' && forcePrecision !== 'lowp') {
+            forcePrecision = null;
+        }
+
+        if (forcePrecision) {
+            if (forcePrecision === 'highp' && device.maxPrecision !== 'highp') {
+                forcePrecision = 'mediump';
+            }
+            if (forcePrecision === 'mediump' && device.maxPrecision === 'lowp') {
+                forcePrecision = 'lowp';
+            }
+        }
 
-    let pcode = 'precision ' + device.precision + ' float;\n';
-    if (device.webgl2) {
-        pcode += '#ifdef GL2\nprecision ' + device.precision + ' sampler2DShadow;\n#endif\n';
+        const precision = forcePrecision ? forcePrecision : device.precision;
+        code = `precision ${precision} float;\n`;
+
+        // TODO: this can be only set on shaders with version 300 or more, so make this optional as many
+        // internal shaders (particles..) are from webgl1 era and don't set any precision. Modified when upgraded.
+        if (shadowPrecision && device.webgl2) {
+            code += `precision ${precision} sampler2DShadow;\n`;
+        }
     }
-    return pcode;
+
+    return code;
 }
 
 function versionCode(device) {
@@ -77,6 +96,73 @@ function versionCode(device) {
     return device.webgl2 ? "#version 300 es\n" : "";
 }
 
+// SpectorJS integration
+function getShaderNameCode(name) {
+    return `#define SHADER_NAME ${name}\n`;
+}
+
+function vertexIntro(device, name, pass, extensionCode) {
+
+    let code = versionCode(device);
+
+    if (device.deviceType === DEVICETYPE_WEBGPU) {
+
+        code += shaderChunks.webgpuVS;
+
+    } else {    // WebGL
+
+        if (extensionCode) {
+            code += extensionCode + "\n";
+        }
+
+        if (device.webgl2) {
+            code += shaderChunks.gles3VS;
+        }
+    }
+
+    code += getShaderNameCode(name);
+    code += ShaderPass.getPassShaderDefine(pass);
+
+    return code;
+}
+
+function fragmentIntro(device, name, pass, extensionCode, forcePrecision) {
+
+    let code = versionCode(device);
+    code += precisionCode(device, forcePrecision, true);
+
+    if (device.deviceType === DEVICETYPE_WEBGPU) {
+
+        code += shaderChunks.webgpuPS;
+
+    } else {    // WebGL
+
+        if (extensionCode) {
+            code += extensionCode + "\n";
+        }
+
+        if (device.webgl2) {    // WebGL 2
+
+            code += shaderChunks.gles3PS;
+
+        } else {    // WebGL 1
+
+            if (device.extStandardDerivatives) {
+                code += "#extension GL_OES_standard_derivatives : enable\n";
+            }
+            if (device.extTextureLod) {
+                code += "#extension GL_EXT_shader_texture_lod : enable\n";
+                code += "#define SUPPORTS_TEXLOD\n";
+            }
+        }
+    }
+
+    code += getShaderNameCode(name);
+    code += ShaderPass.getPassShaderDefine(pass);
+
+    return code;
+}
+
 function dummyFragmentCode() {
     return "void main(void) {gl_FragColor = vec4(0.0);}";
 }
@@ -89,4 +175,4 @@ function end() {
     return '}\n';
 }
 
-export { begin, end, dummyFragmentCode, fogCode, gammaCode, precisionCode, skinCode, tonemapCode, versionCode };
+export { vertexIntro, fragmentIntro, begin, end, dummyFragmentCode, fogCode, gammaCode, precisionCode, skinCode, tonemapCode, versionCode };
diff --git a/src/graphics/program-lib/programs/lit-shader.js b/src/graphics/program-lib/programs/lit-shader.js
index c88f2543b..1b4b36601 100644
--- a/src/graphics/program-lib/programs/lit-shader.js
+++ b/src/graphics/program-lib/programs/lit-shader.js
@@ -1,5 +1,4 @@
 import {
-    DEVICETYPE_WEBGPU,
     SEMANTIC_ATTR8, SEMANTIC_ATTR9, SEMANTIC_ATTR10, SEMANTIC_ATTR11, SEMANTIC_ATTR12, SEMANTIC_ATTR13, SEMANTIC_ATTR14, SEMANTIC_ATTR15,
     SEMANTIC_BLENDINDICES, SEMANTIC_BLENDWEIGHT, SEMANTIC_COLOR, SEMANTIC_NORMAL, SEMANTIC_POSITION, SEMANTIC_TANGENT,
     SEMANTIC_TEXCOORD0, SEMANTIC_TEXCOORD1,
@@ -24,7 +23,7 @@ import {
 import { LightsBuffer } from '../../../scene/lighting/lights-buffer.js';
 import { ShaderPass } from '../../../scene/shader-pass.js';
 
-import { begin, end, fogCode, gammaCode, precisionCode, skinCode, tonemapCode, versionCode } from './common.js';
+import { vertexIntro, fragmentIntro, begin, end, fogCode, gammaCode, skinCode, tonemapCode } from './common.js';
 import { validateUserChunks } from '../chunks/chunk-validation.js';
 
 const builtinAttributes = {
@@ -85,22 +84,6 @@ class LitShader {
             this.chunks = shaderChunks;
         }
 
-        if (options.forceFragmentPrecision &&
-            options.forceFragmentPrecision !== "highp" &&
-            options.forceFragmentPrecision !== "mediump" &&
-            options.forceFragmentPrecision !== "lowp") {
-            options.forceFragmentPrecision = null;
-        }
-
-        if (options.forceFragmentPrecision) {
-            if (options.forceFragmentPrecision === "highp" && device.maxPrecision !== "highp") {
-                options.forceFragmentPrecision = "mediump";
-            }
-            if (options.forceFragmentPrecision === "mediump" && device.maxPrecision === "lowp") {
-                options.forceFragmentPrecision = "lowp";
-            }
-        }
-
         this.lighting = (options.lights.length > 0) || !!options.dirLightMap || !!options.clusteredLightingEnabled;
         this.reflections = !!options.reflectionSource;
         if (!options.useSpecular) options.specularMap = options.glossMap = null;
@@ -128,17 +111,6 @@ class LitShader {
         this.fshader = null;
     }
 
-    _getPassDefineString(pass) {
-        if (pass === SHADER_PICK) {
-            return '#define PICK_PASS\n';
-        } else if (pass === SHADER_DEPTH) {
-            return '#define DEPTH_PASS\n';
-        } else if (ShaderPass.isShadow(pass)) {
-            return '#define SHADOW_PASS\n';
-        }
-        return '';
-    }
-
     _vsAddBaseCode(code, chunks, options) {
         code += chunks.baseVS;
         if (options.nineSlicedMode === SPRITE_RENDERMODE_SLICED ||
@@ -251,8 +223,6 @@ class LitShader {
         let code = '';
         let codeBody = '';
 
-        code += this._getPassDefineString(options.pass);
-
         // code += chunks.baseVS;
         code = this._vsAddBaseCode(code, chunks, options);
 
@@ -447,49 +417,17 @@ class LitShader {
             }
         });
 
-        let startCode = "";
-        if (device.webgl2) {
-            startCode = versionCode(device);
-            if (chunks.extensionVS) {
-                startCode += chunks.extensionVS + "\n";
-            }
-            startCode += chunks.gles3VS;
-        } else {
-            if (chunks.extensionVS) {
-                startCode = chunks.extensionVS + "\n";
-            }
-        }
-
+        const startCode = vertexIntro(device, 'LitShader', this.options.pass, chunks.extensionVS);
         this.vshader = startCode + this.varyings + code;
     }
 
     _fsGetBeginCode() {
-        let code = '';
 
-        if (this.device.webgl2) {
-            code += versionCode(this.device);
-        } else {
-            if (this.device.extStandardDerivatives) {
-                code += "#extension GL_OES_standard_derivatives : enable\n";
-            }
-            if (this.device.extTextureLod) {
-                code += "#extension GL_EXT_shader_texture_lod : enable\n";
-                code += "#define SUPPORTS_TEXLOD\n";
-            }
-        }
-
-        if (this.chunks.extensionPS) {
-            code += this.chunks.extensionPS + "\n";
-        }
-
-        if (this.device.deviceType === DEVICETYPE_WEBGPU) {
-            code += this.chunks.webgpuPS;
-        } else if (this.device.webgl2) {
-            code += this.chunks.gles3PS;
-        }
+        const device = this.device;
+        const chunks = this.chunks;
 
-        code += this.options.forceFragmentPrecision ? "precision " + this.options.forceFragmentPrecision + " float;\n\n" : precisionCode(this.device);
-        code += this._getPassDefineString(this.options.pass);
+        const precision = this.options.forceFragmentPrecision;
+        let code = fragmentIntro(device, 'LitShader', this.options.pass, chunks.extensionPS, precision);
 
         for (let i = 0; i < this.defines.length; i++) {
             code += `#define ${this.defines[i]}\n`;
diff --git a/src/graphics/shader.js b/src/graphics/shader.js
index be2d5e376..cb68b2ff3 100644
--- a/src/graphics/shader.js
+++ b/src/graphics/shader.js
@@ -76,7 +76,9 @@ class Shader {
         this.definition = definition;
         this.name = definition.name || 'Untitled';
 
-        Debug.trace(TRACEID_SHADER_ALLOC, `Alloc: Id ${this.id} ${this.name}`);
+        Debug.trace(TRACEID_SHADER_ALLOC, `Alloc: Id ${this.id} ${this.name}`, {
+            definition
+        });
 
         Debug.assert(definition.vshader, 'No vertex shader has been specified when creating a shader.');
         Debug.assert(definition.fshader, 'No fragment shader has been specified when creating a shader.');
diff --git a/src/input/element-input.js b/src/input/element-input.js
index 32e531422..e7f55a1dd 100644
--- a/src/input/element-input.js
+++ b/src/input/element-input.js
@@ -948,6 +948,11 @@ class ElementInput {
         for (let i = 0, len = this._elements.length; i < len; i++) {
             const element = this._elements[i];
 
+            // check if any of the layers this element renders to is being rendered by the camera
+            if (!element.layers.some(v => camera.layersSet.has(v))) {
+                continue;
+            }
+
             if (element.screen && element.screen.screen.screenSpace) {
                 if (rayScreen === undefined) {
                     rayScreen = this._calculateRayScreen(x, y, camera, rayA) ? rayA : null;
@@ -999,6 +1004,11 @@ class ElementInput {
         for (let i = 0, len = this._elements.length; i < len; i++) {
             const element = this._elements[i];
 
+            // check if any of the layers this element renders to is being rendered by the camera
+            if (!element.layers.some(v => camera.layersSet.has(v))) {
+                continue;
+            }
+
             if (!element.screen || !element.screen.screen.screenSpace) {
                 if (this._checkElement(rayA, element, false) >= 0) {
                     result = element;
diff --git a/src/resources/parser/glb-container-resource.js b/src/resources/parser/glb-container-resource.js
index ab7e89b9d..dbb0d9dfa 100644
--- a/src/resources/parser/glb-container-resource.js
+++ b/src/resources/parser/glb-container-resource.js
@@ -259,7 +259,8 @@ class GlbContainerResource {
     static createModel(glb, defaultMaterial) {
 
         const createMeshInstance = function (model, mesh, skins, skinInstances, materials, node, gltfNode) {
-            const material = (mesh.materialIndex === undefined) ? defaultMaterial : materials[mesh.materialIndex];
+            const materialIndex = glb.meshDefaultMaterials[mesh.id];
+            const material = (materialIndex === undefined) ? defaultMaterial : materials[materialIndex];
             const meshInstance = new MeshInstance(mesh, material, node);
 
             if (mesh.morph) {
diff --git a/src/scene/camera.js b/src/scene/camera.js
index 98d52f88d..63fe50d63 100644
--- a/src/scene/camera.js
+++ b/src/scene/camera.js
@@ -42,6 +42,7 @@ class Camera {
         this._frustumCulling = true;
         this._horizontalFov = false;
         this._layers = [LAYERID_WORLD, LAYERID_DEPTH, LAYERID_SKYBOX, LAYERID_UI, LAYERID_IMMEDIATE];
+        this._layersSet = new Set(this._layers);
         this._nearClip = 0.1;
         this._node = null;
         this._orthoHeight = 10;
@@ -225,12 +226,17 @@ class Camera {
 
     set layers(newValue) {
         this._layers = newValue.slice(0);
+        this._layersSet = new Set(this._layers);
     }
 
     get layers() {
         return this._layers;
     }
 
+    get layersSet() {
+        return this._layersSet;
+    }
+
     set nearClip(newValue) {
         if (this._nearClip !== newValue) {
             this._nearClip = newValue;
diff --git a/src/scene/shader-pass.js b/src/scene/shader-pass.js
index 2ee2a8b32..7932a042e 100644
--- a/src/scene/shader-pass.js
+++ b/src/scene/shader-pass.js
@@ -89,6 +89,23 @@ class ShaderPass {
         Debug.assert(ShaderPass.isShadow(pass));
         return pass;
     }
+
+    /**
+     * Returns the define code line for the shader pass.
+     *
+     * @param {number} pass - The shader pass.
+     * @returns {string} - A code line.
+     */
+    static getPassShaderDefine(pass) {
+        if (pass === SHADER_PICK) {
+            return '#define PICK_PASS\n';
+        } else if (pass === SHADER_DEPTH) {
+            return '#define DEPTH_PASS\n';
+        } else if (ShaderPass.isShadow(pass)) {
+            return '#define SHADOW_PASS\n';
+        }
+        return '';
+    }
 }
 
 export { ShaderPass };


Test patch:
diff --git a/test/asset/asset-list-loader.test.mjs b/test/asset/asset-list-loader.test.mjs
index 9da9a04d6..0a0e0bae7 100644
--- a/test/asset/asset-list-loader.test.mjs
+++ b/test/asset/asset-list-loader.test.mjs
@@ -113,7 +113,7 @@ describe('AssetListLoader', function () {
 
     describe('#load', function () {
 
-        it('can succeed if an asset is already loaded', function (done) {
+        it('can call the ready callback if an asset is already loaded', function (done) {
             const asset = new Asset('model', 'container', { url: `${assetPath}test.glb` });
             const assetListLoader = new AssetListLoader([asset], app.assets);
             asset.on('load', (asset) => {
@@ -130,6 +130,19 @@ describe('AssetListLoader', function () {
             app.assets.load(asset);
         });
 
+        it('can call the load callback if an asset is already loaded', function (done) {
+            const asset = new Asset('model', 'container', { url: `${assetPath}test.glb` });
+            const assetListLoader = new AssetListLoader([asset], app.assets);
+            asset.on('load', (asset) => {
+                expect(asset.loaded).to.equal(true);
+                assetListLoader.load(() => {
+                    done();
+                });
+            });
+            app.assets.add(asset);
+            app.assets.load(asset);
+        });
+
         it('can succeed if one asset is already loaded and another is not', function (done) {
             const assets = [
                 new Asset('model', 'container', { url: `${assetPath}test.glb` }),