Single-file executable with embedded React app
++ This React app runs from an embedded resource inside a single .exe file. +
+Single-file executable with embedded Vue app
++ This Vue app runs from an embedded resource inside a single .exe file. +
+test
"], args: {content: "test
"}} + { + method: "loadRawString", + command: "loadRawString", + parameters: ["test
"], + args: {content: "test
"} + } ] }, { @@ -127,39 +221,91 @@ const contracts: FeatureContract[] = [ {method: "center", command: "center"}, {method: "centerOnCurrentMonitor", command: "centerOnCurrentMonitor"}, {method: "centerOnMonitor", command: "centerOnMonitor", parameters: [1], args: {monitorIndex: 1}}, - {method: "moveWithinCurrentMonitorArea", command: "moveWithinCurrentMonitorArea", parameters: [10, 20], args: {left: 10, top: 20}} + { + method: "moveWithinCurrentMonitorArea", + command: "moveWithinCurrentMonitorArea", + parameters: [10, 20], + args: {left: 10, top: 20} + } ] }, { feature: "size", gets: [ - ["getSizeAsync", "size", {width: 800, height: 600}], ["getHeightAsync", "height", 600], ["getWidthAsync", "width", 800], - ["getMaxSizeAsync", "maxSize", {width: 1600, height: 1200}], ["getMaxHeightAsync", "maxHeight", 1200], ["getMaxWidthAsync", "maxWidth", 1600], - ["getMinSizeAsync", "minSize", {width: 320, height: 200}], ["getMinHeightAsync", "minHeight", 200], ["getMinWidthAsync", "minWidth", 320], + ["getSizeAsync", "size", { + width: 800, + height: 600 + }], ["getHeightAsync", "height", 600], ["getWidthAsync", "width", 800], + ["getMaxSizeAsync", "maxSize", { + width: 1600, + height: 1200 + }], ["getMaxHeightAsync", "maxHeight", 1200], ["getMaxWidthAsync", "maxWidth", 1600], + ["getMinSizeAsync", "minSize", { + width: 320, + height: 200 + }], ["getMinHeightAsync", "minHeight", 200], ["getMinWidthAsync", "minWidth", 320], ["isResizableAsync", "isResizable", true] ].map(([method, command, result]) => ({method: method as string, command: command as string, result})), posts: [ - ["setSize", "setSize", [800, 600], {width: 800, height: 600}], ["setHeight", "setHeight", [600], {height: 600}], ["setWidth", "setWidth", [800], {width: 800}], - ["setMaxSize", "setMaxSize", [1600, 1200], {width: 1600, height: 1200}], ["setMaxHeight", "setMaxHeight", [1200], {height: 1200}], ["setMaxWidth", "setMaxWidth", [1600], {width: 1600}], - ["setMinSize", "setMinSize", [320, 200], {width: 320, height: 200}], ["setMinHeight", "setMinHeight", [200], {height: 200}], ["setMinWidth", "setMinWidth", [320], {width: 320}], - ["resize", "resize", [10, 20, "bottomRight"], {widthOffset: 10, heightOffset: 20, origin: "bottomRight"}], ["setResizable", "setResizable", [false], {resizable: false}] - ].map(([method, command, parameters, args]) => ({method: method as string, command: command as string, parameters: parameters as unknown[], args})) + ["setSize", "setSize", [800, 600], { + width: 800, + height: 600 + }], ["setHeight", "setHeight", [600], {height: 600}], ["setWidth", "setWidth", [800], {width: 800}], + ["setMaxSize", "setMaxSize", [1600, 1200], { + width: 1600, + height: 1200 + }], ["setMaxHeight", "setMaxHeight", [1200], {height: 1200}], ["setMaxWidth", "setMaxWidth", [1600], {width: 1600}], + ["setMinSize", "setMinSize", [320, 200], { + width: 320, + height: 200 + }], ["setMinHeight", "setMinHeight", [200], {height: 200}], ["setMinWidth", "setMinWidth", [320], {width: 320}], + ["resize", "resize", [10, 20, "bottomRight"], { + widthOffset: 10, + heightOffset: 20, + origin: "bottomRight" + }], ["setResizable", "setResizable", [false], {resizable: false}] + ].map(([method, command, parameters, args]) => ({ + method: method as string, + command: command as string, + parameters: parameters as unknown[], + args + })) }, { feature: "state", gets: [ ["isFullScreenAsync", "isFullScreen", false], ["isMaximizedAsync", "isMaximized", false], ["isMinimizedAsync", "isMinimized", false], ["isTopMostAsync", "isTopMost", false], ["isFocusedAsync", "isFocused", true], ["getZoomFactorAsync", "zoomFactor", 100], - ["isZoomEnabledAsync", "isZoomEnabled", true], ["getCachedPreFullScreenBoundsAsync", "cachedPreFullScreenBounds", {x: 0, y: 0, width: 800, height: 600}], + ["isZoomEnabledAsync", "isZoomEnabled", true], ["getCachedPreFullScreenBoundsAsync", "cachedPreFullScreenBounds", { + x: 0, + y: 0, + width: 800, + height: 600 + }], ["getCachedPreMaximizedBoundsAsync", "cachedPreMaximizedBounds", {x: 0, y: 0, width: 800, height: 600}] ].map(([method, command, result]) => ({method: method as string, command: command as string, result})), posts: [ - ["setCachedPreFullScreenBounds", "setCachedPreFullScreenBounds", [{x: 1, y: 2, width: 800, height: 600}], {bounds: {x: 1, y: 2, width: 800, height: 600}}], - ["setCachedPreMaximizedBounds", "setCachedPreMaximizedBounds", [{x: 3, y: 4, width: 1024, height: 768}], {bounds: {x: 3, y: 4, width: 1024, height: 768}}], + ["setCachedPreFullScreenBounds", "setCachedPreFullScreenBounds", [{ + x: 1, + y: 2, + width: 800, + height: 600 + }], {bounds: {x: 1, y: 2, width: 800, height: 600}}], + ["setCachedPreMaximizedBounds", "setCachedPreMaximizedBounds", [{ + x: 3, + y: 4, + width: 1024, + height: 768 + }], {bounds: {x: 3, y: 4, width: 1024, height: 768}}], ["setMaximized", "setMaximized", [false], {maximized: false}], ["toggleMaximized", "toggleMaximized", [], undefined], ["setMinimized", "setMinimized", [false], {minimized: false}], ["setFullScreen", "setFullScreen", [false], {fullScreen: false}], ["setFocused", "setFocused", [], undefined], ["setZoomFactor", "setZoomFactor", [125], {zoom: 125}], ["enableZoom", "enableZoom", [false], {enabled: false}], ["setTopMost", "setTopMost", [false], {topMost: false}] - ].map(([method, command, parameters, args]) => ({method: method as string, command: command as string, parameters: parameters as unknown[], args})) + ].map(([method, command, parameters, args]) => ({ + method: method as string, + command: command as string, + parameters: parameters as unknown[], + args + })) }, { feature: "webMessaging", @@ -180,7 +326,11 @@ describe.each(contracts)("$feature window feature", ({feature, gets = [], posts assignMessageReceivedHandler: vi.fn(), unregisterMessageReceivedHandler: vi.fn() } as unknown as InfiniFrameHostMessaging; - window.infiniframe = {messaging, window: {} as InfiniFrameWindow, utils: {setPointerCapture: vi.fn(), releasePointerCapture: vi.fn()}}; + window.infiniframe = { + messaging, + window: {} as InfiniFrameWindow, + utils: {setPointerCapture: vi.fn(), releasePointerCapture: vi.fn()} + }; windowApi = new InfiniFrameWindow(); window.infiniframe.window = windowApi; }); @@ -223,7 +373,11 @@ describe("strongly typed feature behavior", () => { assignMessageReceivedHandler: vi.fn(), unregisterMessageReceivedHandler: vi.fn() } as unknown as InfiniFrameHostMessaging; - window.infiniframe = {messaging, window: {} as InfiniFrameWindow, utils: {setPointerCapture: vi.fn(), releasePointerCapture: vi.fn()}}; + window.infiniframe = { + messaging, + window: {} as InfiniFrameWindow, + utils: {setPointerCapture: vi.fn(), releasePointerCapture: vi.fn()} + }; windowApi = new InfiniFrameWindow(); window.infiniframe.window = windowApi; }); diff --git a/src/InfiniFrame.Js/TypeScript/Window/InfiniFrameWindowFeatures.ts b/src/InfiniFrame.Js/TypeScript/Window/InfiniFrameWindowFeatures.ts index 08e88e122..4f762fce9 100644 --- a/src/InfiniFrame.Js/TypeScript/Window/InfiniFrameWindowFeatures.ts +++ b/src/InfiniFrame.Js/TypeScript/Window/InfiniFrameWindowFeatures.ts @@ -6,6 +6,7 @@ import type { DebuggingInfiniFrameWindowFeature as InfiniFrameWindowFeatureDebuggingContract, DecorationsInfiniFrameWindowFeature as InfiniFrameWindowFeatureDecorationsContract, FilePickerDialogsInfiniFrameWindowFeature as InfiniFrameWindowFeatureFilePickerDialogsContract, + InfiniFrameWindowFeatures as InfiniFrameWindowFeaturesContract, InvokeInfiniFrameWindowFeature as InfiniFrameWindowFeatureInvokeContract, JavaScriptInfiniFrameWindowFeature as InfiniFrameWindowFeatureJavaScriptContract, LifecycleInfiniFrameWindowFeature as InfiniFrameWindowFeatureLifecycleContract, @@ -15,8 +16,7 @@ import type { PositionInfiniFrameWindowFeature as InfiniFrameWindowFeaturePositionContract, SizeInfiniFrameWindowFeature as InfiniFrameWindowFeatureSizeContract, StateInfiniFrameWindowFeature as InfiniFrameWindowFeatureStateContract, - WebMessagingInfiniFrameWindowFeature as InfiniFrameWindowFeatureWebMessagingContract, - InfiniFrameWindowFeatures as InfiniFrameWindowFeaturesContract + WebMessagingInfiniFrameWindowFeature as InfiniFrameWindowFeatureWebMessagingContract } from "../Contracts"; import { BrowserInfiniFrameWindowFeature, @@ -69,5 +69,5 @@ export class InfiniFrameWindowFeatures implements InfiniFrameWindowFeaturesContr this.webMessaging = new WebMessagingInfiniFrameWindowFeature(); this.javaScript = new JavaScriptInfiniFrameWindowFeature(); } - + } diff --git a/src/InfiniFrame.Js/TypeScript/Window/WindowChrome.test.ts b/src/InfiniFrame.Js/TypeScript/Window/WindowChrome.test.ts index c8ffcb1d4..e6ca688fe 100644 --- a/src/InfiniFrame.Js/TypeScript/Window/WindowChrome.test.ts +++ b/src/InfiniFrame.Js/TypeScript/Window/WindowChrome.test.ts @@ -92,29 +92,21 @@ describe("WindowChrome", () => { minimizeBtn.click(); expect(messaging.sendMessageToHost).toHaveBeenCalledWith( SendToHostMessageIds.windowFeatureRequest, - expect.objectContaining({ - command: expect.stringContaining("minimize") - }) + expect.objectContaining({command: expect.stringContaining("minimize")}) ); vi.clearAllMocks(); - maximizeBtn.click(); expect(messaging.sendMessageToHost).toHaveBeenCalledWith( SendToHostMessageIds.windowFeatureRequest, - expect.objectContaining({ - command: expect.stringContaining("toggleMaximize") - }) + expect.objectContaining({command: expect.stringContaining("toggleMaximize")}) ); vi.clearAllMocks(); - closeBtn.click(); expect(messaging.sendMessageToHost).toHaveBeenCalledWith( SendToHostMessageIds.windowFeatureRequest, - expect.objectContaining({ - command: expect.stringContaining(":close") - }) + expect.objectContaining({command: expect.stringContaining(":close")}) ); }); @@ -128,7 +120,6 @@ describe("WindowChrome", () => { expect(resizeRight.setPointerCapture).toHaveBeenCalledWith(1); vi.clearAllMocks(); - const pointerMove = new PointerEvent("pointermove", { bubbles: true, pointerId: 1, @@ -165,9 +156,7 @@ describe("WindowChrome", () => { minimizeBtn.click(); expect(messaging.sendMessageToHost).toHaveBeenCalledWith( SendToHostMessageIds.windowFeatureRequest, - expect.objectContaining({ - command: expect.stringContaining("minimize") - }) + expect.objectContaining({command: expect.stringContaining("minimize")}) ); }); @@ -183,18 +172,11 @@ describe("WindowChrome", () => { it("maps data-infiniframe-resize values correctly", () => { const testCases = [ - ["top", "top"], - ["right", "right"], - ["bottom", "bottom"], - ["left", "left"], - ["top-left", "topLeft"], - ["top-right", "topRight"], - ["bottom-left", "bottomLeft"], - ["bottom-right", "bottomRight"], - ["topLeft", "topLeft"], - ["topRight", "topRight"], - ["bottomLeft", "bottomLeft"], - ["bottomRight", "bottomRight"] + ["top", "top"], ["right", "right"], ["bottom", "bottom"], ["left", "left"], + ["top-left", "topLeft"], ["top-right", "topRight"], + ["bottom-left", "bottomLeft"], ["bottom-right", "bottomRight"], + ["topLeft", "topLeft"], ["topRight", "topRight"], + ["bottomLeft", "bottomLeft"], ["bottomRight", "bottomRight"] ]; for (const [attrValue, expectedOrigin] of testCases) { @@ -217,14 +199,34 @@ describe("WindowChrome", () => { expect(messaging.sendMessageToHost).toHaveBeenCalledWith( SendToHostMessageIds.windowFeatureRequest, - expect.objectContaining({ - args: expect.objectContaining({origin: expectedOrigin}) - }) + expect.objectContaining({args: expect.objectContaining({origin: expectedOrigin})}) ); testChrome.unregister(); } }); + + it("warns on unknown data-infiniframe-resize value", () => { + const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => { + }); + createElement("div", {"data-infiniframe-resize": "unknown"}); + chrome.register({}); + + expect(warnSpy).toHaveBeenCalled(); + warnSpy.mockRestore(); + }); + + it("ignores data-infiniframe-resize with empty value", () => { + createElement("div", {"data-infiniframe-resize": ""}); + chrome.register({}); + // Should not throw + }); + + it("ignores data-infiniframe-window-action with unknown action", () => { + createElement("button", {"data-infiniframe-window-action": "unknown"}); + chrome.register({}); + // Should not throw + }); }); describe("unregister", () => { @@ -242,7 +244,6 @@ describe("WindowChrome", () => { chrome.unregister(); vi.clearAllMocks(); - dragArea.dispatchEvent(new PointerEvent("pointerdown", {bubbles: true, pointerId: 1, button: 0})); minimizeBtn.click(); resizeEl.dispatchEvent(new PointerEvent("pointerdown", {bubbles: true, pointerId: 1, button: 0})); @@ -256,12 +257,15 @@ describe("WindowChrome", () => { chrome.unregister(); vi.clearAllMocks(); - chrome.register({dragRegion: "#titlebar"}); dragArea.dispatchEvent(new PointerEvent("pointerdown", {bubbles: true, pointerId: 1, button: 0})); expect(messaging.sendMessageToHost).toHaveBeenCalled(); }); + + it("does nothing when not registered", () => { + chrome.unregister(); + }); }); describe("double-click maximize", () => { @@ -273,9 +277,7 @@ describe("WindowChrome", () => { expect(messaging.sendMessageToHost).toHaveBeenCalledWith( SendToHostMessageIds.windowFeatureRequest, - expect.objectContaining({ - command: expect.stringContaining("toggleMaximize") - }) + expect.objectContaining({command: expect.stringContaining("toggleMaximize")}) ); }); }); @@ -292,18 +294,107 @@ describe("WindowChrome", () => { }); }); + describe("pointer move", () => { + it("does nothing when not resizing", () => { + const dragArea = createElement("div", {id: "titlebar"}); + chrome.register({dragRegion: "#titlebar"}); + + const pointerMove = new PointerEvent("pointermove", {bubbles: true, pointerId: 1}); + dragArea.dispatchEvent(pointerMove); + }); + }); + + describe("pointer up", () => { + it("does nothing when not dragging or resizing", () => { + const dragArea = createElement("div", {id: "titlebar"}); + chrome.register({dragRegion: "#titlebar"}); + + const pointerUp = new PointerEvent("pointerup", {bubbles: true, pointerId: 1}); + dragArea.dispatchEvent(pointerUp); + }); + + it("ends drag on pointer up", () => { + const dragArea = createElement("div", {id: "titlebar"}); + chrome.register({dragRegion: "#titlebar"}); + + // Start drag + const pointerDown = new PointerEvent("pointerdown", {bubbles: true, pointerId: 1, button: 0}); + dragArea.dispatchEvent(pointerDown); + + // End drag + const pointerUp = new PointerEvent("pointerup", {bubbles: true, pointerId: 1}); + dragArea.dispatchEvent(pointerUp); + }); + }); + + describe("resize lost capture", () => { + it("cleans up on resize lost pointer capture", () => { + const resizeEl = createElement("div", {id: "resize-right"}); + chrome.register({resize: {right: "#resize-right"}}); + + const pointerDown = new PointerEvent("pointerdown", {bubbles: true, pointerId: 1, button: 0}); + resizeEl.dispatchEvent(pointerDown); + + // Simulate lostpointercapture + const lostCapture = new Event("lostpointercapture"); + resizeEl.dispatchEvent(lostCapture); + }); + }); + + describe("drag lost capture", () => { + it("cleans up on drag lost pointer capture", () => { + const dragArea = createElement("div", {id: "titlebar"}); + chrome.register({dragRegion: "#titlebar"}); + + const pointerDown = new PointerEvent("pointerdown", {bubbles: true, pointerId: 1, button: 0}); + dragArea.dispatchEvent(pointerDown); + + // Simulate lostpointercapture + const lostCapture = new Event("lostpointercapture"); + dragArea.dispatchEvent(lostCapture); + }); + }); + + describe("releasePointerCaptureIfHeld", () => { + it("releases capture when pointerId is non-zero and has capture", () => { + Element.prototype.hasPointerCapture = vi.fn().mockReturnValue(true); + const dragArea = createElement("div", {id: "titlebar"}); + chrome.register({dragRegion: "#titlebar"}); + + // Start drag to set lastPointerId + const pointerDown = new PointerEvent("pointerdown", {bubbles: true, pointerId: 1, button: 0}); + dragArea.dispatchEvent(pointerDown); + + // Double-click triggers releasePointerCaptureIfHeld + dragArea.dispatchEvent(new MouseEvent("dblclick", {bubbles: true})); + + expect(dragArea.releasePointerCapture).toHaveBeenCalled(); + }); + + it("does not release when lastPointerId is 0", () => { + const dragArea = createElement("div", {id: "titlebar"}); + chrome.register({dragRegion: "#titlebar"}); + + // Double-click without pointerDown first + dragArea.dispatchEvent(new MouseEvent("dblclick", {bubbles: true})); + + // Should not throw + }); + }); + describe("edge cases", () => { it("handles register called before DOM ready", () => { const originalReadyState = document.readyState; - Object.defineProperty(document, 'readyState', {value: 'loading', writable: true}); + Object.defineProperty(document, "readyState", {value: "loading", writable: true}); chrome.register({dragRegion: "#titlebar"}); - Object.defineProperty(document, 'readyState', {value: originalReadyState, writable: true}); + Object.defineProperty(document, "readyState", {value: originalReadyState, writable: true}); }); it("handles invalid selectors gracefully", () => { - const consoleWarn = vi.spyOn(console, "warn").mockImplementation(() => {}); + const consoleWarn = vi.spyOn(console, "warn").mockImplementation(() => { + }); chrome.register({ dragRegion: "///invalid///", @@ -312,7 +403,6 @@ describe("WindowChrome", () => { }); expect(chrome).toBeDefined(); - consoleWarn.mockRestore(); }); @@ -328,11 +418,24 @@ describe("WindowChrome", () => { ); expect(restoreCalls).toHaveLength(1); }); + + it("handles empty config", () => { + chrome.register({}); + // Should not throw + }); + + it("setup does nothing when config is null after register", () => { + chrome.register({dragRegion: "#titlebar"}); + // Manually set config to null to test guard + (chrome as any).config = null; + (chrome as any).setup(); + }); }); describe("messaging not ready", () => { it("warns when messaging bridge is not available", () => { - const consoleWarn = vi.spyOn(console, "warn").mockImplementation(() => {}); + const consoleWarn = vi.spyOn(console, "warn").mockImplementation(() => { + }); (window.infiniframe as any).messaging = null; const dragArea = createElement("div", {id: "titlebar"}); @@ -343,7 +446,6 @@ describe("WindowChrome", () => { expect(consoleWarn).toHaveBeenCalledWith( expect.stringContaining("messaging bridge not ready") ); - consoleWarn.mockRestore(); }); }); @@ -357,10 +459,7 @@ describe("WindowChrome", () => { expect(messaging.sendMessageToHost).toHaveBeenCalledWith( SendToHostMessageIds.windowFeatureRequest, - { - command: "__infiniframe:window:features:windowChrome:minimize", - args: undefined - } + {command: "__infiniframe:window:features:windowChrome:minimize", args: undefined} ); }); @@ -371,7 +470,6 @@ describe("WindowChrome", () => { resizeEl.dispatchEvent(new PointerEvent("pointerdown", {bubbles: true, pointerId: 1, button: 0})); vi.clearAllMocks(); - resizeEl.dispatchEvent(new PointerEvent("pointermove", { bubbles: true, pointerId: 1, @@ -388,4 +486,94 @@ describe("WindowChrome", () => { ); }); }); + + describe("mutation observer", () => { + it("responds to childList mutations", () => { + chrome.register({}); + + // Add an element with data attribute to trigger mutation observer + const el = document.createElement("div"); + el.setAttribute("data-infiniframe-drag-region", ""); + document.body.appendChild(el); + }); + + it("responds to attribute mutations on data-infiniframe-drag-region", () => { + const el = createElement("div", {id: "test"}); + chrome.register({}); + + el.setAttribute("data-infiniframe-drag-region", ""); + }); + }); + + describe("pointer events", () => { + it("pointerup ends drag when isDragging is true", () => { + const dragArea = createElement("div", {id: "titlebar"}); + chrome.register({dragRegion: "#titlebar"}); + + // Start drag + const pointerDown = new PointerEvent("pointerdown", {bubbles: true, pointerId: 1, button: 0}); + dragArea.dispatchEvent(pointerDown); + + // End drag + const pointerUp = new PointerEvent("pointerup", {bubbles: true, pointerId: 1}); + dragArea.dispatchEvent(pointerUp); + }); + + it("pointerup ends resize when isResizing is true", () => { + const resizeEl = createElement("div", {id: "resize-right"}); + chrome.register({resize: {right: "#resize-right"}}); + + // Start resize + const pointerDown = new PointerEvent("pointerdown", {bubbles: true, pointerId: 1, button: 0}); + resizeEl.dispatchEvent(pointerDown); + + // End resize + const pointerUp = new PointerEvent("pointerup", {bubbles: true, pointerId: 1}); + resizeEl.dispatchEvent(pointerUp); + }); + + it("pointermove triggers resize when isResizing is true", () => { + const resizeEl = createElement("div", {id: "resize-right"}); + chrome.register({resize: {right: "#resize-right"}}); + + // Start resize + const pointerDown = new PointerEvent("pointerdown", {bubbles: true, pointerId: 1, button: 0}); + resizeEl.dispatchEvent(pointerDown); + + // Move during resize + const pointerMove = new PointerEvent("pointermove", { + bubbles: true, + pointerId: 1, + movementX: 5, + movementY: 3 + }); + resizeEl.dispatchEvent(pointerMove); + + expect(messaging.sendMessageToHost).toHaveBeenCalled(); + }); + + it("pointermove does nothing when not resizing", () => { + const resizeEl = createElement("div", {id: "resize-right"}); + chrome.register({resize: {right: "#resize-right"}}); + + // Move without starting resize + const pointerMove = new PointerEvent("pointermove", { + bubbles: true, + pointerId: 1, + movementX: 5, + movementY: 3 + }); + resizeEl.dispatchEvent(pointerMove); + }); + + it("pointerdown on resize element starts resize", () => { + const resizeEl = createElement("div", {id: "resize-bottom"}); + chrome.register({resize: {bottom: "#resize-bottom"}}); + + const pointerDown = new PointerEvent("pointerdown", {bubbles: true, pointerId: 1, button: 0}); + resizeEl.dispatchEvent(pointerDown); + + expect(resizeEl.setPointerCapture).toHaveBeenCalled(); + }); + }); }); diff --git a/src/InfiniFrame.Js/TypeScript/Window/WindowChrome.ts b/src/InfiniFrame.Js/TypeScript/Window/WindowChrome.ts index 259790eb6..24449bdf5 100644 --- a/src/InfiniFrame.Js/TypeScript/Window/WindowChrome.ts +++ b/src/InfiniFrame.Js/TypeScript/Window/WindowChrome.ts @@ -437,7 +437,8 @@ export class WindowChrome { if (target.hasPointerCapture(this.lastPointerId)) { target.releasePointerCapture(this.lastPointerId); } - } catch { /* Element may no longer exist */ } + } catch { /* Element may no longer exist */ + } this.lastPointerId = 0; } diff --git a/src/InfiniFrame.Js/package-lock.json b/src/InfiniFrame.Js/package-lock.json index 491df5090..c7fc2707f 100644 --- a/src/InfiniFrame.Js/package-lock.json +++ b/src/InfiniFrame.Js/package-lock.json @@ -10,13 +10,13 @@ "license": "GNUv3", "devDependencies": { "@types/node": "^26.2.0", - "@vitest/coverage-v8": "^4.1.10", - "concurrently": "^10.0.4", + "@vitest/coverage-v8": "^4.1.11", + "concurrently": "^10.0.5", "jsdom": "^30.0.1", "terser": "^5.50.0", "typescript": "^7.0.2", - "vite": "^8.2.1", - "vitest": "^4.1.10" + "vite": "^8.2.2", + "vitest": "^4.1.11" } }, "node_modules/@asamuzakjp/css-color": { @@ -334,19 +334,36 @@ } }, "node_modules/@oxc-project/types": { - "version": "0.143.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.143.0.tgz", - "integrity": "sha512-u6JZdLBTLotrNC9Vd6vPssINdzcCzleKAH6EJKImQb7GtYvX5keN2dxkoK44stCc4tffE6QQRtZTXVSzsLUlWA==", + "version": "0.146.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.146.0.tgz", + "integrity": "sha512-XC0QsnnhVe7sLIWmYmdPw7x5P0h4W8vUU3Nv1ySgWXtvCz8NizoAEpGXA0sOYoJQV2Rl13LgURAHQ5cI5ILCSA==", "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/Boshen" } }, + "node_modules/@rolldown/binding-android-arm-eabi": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.5.tgz", + "integrity": "sha512-DLe/i+l8ynIBY7XEQ191TeZvCoowIGa18R+dIV30GW7DiOtp74i/xX8hs8GUjW5ARV7VZuie3d6AumSmCwbeRA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, "node_modules/@rolldown/binding-android-arm64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.3.tgz", - "integrity": "sha512-zrJtHDcaZJ1Fp7xf4hNl+7seH9Cn/N5TwLYkhgXREtBwAd/jaqW3uqeHxpDugJLVICWg4eW44kOQEGJ1r6jCGw==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.5.tgz", + "integrity": "sha512-zXcwKlQApYAOELHd8PwKDFkagYF9Wy4e0RJ+0qnzl9Pjnpj75TEG8ufv40p2J7kCEfwZAsNiuzRIyNNMWT38ig==", "cpu": [ "arm64" ], @@ -361,9 +378,9 @@ } }, "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.3.tgz", - "integrity": "sha512-ieIiibVCp0tX7TLu2cafoNPv8wJyYi01ekXpbf8q2j7F4rGAhhXb/eQh7ge9DRBY78GwmRQtvjZDux7EDbA8kA==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.5.tgz", + "integrity": "sha512-dK4QakI42nzWgJT5sm4y4y/O//D4OxM75/cH28RLV+nzIN9AY+YsbuUVrUTjlLjXR6vpyxFbSsbmNuJ6BP9sww==", "cpu": [ "arm64" ], @@ -378,9 +395,9 @@ } }, "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.3.tgz", - "integrity": "sha512-Zh9tCon19eDXJoihx0rqKhMUlMYqzwj3aPsSuHmI4RWZh62dWUL+DJN4C5YQya5TcQBJU/Fe8+rY0jhXTQITqA==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.5.tgz", + "integrity": "sha512-fqSALaUu1Wjd1nK2uW2kJDWdLCc8lx1IcY+MTY26Aurfdx19anlzhqXOgCFbBFQnlFDTn4TC1/7Nz4Bl2mLP3A==", "cpu": [ "x64" ], @@ -395,9 +412,9 @@ } }, "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.3.tgz", - "integrity": "sha512-nGbJWewA1wrXXZiQhjAT5rhibGfns5ZNkDVqxsO6zJ3f3YvpoDNNmGMSbbhLuXKjNScaBJVOAboztAWVespQMg==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.5.tgz", + "integrity": "sha512-/vCnNxlkxs9tKxNDcyWUePpJ/PgTzxIaVhoM5SmG8UV+GR/IcPam4VYxi7GIMo7PSDuNqlJqvprqii9NqqVCMw==", "cpu": [ "x64" ], @@ -412,9 +429,9 @@ } }, "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.3.tgz", - "integrity": "sha512-QNniJr5Kml0kDEB98jiDOJjXNroxIIi0IXIbdYzY26Xt1pVbeP62+KnoIZLwirOymX/0jDk/2gI/bNUv7A7OIw==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.5.tgz", + "integrity": "sha512-abk0NLA519LxRCszmbE0jYKuQ9YPocOXTiOXOo6Yr+YAT95VH+PtqYAjOJvGKt3viEd/x4qzabAlwd5bHOOARg==", "cpu": [ "arm" ], @@ -429,9 +446,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.3.tgz", - "integrity": "sha512-TkqEAcmmvH3I/q4114NB4RVt6241Dao48pF45uLcFGrwAaIn0iITgTAKP/dLjbN0R4buJjGb91+UHSoFmpgIWw==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.5.tgz", + "integrity": "sha512-Y7eALiJ8lr0M2HH103Js+g7V34wf6snlpZLAsHI90uLhr3PVlNsbFVAXJC9d/V6BnPyKtpSwI+NcB/RLxsQxuA==", "cpu": [ "arm64" ], @@ -449,9 +466,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.3.tgz", - "integrity": "sha512-NHqjnxpsndf4MPymxteFAWHHfkTL8HjWh1KB7z23ofZ6QO2euONuxDXjat69dKZRALnGypg8k8SsK8vZJoXv1Q==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.5.tgz", + "integrity": "sha512-xMvZgnbZg4YVnR/AX2b3oOPDTFYJvUVaJg5FedA/LuvexAtXibZQej4cnTkw3rjsJ/ggUROB64TdtETiim+FYA==", "cpu": [ "arm64" ], @@ -469,9 +486,9 @@ } }, "node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.3.tgz", - "integrity": "sha512-6tbrbwfz5GB9DQ4Jwo6hy9v+vR31xZlvzZ6n5Xut6Hhx5PvrA9q/HsK8KMaYQp063iqZGXwNvZtYNLD7EM/x0w==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.5.tgz", + "integrity": "sha512-GRjeqTUDHTo5GwntsLaAMcBahG3nlpjftXWZLN73HiYQlhwEowvarFgQnRnQZtIp4keXX7quXFbG38uPZBa2EA==", "cpu": [ "ppc64" ], @@ -489,9 +506,9 @@ } }, "node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.3.tgz", - "integrity": "sha512-oyuXxXmoZHjXC917IAPFAAv4wWAa0cM9afk8nx1+9/jNNOX1uPf8yDA6p7G0RypOfw/X0PQt5IfoquY1um+zSg==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.5.tgz", + "integrity": "sha512-vLNTR45F2Uwc8AufkNXPmB4VliaXs+FvcheEogIzOXzO4l+LzieXF5A/TWxLy5HtqpsRCHUfd0lPVrrdgXdLHQ==", "cpu": [ "s390x" ], @@ -509,9 +526,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.3.tgz", - "integrity": "sha512-TytMwF2KVGqP2tgd0I1OY0PAv78dZRAYcF5ssDzjM34SUXCED3uXvSd5+lHoC0bTD6eEdFz7LdQNCO1y0oVk9w==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.5.tgz", + "integrity": "sha512-Mgj59/HTuYeK9Gz2MA+mBWKnHsAgkBSec15ZMb1st3oIfFbX7gCjOae7GydHhzcyQi9Z/7M1QuN9bR3oFqF0jQ==", "cpu": [ "x64" ], @@ -529,9 +546,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.3.tgz", - "integrity": "sha512-/E9m3qstrJFVPoULV25mVQblSNExY2+kBsYe4sy0Tn0yOOgJ8wZbZt3KnRbF/XeU2Gl1STKUQnDNTqhIE5MD4A==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.5.tgz", + "integrity": "sha512-mY8AP0/ichsbhAxGnLa3d3+MwV0EfgrPND2bplI3Ym8T6R2pJ0N87bvrKVwNXmdy3jnr6eQBecdqx/HMknBmpA==", "cpu": [ "x64" ], @@ -549,9 +566,9 @@ } }, "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.3.tgz", - "integrity": "sha512-Kr0OcsoQI816i6HOl3vFHpd1K0eZyh76zgfj4c1nTyaTsd5r2Mj1lwM4R90y/qaCfmTn9eHy0SKwi98eitRxug==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.5.tgz", + "integrity": "sha512-8SLssA2oweAxyRgDp789ACfRb/3P+zNRJpzZxSizxF9m8NUDQ4+3xjo8ttjhVGGw6Qxb70oZiEtIjaKikCO7Yw==", "cpu": [ "arm64" ], @@ -566,9 +583,9 @@ } }, "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.3.tgz", - "integrity": "sha512-hOtMwTqnME+/gJcH/PCZ0wn0zPUjiWOgkHpxbSJpfGKMezHltx1S7/k1SitzVa7Ww2cqrDDaFbZEhcJZO8o+Jw==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.5.tgz", + "integrity": "sha512-vGbruD5zquhoc8D9SViXgN2FBJtNdTyQ4DtG+SWiEGlJiAzoKcZ2xp+xuXCffhubVdt0NJlTZqkeRuERy7g8Cw==", "cpu": [ "arm64" ], @@ -583,9 +600,9 @@ } }, "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.3.tgz", - "integrity": "sha512-ekcqMMkI2PlhYnfzQnB/cEdYUVVJViWvoUyLrbzgDoi3Snfc1mVBwdnc306ufA5ejy8JSPjT2RlW1nQSjW7efg==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.5.tgz", + "integrity": "sha512-e/SXpgISz+IoqVcSSI0rx/d/he8zqLex+/rCWpnHpmVfmPIUjag9H6P7zotf0gJHwPUhQxZ/mF8tr6acebT9yw==", "cpu": [ "x64" ], @@ -989,14 +1006,14 @@ } }, "node_modules/@vitest/coverage-v8": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.10.tgz", - "integrity": "sha512-IM49HmthevbgAO4anp1hwtoT9wYe59w0LR00gr+eagHE+ZJ5lK4sLPeO0ubgoJcwLk6dehU3R24N+FbEEKDc8g==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.11.tgz", + "integrity": "sha512-8MVGEFnJIcdGjcbfKmeq8z0pZHH0JlVtoVZH9Q/qwUp6wyFnEJUBMrw9DCaj+ra3vShGmhavjalMIhPNxZAUcw==", "dev": true, "license": "MIT", "dependencies": { "@bcoe/v8-coverage": "^1.0.2", - "@vitest/utils": "4.1.10", + "@vitest/utils": "4.1.11", "ast-v8-to-istanbul": "^1.0.0", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-report": "^3.0.1", @@ -1010,8 +1027,8 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/browser": "4.1.10", - "vitest": "4.1.10" + "@vitest/browser": "4.1.11", + "vitest": "4.1.11" }, "peerDependenciesMeta": { "@vitest/browser": { @@ -1020,16 +1037,16 @@ } }, "node_modules/@vitest/expect": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.10.tgz", - "integrity": "sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.11.tgz", + "integrity": "sha512-VX2x5vNJXET47KAFzwERI+KRMtTTCSWTfSMKsW7JsUsXV4psq++e3DvZpuTDOpHcxytiDs6p2nhVb2tVDiiUYw==", "dev": true, "license": "MIT", "dependencies": { "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", - "@vitest/spy": "4.1.10", - "@vitest/utils": "4.1.10", + "@vitest/spy": "4.1.11", + "@vitest/utils": "4.1.11", "chai": "^6.2.2", "tinyrainbow": "^3.1.0" }, @@ -1038,13 +1055,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.10.tgz", - "integrity": "sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.11.tgz", + "integrity": "sha512-2XJVD55d1o5AZous5CCGKS74g/riOj9odEt2bQpCVZeblHyHdnMeFl4jl0XjU21stf4mbjUkew2eXQZt65g5CQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "4.1.10", + "@vitest/spy": "4.1.11", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, @@ -1065,9 +1082,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.10.tgz", - "integrity": "sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.11.tgz", + "integrity": "sha512-yiZzPbGTS9Sr/JpFl8zHrcIkAofNbFV6k21vIgQN/cY/oxZeXhJv5sc/MBJ5jFKWmWs+oJHw0UXLZjmf931+Vw==", "dev": true, "license": "MIT", "dependencies": { @@ -1078,13 +1095,13 @@ } }, "node_modules/@vitest/runner": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.10.tgz", - "integrity": "sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.11.tgz", + "integrity": "sha512-LztvUgdwMNJMIkj3hQnnxiC2Xy1zNxq928W/xhjCLaNCzqTZOudjwbQf6v9IntZGPw132i2Lq2rgTRZHD3JHNw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "4.1.10", + "@vitest/utils": "4.1.11", "pathe": "^2.0.3" }, "funding": { @@ -1092,14 +1109,14 @@ } }, "node_modules/@vitest/snapshot": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.10.tgz", - "integrity": "sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.11.tgz", + "integrity": "sha512-pN7ikn1ON7h8ee4gIAp4AzyK+zBtJPzVbqOgu5LCEh4VaJVbPQcgYQYJIMGQPXVeJJq1fnfazis7a5pFNPahog==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.1.10", - "@vitest/utils": "4.1.10", + "@vitest/pretty-format": "4.1.11", + "@vitest/utils": "4.1.11", "magic-string": "^0.30.21", "pathe": "^2.0.3" }, @@ -1108,9 +1125,9 @@ } }, "node_modules/@vitest/spy": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.10.tgz", - "integrity": "sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.11.tgz", + "integrity": "sha512-apNa/prQy2qCeywhnixOHPRCgGNhvg7T4Dapfl1GahLp/R+uhBm5cPyFoNVyqsNd2h1nJxL6BqqdIjiABL60YA==", "dev": true, "license": "MIT", "funding": { @@ -1118,13 +1135,13 @@ } }, "node_modules/@vitest/utils": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.10.tgz", - "integrity": "sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.11.tgz", + "integrity": "sha512-zTCVGpyFsGWBhllOyKlTw/vnr6D9qxsfSDyfbyZmTyjHw5N/VuvzHpHoQjm2ZJzn4RJgx5w4r7V0er69CmLgPQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.1.10", + "@vitest/pretty-format": "4.1.11", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.1.0" }, @@ -1256,9 +1273,9 @@ "license": "MIT" }, "node_modules/concurrently": { - "version": "10.0.4", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-10.0.4.tgz", - "integrity": "sha512-trZql+7l/0+WRAsAnEdctr4+iiOS6ZrViI6H8QWcCF9MFS/LT0dKpe8vluB1to6it+OxSI4VospFTIFMW8DJRw==", + "version": "10.0.5", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-10.0.5.tgz", + "integrity": "sha512-JaP/CoftUrCcAFW/g//RbgEGwlelnEae6cfBLgH6ZdO6s8jPkn6p9SB9u6pdVxYXoiSnFqseOlHfrEfF82TVOg==", "dev": true, "license": "MIT", "dependencies": { @@ -1366,9 +1383,9 @@ } }, "node_modules/es-module-lexer": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.1.tgz", - "integrity": "sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.2.tgz", + "integrity": "sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==", "dev": true, "license": "MIT" }, @@ -2048,13 +2065,13 @@ } }, "node_modules/rolldown": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.3.tgz", - "integrity": "sha512-rn9wpmxplLf7NLNyCk9FyWh3FM43DbY8jOzCdEPzH7uflhTftRbCEpqi6Ly2osgoU8OwObtmavMbWLaWy4LX7A==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.5.tgz", + "integrity": "sha512-VD2IE5PUG4Oj8zz2VGykiYd5wbnjdIiSsNQb8Qu5B+noEp+A78mu2iVvpp27g8es14Tk9rofNs5Tku9iQCS4fA==", "dev": true, "license": "MIT", "dependencies": { - "@oxc-project/types": "=0.143.0", + "@oxc-project/types": "=0.146.0", "@rolldown/pluginutils": "^1.0.0" }, "bin": { @@ -2064,20 +2081,21 @@ "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rolldown/binding-android-arm64": "1.2.3", - "@rolldown/binding-darwin-arm64": "1.2.3", - "@rolldown/binding-darwin-x64": "1.2.3", - "@rolldown/binding-freebsd-x64": "1.2.3", - "@rolldown/binding-linux-arm-gnueabihf": "1.2.3", - "@rolldown/binding-linux-arm64-gnu": "1.2.3", - "@rolldown/binding-linux-arm64-musl": "1.2.3", - "@rolldown/binding-linux-ppc64-gnu": "1.2.3", - "@rolldown/binding-linux-s390x-gnu": "1.2.3", - "@rolldown/binding-linux-x64-gnu": "1.2.3", - "@rolldown/binding-linux-x64-musl": "1.2.3", - "@rolldown/binding-openharmony-arm64": "1.2.3", - "@rolldown/binding-win32-arm64-msvc": "1.2.3", - "@rolldown/binding-win32-x64-msvc": "1.2.3" + "@rolldown/binding-android-arm-eabi": "1.2.5", + "@rolldown/binding-android-arm64": "1.2.5", + "@rolldown/binding-darwin-arm64": "1.2.5", + "@rolldown/binding-darwin-x64": "1.2.5", + "@rolldown/binding-freebsd-x64": "1.2.5", + "@rolldown/binding-linux-arm-gnueabihf": "1.2.5", + "@rolldown/binding-linux-arm64-gnu": "1.2.5", + "@rolldown/binding-linux-arm64-musl": "1.2.5", + "@rolldown/binding-linux-ppc64-gnu": "1.2.5", + "@rolldown/binding-linux-s390x-gnu": "1.2.5", + "@rolldown/binding-linux-x64-gnu": "1.2.5", + "@rolldown/binding-linux-x64-musl": "1.2.5", + "@rolldown/binding-openharmony-arm64": "1.2.5", + "@rolldown/binding-win32-arm64-msvc": "1.2.5", + "@rolldown/binding-win32-x64-msvc": "1.2.5" } }, "node_modules/rxjs": { @@ -2262,9 +2280,9 @@ "license": "MIT" }, "node_modules/tinyexec": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.2.4.tgz", - "integrity": "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.3.0.tgz", + "integrity": "sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==", "dev": true, "license": "MIT", "engines": { @@ -2289,9 +2307,9 @@ } }, "node_modules/tinyrainbow": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz", - "integrity": "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.1.tgz", + "integrity": "sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw==", "dev": true, "license": "MIT", "engines": { @@ -2414,16 +2432,16 @@ "license": "MIT" }, "node_modules/vite": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-8.2.1.tgz", - "integrity": "sha512-EU/eS7BH3XROHh2YnBefjM6DBKA6ZeMZEYQbj7NLWg5wHYlhB8B/Mayd5XsgWq+NFYccDOTemRpdETWR6Ka/lw==", + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.2.2.tgz", + "integrity": "sha512-cFKLV/PRgAUlIRm5WjMjJ86jrftzpqcgH+Us+DS8mI3CDNiH30Whrz8uHL3+MOLPAgqbMBAqWdAHAphOAM+z/Q==", "dev": true, "license": "MIT", "dependencies": { "lightningcss": "^1.33.0", "picomatch": "^4.0.5", - "postcss": "^8.5.25", - "rolldown": "~1.2.1", + "postcss": "^8.5.26", + "rolldown": "~1.2.4", "tinyglobby": "^0.2.17" }, "bin": { @@ -2440,7 +2458,7 @@ }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", - "@vitejs/devtools": "^0.4.0", + "@vitejs/devtools": "^0.4.0 || ^0.5.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", @@ -2492,19 +2510,19 @@ } }, "node_modules/vitest": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.10.tgz", - "integrity": "sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.11.tgz", + "integrity": "sha512-fhACrNXUidIbGSBr5FlbuBkO7VWC1ZyLl0DO4CU2DrQoAPxX84Ysxs+HeGQpii5lZWV1Q4gBZTTu49mF+A6Edw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "4.1.10", - "@vitest/mocker": "4.1.10", - "@vitest/pretty-format": "4.1.10", - "@vitest/runner": "4.1.10", - "@vitest/snapshot": "4.1.10", - "@vitest/spy": "4.1.10", - "@vitest/utils": "4.1.10", + "@vitest/expect": "4.1.11", + "@vitest/mocker": "4.1.11", + "@vitest/pretty-format": "4.1.11", + "@vitest/runner": "4.1.11", + "@vitest/snapshot": "4.1.11", + "@vitest/spy": "4.1.11", + "@vitest/utils": "4.1.11", "es-module-lexer": "^2.0.0", "expect-type": "^1.3.0", "magic-string": "^0.30.21", @@ -2532,12 +2550,12 @@ "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", - "@vitest/browser-playwright": "4.1.10", - "@vitest/browser-preview": "4.1.10", - "@vitest/browser-webdriverio": "4.1.10", - "@vitest/coverage-istanbul": "4.1.10", - "@vitest/coverage-v8": "4.1.10", - "@vitest/ui": "4.1.10", + "@vitest/browser-playwright": "4.1.11", + "@vitest/browser-preview": "4.1.11", + "@vitest/browser-webdriverio": "4.1.11", + "@vitest/coverage-istanbul": "4.1.11", + "@vitest/coverage-v8": "4.1.11", + "@vitest/ui": "4.1.11", "happy-dom": "*", "jsdom": "*", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" diff --git a/src/InfiniFrame.Js/package.json b/src/InfiniFrame.Js/package.json index acf43a8ac..7b2b9d742 100644 --- a/src/InfiniFrame.Js/package.json +++ b/src/InfiniFrame.Js/package.json @@ -15,12 +15,12 @@ "description": "", "devDependencies": { "@types/node": "^26.2.0", - "@vitest/coverage-v8": "^4.1.10", - "concurrently": "^10.0.4", + "@vitest/coverage-v8": "^4.1.11", + "concurrently": "^10.0.5", "jsdom": "^30.0.1", "terser": "^5.50.0", "typescript": "^7.0.2", - "vite": "^8.2.1", - "vitest": "^4.1.10" + "vite": "^8.2.2", + "vitest": "^4.1.11" } } diff --git a/src/InfiniFrame.Js/tsconfig.json b/src/InfiniFrame.Js/tsconfig.json index 380a2abea..9ae87b8fe 100644 --- a/src/InfiniFrame.Js/tsconfig.json +++ b/src/InfiniFrame.Js/tsconfig.json @@ -31,7 +31,8 @@ /* Specify what module code is generated. */ "rootDir": "./TypeScript/", /* Specify the root folder within your source files. */ - "moduleResolution": "bundler", /* Specify how TypeScript looks up a file from a given module specifier. */ + "moduleResolution": "bundler", + /* Specify how TypeScript looks up a file from a given module specifier. */ // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ diff --git a/src/InfiniFrame.Js/vite.config.dev.ts b/src/InfiniFrame.Js/vite.config.dev.ts index f4501f7a0..c7239d012 100644 --- a/src/InfiniFrame.Js/vite.config.dev.ts +++ b/src/InfiniFrame.Js/vite.config.dev.ts @@ -1,5 +1,5 @@ -import { defineConfig } from "vite"; -import { resolve } from "node:path"; +import {defineConfig} from "vite"; +import {resolve} from "node:path"; const entry = resolve(__dirname, "TypeScript/Index.ts"); @@ -17,4 +17,4 @@ export default defineConfig({ fileName: () => "InfiniFrame.dev.js" } } -}); \ No newline at end of file +}); diff --git a/src/InfiniFrame.Js/vite.config.prod.ts b/src/InfiniFrame.Js/vite.config.prod.ts index 743d2a601..23d36a9ee 100644 --- a/src/InfiniFrame.Js/vite.config.prod.ts +++ b/src/InfiniFrame.Js/vite.config.prod.ts @@ -1,5 +1,5 @@ -import { defineConfig } from "vite"; -import { resolve } from "node:path"; +import {defineConfig} from "vite"; +import {resolve} from "node:path"; const entry = resolve(__dirname, "TypeScript/Index.ts"); @@ -27,4 +27,4 @@ export default defineConfig({ mangle: true } } -}); \ No newline at end of file +}); diff --git a/src/InfiniFrame.Js/vitest.config.ts b/src/InfiniFrame.Js/vitest.config.ts index abcbba033..349a4639d 100644 --- a/src/InfiniFrame.Js/vitest.config.ts +++ b/src/InfiniFrame.Js/vitest.config.ts @@ -8,7 +8,19 @@ export default defineConfig({ restoreMocks: true, coverage: { provider: "v8", - reporter: ["text", "lcov"] + reporter: ["text", "lcov"], + include: ["TypeScript/**/*.ts"], + exclude: [ + "TypeScript/Contracts/**", + "TypeScript/Window/Features/index.ts", + "TypeScript/Utils/index.ts" + ], + thresholds: { + lines: 85, + branches: 65, + functions: 90, + statements: 84 + } } } }); diff --git a/src/InfiniFrame.NativeBridge/InfiniFrame.NativeBridge.csproj b/src/InfiniFrame.NativeBridge/InfiniFrame.NativeBridge.csproj index 3616358ee..18b5bce27 100644 --- a/src/InfiniFrame.NativeBridge/InfiniFrame.NativeBridge.csproj +++ b/src/InfiniFrame.NativeBridge/InfiniFrame.NativeBridge.csproj @@ -8,6 +8,10 @@