From e26de2af912d3bd8c4481eeb654b5c77dcbf5720 Mon Sep 17 00:00:00 2001 From: Nev Wylie <54870357+MSNev@users.noreply.github.com> Date: Thu, 30 Jan 2025 12:55:01 -0800 Subject: [PATCH] [BUG] The regex used to parse the stack trace appears to be skipping anonymous lines #2467 --- AISKU/Tests/Unit/src/AISKUSize.Tests.ts | 4 +- .../Unit/src/applicationinsights.e2e.tests.ts | 197 ++- .../Tests/Unit/src/AISKULightSize.Tests.ts | 8 +- common/config/rush/npm-shrinkwrap.json | 1072 +++++++++-------- .../Tests/Unit/src/Exception.tests.ts | 378 +++++- .../src/Telemetry/Exception.ts | 649 +++++++--- 6 files changed, 1583 insertions(+), 725 deletions(-) diff --git a/AISKU/Tests/Unit/src/AISKUSize.Tests.ts b/AISKU/Tests/Unit/src/AISKUSize.Tests.ts index d806f3ece..e3711cb49 100644 --- a/AISKU/Tests/Unit/src/AISKUSize.Tests.ts +++ b/AISKU/Tests/Unit/src/AISKUSize.Tests.ts @@ -54,8 +54,8 @@ function _checkSize(checkType: string, maxSize: number, size: number, isNightly: } export class AISKUSizeCheck extends AITestClass { - private readonly MAX_RAW_SIZE = 144; - private readonly MAX_BUNDLE_SIZE = 144; + private readonly MAX_RAW_SIZE = 145; + private readonly MAX_BUNDLE_SIZE = 145; private readonly MAX_RAW_DEFLATE_SIZE = 58; private readonly MAX_BUNDLE_DEFLATE_SIZE = 58; private readonly rawFilePath = "../dist/es5/applicationinsights-web.min.js"; diff --git a/AISKU/Tests/Unit/src/applicationinsights.e2e.tests.ts b/AISKU/Tests/Unit/src/applicationinsights.e2e.tests.ts index 34e62cd3b..68c807d71 100644 --- a/AISKU/Tests/Unit/src/applicationinsights.e2e.tests.ts +++ b/AISKU/Tests/Unit/src/applicationinsights.e2e.tests.ts @@ -8,7 +8,15 @@ import { TelemetryContext } from '@microsoft/applicationinsights-properties-js'; import { createAsyncResolvedPromise } from '@nevware21/ts-async'; import { CONFIG_ENDPOINT_URL } from '../../../src/InternalConstants'; import { OfflineChannel } from '@microsoft/applicationinsights-offlinechannel-js'; - +import { IStackFrame } from '@microsoft/applicationinsights-common/src/Interfaces/Contracts/IStackFrame'; + +function _checkExpectedFrame(expectedFrame: IStackFrame, actualFrame: IStackFrame, index: number) { + Assert.equal(expectedFrame.assembly, actualFrame.assembly, index + ") Assembly is not as expected"); + Assert.equal(expectedFrame.fileName, actualFrame.fileName, index + ") FileName is not as expected"); + Assert.equal(expectedFrame.line, actualFrame.line, index + ") Line is not as expected"); + Assert.equal(expectedFrame.method, actualFrame.method, index + ") Method is not as expected"); + Assert.equal(expectedFrame.level, actualFrame.level, index + ") Level is not as expected"); +} export class ApplicationInsightsTests extends AITestClass { private static readonly _instrumentationKey = 'b7170927-2d1c-44f1-acec-59f4e1751c11'; @@ -1058,6 +1066,193 @@ export class ApplicationInsightsTests extends AITestClass { }) }); + this.testCaseAsync({ + name: "E2E.GenericTests: trackException with multiple stack frame formats", + stepDelay: 1, + steps: [() => { + let errObj = { + name: "E2E.GenericTests", + reason:{ + message: "Test_Error_Throwing_Inside_UseCallback", + stack: "Error: Test_Error_Throwing_Inside_UseCallback\n" + + "at http://localhost:3000/static/js/main.206f4846.js:2:296748\n" + // Anonymous function with no function name attribution (firefox/ios) + "at Object.Re (http://localhost:3000/static/js/main.206f4846.js:2:16814)\n" + // With class.function attribution + "at je (http://localhost:3000/static/js/main.206f4846.js:2:16968)\n" + // With function name attribution + "at Object. (http://localhost:3000/static/js/main.206f4846.js:2:42819)\n" + // With Object. attribution + "at Object. (../localfile.js:2:1234)\n" + // With Object. attribution and local file + "at (anonymous) @ VM60:1\n" + // With (anonymous) attribution + "at [native code]\n" + // With [native code] attribution + "at (at eval at (http://localhost:3000/static/js/main.206f4846.js:2:296748), :1:1)\n" + // With eval attribution + "at Object.eval (http://localhost:3000/static/js/main.206f4846.js:2:296748)\n" + // With eval attribution + "at eval (http://localhost:3000/static/js/main.206f4846.js:2:296748)\n" + // With eval attribution + "at eval (webpack-internal:///./src/App.tsx:1:1)\n" + // With eval attribution + "at [arguments not available])@file://localhost/stacktrace.js:21\n" + // With arguments not available attribution + "at file://C:/Temp/stacktrace.js:27:1\n" + // With file://localhost attribution + " Line 21 of linked script file://localhost/C:/Temp/stacktrace.js\n" + // With Line 21 of linked script attribution + " Line 11 of inline#1 script in http://localhost:3000/static/js/main.206f4846.js:2:296748\n" + // With Line 11 of inline#1 script attribution + " Line 68 of inline#2 script in file://localhost/teststack.html\n" + // With Line 68 of inline#2 script attribution + "at Function.Module._load (module.js:407:3)\n" + + " at Function.Module.runMain (module.js:575:10)\n"+ + " at startup (node.js:159:18)\n" + + "at Global code (http://example.com/stacktrace.js:11:1)\n" + + "at Object.Module._extensions..js (module.js:550:10)\n" + + " at c@http://example.com/stacktrace.js:9:3\n" + + " at b@http://example.com/stacktrace.js:6:3\n" + + " at a@http://example.com/stacktrace.js:3:3\n" + + "http://localhost:3000/static/js/main.206f4846.js:2:296748\n" + // Anonymous function with no function name attribution (firefox/ios) + " c@http://example.com/stacktrace.js:9:3\n" + + " b@http://example.com/stacktrace.js:6:3\n" + + " a@http://example.com/stacktrace.js:3:3\n" + + " at Object.testMethod (http://localhost:9001/shared/AppInsightsCommon/node_modules/@microsoft/ai-test-framework/dist/es5/ai-test-framework.js:53058:48)" + } + }; + + let exception = Exception.CreateAutoException("Test_Error_Throwing_Inside_UseCallback", + "url", + 9, + 0, + errObj + ); + this._ai.trackException({ exception: exception }, { custom: "custom value" }); + }].concat(this.asserts(1)).concat(() => { + + const expectedParsedStack: IStackFrame[] = [ + { level: 0, method: "", assembly: "at http://localhost:3000/static/js/main.206f4846.js:2:296748", fileName: "http://localhost:3000/static/js/main.206f4846.js", line: 2 }, + { level: 1, method: "Object.Re", assembly: "at Object.Re (http://localhost:3000/static/js/main.206f4846.js:2:16814)", fileName: "http://localhost:3000/static/js/main.206f4846.js", line: 2 }, + { level: 2, method: "je", assembly: "at je (http://localhost:3000/static/js/main.206f4846.js:2:16968)", fileName: "http://localhost:3000/static/js/main.206f4846.js", line: 2 }, + { level: 3, method: "Object.", assembly: "at Object. (http://localhost:3000/static/js/main.206f4846.js:2:42819)", fileName: "http://localhost:3000/static/js/main.206f4846.js", line: 2 }, + { level: 4, method: "Object.", assembly: "at Object. (../localfile.js:2:1234)", fileName: "../localfile.js", line: 2 }, + { level: 5, method: "", assembly: "at (anonymous) @ VM60:1", fileName: "VM60", line: 1 }, + { level: 6, method: "", assembly: "at [native code]", fileName: "", line: 0 }, + { level: 7, method: "", assembly: "at (at eval at (http://localhost:3000/static/js/main.206f4846.js:2:296748), :1:1)", fileName: "http://localhost:3000/static/js/main.206f4846.js", line: 2 }, + { level: 8, method: "Object.eval", assembly: "at Object.eval (http://localhost:3000/static/js/main.206f4846.js:2:296748)", fileName: "http://localhost:3000/static/js/main.206f4846.js", line: 2 }, + { level: 9, method: "eval", assembly: "at eval (http://localhost:3000/static/js/main.206f4846.js:2:296748)", fileName: "http://localhost:3000/static/js/main.206f4846.js", line: 2 }, + { level: 10, method: "eval", assembly: "at eval (webpack-internal:///./src/App.tsx:1:1)", fileName: "webpack-internal:///./src/App.tsx", line: 1 }, + { level: 11, method: "", assembly: "at [arguments not available])@file://localhost/stacktrace.js:21", fileName: "file://localhost/stacktrace.js", line: 21 }, + { level: 12, method: "", assembly: "at file://C:/Temp/stacktrace.js:27:1", fileName: "file://C:/Temp/stacktrace.js", line: 27 }, + { level: 13, method: "", assembly: "Line 21 of linked script file://localhost/C:/Temp/stacktrace.js", fileName: "file://localhost/C:/Temp/stacktrace.js", line: 0 }, + { level: 14, method: "", assembly: "Line 11 of inline#1 script in http://localhost:3000/static/js/main.206f4846.js:2:296748", fileName: "http://localhost:3000/static/js/main.206f4846.js", line: 2 }, + { level: 15, method: "", assembly: "Line 68 of inline#2 script in file://localhost/teststack.html", fileName: "file://localhost/teststack.html", line: 0 }, + { level: 16, method: "Function.Module._load", assembly: "at Function.Module._load (module.js:407:3)", fileName: "module.js", line: 407 }, + { level: 17, method: "Function.Module.runMain", assembly: "at Function.Module.runMain (module.js:575:10)", fileName: "module.js", line: 575 }, + { level: 18, method: "startup", assembly: "at startup (node.js:159:18)", fileName: "node.js", line: 159 }, + { level: 19, method: "", assembly: "at Global code (http://example.com/stacktrace.js:11:1)", fileName: "http://example.com/stacktrace.js", line: 11 }, + { level: 20, method: "Object.Module._extensions..js", assembly: "at Object.Module._extensions..js (module.js:550:10)", fileName: "module.js", line: 550 }, + { level: 21, method: "c", assembly: "at c@http://example.com/stacktrace.js:9:3", fileName: "http://example.com/stacktrace.js", line: 9 }, + { level: 22, method: "b", assembly: "at b@http://example.com/stacktrace.js:6:3", fileName: "http://example.com/stacktrace.js", line: 6 }, + { level: 23, method: "a", assembly: "at a@http://example.com/stacktrace.js:3:3", fileName: "http://example.com/stacktrace.js", line: 3 }, + { level: 24, method: "", assembly: "http://localhost:3000/static/js/main.206f4846.js:2:296748", fileName: "http://localhost:3000/static/js/main.206f4846.js", line: 2 }, + { level: 25, method: "c", assembly: "c@http://example.com/stacktrace.js:9:3", fileName: "http://example.com/stacktrace.js", line: 9 }, + { level: 26, method: "b", assembly: "b@http://example.com/stacktrace.js:6:3", fileName: "http://example.com/stacktrace.js", line: 6 }, + { level: 27, method: "a", assembly: "a@http://example.com/stacktrace.js:3:3", fileName: "http://example.com/stacktrace.js", line: 3 }, + { level: 28, method: "Object.testMethod", assembly: "at Object.testMethod (http://localhost:9001/shared/AppInsightsCommon/node_modules/@microsoft/ai-test-framework/dist/es5/ai-test-framework.js:53058:48)", fileName: "http://localhost:9001/shared/AppInsightsCommon/node_modules/@microsoft/ai-test-framework/dist/es5/ai-test-framework.js", line: 53058 } + ]; + + const payloadStr: string[] = this.getPayloadMessages(this.successSpy); + if (payloadStr.length > 0) { + const payload = JSON.parse(payloadStr[0]); + const data = payload.data; + Assert.ok(data, "Has Data"); + if (data) { + Assert.ok(data.baseData, "Has BaseData"); + let baseData = data.baseData; + if (baseData) { + const ex = baseData.exceptions[0]; + Assert.ok(ex.message.indexOf("Test_Error_Throwing_Inside_UseCallback") !== -1, "Make sure the error message is present [" + ex.message + "]"); + Assert.ok(ex.stack.length > 0, "Has stack"); + Assert.ok(ex.parsedStack, "Stack was parsed"); + Assert.ok(ex.hasFullStack, "Stack has been decoded"); + Assert.equal(ex.parsedStack.length, 29); + for (let lp = 0; lp < ex.parsedStack.length; lp++) { + _checkExpectedFrame(expectedParsedStack[lp], ex.parsedStack[lp], lp); + } + + Assert.ok(baseData.properties, "Has BaseData properties"); + Assert.equal(baseData.properties.custom, "custom value"); + + } + } + } + }) + }) + + this.testCaseAsync({ + name: "E2E.GenericTests: trackException with multiple line message", + stepDelay: 1, + steps: [() => { + let message = "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n" + + "1. You might have mismatching versions of React and the renderer (such as React DOM)\n" + + "2. You might be breaking the Rules of Hooks\n" + + "3. You might have more than one copy of React in the same app\n" + + "See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem."; + let errObj = { + typeName: "Error", + reason:{ + message: "Error: " + message, + stack: "Error: " + message + "\n" + + " at Object.throwInvalidHookError (https://localhost:44365/static/js/bundle.js:201419:13)\n" + + " at useContext (https://localhost:44365/static/js/bundle.js:222943:25)\n" + + " at useTenantContext (https://localhost:44365/static/js/bundle.js:5430:68)\n" + + " at https://localhost:44365/static/js/bundle.js:4337:72\n" + + " at _ZoneDelegate.invoke (https://localhost:44365/static/js/bundle.js:227675:158)\n" + + " at ZoneImpl.run (https://localhost:44365/static/js/bundle.js:227446:35)\n" + + " at https://localhost:44365/static/js/bundle.js:229764:30\n" + + " at _ZoneDelegate.invokeTask (https://localhost:44365/static/js/bundle.js:227700:171)\n" + + " at ZoneImpl.runTask (https://localhost:44365/static/js/bundle.js:227499:37)\n" + + " at ZoneImpl.patchRunTask (https://localhost:44365/static/js/bundle.js:144112:27)" + } + }; + + let exception = Exception.CreateAutoException(message, + "url", + 9, + 0, + errObj + ); + this._ai.trackException({ exception: exception }, { custom: "custom value" }); + }].concat(this.asserts(1)).concat(() => { + + const expectedParsedStack: IStackFrame[] = [ + { level: 0, method: "Object.throwInvalidHookError", assembly: "at Object.throwInvalidHookError (https://localhost:44365/static/js/bundle.js:201419:13)", fileName: "https://localhost:44365/static/js/bundle.js", line: 201419 }, + { level: 1, method: "useContext", assembly: "at useContext (https://localhost:44365/static/js/bundle.js:222943:25)", fileName: "https://localhost:44365/static/js/bundle.js", line: 222943 }, + { level: 2, method: "useTenantContext", assembly: "at useTenantContext (https://localhost:44365/static/js/bundle.js:5430:68)", fileName: "https://localhost:44365/static/js/bundle.js", line: 5430 }, + { level: 3, method: "", assembly: "at https://localhost:44365/static/js/bundle.js:4337:72", fileName: "https://localhost:44365/static/js/bundle.js", line: 4337 }, + { level: 4, method: "_ZoneDelegate.invoke", assembly: "at _ZoneDelegate.invoke (https://localhost:44365/static/js/bundle.js:227675:158)", fileName: "https://localhost:44365/static/js/bundle.js", line: 227675 }, + { level: 5, method: "ZoneImpl.run", assembly: "at ZoneImpl.run (https://localhost:44365/static/js/bundle.js:227446:35)", fileName: "https://localhost:44365/static/js/bundle.js", line: 227446 }, + { level: 6, method: "", assembly: "at https://localhost:44365/static/js/bundle.js:229764:30", fileName: "https://localhost:44365/static/js/bundle.js", line: 229764 }, + { level: 7, method: "_ZoneDelegate.invokeTask", assembly: "at _ZoneDelegate.invokeTask (https://localhost:44365/static/js/bundle.js:227700:171)", fileName: "https://localhost:44365/static/js/bundle.js", line: 227700 }, + { level: 8, method: "ZoneImpl.runTask", assembly: "at ZoneImpl.runTask (https://localhost:44365/static/js/bundle.js:227499:37)", fileName: "https://localhost:44365/static/js/bundle.js", line: 227499 }, + { level: 9, method: "ZoneImpl.patchRunTask", assembly: "at ZoneImpl.patchRunTask (https://localhost:44365/static/js/bundle.js:144112:27)", fileName: "https://localhost:44365/static/js/bundle.js", line: 144112 } + ]; + + const payloadStr: string[] = this.getPayloadMessages(this.successSpy); + if (payloadStr.length > 0) { + const payload = JSON.parse(payloadStr[0]); + const data = payload.data; + Assert.ok(data, "Has Data"); + if (data) { + Assert.ok(data.baseData, "Has BaseData"); + let baseData = data.baseData; + if (baseData) { + const ex = baseData.exceptions[0]; + Assert.ok(ex.message.indexOf("Invalid hook call") !== -1, "Make sure the error message is present [" + ex.message + "]"); + Assert.ok(ex.stack.length > 0, "Has stack"); + Assert.ok(ex.parsedStack, "Stack was parsed"); + Assert.ok(ex.hasFullStack, "Stack has been decoded"); + Assert.equal(ex.parsedStack.length, 10); + for (let lp = 0; lp < ex.parsedStack.length; lp++) { + _checkExpectedFrame(expectedParsedStack[lp], ex.parsedStack[lp], lp); + } + + Assert.ok(baseData.properties, "Has BaseData properties"); + Assert.equal(baseData.properties.custom, "custom value"); + + } + } + } + }) + }) + this.testCaseAsync({ name: "TelemetryContext: track metric", stepDelay: 1, diff --git a/AISKULight/Tests/Unit/src/AISKULightSize.Tests.ts b/AISKULight/Tests/Unit/src/AISKULightSize.Tests.ts index c5318b38f..8008ee53d 100644 --- a/AISKULight/Tests/Unit/src/AISKULightSize.Tests.ts +++ b/AISKULight/Tests/Unit/src/AISKULightSize.Tests.ts @@ -51,10 +51,10 @@ function _checkSize(checkType: string, maxSize: number, size: number, isNightly: } export class AISKULightSizeCheck extends AITestClass { - private readonly MAX_RAW_SIZE = 90; - private readonly MAX_BUNDLE_SIZE = 90; - private readonly MAX_RAW_DEFLATE_SIZE = 37; - private readonly MAX_BUNDLE_DEFLATE_SIZE = 37; + private readonly MAX_RAW_SIZE = 91; + private readonly MAX_BUNDLE_SIZE = 91; + private readonly MAX_RAW_DEFLATE_SIZE = 38; + private readonly MAX_BUNDLE_DEFLATE_SIZE = 38; private readonly rawFilePath = "../dist/es5/applicationinsights-web-basic.min.js"; private readonly currentVer = "3.3.4"; private readonly prodFilePath = `../browser/es5/aib.${this.currentVer[0]}.min.js`; diff --git a/common/config/rush/npm-shrinkwrap.json b/common/config/rush/npm-shrinkwrap.json index e40297247..85c44b8c5 100644 --- a/common/config/rush/npm-shrinkwrap.json +++ b/common/config/rush/npm-shrinkwrap.json @@ -210,12 +210,12 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.0.tgz", - "integrity": "sha512-zdHg2FPIFNKPdcHWtiNT+jEFCHYVplAXRDlQDyqy0zGx/q2parwh7brGJSiTxRk/TSMkbM//zt/f5CHgyTyaSQ==", + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.1.tgz", + "integrity": "sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==", "peer": true, "dependencies": { - "@eslint/object-schema": "^2.1.4", + "@eslint/object-schema": "^2.1.5", "debug": "^4.3.1", "minimatch": "^3.1.2" }, @@ -236,10 +236,13 @@ } }, "node_modules/@eslint/core": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.9.0.tgz", - "integrity": "sha512-7ATR9F0e4W85D/0w7cU0SNj7qkAexMG+bAHEZOjo9akvGuhHE2m7umzWzfnpa0XAg5Kxc1BWmtPMV67jJ+9VUg==", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.10.0.tgz", + "integrity": "sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==", "peer": true, + "dependencies": { + "@types/json-schema": "^7.0.15" + }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } @@ -302,29 +305,30 @@ } }, "node_modules/@eslint/js": { - "version": "9.16.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.16.0.tgz", - "integrity": "sha512-tw2HxzQkrbeuvyj1tG2Yqq+0H9wGoI2IMk4EOsQeX+vmd75FtJAzf+gTA69WF+baUKRYQ3x2kbLE08js5OsTVg==", + "version": "9.19.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.19.0.tgz", + "integrity": "sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==", "peer": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/object-schema": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", - "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.5.tgz", + "integrity": "sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==", "peer": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.3.tgz", - "integrity": "sha512-2b/g5hRmpbb1o4GnTZax9N9m0FXzz9OV42ZzI4rDDMDuHUqigAiQCEWChBWCY4ztAGVRjoWT19v0yMmc5/L5kA==", + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz", + "integrity": "sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==", "peer": true, "dependencies": { + "@eslint/core": "^0.10.0", "levn": "^0.4.1" }, "engines": { @@ -398,42 +402,42 @@ "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" }, "node_modules/@microsoft/api-extractor": { - "version": "7.48.0", - "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.48.0.tgz", - "integrity": "sha512-FMFgPjoilMUWeZXqYRlJ3gCVRhB7WU/HN88n8OLqEsmsG4zBdX/KQdtJfhq95LQTQ++zfu0Em1LLb73NqRCLYQ==", + "version": "7.49.2", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.49.2.tgz", + "integrity": "sha512-DI/WnvhbkHcucxxc4ys00ejCiViFls5EKPrEfe4NV3GGpVkoM5ZXF61HZNSGA8IG0oEV4KfTqIa59Rc3wdMopw==", "dependencies": { - "@microsoft/api-extractor-model": "7.30.0", + "@microsoft/api-extractor-model": "7.30.3", "@microsoft/tsdoc": "~0.15.1", "@microsoft/tsdoc-config": "~0.17.1", - "@rushstack/node-core-library": "5.10.0", + "@rushstack/node-core-library": "5.11.0", "@rushstack/rig-package": "0.5.3", - "@rushstack/terminal": "0.14.3", - "@rushstack/ts-command-line": "4.23.1", + "@rushstack/terminal": "0.14.6", + "@rushstack/ts-command-line": "4.23.4", "lodash": "~4.17.15", "minimatch": "~3.0.3", "resolve": "~1.22.1", "semver": "~7.5.4", "source-map": "~0.6.1", - "typescript": "5.4.2" + "typescript": "5.7.2" }, "bin": { "api-extractor": "bin/api-extractor" } }, "node_modules/@microsoft/api-extractor-model": { - "version": "7.30.0", - "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.30.0.tgz", - "integrity": "sha512-26/LJZBrsWDKAkOWRiQbdVgcfd1F3nyJnAiJzsAgpouPk7LtOIj7PK9aJtBaw/pUXrkotEg27RrT+Jm/q0bbug==", + "version": "7.30.3", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.30.3.tgz", + "integrity": "sha512-yEAvq0F78MmStXdqz9TTT4PZ05Xu5R8nqgwI5xmUmQjWBQ9E6R2n8HB/iZMRciG4rf9iwI2mtuQwIzDXBvHn1w==", "dependencies": { "@microsoft/tsdoc": "~0.15.1", "@microsoft/tsdoc-config": "~0.17.1", - "@rushstack/node-core-library": "5.10.0" + "@rushstack/node-core-library": "5.11.0" } }, "node_modules/@microsoft/api-extractor/node_modules/typescript": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.2.tgz", - "integrity": "sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", + "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -504,17 +508,17 @@ } }, "node_modules/@nevware21/ts-async": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/@nevware21/ts-async/-/ts-async-0.5.3.tgz", - "integrity": "sha512-UsF7eerLsVfid7iV1oXF80qXBwHNBeqSqfh/nPZgirRU1MACmSsj83EZKS2ViFHVfSGG6WIuXMGBP6KciXfYhA==", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/@nevware21/ts-async/-/ts-async-0.5.4.tgz", + "integrity": "sha512-IBTyj29GwGlxfzXw2NPnzty+w0Adx61Eze1/lknH/XIVdxtF9UnOpk76tnrHXWa6j84a1RR9hsOcHQPFv9qJjA==", "dependencies": { - "@nevware21/ts-utils": ">= 0.11.5 < 2.x" + "@nevware21/ts-utils": ">= 0.11.6 < 2.x" } }, "node_modules/@nevware21/ts-utils": { - "version": "0.11.5", - "resolved": "https://registry.npmjs.org/@nevware21/ts-utils/-/ts-utils-0.11.5.tgz", - "integrity": "sha512-7nIzWKR50mf3htOg53kwPLqD5iJaRfVyBvb1NJhlIncyP1WzK8vAQbU9rqIsRtv7td1CnqspdP6IWNEjOjaeug==" + "version": "0.11.6", + "resolved": "https://registry.npmjs.org/@nevware21/ts-utils/-/ts-utils-0.11.6.tgz", + "integrity": "sha512-OUUJTh3fnaUSzg9DEHgv3d7jC+DnPL65mIO7RaR+jWve7+MmcgIvF79gY97DPQ4frH+IpNR78YAYd/dW4gK3kg==" }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", @@ -584,9 +588,9 @@ } }, "node_modules/@rollup/plugin-node-resolve": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.3.0.tgz", - "integrity": "sha512-9eO5McEICxMzJpDW9OnMYSv4Sta3hmt7VtBFz5zR9273suNOydOyq/FrGeGy+KsTRFm8w0SLVhzig2ILFT63Ag==", + "version": "15.3.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.3.1.tgz", + "integrity": "sha512-tgg6b91pAybXHJQMAAwW9VuWBO6Thi+q7BCNARLwSqlmsHz0XYURtGvh/AuwSADXSI4h/2uHbs7s4FzlZDGSGA==", "dependencies": { "@rollup/pluginutils": "^5.0.1", "@types/resolve": "1.20.2", @@ -627,17 +631,17 @@ } }, "node_modules/@rollup/plugin-replace/node_modules/magic-string": { - "version": "0.30.14", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.14.tgz", - "integrity": "sha512-5c99P1WKTed11ZC0HMJOj6CDIue6F8ySu+bJL+85q1zBEIY8IklrJ1eiKC2NDRh3Ct3FcvmJPyQHb9erXMTJNw==", + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "node_modules/@rollup/pluginutils": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.3.tgz", - "integrity": "sha512-Pnsb6f32CD2W3uCaLZIzDmeFyQ2b8UWMFI7xtwUezpcGBDVDW6y9XgAWIlARiGAo6eNF5FK5aQTr0LFyNyqq5A==", + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.4.tgz", + "integrity": "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==", "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", @@ -1400,14 +1404,14 @@ } }, "node_modules/@rushstack/node-core-library": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-5.10.0.tgz", - "integrity": "sha512-2pPLCuS/3x7DCd7liZkqOewGM0OzLyCacdvOe8j6Yrx9LkETGnxul1t7603bIaB8nUAooORcct9fFDOQMbWAgw==", + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-5.11.0.tgz", + "integrity": "sha512-I8+VzG9A0F3nH2rLpPd7hF8F7l5Xb7D+ldrWVZYegXM6CsKkvWc670RlgK3WX8/AseZfXA/vVrh0bpXe2Y2UDQ==", "dependencies": { "ajv": "~8.13.0", "ajv-draft-04": "~1.0.0", "ajv-formats": "~3.0.1", - "fs-extra": "~7.0.1", + "fs-extra": "~11.3.0", "import-lazy": "~4.0.0", "jju": "~1.4.0", "resolve": "~1.22.1", @@ -1447,11 +1451,11 @@ } }, "node_modules/@rushstack/terminal": { - "version": "0.14.3", - "resolved": "https://registry.npmjs.org/@rushstack/terminal/-/terminal-0.14.3.tgz", - "integrity": "sha512-csXbZsAdab/v8DbU1sz7WC2aNaKArcdS/FPmXMOXEj/JBBZMvDK0+1b4Qao0kkG0ciB1Qe86/Mb68GjH6/TnMw==", + "version": "0.14.6", + "resolved": "https://registry.npmjs.org/@rushstack/terminal/-/terminal-0.14.6.tgz", + "integrity": "sha512-4nMUy4h0u5PGXVG71kEA9uYI3l8GjVqewoHOFONiM6fuqS51ORdaJZ5ZXB2VZEGUyfg1TOTSy88MF2cdAy+lqA==", "dependencies": { - "@rushstack/node-core-library": "5.10.0", + "@rushstack/node-core-library": "5.11.0", "supports-color": "~8.1.1" }, "peerDependencies": { @@ -1464,61 +1468,77 @@ } }, "node_modules/@rushstack/ts-command-line": { - "version": "4.23.1", - "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.23.1.tgz", - "integrity": "sha512-40jTmYoiu/xlIpkkRsVfENtBq4CW3R4azbL0Vmda+fMwHWqss6wwf/Cy/UJmMqIzpfYc2OTnjYP1ZLD3CmyeCA==", + "version": "4.23.4", + "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.23.4.tgz", + "integrity": "sha512-pqmzDJCm0TS8VyeqnzcJ7ncwXgiLDQ6LVmXXfqv2nPL6VIz+UpyTpNVfZRJpyyJ+UDxqob1vIj2liaUfBjv8/A==", "dependencies": { - "@rushstack/terminal": "0.14.3", + "@rushstack/terminal": "0.14.6", "@types/argparse": "1.0.38", "argparse": "~1.0.9", "string-argv": "~0.3.1" } }, "node_modules/@shikijs/core": { - "version": "1.24.0", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.24.0.tgz", - "integrity": "sha512-6pvdH0KoahMzr6689yh0QJ3rCgF4j1XsXRHNEeEN6M4xJTfQ6QPWrmHzIddotg+xPJUPEPzYzYCKzpYyhTI6Gw==", - "dependencies": { - "@shikijs/engine-javascript": "1.24.0", - "@shikijs/engine-oniguruma": "1.24.0", - "@shikijs/types": "1.24.0", - "@shikijs/vscode-textmate": "^9.3.0", + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.29.2.tgz", + "integrity": "sha512-vju0lY9r27jJfOY4Z7+Rt/nIOjzJpZ3y+nYpqtUZInVoXQ/TJZcfGnNOGnKjFdVZb8qexiCuSlZRKcGfhhTTZQ==", + "dependencies": { + "@shikijs/engine-javascript": "1.29.2", + "@shikijs/engine-oniguruma": "1.29.2", + "@shikijs/types": "1.29.2", + "@shikijs/vscode-textmate": "^10.0.1", "@types/hast": "^3.0.4", - "hast-util-to-html": "^9.0.3" + "hast-util-to-html": "^9.0.4" } }, "node_modules/@shikijs/engine-javascript": { - "version": "1.24.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.24.0.tgz", - "integrity": "sha512-ZA6sCeSsF3Mnlxxr+4wGEJ9Tto4RHmfIS7ox8KIAbH0MTVUkw3roHPHZN+LlJMOHJJOVupe6tvuAzRpN8qK1vA==", + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.29.2.tgz", + "integrity": "sha512-iNEZv4IrLYPv64Q6k7EPpOCE/nuvGiKl7zxdq0WFuRPF5PAE9PRo2JGq/d8crLusM59BRemJ4eOqrFrC4wiQ+A==", "dependencies": { - "@shikijs/types": "1.24.0", - "@shikijs/vscode-textmate": "^9.3.0", - "oniguruma-to-es": "0.7.0" + "@shikijs/types": "1.29.2", + "@shikijs/vscode-textmate": "^10.0.1", + "oniguruma-to-es": "^2.2.0" } }, "node_modules/@shikijs/engine-oniguruma": { - "version": "1.24.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.24.0.tgz", - "integrity": "sha512-Eua0qNOL73Y82lGA4GF5P+G2+VXX9XnuUxkiUuwcxQPH4wom+tE39kZpBFXfUuwNYxHSkrSxpB1p4kyRW0moSg==", + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.29.2.tgz", + "integrity": "sha512-7iiOx3SG8+g1MnlzZVDYiaeHe7Ez2Kf2HrJzdmGwkRisT7r4rak0e655AcM/tF9JG/kg5fMNYlLLKglbN7gBqA==", + "dependencies": { + "@shikijs/types": "1.29.2", + "@shikijs/vscode-textmate": "^10.0.1" + } + }, + "node_modules/@shikijs/langs": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-1.29.2.tgz", + "integrity": "sha512-FIBA7N3LZ+223U7cJDUYd5shmciFQlYkFXlkKVaHsCPgfVLiO+e12FmQE6Tf9vuyEsFe3dIl8qGWKXgEHL9wmQ==", + "dependencies": { + "@shikijs/types": "1.29.2" + } + }, + "node_modules/@shikijs/themes": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-1.29.2.tgz", + "integrity": "sha512-i9TNZlsq4uoyqSbluIcZkmPL9Bfi3djVxRnofUHwvx/h6SRW3cwgBC5SML7vsDcWyukY0eCzVN980rqP6qNl9g==", "dependencies": { - "@shikijs/types": "1.24.0", - "@shikijs/vscode-textmate": "^9.3.0" + "@shikijs/types": "1.29.2" } }, "node_modules/@shikijs/types": { - "version": "1.24.0", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.24.0.tgz", - "integrity": "sha512-aptbEuq1Pk88DMlCe+FzXNnBZ17LCiLIGWAeCWhoFDzia5Q5Krx3DgnULLiouSdd6+LUM39XwXGppqYE0Ghtug==", + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.29.2.tgz", + "integrity": "sha512-VJjK0eIijTZf0QSTODEXCqinjBn0joAHQ+aPSBzrv4O2d/QSbsMw+ZeSRx03kV34Hy7NzUvV/7NqfYGRLrASmw==", "dependencies": { - "@shikijs/vscode-textmate": "^9.3.0", + "@shikijs/vscode-textmate": "^10.0.1", "@types/hast": "^3.0.4" } }, "node_modules/@shikijs/vscode-textmate": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-9.3.0.tgz", - "integrity": "sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA==" + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.1.tgz", + "integrity": "sha512-fTIQwLF+Qhuws31iw7Ncl1R3HUDtGwIipiJ9iU+UsDUwMhegFcQKQHd51nZjb7CArq0MvON8rbgCGQYWHUKAdg==" }, "node_modules/@sindresorhus/is": { "version": "4.6.0", @@ -1672,9 +1692,9 @@ } }, "node_modules/@types/lodash": { - "version": "4.17.13", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.13.tgz", - "integrity": "sha512-lfx+dftrEZcdBPczf9d0Qv0x+j/rfNCMuC6OcfXmO8gkfeNAY88PgKUbvG56whcN23gc27yenwF6oJZXGFpYxg==" + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-w/P33JFeySuhN6JLkysYUK2gEmy9kHHFN7E8ro0tkfmlDOgxBDzWEZ/J8cWA+fHqFevpswDTFZnDx+R9lbL6xw==" }, "node_modules/@types/mdast": { "version": "4.0.4", @@ -1700,9 +1720,9 @@ "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" }, "node_modules/@types/prop-types": { - "version": "15.7.13", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", - "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==" + "version": "15.7.14", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", + "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==" }, "node_modules/@types/qunit": { "version": "2.19.12", @@ -1720,11 +1740,11 @@ } }, "node_modules/@types/react-dom": { - "version": "16.9.24", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.24.tgz", - "integrity": "sha512-Gcmq2JTDheyWn/1eteqyzzWKSqDjYU6KYsIvH7thb7CR5OYInAWOX+7WnKf6PaU/cbdOc4szJItcDEJO7UGmfA==", - "dependencies": { - "@types/react": "^16" + "version": "16.9.25", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.25.tgz", + "integrity": "sha512-ZK//eAPhwft9Ul2/Zj+6O11YR6L4JX0J2sVeBC9Ft7x7HFN7xk7yUV/zDxqV6rjvqgl6r8Dq7oQImxtyf/Mzcw==", + "peerDependencies": { + "@types/react": "^16.0.0" } }, "node_modules/@types/resolve": { @@ -1765,20 +1785,20 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.17.0.tgz", - "integrity": "sha512-HU1KAdW3Tt8zQkdvNoIijfWDMvdSweFYm4hWh+KwhPstv+sCmWb89hCIP8msFm9N1R/ooh9honpSuvqKWlYy3w==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.22.0.tgz", + "integrity": "sha512-4Uta6REnz/xEJMvwf72wdUnC3rr4jAQf5jnTkeRQ9b6soxLxhDEbS/pfMPoJLDfFPNVRdryqWUIV/2GZzDJFZw==", "peer": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.17.0", - "@typescript-eslint/type-utils": "8.17.0", - "@typescript-eslint/utils": "8.17.0", - "@typescript-eslint/visitor-keys": "8.17.0", + "@typescript-eslint/scope-manager": "8.22.0", + "@typescript-eslint/type-utils": "8.22.0", + "@typescript-eslint/utils": "8.22.0", + "@typescript-eslint/visitor-keys": "8.22.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.0.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1789,24 +1809,20 @@ }, "peerDependencies": { "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.17.0.tgz", - "integrity": "sha512-Drp39TXuUlD49F7ilHHCG7TTg8IkA+hxCuULdmzWYICxGXvDXmDmWEjJYZQYgf6l/TFfYNE167m7isnc3xlIEg==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.22.0.tgz", + "integrity": "sha512-MqtmbdNEdoNxTPzpWiWnqNac54h8JDAmkWtJExBVVnSrSmi9z+sZUt0LfKqk9rjqmKOIeRhO4fHHJ1nQIjduIQ==", "peer": true, "dependencies": { - "@typescript-eslint/scope-manager": "8.17.0", - "@typescript-eslint/types": "8.17.0", - "@typescript-eslint/typescript-estree": "8.17.0", - "@typescript-eslint/visitor-keys": "8.17.0", + "@typescript-eslint/scope-manager": "8.22.0", + "@typescript-eslint/types": "8.22.0", + "@typescript-eslint/typescript-estree": "8.22.0", + "@typescript-eslint/visitor-keys": "8.22.0", "debug": "^4.3.4" }, "engines": { @@ -1817,22 +1833,18 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.17.0.tgz", - "integrity": "sha512-/ewp4XjvnxaREtqsZjF4Mfn078RD/9GmiEAtTeLQ7yFdKnqwTOgRMSvFz4et9U5RiJQ15WTGXPLj89zGusvxBg==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.22.0.tgz", + "integrity": "sha512-/lwVV0UYgkj7wPSw0o8URy6YI64QmcOdwHuGuxWIYznO6d45ER0wXUbksr9pYdViAofpUCNJx/tAzNukgvaaiQ==", "peer": true, "dependencies": { - "@typescript-eslint/types": "8.17.0", - "@typescript-eslint/visitor-keys": "8.17.0" + "@typescript-eslint/types": "8.22.0", + "@typescript-eslint/visitor-keys": "8.22.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1843,15 +1855,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.17.0.tgz", - "integrity": "sha512-q38llWJYPd63rRnJ6wY/ZQqIzPrBCkPdpIsaCfkR3Q4t3p6sb422zougfad4TFW9+ElIFLVDzWGiGAfbb/v2qw==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.22.0.tgz", + "integrity": "sha512-NzE3aB62fDEaGjaAYZE4LH7I1MUwHooQ98Byq0G0y3kkibPJQIXVUspzlFOmOfHhiDLwKzMlWxaNv+/qcZurJA==", "peer": true, "dependencies": { - "@typescript-eslint/typescript-estree": "8.17.0", - "@typescript-eslint/utils": "8.17.0", + "@typescript-eslint/typescript-estree": "8.22.0", + "@typescript-eslint/utils": "8.22.0", "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.0.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1861,18 +1873,14 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/types": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.17.0.tgz", - "integrity": "sha512-gY2TVzeve3z6crqh2Ic7Cr+CAv6pfb0Egee7J5UAVWCpVvDI/F71wNfolIim4FE6hT15EbpZFVUj9j5i38jYXA==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.22.0.tgz", + "integrity": "sha512-0S4M4baNzp612zwpD4YOieP3VowOARgK2EkN/GBn95hpyF8E2fbMT55sRHWBq+Huaqk3b3XK+rxxlM8sPgGM6A==", "peer": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1883,19 +1891,19 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.17.0.tgz", - "integrity": "sha512-JqkOopc1nRKZpX+opvKqnM3XUlM7LpFMD0lYxTqOTKQfCWAmxw45e3qlOCsEqEB2yuacujivudOFpCnqkBDNMw==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.22.0.tgz", + "integrity": "sha512-SJX99NAS2ugGOzpyhMza/tX+zDwjvwAtQFLsBo3GQxiGcvaKlqGBkmZ+Y1IdiSi9h4Q0Lr5ey+Cp9CGWNY/F/w==", "peer": true, "dependencies": { - "@typescript-eslint/types": "8.17.0", - "@typescript-eslint/visitor-keys": "8.17.0", + "@typescript-eslint/types": "8.22.0", + "@typescript-eslint/visitor-keys": "8.22.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.0.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1904,10 +1912,8 @@ "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { @@ -1935,9 +1941,9 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.0.tgz", + "integrity": "sha512-DrfFnPzblFmNrIZzg5RzHegbiRWg7KMR7btwi2yjHwx06zsUbO5g613sVwEV7FTwmzJu+Io0lJe2GJ3LxqpvBQ==", "peer": true, "bin": { "semver": "bin/semver.js" @@ -1947,15 +1953,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.17.0.tgz", - "integrity": "sha512-bQC8BnEkxqG8HBGKwG9wXlZqg37RKSMY7v/X8VEWD8JG2JuTHuNK0VFvMPMUKQcbk6B+tf05k+4AShAEtCtJ/w==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.22.0.tgz", + "integrity": "sha512-T8oc1MbF8L+Bk2msAvCUzjxVB2Z2f+vXYfcucE2wOmYs7ZUwco5Ep0fYZw8quNwOiw9K8GYVL+Kgc2pETNTLOg==", "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.17.0", - "@typescript-eslint/types": "8.17.0", - "@typescript-eslint/typescript-estree": "8.17.0" + "@typescript-eslint/scope-manager": "8.22.0", + "@typescript-eslint/types": "8.22.0", + "@typescript-eslint/typescript-estree": "8.22.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1965,21 +1971,17 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.17.0.tgz", - "integrity": "sha512-1Hm7THLpO6ww5QU6H/Qp+AusUUl+z/CAm3cNZZ0jQvon9yicgO7Rwd+/WWRpMKLYV6p2UvdbR27c86rzCPpreg==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.22.0.tgz", + "integrity": "sha512-AWpYAXnUgvLNabGTy3uBylkgZoosva/miNd1I8Bz3SjotmQPbVqhO4Cczo8AsZ44XVErEBPr/CRSgaj8sG7g0w==", "peer": true, "dependencies": { - "@typescript-eslint/types": "8.17.0", + "@typescript-eslint/types": "8.22.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -2003,9 +2005,9 @@ } }, "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==" }, "node_modules/abbrev": { "version": "1.1.1", @@ -2340,9 +2342,9 @@ } }, "node_modules/browserslist": { - "version": "4.24.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", - "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", + "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", "funding": [ { "type": "opencollective", @@ -2358,9 +2360,9 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001669", - "electron-to-chromium": "^1.5.41", - "node-releases": "^2.0.18", + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.1" }, "bin": { @@ -2448,9 +2450,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001686", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001686.tgz", - "integrity": "sha512-Y7deg0Aergpa24M3qLC5xjNklnKnhsmSyR/V89dLZ1n0ucJIFNs7PgR2Yfa/Zf6W79SbBicgtGxZr2juHkEUIA==", + "version": "1.0.30001696", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001696.tgz", + "integrity": "sha512-pDCPkvzfa39ehJtJ+OwGT/2yvT2SbjfHhiIW2LWOAcMQ7BzwxT/XuyUp4OTOd0XFWA6BKw0JalnBHgSi5DGJBQ==", "funding": [ { "type": "opencollective", @@ -2751,9 +2753,9 @@ } }, "node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "dependencies": { "ms": "^2.1.3" }, @@ -2896,9 +2898,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { - "version": "1.5.68", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.68.tgz", - "integrity": "sha512-FgMdJlma0OzUYlbrtZ4AeXjKxKPk6KT8WOP8BjcqxWtlg8qyJQjRzPJzUtUn5GBg1oQ26hFs7HOOHJMYiJRnvQ==" + "version": "1.5.90", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.90.tgz", + "integrity": "sha512-C3PN4aydfW91Natdyd449Kw+BzhLmof6tzy5W1pFC5SpQxVXT+oyiyOG9AgYYSN9OdA/ik3YkCrpwqI8ug5Tug==" }, "node_modules/emoji-regex-xs": { "version": "1.0.0", @@ -2966,18 +2968,18 @@ } }, "node_modules/eslint": { - "version": "9.16.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.16.0.tgz", - "integrity": "sha512-whp8mSQI4C8VXd+fLgSM0lh3UlmcFtVwUQjyKCFfsp+2ItAIYhlq/hqGahGqHE6cv9unM41VlqKk2VtKYR2TaA==", + "version": "9.19.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.19.0.tgz", + "integrity": "sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==", "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.19.0", - "@eslint/core": "^0.9.0", + "@eslint/core": "^0.10.0", "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "9.16.0", - "@eslint/plugin-kit": "^0.2.3", + "@eslint/js": "9.19.0", + "@eslint/plugin-kit": "^0.2.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.1", @@ -2985,7 +2987,7 @@ "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.5", + "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.2.0", @@ -3283,15 +3285,15 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "micromatch": "^4.0.8" }, "engines": { "node": ">=8.6.0" @@ -3321,9 +3323,9 @@ "peer": true }, "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.0.tgz", + "integrity": "sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==", "dependencies": { "reusify": "^1.0.4" } @@ -3499,16 +3501,16 @@ "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" }, "node_modules/fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", + "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": ">=6 <7 || >=8" + "node": ">=14.14" } }, "node_modules/fs.realpath": { @@ -4058,9 +4060,9 @@ } }, "node_modules/hast-util-to-html": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.3.tgz", - "integrity": "sha512-M17uBDzMJ9RPCqLMO92gNNUDuBSq10a25SDBI08iCCxmorf4Yy6sYHK57n9WAbRAAaU+DuR4W6GN9K4DFZesYg==", + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.4.tgz", + "integrity": "sha512-wxQzXtdbhiwGAUKrnQJXlOPmHnEehzphwkK7aluUPQ+lEc1xefC8pblMgpp2w5ldBTEfveRIrADcrhGIWrlTDA==", "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", @@ -4276,9 +4278,9 @@ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" }, "node_modules/is-core-module": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", - "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "dependencies": { "hasown": "^2.0.2" }, @@ -4451,9 +4453,12 @@ "peer": true }, "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -4964,9 +4969,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==" + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==" }, "node_modules/node-watch": { "version": "0.7.3", @@ -5084,13 +5089,13 @@ } }, "node_modules/oniguruma-to-es": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-0.7.0.tgz", - "integrity": "sha512-HRaRh09cE0gRS3+wi2zxekB+I5L8C/gN60S+vb11eADHUaB/q4u8wGGOX3GvwvitG8ixaeycZfeoyruKQzUgNg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-2.3.0.tgz", + "integrity": "sha512-bwALDxriqfKGfUufKGGepCzu9x7nJQuoRoAFp4AnwehhC2crqrDIAP/uN2qdlsAvSMpeRC3+Yzhqc7hLmle5+g==", "dependencies": { "emoji-regex-xs": "^1.0.0", - "regex": "^5.0.2", - "regex-recursion": "^4.3.0" + "regex": "^5.1.1", + "regex-recursion": "^5.1.1" } }, "node_modules/optionator": { @@ -5650,9 +5655,9 @@ } }, "node_modules/qunit": { - "version": "2.23.0", - "resolved": "https://registry.npmjs.org/qunit/-/qunit-2.23.0.tgz", - "integrity": "sha512-r4hCsZqUvSyuUUHbCt2kYW1AECD7KTdhKW9mSUuCu51UO44o6oz6L+F3coeryj79MWF7o+S+szJ9Icrr9yalvQ==", + "version": "2.24.1", + "resolved": "https://registry.npmjs.org/qunit/-/qunit-2.24.1.tgz", + "integrity": "sha512-Eu0k/5JDjx0QnqxsE1WavnDNDgL1zgMZKsMw/AoAxnsl9p4RgyLODyo2N7abZY7CEAnvl5YUqFZdkImzbgXzSg==", "dependencies": { "commander": "7.2.0", "node-watch": "0.7.3", @@ -5764,18 +5769,19 @@ } }, "node_modules/regex": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/regex/-/regex-5.0.2.tgz", - "integrity": "sha512-/pczGbKIQgfTMRV0XjABvc5RzLqQmwqxLHdQao2RTXPk+pmTXB2P0IaUHYdYyk412YLwUIkaeMd5T+RzVgTqnQ==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/regex/-/regex-5.1.1.tgz", + "integrity": "sha512-dN5I359AVGPnwzJm2jN1k0W9LPZ+ePvoOeVMMfqIMFz53sSwXkxaJoxr50ptnsC771lK95BnTrVSZxq0b9yCGw==", "dependencies": { "regex-utilities": "^2.3.0" } }, "node_modules/regex-recursion": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-4.3.0.tgz", - "integrity": "sha512-5LcLnizwjcQ2ALfOj95MjcatxyqF5RPySx9yT+PaXu3Gox2vyAtLDjHB8NTJLtMGkvyau6nI3CfpwFCjPUIs/A==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-5.1.1.tgz", + "integrity": "sha512-ae7SBCbzVNrIjgSbh7wMznPcQel1DNlDtzensnFxpiNpXt1U2ju/bHugH422r+4LAVS1FpW1YCwilmnNsjum9w==", "dependencies": { + "regex": "^5.1.1", "regex-utilities": "^2.3.0" } }, @@ -5802,17 +5808,20 @@ } }, "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", "dependencies": { - "is-core-module": "^2.13.0", + "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -6009,6 +6018,14 @@ "node": ">=0.10.0" } }, + "node_modules/rollup-plugin-copy/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, "node_modules/rollup-plugin-copy/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -6020,6 +6037,14 @@ "node": "*" } }, + "node_modules/rollup-plugin-copy/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/rollup-plugin-minify-es": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/rollup-plugin-minify-es/-/rollup-plugin-minify-es-1.1.1.tgz", @@ -6275,15 +6300,17 @@ } }, "node_modules/shiki": { - "version": "1.24.0", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.24.0.tgz", - "integrity": "sha512-qIneep7QRwxRd5oiHb8jaRzH15V/S8F3saCXOdjwRLgozZJr5x2yeBhQtqkO3FSzQDwYEFAYuifg4oHjpDghrg==", - "dependencies": { - "@shikijs/core": "1.24.0", - "@shikijs/engine-javascript": "1.24.0", - "@shikijs/engine-oniguruma": "1.24.0", - "@shikijs/types": "1.24.0", - "@shikijs/vscode-textmate": "^9.3.0", + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.29.2.tgz", + "integrity": "sha512-njXuliz/cP+67jU2hukkxCNuH1yUi4QfdZZY+sMr5PPrIyXSu5iTb/qYC4BiWWB0vZ+7TbdvYUCeL23zpwCfbg==", + "dependencies": { + "@shikijs/core": "1.29.2", + "@shikijs/engine-javascript": "1.29.2", + "@shikijs/engine-oniguruma": "1.29.2", + "@shikijs/langs": "1.29.2", + "@shikijs/themes": "1.29.2", + "@shikijs/types": "1.29.2", + "@shikijs/vscode-textmate": "^10.0.1", "@types/hast": "^3.0.4" } }, @@ -6533,15 +6560,15 @@ } }, "node_modules/ts-api-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", - "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.0.tgz", + "integrity": "sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==", "peer": true, "engines": { - "node": ">=16" + "node": ">=18.12" }, "peerDependencies": { - "typescript": ">=4.2.0" + "typescript": ">=4.8.4" } }, "node_modules/tslib": { @@ -6626,9 +6653,9 @@ } }, "node_modules/typedoc/node_modules/yaml": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz", - "integrity": "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz", + "integrity": "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==", "bin": { "yaml": "bin.mjs" }, @@ -6783,11 +6810,11 @@ } }, "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "engines": { - "node": ">= 4.0.0" + "node": ">= 10.0.0" } }, "node_modules/unpipe": { @@ -6799,9 +6826,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", - "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz", + "integrity": "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==", "funding": [ { "type": "opencollective", @@ -6818,7 +6845,7 @@ ], "dependencies": { "escalade": "^3.2.0", - "picocolors": "^1.1.0" + "picocolors": "^1.1.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -7136,12 +7163,12 @@ "peer": true }, "@eslint/config-array": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.0.tgz", - "integrity": "sha512-zdHg2FPIFNKPdcHWtiNT+jEFCHYVplAXRDlQDyqy0zGx/q2parwh7brGJSiTxRk/TSMkbM//zt/f5CHgyTyaSQ==", + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.1.tgz", + "integrity": "sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==", "peer": true, "requires": { - "@eslint/object-schema": "^2.1.4", + "@eslint/object-schema": "^2.1.5", "debug": "^4.3.1", "minimatch": "^3.1.2" }, @@ -7158,10 +7185,13 @@ } }, "@eslint/core": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.9.0.tgz", - "integrity": "sha512-7ATR9F0e4W85D/0w7cU0SNj7qkAexMG+bAHEZOjo9akvGuhHE2m7umzWzfnpa0XAg5Kxc1BWmtPMV67jJ+9VUg==", - "peer": true + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.10.0.tgz", + "integrity": "sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==", + "peer": true, + "requires": { + "@types/json-schema": "^7.0.15" + } }, "@eslint/eslintrc": { "version": "3.2.0", @@ -7210,23 +7240,24 @@ } }, "@eslint/js": { - "version": "9.16.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.16.0.tgz", - "integrity": "sha512-tw2HxzQkrbeuvyj1tG2Yqq+0H9wGoI2IMk4EOsQeX+vmd75FtJAzf+gTA69WF+baUKRYQ3x2kbLE08js5OsTVg==", + "version": "9.19.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.19.0.tgz", + "integrity": "sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==", "peer": true }, "@eslint/object-schema": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", - "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.5.tgz", + "integrity": "sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==", "peer": true }, "@eslint/plugin-kit": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.3.tgz", - "integrity": "sha512-2b/g5hRmpbb1o4GnTZax9N9m0FXzz9OV42ZzI4rDDMDuHUqigAiQCEWChBWCY4ztAGVRjoWT19v0yMmc5/L5kA==", + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz", + "integrity": "sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==", "peer": true, "requires": { + "@eslint/core": "^0.10.0", "levn": "^0.4.1" } }, @@ -7272,40 +7303,40 @@ "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" }, "@microsoft/api-extractor": { - "version": "7.48.0", - "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.48.0.tgz", - "integrity": "sha512-FMFgPjoilMUWeZXqYRlJ3gCVRhB7WU/HN88n8OLqEsmsG4zBdX/KQdtJfhq95LQTQ++zfu0Em1LLb73NqRCLYQ==", + "version": "7.49.2", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.49.2.tgz", + "integrity": "sha512-DI/WnvhbkHcucxxc4ys00ejCiViFls5EKPrEfe4NV3GGpVkoM5ZXF61HZNSGA8IG0oEV4KfTqIa59Rc3wdMopw==", "requires": { - "@microsoft/api-extractor-model": "7.30.0", + "@microsoft/api-extractor-model": "7.30.3", "@microsoft/tsdoc": "~0.15.1", "@microsoft/tsdoc-config": "~0.17.1", - "@rushstack/node-core-library": "5.10.0", + "@rushstack/node-core-library": "5.11.0", "@rushstack/rig-package": "0.5.3", - "@rushstack/terminal": "0.14.3", - "@rushstack/ts-command-line": "4.23.1", + "@rushstack/terminal": "0.14.6", + "@rushstack/ts-command-line": "4.23.4", "lodash": "~4.17.15", "minimatch": "~3.0.3", "resolve": "~1.22.1", "semver": "~7.5.4", "source-map": "~0.6.1", - "typescript": "5.4.2" + "typescript": "5.7.2" }, "dependencies": { "typescript": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.2.tgz", - "integrity": "sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==" + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", + "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==" } } }, "@microsoft/api-extractor-model": { - "version": "7.30.0", - "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.30.0.tgz", - "integrity": "sha512-26/LJZBrsWDKAkOWRiQbdVgcfd1F3nyJnAiJzsAgpouPk7LtOIj7PK9aJtBaw/pUXrkotEg27RrT+Jm/q0bbug==", + "version": "7.30.3", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.30.3.tgz", + "integrity": "sha512-yEAvq0F78MmStXdqz9TTT4PZ05Xu5R8nqgwI5xmUmQjWBQ9E6R2n8HB/iZMRciG4rf9iwI2mtuQwIzDXBvHn1w==", "requires": { "@microsoft/tsdoc": "~0.15.1", "@microsoft/tsdoc-config": "~0.17.1", - "@rushstack/node-core-library": "5.10.0" + "@rushstack/node-core-library": "5.11.0" } }, "@microsoft/dynamicproto-js": { @@ -7352,17 +7383,17 @@ } }, "@nevware21/ts-async": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/@nevware21/ts-async/-/ts-async-0.5.3.tgz", - "integrity": "sha512-UsF7eerLsVfid7iV1oXF80qXBwHNBeqSqfh/nPZgirRU1MACmSsj83EZKS2ViFHVfSGG6WIuXMGBP6KciXfYhA==", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/@nevware21/ts-async/-/ts-async-0.5.4.tgz", + "integrity": "sha512-IBTyj29GwGlxfzXw2NPnzty+w0Adx61Eze1/lknH/XIVdxtF9UnOpk76tnrHXWa6j84a1RR9hsOcHQPFv9qJjA==", "requires": { - "@nevware21/ts-utils": ">= 0.11.5 < 2.x" + "@nevware21/ts-utils": ">= 0.11.6 < 2.x" } }, "@nevware21/ts-utils": { - "version": "0.11.5", - "resolved": "https://registry.npmjs.org/@nevware21/ts-utils/-/ts-utils-0.11.5.tgz", - "integrity": "sha512-7nIzWKR50mf3htOg53kwPLqD5iJaRfVyBvb1NJhlIncyP1WzK8vAQbU9rqIsRtv7td1CnqspdP6IWNEjOjaeug==" + "version": "0.11.6", + "resolved": "https://registry.npmjs.org/@nevware21/ts-utils/-/ts-utils-0.11.6.tgz", + "integrity": "sha512-OUUJTh3fnaUSzg9DEHgv3d7jC+DnPL65mIO7RaR+jWve7+MmcgIvF79gY97DPQ4frH+IpNR78YAYd/dW4gK3kg==" }, "@nodelib/fs.scandir": { "version": "2.1.5", @@ -7411,9 +7442,9 @@ } }, "@rollup/plugin-node-resolve": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.3.0.tgz", - "integrity": "sha512-9eO5McEICxMzJpDW9OnMYSv4Sta3hmt7VtBFz5zR9273suNOydOyq/FrGeGy+KsTRFm8w0SLVhzig2ILFT63Ag==", + "version": "15.3.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.3.1.tgz", + "integrity": "sha512-tgg6b91pAybXHJQMAAwW9VuWBO6Thi+q7BCNARLwSqlmsHz0XYURtGvh/AuwSADXSI4h/2uHbs7s4FzlZDGSGA==", "requires": { "@rollup/pluginutils": "^5.0.1", "@types/resolve": "1.20.2", @@ -7432,9 +7463,9 @@ }, "dependencies": { "magic-string": { - "version": "0.30.14", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.14.tgz", - "integrity": "sha512-5c99P1WKTed11ZC0HMJOj6CDIue6F8ySu+bJL+85q1zBEIY8IklrJ1eiKC2NDRh3Ct3FcvmJPyQHb9erXMTJNw==", + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", "requires": { "@jridgewell/sourcemap-codec": "^1.5.0" } @@ -7442,9 +7473,9 @@ } }, "@rollup/pluginutils": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.3.tgz", - "integrity": "sha512-Pnsb6f32CD2W3uCaLZIzDmeFyQ2b8UWMFI7xtwUezpcGBDVDW6y9XgAWIlARiGAo6eNF5FK5aQTr0LFyNyqq5A==", + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.4.tgz", + "integrity": "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==", "requires": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", @@ -8166,14 +8197,14 @@ } }, "@rushstack/node-core-library": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-5.10.0.tgz", - "integrity": "sha512-2pPLCuS/3x7DCd7liZkqOewGM0OzLyCacdvOe8j6Yrx9LkETGnxul1t7603bIaB8nUAooORcct9fFDOQMbWAgw==", + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-5.11.0.tgz", + "integrity": "sha512-I8+VzG9A0F3nH2rLpPd7hF8F7l5Xb7D+ldrWVZYegXM6CsKkvWc670RlgK3WX8/AseZfXA/vVrh0bpXe2Y2UDQ==", "requires": { "ajv": "~8.13.0", "ajv-draft-04": "~1.0.0", "ajv-formats": "~3.0.1", - "fs-extra": "~7.0.1", + "fs-extra": "~11.3.0", "import-lazy": "~4.0.0", "jju": "~1.4.0", "resolve": "~1.22.1", @@ -8203,70 +8234,86 @@ } }, "@rushstack/terminal": { - "version": "0.14.3", - "resolved": "https://registry.npmjs.org/@rushstack/terminal/-/terminal-0.14.3.tgz", - "integrity": "sha512-csXbZsAdab/v8DbU1sz7WC2aNaKArcdS/FPmXMOXEj/JBBZMvDK0+1b4Qao0kkG0ciB1Qe86/Mb68GjH6/TnMw==", + "version": "0.14.6", + "resolved": "https://registry.npmjs.org/@rushstack/terminal/-/terminal-0.14.6.tgz", + "integrity": "sha512-4nMUy4h0u5PGXVG71kEA9uYI3l8GjVqewoHOFONiM6fuqS51ORdaJZ5ZXB2VZEGUyfg1TOTSy88MF2cdAy+lqA==", "requires": { - "@rushstack/node-core-library": "5.10.0", + "@rushstack/node-core-library": "5.11.0", "supports-color": "~8.1.1" } }, "@rushstack/ts-command-line": { - "version": "4.23.1", - "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.23.1.tgz", - "integrity": "sha512-40jTmYoiu/xlIpkkRsVfENtBq4CW3R4azbL0Vmda+fMwHWqss6wwf/Cy/UJmMqIzpfYc2OTnjYP1ZLD3CmyeCA==", + "version": "4.23.4", + "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.23.4.tgz", + "integrity": "sha512-pqmzDJCm0TS8VyeqnzcJ7ncwXgiLDQ6LVmXXfqv2nPL6VIz+UpyTpNVfZRJpyyJ+UDxqob1vIj2liaUfBjv8/A==", "requires": { - "@rushstack/terminal": "0.14.3", + "@rushstack/terminal": "0.14.6", "@types/argparse": "1.0.38", "argparse": "~1.0.9", "string-argv": "~0.3.1" } }, "@shikijs/core": { - "version": "1.24.0", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.24.0.tgz", - "integrity": "sha512-6pvdH0KoahMzr6689yh0QJ3rCgF4j1XsXRHNEeEN6M4xJTfQ6QPWrmHzIddotg+xPJUPEPzYzYCKzpYyhTI6Gw==", - "requires": { - "@shikijs/engine-javascript": "1.24.0", - "@shikijs/engine-oniguruma": "1.24.0", - "@shikijs/types": "1.24.0", - "@shikijs/vscode-textmate": "^9.3.0", + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.29.2.tgz", + "integrity": "sha512-vju0lY9r27jJfOY4Z7+Rt/nIOjzJpZ3y+nYpqtUZInVoXQ/TJZcfGnNOGnKjFdVZb8qexiCuSlZRKcGfhhTTZQ==", + "requires": { + "@shikijs/engine-javascript": "1.29.2", + "@shikijs/engine-oniguruma": "1.29.2", + "@shikijs/types": "1.29.2", + "@shikijs/vscode-textmate": "^10.0.1", "@types/hast": "^3.0.4", - "hast-util-to-html": "^9.0.3" + "hast-util-to-html": "^9.0.4" } }, "@shikijs/engine-javascript": { - "version": "1.24.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.24.0.tgz", - "integrity": "sha512-ZA6sCeSsF3Mnlxxr+4wGEJ9Tto4RHmfIS7ox8KIAbH0MTVUkw3roHPHZN+LlJMOHJJOVupe6tvuAzRpN8qK1vA==", + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.29.2.tgz", + "integrity": "sha512-iNEZv4IrLYPv64Q6k7EPpOCE/nuvGiKl7zxdq0WFuRPF5PAE9PRo2JGq/d8crLusM59BRemJ4eOqrFrC4wiQ+A==", "requires": { - "@shikijs/types": "1.24.0", - "@shikijs/vscode-textmate": "^9.3.0", - "oniguruma-to-es": "0.7.0" + "@shikijs/types": "1.29.2", + "@shikijs/vscode-textmate": "^10.0.1", + "oniguruma-to-es": "^2.2.0" } }, "@shikijs/engine-oniguruma": { - "version": "1.24.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.24.0.tgz", - "integrity": "sha512-Eua0qNOL73Y82lGA4GF5P+G2+VXX9XnuUxkiUuwcxQPH4wom+tE39kZpBFXfUuwNYxHSkrSxpB1p4kyRW0moSg==", + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.29.2.tgz", + "integrity": "sha512-7iiOx3SG8+g1MnlzZVDYiaeHe7Ez2Kf2HrJzdmGwkRisT7r4rak0e655AcM/tF9JG/kg5fMNYlLLKglbN7gBqA==", + "requires": { + "@shikijs/types": "1.29.2", + "@shikijs/vscode-textmate": "^10.0.1" + } + }, + "@shikijs/langs": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-1.29.2.tgz", + "integrity": "sha512-FIBA7N3LZ+223U7cJDUYd5shmciFQlYkFXlkKVaHsCPgfVLiO+e12FmQE6Tf9vuyEsFe3dIl8qGWKXgEHL9wmQ==", + "requires": { + "@shikijs/types": "1.29.2" + } + }, + "@shikijs/themes": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-1.29.2.tgz", + "integrity": "sha512-i9TNZlsq4uoyqSbluIcZkmPL9Bfi3djVxRnofUHwvx/h6SRW3cwgBC5SML7vsDcWyukY0eCzVN980rqP6qNl9g==", "requires": { - "@shikijs/types": "1.24.0", - "@shikijs/vscode-textmate": "^9.3.0" + "@shikijs/types": "1.29.2" } }, "@shikijs/types": { - "version": "1.24.0", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.24.0.tgz", - "integrity": "sha512-aptbEuq1Pk88DMlCe+FzXNnBZ17LCiLIGWAeCWhoFDzia5Q5Krx3DgnULLiouSdd6+LUM39XwXGppqYE0Ghtug==", + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.29.2.tgz", + "integrity": "sha512-VJjK0eIijTZf0QSTODEXCqinjBn0joAHQ+aPSBzrv4O2d/QSbsMw+ZeSRx03kV34Hy7NzUvV/7NqfYGRLrASmw==", "requires": { - "@shikijs/vscode-textmate": "^9.3.0", + "@shikijs/vscode-textmate": "^10.0.1", "@types/hast": "^3.0.4" } }, "@shikijs/vscode-textmate": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-9.3.0.tgz", - "integrity": "sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA==" + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.1.tgz", + "integrity": "sha512-fTIQwLF+Qhuws31iw7Ncl1R3HUDtGwIipiJ9iU+UsDUwMhegFcQKQHd51nZjb7CArq0MvON8rbgCGQYWHUKAdg==" }, "@sindresorhus/is": { "version": "4.6.0", @@ -8411,9 +8458,9 @@ } }, "@types/lodash": { - "version": "4.17.13", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.13.tgz", - "integrity": "sha512-lfx+dftrEZcdBPczf9d0Qv0x+j/rfNCMuC6OcfXmO8gkfeNAY88PgKUbvG56whcN23gc27yenwF6oJZXGFpYxg==" + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-w/P33JFeySuhN6JLkysYUK2gEmy9kHHFN7E8ro0tkfmlDOgxBDzWEZ/J8cWA+fHqFevpswDTFZnDx+R9lbL6xw==" }, "@types/mdast": { "version": "4.0.4", @@ -8439,9 +8486,9 @@ "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" }, "@types/prop-types": { - "version": "15.7.13", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", - "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==" + "version": "15.7.14", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", + "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==" }, "@types/qunit": { "version": "2.19.12", @@ -8459,12 +8506,10 @@ } }, "@types/react-dom": { - "version": "16.9.24", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.24.tgz", - "integrity": "sha512-Gcmq2JTDheyWn/1eteqyzzWKSqDjYU6KYsIvH7thb7CR5OYInAWOX+7WnKf6PaU/cbdOc4szJItcDEJO7UGmfA==", - "requires": { - "@types/react": "^16" - } + "version": "16.9.25", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.25.tgz", + "integrity": "sha512-ZK//eAPhwft9Ul2/Zj+6O11YR6L4JX0J2sVeBC9Ft7x7HFN7xk7yUV/zDxqV6rjvqgl6r8Dq7oQImxtyf/Mzcw==", + "requires": {} }, "@types/resolve": { "version": "1.20.2", @@ -8504,77 +8549,77 @@ } }, "@typescript-eslint/eslint-plugin": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.17.0.tgz", - "integrity": "sha512-HU1KAdW3Tt8zQkdvNoIijfWDMvdSweFYm4hWh+KwhPstv+sCmWb89hCIP8msFm9N1R/ooh9honpSuvqKWlYy3w==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.22.0.tgz", + "integrity": "sha512-4Uta6REnz/xEJMvwf72wdUnC3rr4jAQf5jnTkeRQ9b6soxLxhDEbS/pfMPoJLDfFPNVRdryqWUIV/2GZzDJFZw==", "peer": true, "requires": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.17.0", - "@typescript-eslint/type-utils": "8.17.0", - "@typescript-eslint/utils": "8.17.0", - "@typescript-eslint/visitor-keys": "8.17.0", + "@typescript-eslint/scope-manager": "8.22.0", + "@typescript-eslint/type-utils": "8.22.0", + "@typescript-eslint/utils": "8.22.0", + "@typescript-eslint/visitor-keys": "8.22.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.0.0" } }, "@typescript-eslint/parser": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.17.0.tgz", - "integrity": "sha512-Drp39TXuUlD49F7ilHHCG7TTg8IkA+hxCuULdmzWYICxGXvDXmDmWEjJYZQYgf6l/TFfYNE167m7isnc3xlIEg==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.22.0.tgz", + "integrity": "sha512-MqtmbdNEdoNxTPzpWiWnqNac54h8JDAmkWtJExBVVnSrSmi9z+sZUt0LfKqk9rjqmKOIeRhO4fHHJ1nQIjduIQ==", "peer": true, "requires": { - "@typescript-eslint/scope-manager": "8.17.0", - "@typescript-eslint/types": "8.17.0", - "@typescript-eslint/typescript-estree": "8.17.0", - "@typescript-eslint/visitor-keys": "8.17.0", + "@typescript-eslint/scope-manager": "8.22.0", + "@typescript-eslint/types": "8.22.0", + "@typescript-eslint/typescript-estree": "8.22.0", + "@typescript-eslint/visitor-keys": "8.22.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.17.0.tgz", - "integrity": "sha512-/ewp4XjvnxaREtqsZjF4Mfn078RD/9GmiEAtTeLQ7yFdKnqwTOgRMSvFz4et9U5RiJQ15WTGXPLj89zGusvxBg==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.22.0.tgz", + "integrity": "sha512-/lwVV0UYgkj7wPSw0o8URy6YI64QmcOdwHuGuxWIYznO6d45ER0wXUbksr9pYdViAofpUCNJx/tAzNukgvaaiQ==", "peer": true, "requires": { - "@typescript-eslint/types": "8.17.0", - "@typescript-eslint/visitor-keys": "8.17.0" + "@typescript-eslint/types": "8.22.0", + "@typescript-eslint/visitor-keys": "8.22.0" } }, "@typescript-eslint/type-utils": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.17.0.tgz", - "integrity": "sha512-q38llWJYPd63rRnJ6wY/ZQqIzPrBCkPdpIsaCfkR3Q4t3p6sb422zougfad4TFW9+ElIFLVDzWGiGAfbb/v2qw==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.22.0.tgz", + "integrity": "sha512-NzE3aB62fDEaGjaAYZE4LH7I1MUwHooQ98Byq0G0y3kkibPJQIXVUspzlFOmOfHhiDLwKzMlWxaNv+/qcZurJA==", "peer": true, "requires": { - "@typescript-eslint/typescript-estree": "8.17.0", - "@typescript-eslint/utils": "8.17.0", + "@typescript-eslint/typescript-estree": "8.22.0", + "@typescript-eslint/utils": "8.22.0", "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.0.0" } }, "@typescript-eslint/types": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.17.0.tgz", - "integrity": "sha512-gY2TVzeve3z6crqh2Ic7Cr+CAv6pfb0Egee7J5UAVWCpVvDI/F71wNfolIim4FE6hT15EbpZFVUj9j5i38jYXA==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.22.0.tgz", + "integrity": "sha512-0S4M4baNzp612zwpD4YOieP3VowOARgK2EkN/GBn95hpyF8E2fbMT55sRHWBq+Huaqk3b3XK+rxxlM8sPgGM6A==", "peer": true }, "@typescript-eslint/typescript-estree": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.17.0.tgz", - "integrity": "sha512-JqkOopc1nRKZpX+opvKqnM3XUlM7LpFMD0lYxTqOTKQfCWAmxw45e3qlOCsEqEB2yuacujivudOFpCnqkBDNMw==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.22.0.tgz", + "integrity": "sha512-SJX99NAS2ugGOzpyhMza/tX+zDwjvwAtQFLsBo3GQxiGcvaKlqGBkmZ+Y1IdiSi9h4Q0Lr5ey+Cp9CGWNY/F/w==", "peer": true, "requires": { - "@typescript-eslint/types": "8.17.0", - "@typescript-eslint/visitor-keys": "8.17.0", + "@typescript-eslint/types": "8.22.0", + "@typescript-eslint/visitor-keys": "8.22.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.0.0" }, "dependencies": { "brace-expansion": { @@ -8596,32 +8641,32 @@ } }, "semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.0.tgz", + "integrity": "sha512-DrfFnPzblFmNrIZzg5RzHegbiRWg7KMR7btwi2yjHwx06zsUbO5g613sVwEV7FTwmzJu+Io0lJe2GJ3LxqpvBQ==", "peer": true } } }, "@typescript-eslint/utils": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.17.0.tgz", - "integrity": "sha512-bQC8BnEkxqG8HBGKwG9wXlZqg37RKSMY7v/X8VEWD8JG2JuTHuNK0VFvMPMUKQcbk6B+tf05k+4AShAEtCtJ/w==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.22.0.tgz", + "integrity": "sha512-T8oc1MbF8L+Bk2msAvCUzjxVB2Z2f+vXYfcucE2wOmYs7ZUwco5Ep0fYZw8quNwOiw9K8GYVL+Kgc2pETNTLOg==", "peer": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.17.0", - "@typescript-eslint/types": "8.17.0", - "@typescript-eslint/typescript-estree": "8.17.0" + "@typescript-eslint/scope-manager": "8.22.0", + "@typescript-eslint/types": "8.22.0", + "@typescript-eslint/typescript-estree": "8.22.0" } }, "@typescript-eslint/visitor-keys": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.17.0.tgz", - "integrity": "sha512-1Hm7THLpO6ww5QU6H/Qp+AusUUl+z/CAm3cNZZ0jQvon9yicgO7Rwd+/WWRpMKLYV6p2UvdbR27c86rzCPpreg==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.22.0.tgz", + "integrity": "sha512-AWpYAXnUgvLNabGTy3uBylkgZoosva/miNd1I8Bz3SjotmQPbVqhO4Cczo8AsZ44XVErEBPr/CRSgaj8sG7g0w==", "peer": true, "requires": { - "@typescript-eslint/types": "8.17.0", + "@typescript-eslint/types": "8.22.0", "eslint-visitor-keys": "^4.2.0" }, "dependencies": { @@ -8634,9 +8679,9 @@ } }, "@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==" }, "abbrev": { "version": "1.1.1", @@ -8877,13 +8922,13 @@ } }, "browserslist": { - "version": "4.24.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", - "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", + "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", "requires": { - "caniuse-lite": "^1.0.30001669", - "electron-to-chromium": "^1.5.41", - "node-releases": "^2.0.18", + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.1" } }, @@ -8936,9 +8981,9 @@ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" }, "caniuse-lite": { - "version": "1.0.30001686", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001686.tgz", - "integrity": "sha512-Y7deg0Aergpa24M3qLC5xjNklnKnhsmSyR/V89dLZ1n0ucJIFNs7PgR2Yfa/Zf6W79SbBicgtGxZr2juHkEUIA==" + "version": "1.0.30001696", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001696.tgz", + "integrity": "sha512-pDCPkvzfa39ehJtJ+OwGT/2yvT2SbjfHhiIW2LWOAcMQ7BzwxT/XuyUp4OTOd0XFWA6BKw0JalnBHgSi5DGJBQ==" }, "ccount": { "version": "2.0.1", @@ -9162,9 +9207,9 @@ "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==" }, "debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "requires": { "ms": "^2.1.3" } @@ -9257,9 +9302,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "electron-to-chromium": { - "version": "1.5.68", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.68.tgz", - "integrity": "sha512-FgMdJlma0OzUYlbrtZ4AeXjKxKPk6KT8WOP8BjcqxWtlg8qyJQjRzPJzUtUn5GBg1oQ26hFs7HOOHJMYiJRnvQ==" + "version": "1.5.90", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.90.tgz", + "integrity": "sha512-C3PN4aydfW91Natdyd449Kw+BzhLmof6tzy5W1pFC5SpQxVXT+oyiyOG9AgYYSN9OdA/ik3YkCrpwqI8ug5Tug==" }, "emoji-regex-xs": { "version": "1.0.0", @@ -9309,18 +9354,18 @@ "peer": true }, "eslint": { - "version": "9.16.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.16.0.tgz", - "integrity": "sha512-whp8mSQI4C8VXd+fLgSM0lh3UlmcFtVwUQjyKCFfsp+2ItAIYhlq/hqGahGqHE6cv9unM41VlqKk2VtKYR2TaA==", + "version": "9.19.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.19.0.tgz", + "integrity": "sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==", "peer": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.19.0", - "@eslint/core": "^0.9.0", + "@eslint/core": "^0.10.0", "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "9.16.0", - "@eslint/plugin-kit": "^0.2.3", + "@eslint/js": "9.19.0", + "@eslint/plugin-kit": "^0.2.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.1", @@ -9328,7 +9373,7 @@ "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.5", + "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.2.0", @@ -9538,15 +9583,15 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "requires": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "micromatch": "^4.0.8" }, "dependencies": { "glob-parent": { @@ -9572,9 +9617,9 @@ "peer": true }, "fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.0.tgz", + "integrity": "sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==", "requires": { "reusify": "^1.0.4" } @@ -9716,13 +9761,13 @@ "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" }, "fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", + "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" } }, "fs.realpath": { @@ -10120,9 +10165,9 @@ } }, "hast-util-to-html": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.3.tgz", - "integrity": "sha512-M17uBDzMJ9RPCqLMO92gNNUDuBSq10a25SDBI08iCCxmorf4Yy6sYHK57n9WAbRAAaU+DuR4W6GN9K4DFZesYg==", + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.4.tgz", + "integrity": "sha512-wxQzXtdbhiwGAUKrnQJXlOPmHnEehzphwkK7aluUPQ+lEc1xefC8pblMgpp2w5ldBTEfveRIrADcrhGIWrlTDA==", "requires": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", @@ -10275,9 +10320,9 @@ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" }, "is-core-module": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", - "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "requires": { "hasown": "^2.0.2" } @@ -10416,11 +10461,12 @@ "peer": true }, "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "requires": { - "graceful-fs": "^4.1.6" + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" } }, "just-extend": { @@ -10805,9 +10851,9 @@ } }, "node-releases": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==" + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==" }, "node-watch": { "version": "0.7.3", @@ -10892,13 +10938,13 @@ } }, "oniguruma-to-es": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-0.7.0.tgz", - "integrity": "sha512-HRaRh09cE0gRS3+wi2zxekB+I5L8C/gN60S+vb11eADHUaB/q4u8wGGOX3GvwvitG8ixaeycZfeoyruKQzUgNg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-2.3.0.tgz", + "integrity": "sha512-bwALDxriqfKGfUufKGGepCzu9x7nJQuoRoAFp4AnwehhC2crqrDIAP/uN2qdlsAvSMpeRC3+Yzhqc7hLmle5+g==", "requires": { "emoji-regex-xs": "^1.0.0", - "regex": "^5.0.2", - "regex-recursion": "^4.3.0" + "regex": "^5.1.1", + "regex-recursion": "^5.1.1" } }, "optionator": { @@ -11283,9 +11329,9 @@ "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==" }, "qunit": { - "version": "2.23.0", - "resolved": "https://registry.npmjs.org/qunit/-/qunit-2.23.0.tgz", - "integrity": "sha512-r4hCsZqUvSyuUUHbCt2kYW1AECD7KTdhKW9mSUuCu51UO44o6oz6L+F3coeryj79MWF7o+S+szJ9Icrr9yalvQ==", + "version": "2.24.1", + "resolved": "https://registry.npmjs.org/qunit/-/qunit-2.24.1.tgz", + "integrity": "sha512-Eu0k/5JDjx0QnqxsE1WavnDNDgL1zgMZKsMw/AoAxnsl9p4RgyLODyo2N7abZY7CEAnvl5YUqFZdkImzbgXzSg==", "requires": { "commander": "7.2.0", "node-watch": "0.7.3", @@ -11377,18 +11423,19 @@ } }, "regex": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/regex/-/regex-5.0.2.tgz", - "integrity": "sha512-/pczGbKIQgfTMRV0XjABvc5RzLqQmwqxLHdQao2RTXPk+pmTXB2P0IaUHYdYyk412YLwUIkaeMd5T+RzVgTqnQ==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/regex/-/regex-5.1.1.tgz", + "integrity": "sha512-dN5I359AVGPnwzJm2jN1k0W9LPZ+ePvoOeVMMfqIMFz53sSwXkxaJoxr50ptnsC771lK95BnTrVSZxq0b9yCGw==", "requires": { "regex-utilities": "^2.3.0" } }, "regex-recursion": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-4.3.0.tgz", - "integrity": "sha512-5LcLnizwjcQ2ALfOj95MjcatxyqF5RPySx9yT+PaXu3Gox2vyAtLDjHB8NTJLtMGkvyau6nI3CfpwFCjPUIs/A==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-5.1.1.tgz", + "integrity": "sha512-ae7SBCbzVNrIjgSbh7wMznPcQel1DNlDtzensnFxpiNpXt1U2ju/bHugH422r+4LAVS1FpW1YCwilmnNsjum9w==", "requires": { + "regex": "^5.1.1", "regex-utilities": "^2.3.0" } }, @@ -11409,11 +11456,11 @@ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" }, "resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", "requires": { - "is-core-module": "^2.13.0", + "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" } @@ -11553,6 +11600,14 @@ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.1.tgz", "integrity": "sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==" }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "requires": { + "graceful-fs": "^4.1.6" + } + }, "minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -11560,6 +11615,11 @@ "requires": { "brace-expansion": "^1.1.7" } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" } } }, @@ -11751,15 +11811,17 @@ "peer": true }, "shiki": { - "version": "1.24.0", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.24.0.tgz", - "integrity": "sha512-qIneep7QRwxRd5oiHb8jaRzH15V/S8F3saCXOdjwRLgozZJr5x2yeBhQtqkO3FSzQDwYEFAYuifg4oHjpDghrg==", - "requires": { - "@shikijs/core": "1.24.0", - "@shikijs/engine-javascript": "1.24.0", - "@shikijs/engine-oniguruma": "1.24.0", - "@shikijs/types": "1.24.0", - "@shikijs/vscode-textmate": "^9.3.0", + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.29.2.tgz", + "integrity": "sha512-njXuliz/cP+67jU2hukkxCNuH1yUi4QfdZZY+sMr5PPrIyXSu5iTb/qYC4BiWWB0vZ+7TbdvYUCeL23zpwCfbg==", + "requires": { + "@shikijs/core": "1.29.2", + "@shikijs/engine-javascript": "1.29.2", + "@shikijs/engine-oniguruma": "1.29.2", + "@shikijs/langs": "1.29.2", + "@shikijs/themes": "1.29.2", + "@shikijs/types": "1.29.2", + "@shikijs/vscode-textmate": "^10.0.1", "@types/hast": "^3.0.4" } }, @@ -11945,9 +12007,9 @@ "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==" }, "ts-api-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", - "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.0.tgz", + "integrity": "sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==", "peer": true, "requires": {} }, @@ -12009,9 +12071,9 @@ } }, "yaml": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz", - "integrity": "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==" + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz", + "integrity": "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==" } } }, @@ -12120,9 +12182,9 @@ } }, "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==" }, "unpipe": { "version": "1.0.0", @@ -12130,12 +12192,12 @@ "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" }, "update-browserslist-db": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", - "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz", + "integrity": "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==", "requires": { "escalade": "^3.2.0", - "picocolors": "^1.1.0" + "picocolors": "^1.1.1" } }, "uri-js": { diff --git a/shared/AppInsightsCommon/Tests/Unit/src/Exception.tests.ts b/shared/AppInsightsCommon/Tests/Unit/src/Exception.tests.ts index dced51758..495c3c7e2 100644 --- a/shared/AppInsightsCommon/Tests/Unit/src/Exception.tests.ts +++ b/shared/AppInsightsCommon/Tests/Unit/src/Exception.tests.ts @@ -2,7 +2,16 @@ import { Assert, AITestClass } from "@microsoft/ai-test-framework"; import { DataSanitizerValues, Exception } from "../../../src/applicationinsights-common" import { DiagnosticLogger } from "@microsoft/applicationinsights-core-js"; import { IExceptionInternal, IExceptionDetailsInternal, IExceptionStackFrameInternal } from "../../../src/Interfaces/IExceptionTelemetry"; -import { _ExceptionDetails, _StackFrame } from "../../../src/Telemetry/Exception"; +import { _createExceptionDetails, _createExDetailsFromInterface, _extractStackFrame, _parsedFrameToInterface, _IParsedStackFrame } from "../../../src/Telemetry/Exception"; +import { IStackFrame } from "../../../src/Interfaces/Contracts/IStackFrame"; + +function _checkExpectedFrame(expectedFrame: IStackFrame, actualFrame: IStackFrame, index: number) { + Assert.equal(expectedFrame.assembly, actualFrame.assembly, index + ") Assembly is not as expected"); + Assert.equal(expectedFrame.fileName, actualFrame.fileName, index + ") FileName is not as expected"); + Assert.equal(expectedFrame.line, actualFrame.line, index + ") Line is not as expected"); + Assert.equal(expectedFrame.method, actualFrame.method, index + ") Method is not as expected"); + Assert.equal(expectedFrame.level, actualFrame.level, index + ") Level is not as expected"); +} export class ExceptionTests extends AITestClass { logger = new DiagnosticLogger(); @@ -39,7 +48,7 @@ export class ExceptionTests extends AITestClass { name: "ExceptionDetails: ExceptionDetails can be exported to interface format", test: () => { try { - const exceptionDetails = new _ExceptionDetails(this.logger, new Error("test error")); + const exceptionDetails = _createExceptionDetails(this.logger, new Error("test error")); Assert.ok(exceptionDetails, "ExceptionDetails instance is created"); const exceptionDetailsInterface: IExceptionDetailsInternal = exceptionDetails.toInterface(); @@ -49,9 +58,9 @@ export class ExceptionTests extends AITestClass { Assert.deepEqual(exceptionDetails.message, exceptionDetailsInterface.message); Assert.deepEqual(exceptionDetails.hasFullStack, exceptionDetailsInterface.hasFullStack); Assert.deepEqual(exceptionDetails.stack, exceptionDetailsInterface.stack); - Assert.deepEqual(exceptionDetails.parsedStack && exceptionDetails.parsedStack.map((frame: _StackFrame) => frame.toInterface()), exceptionDetailsInterface.parsedStack); + Assert.deepEqual(exceptionDetails.parsedStack && exceptionDetails.parsedStack.map((frame: any) => _parsedFrameToInterface(frame)), exceptionDetailsInterface.parsedStack); - const exceptionDetailsConverted = _ExceptionDetails.CreateFromInterface(this.logger, exceptionDetailsInterface); + const exceptionDetailsConverted = _createExDetailsFromInterface(this.logger, exceptionDetailsInterface); Assert.deepEqual(exceptionDetails, exceptionDetailsConverted); } catch (e) { console.log(e.stack); @@ -85,7 +94,7 @@ export class ExceptionTests extends AITestClass { 0, errObj ); - const exceptionDetails = new _ExceptionDetails(this.logger, exception); + const exceptionDetails = _createExceptionDetails(this.logger, exception); for (let i = 0; i < exceptionDetails.parsedStack.length; i++) { Assert.equal(MAX_STRING_LENGTH, exceptionDetails.parsedStack[i].assembly.length); @@ -122,7 +131,7 @@ export class ExceptionTests extends AITestClass { 0, errObj ); - const exceptionDetails = new _ExceptionDetails(this.logger, exception); + const exceptionDetails = _createExceptionDetails(this.logger, exception); for (let i = 0; i < exceptionDetails.parsedStack.length; i++) { Assert.equal(MAX_STRING_LENGTH, exceptionDetails.parsedStack[i].fileName.length); @@ -144,18 +153,15 @@ export class ExceptionTests extends AITestClass { Assert.ok(true); return; } - const stackFrame = new _StackFrame(stack.split("\n")[0], 0); + const stackFrame = _extractStackFrame(stack.split("\n")[0], 0); Assert.ok(stackFrame, "StackFrame instance is created"); - const stackFrameInterface: IExceptionStackFrameInternal = stackFrame.toInterface(); - Assert.deepEqual(stackFrame.level, stackFrameInterface.level); - Assert.deepEqual(stackFrame.method, stackFrameInterface.method); - Assert.deepEqual(stackFrame.assembly, stackFrameInterface.assembly); - Assert.deepEqual(stackFrame.fileName, stackFrameInterface.fileName); - Assert.deepEqual(stackFrame.line, stackFrameInterface.line); - - // var stackFrameConverted = _StackFrame.CreateFromInterface(stackFrameInterface); - // Assert.deepEqual(stackFrame, stackFrameConverted); + const stackFrameInterface: IExceptionStackFrameInternal = _parsedFrameToInterface(stackFrame!); + Assert.deepEqual(stackFrame!.level, stackFrameInterface.level); + Assert.deepEqual(stackFrame!.method, stackFrameInterface.method); + Assert.deepEqual(stackFrame!.assembly, stackFrameInterface.assembly); + Assert.deepEqual(stackFrame!.fileName, stackFrameInterface.fileName); + Assert.deepEqual(stackFrame!.line, stackFrameInterface.line); } }); @@ -183,5 +189,345 @@ export class ExceptionTests extends AITestClass { Assert.deepEqual(exception.stackDetails, errDetail); } }); + + this.testCase({ + name: "StackFrame: Validate different stack formats", + test:() => { + let errObj = { + reason:{ + message: "Test_Error_Throwing_Inside_UseCallback", + stack: "Error: Test_Error_Throwing_Inside_UseCallback\n" + + "at http://localhost:3000/static/js/main.206f4846.js:2:296748\n" + // Anonymous function with no function name attribution (firefox/ios) + "at Object.Re (http://localhost:3000/static/js/main.206f4846.js:2:16814)\n" + // With class.function attribution + "at je (http://localhost:3000/static/js/main.206f4846.js:2:16968)\n" + // With function name attribution + "at Object. (http://localhost:3000/static/js/main.206f4846.js:2:42819)\n" + // With Object. attribution + "at Object. (../localfile.js:2:1234)\n" + // With Object. attribution and local file + "at (anonymous) @ VM60:1\n" + // With (anonymous) attribution + "at [native code]\n" + // With [native code] attribution + "at (at eval at (http://localhost:3000/static/js/main.206f4846.js:2:296748), :1:1)\n" + // With eval attribution + "at Object.eval (http://localhost:3000/static/js/main.206f4846.js:2:296748)\n" + // With eval attribution + "at eval (http://localhost:3000/static/js/main.206f4846.js:2:296748)\n" + // With eval attribution + "at eval (webpack-internal:///./src/App.tsx:1:1)\n" + // With eval attribution + "at [arguments not available])@file://localhost/stacktrace.js:21\n" + // With arguments not available attribution + "at file://C:/Temp/stacktrace.js:27:1\n" + // With file://localhost attribution + " Line 21 of linked script file://localhost/C:/Temp/stacktrace.js\n" + // With Line 21 of linked script attribution + " Line 11 of inline#1 script in http://localhost:3000/static/js/main.206f4846.js:2:296748\n" + // With Line 11 of inline#1 script attribution + " Line 68 of inline#2 script in file://localhost/teststack.html\n" + // With Line 68 of inline#2 script attribution + "at Function.Module._load (module.js:407:3)\n" + + " at Function.Module.runMain (module.js:575:10)\n"+ + " at startup (node.js:159:18)\n" + + "at Global code (http://example.com/stacktrace.js:11:1)\n" + + "at Object.Module._extensions..js (module.js:550:10)\n" + + " at c@http://example.com/stacktrace.js:9:3\n" + + " at b@http://example.com/stacktrace.js:6:3\n" + + " at a@http://example.com/stacktrace.js:3:3\n" + + "http://localhost:3000/static/js/main.206f4846.js:2:296748\n" + // Anonymous function with no function name attribution (firefox/ios) + " c@http://example.com/stacktrace.js:9:3\n" + + " b@http://example.com/stacktrace.js:6:3\n" + + " a@http://example.com/stacktrace.js:3:3\n" + + " at Object.testMethod (http://localhost:9001/shared/AppInsightsCommon/node_modules/@microsoft/ai-test-framework/dist/es5/ai-test-framework.js:53058:48)" + } + }; + + const expectedParsedStack: IStackFrame[] = [ + { level: 0, method: "", assembly: "at http://localhost:3000/static/js/main.206f4846.js:2:296748", fileName: "http://localhost:3000/static/js/main.206f4846.js", line: 2 }, + { level: 1, method: "Object.Re", assembly: "at Object.Re (http://localhost:3000/static/js/main.206f4846.js:2:16814)", fileName: "http://localhost:3000/static/js/main.206f4846.js", line: 2 }, + { level: 2, method: "je", assembly: "at je (http://localhost:3000/static/js/main.206f4846.js:2:16968)", fileName: "http://localhost:3000/static/js/main.206f4846.js", line: 2 }, + { level: 3, method: "Object.", assembly: "at Object. (http://localhost:3000/static/js/main.206f4846.js:2:42819)", fileName: "http://localhost:3000/static/js/main.206f4846.js", line: 2 }, + { level: 4, method: "Object.", assembly: "at Object. (../localfile.js:2:1234)", fileName: "../localfile.js", line: 2 }, + { level: 5, method: "", assembly: "at (anonymous) @ VM60:1", fileName: "VM60", line: 1 }, + { level: 6, method: "", assembly: "at [native code]", fileName: "", line: 0 }, + { level: 7, method: "", assembly: "at (at eval at (http://localhost:3000/static/js/main.206f4846.js:2:296748), :1:1)", fileName: "http://localhost:3000/static/js/main.206f4846.js", line: 2 }, + { level: 8, method: "Object.eval", assembly: "at Object.eval (http://localhost:3000/static/js/main.206f4846.js:2:296748)", fileName: "http://localhost:3000/static/js/main.206f4846.js", line: 2 }, + { level: 9, method: "eval", assembly: "at eval (http://localhost:3000/static/js/main.206f4846.js:2:296748)", fileName: "http://localhost:3000/static/js/main.206f4846.js", line: 2 }, + { level: 10, method: "eval", assembly: "at eval (webpack-internal:///./src/App.tsx:1:1)", fileName: "webpack-internal:///./src/App.tsx", line: 1 }, + { level: 11, method: "", assembly: "at [arguments not available])@file://localhost/stacktrace.js:21", fileName: "file://localhost/stacktrace.js", line: 21 }, + { level: 12, method: "", assembly: "at file://C:/Temp/stacktrace.js:27:1", fileName: "file://C:/Temp/stacktrace.js", line: 27 }, + { level: 13, method: "", assembly: "Line 21 of linked script file://localhost/C:/Temp/stacktrace.js", fileName: "file://localhost/C:/Temp/stacktrace.js", line: 0 }, + { level: 14, method: "", assembly: "Line 11 of inline#1 script in http://localhost:3000/static/js/main.206f4846.js:2:296748", fileName: "http://localhost:3000/static/js/main.206f4846.js", line: 2 }, + { level: 15, method: "", assembly: "Line 68 of inline#2 script in file://localhost/teststack.html", fileName: "file://localhost/teststack.html", line: 0 }, + { level: 16, method: "Function.Module._load", assembly: "at Function.Module._load (module.js:407:3)", fileName: "module.js", line: 407 }, + { level: 17, method: "Function.Module.runMain", assembly: "at Function.Module.runMain (module.js:575:10)", fileName: "module.js", line: 575 }, + { level: 18, method: "startup", assembly: "at startup (node.js:159:18)", fileName: "node.js", line: 159 }, + { level: 19, method: "", assembly: "at Global code (http://example.com/stacktrace.js:11:1)", fileName: "http://example.com/stacktrace.js", line: 11 }, + { level: 20, method: "Object.Module._extensions..js", assembly: "at Object.Module._extensions..js (module.js:550:10)", fileName: "module.js", line: 550 }, + { level: 21, method: "c", assembly: "at c@http://example.com/stacktrace.js:9:3", fileName: "http://example.com/stacktrace.js", line: 9 }, + { level: 22, method: "b", assembly: "at b@http://example.com/stacktrace.js:6:3", fileName: "http://example.com/stacktrace.js", line: 6 }, + { level: 23, method: "a", assembly: "at a@http://example.com/stacktrace.js:3:3", fileName: "http://example.com/stacktrace.js", line: 3 }, + { level: 24, method: "", assembly: "http://localhost:3000/static/js/main.206f4846.js:2:296748", fileName: "http://localhost:3000/static/js/main.206f4846.js", line: 2 }, + { level: 25, method: "c", assembly: "c@http://example.com/stacktrace.js:9:3", fileName: "http://example.com/stacktrace.js", line: 9 }, + { level: 26, method: "b", assembly: "b@http://example.com/stacktrace.js:6:3", fileName: "http://example.com/stacktrace.js", line: 6 }, + { level: 27, method: "a", assembly: "a@http://example.com/stacktrace.js:3:3", fileName: "http://example.com/stacktrace.js", line: 3 }, + { level: 28, method: "Object.testMethod", assembly: "at Object.testMethod (http://localhost:9001/shared/AppInsightsCommon/node_modules/@microsoft/ai-test-framework/dist/es5/ai-test-framework.js:53058:48)", fileName: "http://localhost:9001/shared/AppInsightsCommon/node_modules/@microsoft/ai-test-framework/dist/es5/ai-test-framework.js", line: 53058 } + ]; + + let exception = Exception.CreateAutoException("message", + "url", + 9, + 0, + errObj + ); + + Assert.ok(exception.stackDetails); + Assert.equal(exception.stackDetails?.src, errObj.reason.stack); + Assert.equal(exception.stackDetails?.obj.length, 30); + + const exceptionDetails = _createExceptionDetails(this.logger, exception); + Assert.equal(exceptionDetails.stack, errObj.reason.stack); + Assert.equal(exceptionDetails.parsedStack.length, 29); + for (let lp = 0; lp < exceptionDetails.parsedStack.length; lp++) { + _checkExpectedFrame(expectedParsedStack[lp], exceptionDetails.parsedStack[lp], lp); + } + } + }); + + this.testCase({ + name: "StackFrame: Validate individual different stack formatting", + test:() => { + let testStacks: Array<{src: string, frame: IStackFrame }> = [ + { + src: "at http://localhost:3000/static/js/main.206f4846.js:2:296748", // Anonymous function with no function name attribution (firefox/ios) + frame: { level: 0, method: "", assembly: "at http://localhost:3000/static/js/main.206f4846.js:2:296748", fileName: "http://localhost:3000/static/js/main.206f4846.js", line: 2 } + }, + { + src: "at Object.Re (http://localhost:3000/static/js/main.206f4846.js:2:16814)", // With class.function attribution + frame: { level: 0, method: "Object.Re", assembly: "at Object.Re (http://localhost:3000/static/js/main.206f4846.js:2:16814)", fileName: "http://localhost:3000/static/js/main.206f4846.js", line: 2 } + }, + { + src: "at je (http://localhost:3000/static/js/main.206f4846.js:2:16968)", // With function name attribution + frame: { level: 0, method: "je", assembly: "at je (http://localhost:3000/static/js/main.206f4846.js:2:16968)", fileName: "http://localhost:3000/static/js/main.206f4846.js", line: 2 } + }, + { + src: "at Object. (http://localhost:3000/static/js/main.206f4846.js:2:42819)", // With Object. attribution + frame: { level: 0, method: "Object.", assembly: "at Object. (http://localhost:3000/static/js/main.206f4846.js:2:42819)", fileName: "http://localhost:3000/static/js/main.206f4846.js", line: 2 } + }, + { + src: "at Object. (../localfile.js:2:1234)", // With Object. attribution and local file + frame: { level: 0, method: "Object.", assembly: "at Object. (../localfile.js:2:1234)", fileName: "../localfile.js", line: 2 } + }, + { + src: "at (anonymous) @ VM60:1", // With (anonymous) attribution + frame: { level: 0, method: "", assembly: "at (anonymous) @ VM60:1", fileName: "VM60", line: 1 } + }, + { + src: "at [native code]", // With [native code] attribution + frame: { level: 0, method: "", assembly: "at [native code]", fileName: "", line: 0 } + }, + { + src: "at (at eval at (http://localhost:3000/static/js/main.206f4846.js:2:296748), :1:1)", // With eval attribution + frame: { level: 0, method: "", assembly: "at (at eval at (http://localhost:3000/static/js/main.206f4846.js:2:296748), :1:1)", fileName: "http://localhost:3000/static/js/main.206f4846.js", line: 2 } + }, + { + src: "at Object.eval (http://localhost:3000/static/js/main.206f4846.js:2:296748)", // With eval attribution + frame: { level: 0, method: "Object.eval", assembly: "at Object.eval (http://localhost:3000/static/js/main.206f4846.js:2:296748)", fileName: "http://localhost:3000/static/js/main.206f4846.js", line: 2 } + }, + { + src: "at eval (http://localhost:3000/static/js/main.206f4846.js:2:296748)", // With eval attribution + frame: { level: 0, method: "eval", assembly: "at eval (http://localhost:3000/static/js/main.206f4846.js:2:296748)", fileName: "http://localhost:3000/static/js/main.206f4846.js", line: 2 } + }, + { + src: "at eval (webpack-internal:///./src/App.tsx:1:1)", // With eval attribution + frame: { level: 0, method: "eval", assembly: "at eval (webpack-internal:///./src/App.tsx:1:1)", fileName: "webpack-internal:///./src/App.tsx", line: 1 } + }, + { + src: "at [arguments not available])@file://localhost/stacktrace.js:21", // With arguments not available attribution + frame: { level: 0, method: "", assembly: "at [arguments not available])@file://localhost/stacktrace.js:21", fileName: "file://localhost/stacktrace.js", line: 21 } + }, + { + src: "at file://C:/Temp/stacktrace.js:27:1", // With file://localhost attribution + frame: { level: 0, method: "", assembly: "at file://C:/Temp/stacktrace.js:27:1", fileName: "file://C:/Temp/stacktrace.js", line: 27 } + }, + { + src: " Line 21 of linked script file://localhost/C:/Temp/stacktrace.js", // With Line 21 of linked script attribution + frame: { level: 0, method: "", assembly: "Line 21 of linked script file://localhost/C:/Temp/stacktrace.js", fileName: "file://localhost/C:/Temp/stacktrace.js", line: 0 } + }, + { + src: " Line 11 of inline#1 script in http://localhost:3000/static/js/main.206f4846.js:2:296748", // With Line 11 of inline#1 script attribution + frame: { level: 0, method: "", assembly: "Line 11 of inline#1 script in http://localhost:3000/static/js/main.206f4846.js:2:296748", fileName: "http://localhost:3000/static/js/main.206f4846.js", line: 2 } + }, + { + src: " Line 68 of inline#2 script in file://localhost/teststack.html", // With Line 68 of inline#2 script attribution + frame: { level: 0, method: "", assembly: "Line 68 of inline#2 script in file://localhost/teststack.html", fileName: "file://localhost/teststack.html", line: 0 } + }, + { + src: "at Function.Module._load (module.js:407:3)", + frame: { level: 0, method: "Function.Module._load", assembly: "at Function.Module._load (module.js:407:3)", fileName: "module.js", line: 407 } + }, + { + src: " at Function.Module.runMain (module.js:575:10)", + frame: { level: 0, method: "Function.Module.runMain", assembly: "at Function.Module.runMain (module.js:575:10)", fileName: "module.js", line: 575 } + }, + { + src: " at startup (node.js:159:18)", + frame: { level: 0, method: "startup", assembly: "at startup (node.js:159:18)", fileName: "node.js", line: 159 } + }, + { + src: "at Global code (http://example.com/stacktrace.js:11:1)", + frame: { level: 0, method: "", assembly: "at Global code (http://example.com/stacktrace.js:11:1)", fileName: "http://example.com/stacktrace.js", line: 11 } + }, + { + src: "at Object.Module._extensions..js (module.js:550:10)", + frame: { level: 0, method: "Object.Module._extensions..js", assembly: "at Object.Module._extensions..js (module.js:550:10)", fileName: "module.js", line: 550 } + }, + { + src: " at c@http://example.com/stacktrace.js:9:3", + frame: { level: 0, method: "c", assembly: "at c@http://example.com/stacktrace.js:9:3", fileName: "http://example.com/stacktrace.js", line: 9 } + }, + { + src: " at b@http://example.com/stacktrace.js:6:3", + frame: { level: 0, method: "b", assembly: "at b@http://example.com/stacktrace.js:6:3", fileName: "http://example.com/stacktrace.js", line: 6 } + }, + { + src: " at a@http://example.com/stacktrace.js:3:3", + frame: { level: 0, method: "a", assembly: "at a@http://example.com/stacktrace.js:3:3", fileName: "http://example.com/stacktrace.js", line: 3 } + }, + { + src: "http://localhost:3000/static/js/main.206f4846.js:2:296748", // Anonymous function with no function name attribution (firefox/ios) + frame: { level: 0, method: "", assembly: "http://localhost:3000/static/js/main.206f4846.js:2:296748", fileName: "http://localhost:3000/static/js/main.206f4846.js", line: 2 } + }, + { + src: " c@http://example.com/stacktrace.js:9:3", + frame: { level: 0, method: "c", assembly: "c@http://example.com/stacktrace.js:9:3", fileName: "http://example.com/stacktrace.js", line: 9 } + }, + { + src: " b@http://example.com/stacktrace.js:6:3", + frame: { level: 0, method: "b", assembly: "b@http://example.com/stacktrace.js:6:3", fileName: "http://example.com/stacktrace.js", line: 6 } + }, + { + src: " a@http://example.com/stacktrace.js:3:3", + frame: { level: 0, method: "a", assembly: "a@http://example.com/stacktrace.js:3:3", fileName: "http://example.com/stacktrace.js", line: 3 } + }, + { + src: " at Object.testMethod (http://localhost:9001/shared/AppInsightsCommon/node_modules/@microsoft/ai-test-framework/dist/es5/ai-test-framework.js:53058:48)", + frame: { level: 0, method: "Object.testMethod", assembly: "at Object.testMethod (http://localhost:9001/shared/AppInsightsCommon/node_modules/@microsoft/ai-test-framework/dist/es5/ai-test-framework.js:53058:48)", fileName: "http://localhost:9001/shared/AppInsightsCommon/node_modules/@microsoft/ai-test-framework/dist/es5/ai-test-framework.js", line: 53058 } + } + ]; + + for (let lp = 0; lp < testStacks.length; lp++) { + let stackFrame = _extractStackFrame(testStacks[lp].src, 0); + _checkExpectedFrame(testStacks[lp].frame, stackFrame!, lp); + } + } + }); + + this.testCase({ + name: "StackFrame: Standard Chrome exception stack", + test:() => { + let errObj = { + reason:{ + message: "TypeError: Cannot read property 'b' of undefined", + stack: "TypeError: Cannot read property 'b' of undefined\n" + + " at ApplicationInsightsTests. (http://localhost:9001/AISKU/Tests/Unit/dist/aiskuunittests.tests.js:4578:40)\n" + + " at trigger_1 (http://localhost:9001/AISKU/node_modules/@microsoft/ai-test-framework/dist/es5/ai-test-framework.js:52923:59)\n" + + " at Object.testMethod (http://localhost:9001/AISKU/node_modules/@microsoft/ai-test-framework/dist/es5/ai-test-framework.js:52964:21)\n" + + " at runTest (http://localhost:9001/common/Tests/External/qunit-2.9.3.js:2725:35)\n" + + " at Test.run (http://localhost:9001/common/Tests/External/qunit-2.9.3.js:2708:9)\n" + + " at http://localhost:9001/common/Tests/External/qunit-2.9.3.js:2972:16\n" + + " at processTaskQueue (http://localhost:9001/common/Tests/External/qunit-2.9.3.js:2293:26)\n" + + " at http://localhost:9001/common/Tests/External/qunit-2.9.3.js:2297:13" + } + }; + let errDetail = { + src: errObj.reason.stack, + obj:[ + "TypeError: Cannot read property 'b' of undefined", + "at ApplicationInsightsTests. (http://localhost:9001/AISKU/Tests/Unit/dist/aiskuunittests.tests.js:4578:40)", + "at trigger_1 (http://localhost:9001/AISKU/node_modules/@microsoft/ai-test-framework/dist/es5/ai-test-framework.js:52923:59)", + "at Object.testMethod (http://localhost:9001/AISKU/node_modules/@microsoft/ai-test-framework/dist/es5/ai-test-framework.js:52964:21)", + "at runTest (http://localhost:9001/common/Tests/External/qunit-2.9.3.js:2725:35)", + "at Test.run (http://localhost:9001/common/Tests/External/qunit-2.9.3.js:2708:9)", + "at http://localhost:9001/common/Tests/External/qunit-2.9.3.js:2972:16", + "at processTaskQueue (http://localhost:9001/common/Tests/External/qunit-2.9.3.js:2293:26)", + "at http://localhost:9001/common/Tests/External/qunit-2.9.3.js:2297:13" + ] + }; + let exception = Exception.CreateAutoException("message", + "url", + 9, + 0, + errObj + ); + + Assert.ok(exception.stackDetails); + + const expectedParsedStack: IStackFrame[] = [ + { level: 0, method: "ApplicationInsightsTests.", assembly: "at ApplicationInsightsTests. (http://localhost:9001/AISKU/Tests/Unit/dist/aiskuunittests.tests.js:4578:40)", fileName: "http://localhost:9001/AISKU/Tests/Unit/dist/aiskuunittests.tests.js", line: 4578 }, + { level: 1, method: "trigger_1", assembly: "at trigger_1 (http://localhost:9001/AISKU/node_modules/@microsoft/ai-test-framework/dist/es5/ai-test-framework.js:52923:59)", fileName: "http://localhost:9001/AISKU/node_modules/@microsoft/ai-test-framework/dist/es5/ai-test-framework.js", line: 52923 }, + { level: 2, method: "Object.testMethod", assembly: "at Object.testMethod (http://localhost:9001/AISKU/node_modules/@microsoft/ai-test-framework/dist/es5/ai-test-framework.js:52964:21)", fileName: "http://localhost:9001/AISKU/node_modules/@microsoft/ai-test-framework/dist/es5/ai-test-framework.js", line: 52964 }, + { level: 3, method: "runTest", assembly: "at runTest (http://localhost:9001/common/Tests/External/qunit-2.9.3.js:2725:35)", fileName: "http://localhost:9001/common/Tests/External/qunit-2.9.3.js", line: 2725 }, + { level: 4, method: "Test.run", assembly: "at Test.run (http://localhost:9001/common/Tests/External/qunit-2.9.3.js:2708:9)", fileName: "http://localhost:9001/common/Tests/External/qunit-2.9.3.js", line: 2708 }, + { level: 5, method: "", assembly: "at http://localhost:9001/common/Tests/External/qunit-2.9.3.js:2972:16", fileName: "http://localhost:9001/common/Tests/External/qunit-2.9.3.js", line: 2972 }, + { level: 6, method: "processTaskQueue", assembly: "at processTaskQueue (http://localhost:9001/common/Tests/External/qunit-2.9.3.js:2293:26)", fileName: "http://localhost:9001/common/Tests/External/qunit-2.9.3.js", line: 2293 }, + { level: 7, method: "", assembly: "at http://localhost:9001/common/Tests/External/qunit-2.9.3.js:2297:13", fileName: "http://localhost:9001/common/Tests/External/qunit-2.9.3.js", line: 2297 } + ]; + + const exceptionDetails = _createExceptionDetails(this.logger, exception); + Assert.equal(exceptionDetails.stack, errObj.reason.stack); + Assert.equal(exceptionDetails.parsedStack.length, 8); + for (let lp = 0; lp < exceptionDetails.parsedStack.length; lp++) { + _checkExpectedFrame(expectedParsedStack[lp], exceptionDetails.parsedStack[lp], lp); + } + } + }); + + this.testCase({ + name: "StackFrame: handle multiple line message stack", + test:() => { + let errObj = { + reason:{ + message: "Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n" + + "1. You might have mismatching versions of React and the renderer (such as React DOM)\n" + + "2. You might be breaking the Rules of Hooks\n" + + "3. You might have more than one copy of React in the same app\n", + stack: "Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n" + + "1. You might have mismatching versions of React and the renderer (such as React DOM)\n" + + "2. You might be breaking the Rules of Hooks\n" + + "3. You might have more than one copy of React in the same app\n" + + "See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.\n" + + " at Object.throwInvalidHookError (https://localhost:44365/static/js/bundle.js:201419:13)\n" + + " at useContext (https://localhost:44365/static/js/bundle.js:222943:25)\n" + + " at useTenantContext (https://localhost:44365/static/js/bundle.js:5430:68)\n" + + " at https://localhost:44365/static/js/bundle.js:4337:72\n" + + " at _ZoneDelegate.invoke (https://localhost:44365/static/js/bundle.js:227675:158)\n" + + " at ZoneImpl.run (https://localhost:44365/static/js/bundle.js:227446:35)\n" + + " at https://localhost:44365/static/js/bundle.js:229764:30\n" + + " at _ZoneDelegate.invokeTask (https://localhost:44365/static/js/bundle.js:227700:171)\n" + + " at ZoneImpl.runTask (https://localhost:44365/static/js/bundle.js:227499:37)\n" + + " at ZoneImpl.patchRunTask (https://localhost:44365/static/js/bundle.js:144112:27)" + } + }; + + const expectedParsedStack: IStackFrame[] = [ + { level: 0, method: "Object.throwInvalidHookError", assembly: "at Object.throwInvalidHookError (https://localhost:44365/static/js/bundle.js:201419:13)", fileName: "https://localhost:44365/static/js/bundle.js", line: 201419 }, + { level: 1, method: "useContext", assembly: "at useContext (https://localhost:44365/static/js/bundle.js:222943:25)", fileName: "https://localhost:44365/static/js/bundle.js", line: 222943 }, + { level: 2, method: "useTenantContext", assembly: "at useTenantContext (https://localhost:44365/static/js/bundle.js:5430:68)", fileName: "https://localhost:44365/static/js/bundle.js", line: 5430 }, + { level: 3, method: "", assembly: "at https://localhost:44365/static/js/bundle.js:4337:72", fileName: "https://localhost:44365/static/js/bundle.js", line: 4337 }, + { level: 4, method: "_ZoneDelegate.invoke", assembly: "at _ZoneDelegate.invoke (https://localhost:44365/static/js/bundle.js:227675:158)", fileName: "https://localhost:44365/static/js/bundle.js", line: 227675 }, + { level: 5, method: "ZoneImpl.run", assembly: "at ZoneImpl.run (https://localhost:44365/static/js/bundle.js:227446:35)", fileName: "https://localhost:44365/static/js/bundle.js", line: 227446 }, + { level: 6, method: "", assembly: "at https://localhost:44365/static/js/bundle.js:229764:30", fileName: "https://localhost:44365/static/js/bundle.js", line: 229764 }, + { level: 7, method: "_ZoneDelegate.invokeTask", assembly: "at _ZoneDelegate.invokeTask (https://localhost:44365/static/js/bundle.js:227700:171)", fileName: "https://localhost:44365/static/js/bundle.js", line: 227700 }, + { level: 8, method: "ZoneImpl.runTask", assembly: "at ZoneImpl.runTask (https://localhost:44365/static/js/bundle.js:227499:37)", fileName: "https://localhost:44365/static/js/bundle.js", line: 227499 }, + { level: 9, method: "ZoneImpl.patchRunTask", assembly: "at ZoneImpl.patchRunTask (https://localhost:44365/static/js/bundle.js:144112:27)", fileName: "https://localhost:44365/static/js/bundle.js", line: 144112 } + ]; + + let exception = Exception.CreateAutoException("message", + "url", + 9, + 0, + errObj + ); + + Assert.ok(exception.stackDetails); + Assert.equal(exception.stackDetails?.src, errObj.reason.stack); + Assert.equal(exception.stackDetails?.obj.length, 15); + + const exceptionDetails = _createExceptionDetails(this.logger, exception); + Assert.equal(exceptionDetails.stack, errObj.reason.stack); + Assert.equal(exceptionDetails.parsedStack.length, 10); + for (let lp = 0; lp < exceptionDetails.parsedStack.length; lp++) { + _checkExpectedFrame(expectedParsedStack[lp], exceptionDetails.parsedStack[lp], lp); + } + } + }); } } \ No newline at end of file diff --git a/shared/AppInsightsCommon/src/Telemetry/Exception.ts b/shared/AppInsightsCommon/src/Telemetry/Exception.ts index 6d669b1cc..c45da9bf9 100644 --- a/shared/AppInsightsCommon/src/Telemetry/Exception.ts +++ b/shared/AppInsightsCommon/src/Telemetry/Exception.ts @@ -4,21 +4,163 @@ import { IDiagnosticLogger, arrForEach, arrMap, isArray, isError, isFunction, isNullOrUndefined, isObject, isString, strTrim } from "@microsoft/applicationinsights-core-js"; -import { getWindow, strIndexOf } from "@nevware21/ts-utils"; +import { asString, getWindow, objFreeze, strIndexOf } from "@nevware21/ts-utils"; import { strNotSpecified } from "../Constants"; import { FieldType } from "../Enums"; import { IExceptionData } from "../Interfaces/Contracts/IExceptionData"; import { IExceptionDetails } from "../Interfaces/Contracts/IExceptionDetails"; import { IStackFrame } from "../Interfaces/Contracts/IStackFrame"; import { SeverityLevel } from "../Interfaces/Contracts/SeverityLevel"; -import { - IAutoExceptionTelemetry, IExceptionDetailsInternal, IExceptionInternal, IExceptionStackFrameInternal, IStackDetails -} from "../Interfaces/IExceptionTelemetry"; +import { IAutoExceptionTelemetry, IExceptionDetailsInternal, IExceptionInternal, IStackDetails } from "../Interfaces/IExceptionTelemetry"; import { ISerializable } from "../Interfaces/Telemetry/ISerializable"; import { dataSanitizeException, dataSanitizeMeasurements, dataSanitizeMessage, dataSanitizeProperties, dataSanitizeString } from "./Common/DataSanitizer"; +// These Regex covers the following patterns +// 1. Chrome/Firefox/IE/Edge: +// at functionName (filename:lineNumber:columnNumber) +// at functionName (filename:lineNumber) +// at filename:lineNumber:columnNumber +// at filename:lineNumber +// at functionName@filename:lineNumber:columnNumber +// 2. Safari / Opera: +// functionName@filename:lineNumber:columnNumber +// functionName@filename:lineNumber +// filename:lineNumber:columnNumber +// filename:lineNumber +// Line ## of scriptname script filename:lineNumber:columnNumber +// Line ## of scriptname script filename +// 3. IE/Edge (Additional formats) +// at functionName@filename:lineNumber + +const STACKFRAME_BASE_SIZE = 58; // '{"method":"","level":,"assembly":"","fileName":"","line":}'.length + +/** + * Check if the string conforms to what looks like a stack frame line and not just a general message + * comment or other non-stack related info. + * + * This should be used to filter out any leading "message" lines from a stack trace, before attempting to parse + * the individual stack frames. Once you have estabilsted the start of the stack frames you can then use the + * FULL_STACK_FRAME_1, FULL_STACK_FRAME_2, FULL_STACK_FRAME_3, and EXTRACT_FILENAME to parse the individual + * stack frames to extract the method, filename, line number, and column number. + * These may still provide invalid matches, so the sequence of execution is important to avoid providing + * an invalid parsed stack. + */ +const IS_FRAME = /^\s{0,50}(from\s|at\s|Line\s{1,5}\d{1,10}\s{1,5}of|\w{1,50}@\w{1,80}|[^\(\s\n]+:[0-9\?]+(?::[0-9\?]+)?)/; + +/** + * Parse a well formed stack frame with both the line and column numbers + * ---------------------------------- + * **Primary focus of the matching** + * - at functionName (filename:lineNumber:columnNumber) + * - at filename:lineNumber:columnNumber + * - at functionName@filename:lineNumber:columnNumber + * - functionName (filename:lineNumber:columnNumber) + * - filename:lineNumber:columnNumber + * - functionName@filename:lineNumber:columnNumber + */ +const FULL_STACK_FRAME_1 = /^(?:\s{0,50}at)?\s{0,50}([^\@\()\s]+)?\s{0,50}(?:\s|\@|\()\s{0,5}([^\(\s\n\]]+):([0-9\?]+):([0-9\?]+)\)?$/; + +/** + * Parse a well formed stack frame with only a line number. + * ---------------------------------- + * > Note: this WILL also match with line and column number, but the line number is included with the filename + * > you should attempt to match with FULL_STACK_FRAME_1 first. + * + * **Primary focus of the matching (run FULL_STACK_FRAME_1 first)** + * - at functionName (filename:lineNumber) + * - at filename:lineNumber + * - at functionName@filename:lineNumber + * - functionName (filename:lineNumber) + * - filename:lineNumber + * - functionName@filename:lineNumber + * + * **Secondary matches** + * - at functionName (filename:lineNumber:columnNumber) + * - at filename:lineNumber:columnNumber + * - at functionName@filename:lineNumber:columnNumber + * - functionName (filename:lineNumber:columnNumber) + * - filename:lineNumber:columnNumber + * - functionName@filename:lineNumber:columnNumber + */ +const FULL_STACK_FRAME_2 = /^(?:\s{0,50}at)?\s{0,50}([^\@\()\s]+)?\s{0,50}(?:\s|\@|\()\s{0,5}([^\(\s\n\]]+):([0-9\?]+)\)?$/; + +/** + * Attempt to Parse a frame that doesn't include a line or column number. + * ---------------------------------- + * > Note: this WILL also match lines with a line or line and column number, you should attempt to match with + * both FULL_STACK_FRAME_1 and FULL_STACK_FRAME_2 first to avoid false positives. + * + * **Unexpected Invalid Matches** (Matches that should be avoided -- by using the FULL_STACK_FRAME_1 and FULL_STACK_FRAME_2 first) + * - at https://localhost:44365/static/node_bundles/@microsoft/blah/js/bundle.js:144112:27 + * - at https://localhost:44365/static/node_bundles/@microsoft/blah/js/bundle.js:144112:27 + * + * **Primary focus of the matching (run FULL_STACK_FRAME_1 first)** + * - at functionName@filename + * - at functionName (filename) + * - at functionName filename + * - at filename <- Will actuall match this as the "method" and not the filename (care should be taken to avoid this) + * - functionName@filename + * - functionName (filename) + * - functionName filename + * - functionName + * + * **Secondary matches** (The line and column numbers will be included with the matched filename) + * - at functionName (filename:lineNumber:columnNumber) + * - at functionName (filename:lineNumber) + * - at filename:lineNumber:columnNumber + * - at filename:lineNumber + * - at functionName@filename:lineNumber:columnNumber + * - at functionName@filename:lineNumber + * - functionName (filename:lineNumber:columnNumber) + * - functionName (filename:lineNumber) + * - filename:lineNumber:columnNumber + * - filename:lineNumber + * - functionName@filename:lineNumber:columnNumber + * - functionName@filename:lineNumber + */ +const FULL_STACK_FRAME_3 = /^(?:\s{0,50}at)?\s{0,50}([^\@\()\s]+)?\s{0,50}(?:\s|\@|\()\s{0,5}([^\(\s\n\)\]]+)\)?$/; + +/** + * Attempt to extract the filename (with or without line and column numbers) from a string. + * ---------------------------------- + * > Note: this will only match the filename (with any line or column numbers) and will + * > return what looks like the filename, however, it will also match random strings that + * > look like a filename, so care should be taken to ensure that the filename is actually + * > a filename before using it. + * > + * > It is recommended to use this in conjunction with the FULL_STACK_FRAME_1, FULL_STACK_FRAME_2, and FULL_STACK_FRAME_3 + * > to ensure first to reduce false matches, if all of these fail then you can use this to extract the filename from a random + * > strings to identify any potential filename from a known stack frame line. + * + * **Known Invalid matching** + * + * This regex will basically match any "final" string of a line or one that is trailed by a comma, so this should not + * be used as the "only" matching regex, but rather as a final fallback to extract the filename from a string. + * If you are certain that the string line is a stack frame and not part of the exception message (lines before the stack) + * or trailing comments, then you can use this to extract the filename and then further parse with PARSE_FILENAME_LINE_COL + * and PARSE_FILENAME_LINE_ONLY to extract any potential the line and column numbers. + * + * **Primary focus of the matching** + * - at (anonymous) @ VM60:1 + * - Line 21 of linked script file://localhost/C:/Temp/stacktrace.js + * - Line 11 of inline#1 script in http://localhost:3000/static/js/main.206f4846.js:2:296748 + * - Line 68 of inline#2 script in file://localhost/teststack.html + * - at Global code (http://example.com/stacktrace.js:11:1) + */ +const EXTRACT_FILENAME = /(?:^|\(|\s{0,10}[\w\)]+\@)?([^\(\n\s\]\)]+)(?:\:([0-9]+)(?:\:([0-9]+))?)?\)?(?:,|$)/; + +/** + * Attempt to extract the filename, line number, and column number from a string. + */ +const PARSE_FILENAME_LINE_COL = /([^\(\s\n]+):([0-9]+):([0-9]+)$/; + +/** + * Attempt to extract the filename and line number from a string. + */ +const PARSE_FILENAME_LINE_ONLY = /([^\(\s\n]+):([0-9]+)$/; + const NoMethod = ""; const strError = "error"; const strStack = "stack"; @@ -27,6 +169,76 @@ const strErrorSrc = "errorSrc"; const strMessage = "message"; const strDescription = "description"; +interface _ParseSequence { + /** + * The regular expression to match the frame + */ + re: RegExp; + + /** + * The expected number of matches in the regex, if this number is detected it will be considered a match + */ + len: number; + + /** + * The index into the matches to be used as the method name + */ + m?: number; + + /** + * The index into the matches to be used as the filename + */ + fn: number; + + /** + * The index into the matches to be used as the line number + */ + ln?: number; + + /** + * The index into the matches to be used as the column number + */ + col?: number; + + /** + * A function to pre-process the frame before it is parsed, this is persistent and any changes + * will affect all subsequent frames + * @param frame + * @returns + */ + pre?: (frame: string) => string; + + /** + * A Check function to determine if the frame should be processed or dropped + * @param frame + * @returns + */ + chk?: (frame: string) => boolean; + + /** + * Convert / Handle the matching frame + * @param frame - The frame to be processed + * @param matches - The matches from the regex + * @returns + */ + hdl?: (frame: IStackFrame, parseSequence: _ParseSequence, matches: RegExpMatchArray) => void; +} + +const _parseSequence: _ParseSequence[] = [ + { re: FULL_STACK_FRAME_1, len: 5, m: 1, fn: 2, ln: 3, col: 4 }, + { chk: _ignoreNative, pre: _scrubAnonymous, re: FULL_STACK_FRAME_2, len: 4, m: 1, fn: 2, ln: 3 }, + { re: FULL_STACK_FRAME_3, len: 3, m: 1, fn: 2, hdl: _handleFilename }, + { re: EXTRACT_FILENAME, len: 2, fn: 1, hdl: _handleFilename } +]; + +function _scrubAnonymous(frame: string) { + return frame.replace(/(\(anonymous\))/, ""); +} + +function _ignoreNative(frame: string) { + return strIndexOf(frame, "[native") < 0; +} + function _stringify(value: any, convertToString: boolean) { let result = value; if (result && !isString(result)) { @@ -197,9 +409,7 @@ function _formatStackTrace(stackDetails: IStackDetails) { if (stackDetails) { if (stackDetails.obj) { - arrForEach(stackDetails.obj, (entry) => { - stack += entry + "\n"; - }); + stack = stackDetails.obj.join("\n"); } else { stack = stackDetails.src || ""; } @@ -209,21 +419,27 @@ function _formatStackTrace(stackDetails: IStackDetails) { return stack; } -function _parseStack(stack:IStackDetails): _StackFrame[] { - let parsedStack: _StackFrame[]; +function _parseStack(stack:IStackDetails): _IParsedStackFrame[] { + let parsedStack: _IParsedStackFrame[]; let frames = stack.obj; if (frames && frames.length > 0) { parsedStack = []; let level = 0; + let foundStackStart = false; let totalSizeInBytes = 0; - arrForEach(frames, (frame) => { - let theFrame = frame.toString(); - if (_StackFrame.regex.test(theFrame)) { - const parsedFrame = new _StackFrame(theFrame, level++); - totalSizeInBytes += parsedFrame.sizeInBytes; - parsedStack.push(parsedFrame); + if (foundStackStart || _isStackFrame(frame)) { + let theFrame = asString(frame); + + // Once we have found the first stack frame we treat the rest of the lines as part of the stack + foundStackStart = true; + let parsedFrame: _IParsedStackFrame = _extractStackFrame(theFrame, level); + if (parsedFrame) { + totalSizeInBytes += parsedFrame.sizeInBytes; + parsedStack.push(parsedFrame); + level++; + } } }); @@ -374,7 +590,7 @@ export class Exception implements IExceptionData, ISerializable { properties.id = id; } - _self.exceptions = [new _ExceptionDetails(logger, exception, properties)]; + _self.exceptions = [_createExceptionDetails(logger, exception, properties)]; _self.properties = dataSanitizeProperties(logger, properties); _self.measurements = dataSanitizeMeasurements(logger, measurements); if (severityLevel) { @@ -432,8 +648,8 @@ export class Exception implements IExceptionData, ISerializable { } public static CreateFromInterface(logger: IDiagnosticLogger, exception: IExceptionInternal, properties?: any, measurements?: { [key: string]: number }): Exception { - const exceptions: _ExceptionDetails[] = exception.exceptions - && arrMap(exception.exceptions, (ex: IExceptionDetailsInternal) => _ExceptionDetails.CreateFromInterface(logger, ex)); + const exceptions: _IExceptionDetails[] = exception.exceptions + && arrMap(exception.exceptions, (ex: IExceptionDetailsInternal) => _createExDetailsFromInterface(logger, ex)); const exceptionData = new Exception(logger, {...exception, exceptions}, properties, measurements); return exceptionData; } @@ -442,7 +658,7 @@ export class Exception implements IExceptionData, ISerializable { const { exceptions, properties, measurements, severityLevel, problemGroup, id, isManual } = this; const exceptionDetailsInterface = exceptions instanceof Array - && arrMap(exceptions, (exception: _ExceptionDetails) => exception.toInterface()) + && arrMap(exceptions, (exception: _IExceptionDetails) => exception.toInterface()) || undefined; return { @@ -478,211 +694,250 @@ export class Exception implements IExceptionData, ISerializable { public static formatError = _formatErrorCode; } -export class _ExceptionDetails implements IExceptionDetails, ISerializable { +const exDetailsAiDataContract = objFreeze({ + id: FieldType.Default, + outerId: FieldType.Default, + typeName: FieldType.Required, + message: FieldType.Required, + hasFullStack: FieldType.Default, + stack: FieldType.Default, + parsedStack: FieldType.Array +}); + +interface _IExceptionDetails extends IExceptionDetails, ISerializable { + toInterface: () => IExceptionDetailsInternal; +} - public aiDataContract = { - id: FieldType.Default, - outerId: FieldType.Default, - typeName: FieldType.Required, - message: FieldType.Required, - hasFullStack: FieldType.Default, - stack: FieldType.Default, - parsedStack: FieldType.Array +function _toInterface() { + let _self = this; + const parsedStack = isArray(_self.parsedStack) + && arrMap(_self.parsedStack, (frame: _IParsedStackFrame) => _parsedFrameToInterface(frame)); + + const exceptionDetailsInterface: IExceptionDetailsInternal = { + id: _self.id, + outerId: _self.outerId, + typeName: _self.typeName, + message: _self.message, + hasFullStack: _self.hasFullStack, + stack: _self[strStack], + parsedStack: parsedStack || undefined }; - /** - * In case exception is nested (outer exception contains inner one), the id and outerId properties are used to represent the nesting. - */ - public id: number; + return exceptionDetailsInterface; +} - /** - * The value of outerId is a reference to an element in ExceptionDetails that represents the outer exception - */ - public outerId: number; - - /** - * Exception type name. - */ - public typeName: string; - - /** - * Exception message. - */ - public message: string; - - /** - * Indicates if full exception stack is provided in the exception. The stack may be trimmed, such as in the case of a StackOverflow exception. - */ - public hasFullStack: boolean; - - /** - * Text describing the stack. Either stack or parsedStack should have a value. - */ - public stack: string; - - /** - * List of stack frames. Either stack or parsedStack should have a value. - */ - public parsedStack: IStackFrame[]; /* [] */ - - constructor(logger: IDiagnosticLogger, exception: Error | IExceptionDetailsInternal | IAutoExceptionTelemetry, properties?: {[key: string]: any}) { - let _self = this; - if (!_isExceptionDetailsInternal(exception)) { - let error = exception as any; - let evt = error && error.evt; - if (!isError(error)) { - error = error[strError] || evt || error; - } +export function _createExceptionDetails(logger: IDiagnosticLogger, exception: Error | IExceptionDetailsInternal | IAutoExceptionTelemetry, properties?: {[key: string]: any}): _IExceptionDetails { + + let id: number; + let outerId: number; + let typeName: string; + let message: string; + let hasFullStack: boolean; + let theStack: string; + let parsedStack: IStackFrame[]; + + if (!_isExceptionDetailsInternal(exception)) { + let error = exception as any; + let evt = error && error.evt; + if (!isError(error)) { + error = error[strError] || evt || error; + } - _self.typeName = dataSanitizeString(logger, _getErrorType(error)) || strNotSpecified; - _self.message = dataSanitizeMessage(logger, _formatMessage(exception || error, _self.typeName)) || strNotSpecified; - const stack = exception[strStackDetails] || _getStackFromErrorObj(exception); - _self.parsedStack = _parseStack(stack); - - // after parsedStack is inited, iterate over each frame object, sanitize its assembly field - if (isArray(_self.parsedStack)){ - arrMap(_self.parsedStack, (frame: _StackFrame) => { - frame.assembly = dataSanitizeString(logger, frame.assembly); - frame.fileName = dataSanitizeString(logger, frame.fileName); - }); - } - - _self[strStack] = dataSanitizeException(logger, _formatStackTrace(stack)); - _self.hasFullStack = isArray(_self.parsedStack) && _self.parsedStack.length > 0; + typeName = dataSanitizeString(logger, _getErrorType(error)) || strNotSpecified; + message = dataSanitizeMessage(logger, _formatMessage(exception || error, typeName)) || strNotSpecified; + const stack = exception[strStackDetails] || _getStackFromErrorObj(exception); + parsedStack = _parseStack(stack); - if (properties) { - properties.typeName = properties.typeName || _self.typeName; - } - } else { - _self.typeName = exception.typeName; - _self.message = exception.message; - _self[strStack] = exception[strStack]; - _self.parsedStack = exception.parsedStack || []; - _self.hasFullStack = exception.hasFullStack; + // after parsedStack is inited, iterate over each frame object, sanitize its assembly field + if (isArray(parsedStack)){ + arrMap(parsedStack, (frame: IStackFrame) => { + frame.assembly = dataSanitizeString(logger, frame.assembly); + frame.fileName = dataSanitizeString(logger, frame.fileName); + }); } + + theStack = dataSanitizeException(logger, _formatStackTrace(stack)); + hasFullStack = isArray(parsedStack) && parsedStack.length > 0; + + if (properties) { + properties.typeName = properties.typeName || typeName; + } + } else { + typeName = exception.typeName; + message = exception.message; + theStack = exception[strStack]; + parsedStack = exception.parsedStack || []; + hasFullStack = exception.hasFullStack; } - public toInterface(): IExceptionDetailsInternal { - let _self = this; - const parsedStack = _self.parsedStack instanceof Array - && arrMap(_self.parsedStack, (frame: _StackFrame) => frame.toInterface()); - - const exceptionDetailsInterface: IExceptionDetailsInternal = { - id: _self.id, - outerId: _self.outerId, - typeName: _self.typeName, - message: _self.message, - hasFullStack: _self.hasFullStack, - stack: _self[strStack], - parsedStack: parsedStack || undefined - }; + return { + aiDataContract: exDetailsAiDataContract, + id: id, + outerId: outerId, + typeName: typeName, + message: message, + hasFullStack: hasFullStack, + stack: theStack, + parsedStack: parsedStack, + toInterface: _toInterface + }; +} - return exceptionDetailsInterface; +export function _createExDetailsFromInterface(logger:IDiagnosticLogger, exception: IExceptionDetailsInternal): _IExceptionDetails { + const parsedStack = (isArray(exception.parsedStack) + && arrMap(exception.parsedStack, frame => _stackFrameFromInterface(frame))) + || exception.parsedStack; + + const exceptionDetails = _createExceptionDetails(logger, {...exception, parsedStack}); + + return exceptionDetails; +} + +function _parseFilename(theFrame: IStackFrame, fileName: string) { + const lineCol = fileName.match(PARSE_FILENAME_LINE_COL); + if (lineCol && lineCol.length >= 4) { + theFrame.fileName = lineCol[1]; + theFrame.line = parseInt(lineCol[2]); + } else { + const lineNo = fileName.match(PARSE_FILENAME_LINE_ONLY); + if (lineNo && lineNo.length >= 3) { + theFrame.fileName = lineNo[1]; + theFrame.line = parseInt(lineNo[2]); + } else { + theFrame.fileName = fileName; + } } +} - public static CreateFromInterface(logger:IDiagnosticLogger, exception: IExceptionDetailsInternal): _ExceptionDetails { - const parsedStack = (exception.parsedStack instanceof Array - && arrMap(exception.parsedStack, frame => _StackFrame.CreateFromInterface(frame))) - || exception.parsedStack; +function _handleFilename(theFrame: IStackFrame, sequence: _ParseSequence, matches: RegExpMatchArray) { + let filename = theFrame.fileName; + + if (sequence.fn && matches && matches.length > sequence.fn) { + if (sequence.ln && matches.length > sequence.ln) { + filename = strTrim(matches[sequence.fn] || ""); + theFrame.line = parseInt(strTrim(matches[sequence.ln] || "")) || 0; + } else { + filename = strTrim(matches[sequence.fn] || ""); + } + } - const exceptionDetails = new _ExceptionDetails(logger, {...exception, parsedStack}); + if (filename) { + _parseFilename(theFrame, filename); + } +} - return exceptionDetails; +function _isStackFrame(frame: string) { + let result = false; + if (frame && isString(frame)) { + let trimmedFrame = strTrim(frame); + if (trimmedFrame) { + result = IS_FRAME.test(trimmedFrame); + } } + + return result; } -export class _StackFrame implements IStackFrame, ISerializable { +export interface _IParsedStackFrame extends IStackFrame, ISerializable { + sizeInBytes: number; +} - // regex to match stack frames from ie/chrome/ff - // methodName=$2, fileName=$4, lineNo=$5, column=$6 - public static regex = /^([\s]+at)?[\s]{0,50}([^\@\()]+?)[\s]{0,50}(\@|\()([^\(\n]+):([0-9]+):([0-9]+)(\)?)$/; - public static baseSize = 58; // '{"method":"","level":,"assembly":"","fileName":"","line":}'.length +const stackFrameAiDataContract = objFreeze({ + level: FieldType.Required, + method: FieldType.Required, + assembly: FieldType.Default, + fileName: FieldType.Default, + line: FieldType.Default +}); + +export function _extractStackFrame(frame: string, level: number): _IParsedStackFrame | undefined { + let theFrame: _IParsedStackFrame; + + if (frame && isString(frame) && strTrim(frame)) { + theFrame = { + aiDataContract: stackFrameAiDataContract, + level: level, + assembly: strTrim(frame), + method: NoMethod, + fileName: "", + line: 0, + sizeInBytes: 0 + }; - public sizeInBytes: number; /* 0 */ + let idx = 0; + while(idx < _parseSequence.length) { + let sequence = _parseSequence[idx]; + if (sequence.chk && !sequence.chk(frame)) { + break; + } + if (sequence.pre) { + frame = sequence.pre(frame); + } - public aiDataContract = { - level: FieldType.Required, - method: FieldType.Required, - assembly: FieldType.Default, - fileName: FieldType.Default, - line: FieldType.Default - }; + // Attempt to "parse" the stack frame + const matches = frame.match(sequence.re); + if (matches && matches.length >= sequence.len) { + if (sequence.m) { + theFrame.method = strTrim(matches[sequence.m] || NoMethod); + } - /** - * Level in the call stack. For the long stacks SDK may not report every function in a call stack. - */ - public level: number; + if (sequence.hdl) { + // Run any custom handler + sequence.hdl(theFrame, sequence, matches); + } else if (sequence.fn) { + if (sequence.ln) { + theFrame.fileName = strTrim(matches[sequence.fn] || ""); + theFrame.line = parseInt(strTrim(matches[sequence.ln] || "")) || 0; + } else { + _parseFilename(theFrame, matches[sequence.fn] || ""); + } + } - /** - * Method name. - */ - public method: string; - - /** - * Name of the assembly (dll, jar, etc.) containing this function. - */ - public assembly: string; - - /** - * File name or URL of the method implementation. - */ - public fileName: string; - - /** - * Line number of the code implementation. - */ - public line: number; - - constructor(sourceFrame: string | IExceptionStackFrameInternal, level: number) { - let _self = this; - _self.sizeInBytes = 0; - - // Not converting this to isString() as typescript uses this logic to "understand" the different - // types for the 2 different code paths - if (typeof sourceFrame === "string") { - const frame: string = sourceFrame; - _self.level = level; - _self.method = NoMethod; - _self.assembly = strTrim(frame); - _self.fileName = ""; - _self.line = 0; - const matches = frame.match(_StackFrame.regex); - if (matches && matches.length >= 5) { - _self.method = strTrim(matches[2]) || _self.method; - _self.fileName = strTrim(matches[4]); - _self.line = parseInt(matches[5]) || 0; + // We found a match so stop looking + break; } - } else { - _self.level = sourceFrame.level; - _self.method = sourceFrame.method; - _self.assembly = sourceFrame.assembly; - _self.fileName = sourceFrame.fileName; - _self.line = sourceFrame.line; - _self.sizeInBytes = 0; + idx++; } + } - _self.sizeInBytes += _self.method.length; - _self.sizeInBytes += _self.fileName.length; - _self.sizeInBytes += _self.assembly.length; + return _populateFrameSizeInBytes(theFrame); +} - // todo: these might need to be removed depending on how the back-end settles on their size calculation - _self.sizeInBytes += _StackFrame.baseSize; - _self.sizeInBytes += _self.level.toString().length; - _self.sizeInBytes += _self.line.toString().length; - } +function _stackFrameFromInterface(frame: IStackFrame): _IParsedStackFrame { + let parsedFrame: _IParsedStackFrame = { + aiDataContract: stackFrameAiDataContract, + level: frame.level, + method: frame.method, + assembly: frame.assembly, + fileName: frame.fileName, + line: frame.line, + sizeInBytes: 0 + }; - public static CreateFromInterface(frame: IExceptionStackFrameInternal) { - return new _StackFrame(frame, null /* level is available in frame interface */); - } + return _populateFrameSizeInBytes(parsedFrame); +} - public toInterface() { - let _self = this; - return { - level: _self.level, - method: _self.method, - assembly: _self.assembly, - fileName: _self.fileName, - line: _self.line - }; +function _populateFrameSizeInBytes(frame: _IParsedStackFrame): _IParsedStackFrame { + let sizeInBytes = STACKFRAME_BASE_SIZE; + if (frame) { + sizeInBytes += frame.method.length; + sizeInBytes += frame.assembly.length; + sizeInBytes += frame.fileName.length; + sizeInBytes += frame.level.toString().length; + sizeInBytes += frame.line.toString().length; + + frame.sizeInBytes = sizeInBytes; } + + return frame; +} + +export function _parsedFrameToInterface(frame: _IParsedStackFrame): IStackFrame { + return { + level: frame.level, + method: frame.method, + assembly: frame.assembly, + fileName: frame.fileName, + line: frame.line + }; }