diff --git a/.changeset/curly-paws-switch.md b/.changeset/curly-paws-switch.md new file mode 100644 index 000000000..d31f44b5d --- /dev/null +++ b/.changeset/curly-paws-switch.md @@ -0,0 +1,5 @@ +--- +"@preact/signals-react": patch +--- + +Setup internal infrastructure for upcoming major change diff --git a/karma.conf.js b/karma.conf.js index 220d3fe7d..5c61e1950 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -30,6 +30,13 @@ var localLaunchers = { }, }; +/* eslint-disable no-console */ +const signalsTransformPath = require.resolve("./packages/react-transform"); +console.log(`Transforming tests using ${signalsTransformPath}.`); +console.log( + `Manually re-compile & re-run tests to validate changes to react-transform` +); + const subPkgPath = pkgName => { if (!minify) { return path.join(__dirname, pkgName, "src", "index.ts"); @@ -62,6 +69,8 @@ function createEsbuildPlugin() { "@preact/signals-core": subPkgPath("./packages/core"), "@preact/signals": subPkgPath("./packages/preact"), "@preact/signals-react": subPkgPath("./packages/react"), + "@preact/signals-react/auto": subPkgPath("./packages/react/auto"), + "@preact/signals-react/runtime": subPkgPath("./packages/react/runtime"), "@preact/signals-react-transform": subPkgPath("./packages/react-transform"), }; @@ -145,6 +154,20 @@ function createEsbuildPlugin() { }, ]; + /** @type {any} */ + let signalsTransform = false; + if ( + args.path.includes("packages/react/test/shared") || + args.path.includes("packages/react/runtime/test") + ) { + signalsTransform = [ + signalsTransformPath, + { + mode: "auto", + }, + ]; + } + const downlevelPlugin = [ "@babel/preset-env", { @@ -168,6 +191,7 @@ function createEsbuildPlugin() { sourceMaps: "inline", presets: downlevel ? [ts, jsx, downlevelPlugin] : [ts, jsx], plugins: [ + signalsTransform, coverage && coveragePlugin, minify && renamePlugin, ].filter(Boolean), @@ -198,7 +222,14 @@ function createEsbuildPlugin() { }; } -const pkgList = ["core", "preact", "react", "react/runtime", "react-transform"]; +const pkgList = [ + "core", + "preact", + "react", + "react/auto", + "react/runtime", + "react-transform", +]; module.exports = function (config) { config.set({ diff --git a/package.json b/package.json index 6cac0dad4..d4cfa60d9 100644 --- a/package.json +++ b/package.json @@ -3,16 +3,18 @@ "private": true, "scripts": { "prebuild": "rimraf packages/core/dist/ packages/preact/dist", - "build": "pnpm build:core && pnpm build:preact && pnpm build:react-runtime && pnpm build:react && pnpm build:react-transform", + "build": "pnpm build:core && pnpm build:preact && pnpm build:react-runtime && pnpm build:react-auto && pnpm build:react && pnpm build:react-transform", "_build": "microbundle --raw --globals @preact/signals-core=preactSignalsCore,preact/hooks=preactHooks", "build:core": "pnpm _build --cwd packages/core && pnpm postbuild:core", "build:preact": "pnpm _build --cwd packages/preact && pnpm postbuild:preact", "build:react": "pnpm _build --cwd packages/react && pnpm postbuild:react", + "build:react-auto": "pnpm _build --cwd packages/react/auto && pnpm postbuild:react-auto", "build:react-runtime": "pnpm _build --cwd packages/react/runtime && pnpm postbuild:react-runtime", "build:react-transform": "pnpm _build --no-compress --cwd packages/react-transform", "postbuild:core": "cd packages/core/dist && mv -f index.d.ts signals-core.d.ts", "postbuild:preact": "cd packages/preact/dist && mv -f preact/src/index.d.ts signals.d.ts && rm -dr preact", "postbuild:react": "cd packages/react/dist && mv -f react/src/index.d.ts signals.d.ts && rm -dr react", + "postbuild:react-auto": "cd packages/react/auto/dist && mv -f react/auto/src/*.d.ts . && rm -dr react", "postbuild:react-runtime": "cd packages/react/runtime/dist && mv -f react/runtime/src/*.d.ts . && rm -dr react", "postbuild": "node ./scripts/node-13-exports.js", "lint": "pnpm lint:eslint && pnpm lint:tsc", diff --git a/packages/react/auto/package.json b/packages/react/auto/package.json new file mode 100644 index 000000000..fa473061a --- /dev/null +++ b/packages/react/auto/package.json @@ -0,0 +1,25 @@ +{ + "name": "@preact/signals-react-auto", + "description": "Sub package for @preact/signals-react that patches React to automatically update when signals change", + "private": true, + "amdName": "reactSignalsAuto", + "main": "dist/auto.js", + "module": "dist/auto.module.js", + "unpkg": "dist/auto.min.js", + "types": "dist/index.d.ts", + "mangle": "../../../mangle.json", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "browser": "./dist/auto.module.js", + "import": "./dist/auto.mjs", + "require": "./dist/auto.js" + } + }, + "dependencies": {}, + "peerDependencies": { + "@preact/signals-core": "workspace:^1.3.0", + "@preact/signals-react": "workspace:*", + "react": "^16.14.0 || 17.x || 18.x" + } +} diff --git a/packages/react/auto/src/index.ts b/packages/react/auto/src/index.ts new file mode 100644 index 000000000..cd1a0c7e6 --- /dev/null +++ b/packages/react/auto/src/index.ts @@ -0,0 +1,2 @@ +import { installAutoSignalTracking } from "@preact/signals-react/runtime"; +installAutoSignalTracking(); diff --git a/packages/react/auto/test/browser/mounts.test.tsx b/packages/react/auto/test/browser/mounts.test.tsx new file mode 100644 index 000000000..9a78f3cda --- /dev/null +++ b/packages/react/auto/test/browser/mounts.test.tsx @@ -0,0 +1,42 @@ +// @ts-expect-error +globalThis.IS_REACT_ACT_ENVIRONMENT = true; + +import { mountSignalsTests } from "../../../test/shared/mounting"; +import { + act, + getConsoleErrorSpy, + checkConsoleErrorLogs, + createRoot, + type Root, +} from "../../../test/shared/utils.js"; + +import "@preact/signals-react/auto"; + +describe("@preact/signals-react/auto", () => { + describe("mounting", () => { + let scratch: HTMLDivElement; + let root: Root; + + async function render(element: JSX.Element): Promise { + await act(() => { + root.render(element); + }); + return scratch.innerHTML; + } + + beforeEach(async () => { + scratch = document.createElement("div"); + document.body.appendChild(scratch); + getConsoleErrorSpy().resetHistory(); + + root = await createRoot(scratch); + }); + + afterEach(async () => { + scratch.remove(); + checkConsoleErrorLogs(); + }); + + mountSignalsTests(render); + }); +}); diff --git a/packages/react/auto/test/browser/updates.test.tsx b/packages/react/auto/test/browser/updates.test.tsx new file mode 100644 index 000000000..fea8d5f7f --- /dev/null +++ b/packages/react/auto/test/browser/updates.test.tsx @@ -0,0 +1,12 @@ +// @ts-expect-error +globalThis.IS_REACT_ACT_ENVIRONMENT = true; + +import { updateSignalsTests } from "../../../test/shared/updates"; +import "@preact/signals-react/auto"; + +describe("@preact/signals-react/auto", () => { + describe("updating", () => { + // calledOnce + updateSignalsTests(); + }); +}); diff --git a/packages/react/auto/test/node/renderToStaticMarkup.test.tsx b/packages/react/auto/test/node/renderToStaticMarkup.test.tsx new file mode 100644 index 000000000..277476bd4 --- /dev/null +++ b/packages/react/auto/test/node/renderToStaticMarkup.test.tsx @@ -0,0 +1,24 @@ +import { signal, useSignalEffect } from "@preact/signals-react"; +import { createElement } from "react"; +import { renderToStaticMarkup } from "react-dom/server"; +import { mountSignalsTests } from "../../../test/shared/mounting"; + +describe("@preact/signals-react/auto", () => { + describe("renderToStaticMarkup", () => { + mountSignalsTests(el => Promise.resolve(renderToStaticMarkup(el))); + + it("should not invoke useSignalEffect", async () => { + const spy = sinon.spy(); + const sig = signal("foo"); + + function App() { + useSignalEffect(() => spy(sig.value)); + return

{sig.value}

; + } + + const html = await renderToStaticMarkup(); + expect(html).to.equal("

foo

"); + expect(spy.called).to.be.false; + }); + }); +}); diff --git a/packages/react/package.json b/packages/react/package.json index 969c881b0..72b6ee060 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -51,7 +51,7 @@ "README.md" ], "scripts": { - "prepublishOnly": "cd ../.. && pnpm build:react-runtime && pnpm build:react" + "prepublishOnly": "cd ../.. && pnpm build:react-runtime && pnpm build:react-auto && pnpm build:react" }, "dependencies": { "@preact/signals-core": "workspace:^1.4.0", diff --git a/packages/react/runtime/test/browser/mounts.test.tsx b/packages/react/runtime/test/browser/mounts.test.tsx new file mode 100644 index 000000000..76ff7aa9d --- /dev/null +++ b/packages/react/runtime/test/browser/mounts.test.tsx @@ -0,0 +1,40 @@ +// @ts-expect-error +globalThis.IS_REACT_ACT_ENVIRONMENT = true; + +import { mountSignalsTests } from "../../../test/shared/mounting"; +import { + act, + getConsoleErrorSpy, + checkConsoleErrorLogs, + createRoot, + type Root, +} from "../../../test/shared/utils.js"; + +describe("@preact/signals-react/runtime", () => { + describe("mounting", () => { + let scratch: HTMLDivElement; + let root: Root; + + async function render(element: JSX.Element): Promise { + await act(() => { + root.render(element); + }); + return scratch.innerHTML; + } + + beforeEach(async () => { + scratch = document.createElement("div"); + document.body.appendChild(scratch); + getConsoleErrorSpy().resetHistory(); + + root = await createRoot(scratch); + }); + + afterEach(async () => { + scratch.remove(); + checkConsoleErrorLogs(); + }); + + mountSignalsTests(render); + }); +}); diff --git a/packages/react/runtime/test/browser/updates.test.tsx b/packages/react/runtime/test/browser/updates.test.tsx new file mode 100644 index 000000000..762081f7e --- /dev/null +++ b/packages/react/runtime/test/browser/updates.test.tsx @@ -0,0 +1,10 @@ +// @ts-expect-error +globalThis.IS_REACT_ACT_ENVIRONMENT = true; + +import { updateSignalsTests } from "../../../test/shared/updates"; + +describe("@preact/signals-react/runtime", () => { + describe("updating", () => { + updateSignalsTests(true); + }); +}); diff --git a/packages/react/runtime/test/useSignals.test.tsx b/packages/react/runtime/test/browser/useSignals.test.tsx similarity index 99% rename from packages/react/runtime/test/useSignals.test.tsx rename to packages/react/runtime/test/browser/useSignals.test.tsx index c941e27d9..5db7d4ffb 100644 --- a/packages/react/runtime/test/useSignals.test.tsx +++ b/packages/react/runtime/test/browser/useSignals.test.tsx @@ -8,7 +8,7 @@ import { checkHangingAct, getConsoleErrorSpy, checkConsoleErrorLogs, -} from "../../test/shared/utils"; +} from "../../../test/shared/utils"; describe("useSignals", () => { let scratch: HTMLDivElement; diff --git a/packages/react/runtime/test/node/renderToStaticMarkup.test.tsx b/packages/react/runtime/test/node/renderToStaticMarkup.test.tsx new file mode 100644 index 000000000..25c86dc93 --- /dev/null +++ b/packages/react/runtime/test/node/renderToStaticMarkup.test.tsx @@ -0,0 +1,24 @@ +import { signal, useSignalEffect } from "@preact/signals-react"; +import { createElement } from "react"; +import { renderToStaticMarkup } from "react-dom/server"; +import { mountSignalsTests } from "../../../test/shared/mounting"; + +describe("@preact/signals-react/runtime", () => { + describe("renderToStaticMarkup", () => { + mountSignalsTests(el => Promise.resolve(renderToStaticMarkup(el))); + + it("should not invoke useSignalEffect", async () => { + const spy = sinon.spy(); + const sig = signal("foo"); + + function App() { + useSignalEffect(() => spy(sig.value)); + return

{sig.value}

; + } + + const html = await renderToStaticMarkup(); + expect(html).to.equal("

foo

"); + expect(spy.called).to.be.false; + }); + }); +}); diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index b2c03f140..9c47acb10 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -8,8 +8,12 @@ import { untracked, } from "@preact/signals-core"; import type { ReactElement } from "react"; -import { useSignal, useComputed, useSignalEffect } from "../runtime"; -import { installAutoSignalTracking } from "../runtime/src/auto"; +import { + useSignal, + useComputed, + useSignalEffect, + installAutoSignalTracking, +} from "../runtime/src/index"; // TODO: This duplicates runtime code between main and sub runtime packages export { signal, diff --git a/packages/react/test/browser/mounts.test.tsx b/packages/react/test/browser/mounts.test.tsx deleted file mode 100644 index af132cac9..000000000 --- a/packages/react/test/browser/mounts.test.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { mountSignalsTests } from "../shared/mounting"; -import { - Root, - createRoot, - act, - getConsoleErrorSpy, - checkConsoleErrorLogs, -} from "../shared/utils"; - -describe("@preact/signals-react mounting", () => { - let scratch: HTMLDivElement; - let root: Root; - - async function render(element: JSX.Element | null): Promise { - await act(() => root.render(element)); - return scratch.innerHTML; - } - - beforeEach(async () => { - scratch = document.createElement("div"); - document.body.appendChild(scratch); - root = await createRoot(scratch); - getConsoleErrorSpy().resetHistory(); - }); - - afterEach(async () => { - scratch.remove(); - checkConsoleErrorLogs(); - }); - - mountSignalsTests(render); -}); diff --git a/packages/react/test/browser/react-router.test.tsx b/packages/react/test/browser/react-router.test.tsx index eaa1dd8dc..50f0b57af 100644 --- a/packages/react/test/browser/react-router.test.tsx +++ b/packages/react/test/browser/react-router.test.tsx @@ -1,4 +1,4 @@ -// @ts-ignore-next-line +// @ts-expect-error globalThis.IS_REACT_ACT_ENVIRONMENT = true; import { signal } from "@preact/signals-react"; diff --git a/packages/react/test/node/renderToStaticMarkup.test.tsx b/packages/react/test/node/renderToStaticMarkup.test.tsx index 08ad99be9..9a8bccc90 100644 --- a/packages/react/test/node/renderToStaticMarkup.test.tsx +++ b/packages/react/test/node/renderToStaticMarkup.test.tsx @@ -4,7 +4,7 @@ import { renderToStaticMarkup } from "react-dom/server"; import { mountSignalsTests } from "../shared/mounting"; describe("renderToStaticMarkup", () => { - mountSignalsTests(renderToStaticMarkup); + mountSignalsTests(el => Promise.resolve(renderToStaticMarkup(el))); it("should not invoke useSignalEffect", async () => { const spy = sinon.spy(); diff --git a/packages/react/test/shared/mounting.tsx b/packages/react/test/shared/mounting.tsx index cef29aca4..2ca9ad473 100644 --- a/packages/react/test/shared/mounting.tsx +++ b/packages/react/test/shared/mounting.tsx @@ -1,28 +1,11 @@ -// @ts-ignore-next-line -globalThis.IS_REACT_ACT_ENVIRONMENT = true; - -import { - signal, - computed, - useComputed, - useSignal, -} from "@preact/signals-react"; +import { signal, computed } from "@preact/signals-core"; +import { useComputed, useSignal } from "@preact/signals-react/runtime"; import { expect } from "chai"; import { createElement, useReducer, StrictMode, useState } from "react"; -import { getConsoleErrorSpy, checkConsoleErrorLogs } from "./utils"; - export function mountSignalsTests( - render: (element: JSX.Element) => string | Promise + render: (element: JSX.Element) => Promise ) { - beforeEach(async () => { - getConsoleErrorSpy().resetHistory(); - }); - - afterEach(async () => { - checkConsoleErrorLogs(); - }); - describe("mount text bindings", () => { it("should render text without signals", async () => { const html = await render(test); diff --git a/packages/react/test/browser/updates.test.tsx b/packages/react/test/shared/updates.tsx similarity index 91% rename from packages/react/test/browser/updates.test.tsx rename to packages/react/test/shared/updates.tsx index a1df8d356..8066cca15 100644 --- a/packages/react/test/browser/updates.test.tsx +++ b/packages/react/test/shared/updates.tsx @@ -1,13 +1,9 @@ -// @ts-ignore-next-line -globalThis.IS_REACT_ACT_ENVIRONMENT = true; - +import { signal, computed } from "@preact/signals-core"; import { - signal, - computed, useComputed, - useSignalEffect, useSignal, -} from "@preact/signals-react"; + useSignalEffect, +} from "@preact/signals-react/runtime"; import type { Signal, ReadonlySignal } from "@preact/signals-react"; import { createElement, @@ -24,31 +20,36 @@ import { useRef, } from "react"; import type { FunctionComponent } from "react"; - import { renderToStaticMarkup } from "react-dom/server"; + import { - createRoot, - Root, act, - checkHangingAct, + createRoot, isReact16, isProd, getConsoleErrorSpy, checkConsoleErrorLogs, -} from "../shared/utils"; + checkHangingAct, + Root, +} from "./utils"; -describe("@preact/signals-react updating", () => { +export function updateSignalsTests(usingTransform = false) { let scratch: HTMLDivElement; let root: Root; - - async function render(element: Parameters[0]) { - await act(() => root.render(element)); - } + let render: Root["render"]; beforeEach(async () => { scratch = document.createElement("div"); document.body.appendChild(scratch); - root = await createRoot(scratch); + + const realRoot = await createRoot(scratch); + root = { + render: element => act(() => realRoot.render(element)), + unmount: () => act(() => realRoot.unmount()), + }; + + render = root.render.bind(root); + getConsoleErrorSpy().resetHistory(); }); @@ -197,23 +198,26 @@ describe("@preact/signals-react updating", () => { expect(scratch.innerHTML).to.equal("
1
1
"); }); - it("should subscribe to signals passed as props to DOM elements", async () => { - const className = signal("foo"); - function App() { - // @ts-expect-error React types don't allow signals on DOM elements :/ - return
; - } + // React transform doesn't support this yet. + if (!usingTransform) { + it("should subscribe to signals passed as props to DOM elements", async () => { + const className = signal("foo"); + function App() { + // @ts-expect-error React types don't allow signals on DOM elements :/ + return
; + } - await render(); + await render(); - expect(scratch.innerHTML).to.equal('
'); + expect(scratch.innerHTML).to.equal('
'); - await act(() => { - className.value = "bar"; - }); + await act(() => { + className.value = "bar"; + }); - expect(scratch.innerHTML).to.equal('
'); - }); + expect(scratch.innerHTML).to.equal('
'); + }); + } it("should activate signal accessed in render", async () => { const sig = signal(null); @@ -343,30 +347,36 @@ describe("@preact/signals-react updating", () => { } }); - it("should render static markup of a component", async () => { - const count = signal(0); - - const StaticMarkupTest = () => { - return ( -
-						{renderToStaticMarkup({count})}
-						{renderToStaticMarkup({count.value})}
-					
- ); - }; - - await render(); - expect(scratch.textContent).to.equal("00"); - - for (let i = 0; i < 3; i++) { - await act(async () => { - count.value += 1; - }); - expect(scratch.textContent).to.equal( - `${count.value}${count.value}` - ); - } - }); + // Babel transform doesn't yet support this case. + if (!usingTransform) { + it("should render static markup of a component", async () => { + const count = signal(0); + + // In this test, the {count} signal is rendered as a SignalValue text + // synchronously during the render of StaticMarkupTest. This situation + // trips up some of our previous integrations into React. + const StaticMarkupTest = () => { + return ( +
+							{renderToStaticMarkup({count})}
+							{renderToStaticMarkup({count.value})}
+						
+ ); + }; + + await render(); + expect(scratch.textContent).to.equal("00"); + + for (let i = 0; i < 3; i++) { + await act(async () => { + count.value += 1; + }); + expect(scratch.textContent).to.equal( + `${count.value}${count.value}` + ); + } + }); + } it("should correctly render components that have useReducer()", async () => { const count = signal(0); @@ -838,4 +848,4 @@ describe("@preact/signals-react updating", () => { expect(cleanup).to.have.been.calledWith("foo", isReact16 ? child : null); }); }); -}); +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8e4021dc1..93b711b8b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2789,7 +2789,7 @@ packages: postcss: ^8.1.0 dependencies: browserslist: 4.21.9 - caniuse-lite: 1.0.30001374 + caniuse-lite: 1.0.30001543 fraction.js: 4.2.0 normalize-range: 0.1.2 picocolors: 1.0.0 @@ -2986,7 +2986,7 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true dependencies: - caniuse-lite: 1.0.30001374 + caniuse-lite: 1.0.30001543 electron-to-chromium: 1.4.211 node-releases: 2.0.6 update-browserslist-db: 1.0.5(browserslist@4.21.3) @@ -2997,7 +2997,7 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true dependencies: - caniuse-lite: 1.0.30001515 + caniuse-lite: 1.0.30001543 electron-to-chromium: 1.4.457 node-releases: 2.0.13 update-browserslist-db: 1.0.11(browserslist@4.21.9) @@ -3059,17 +3059,13 @@ packages: resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} dependencies: browserslist: 4.21.9 - caniuse-lite: 1.0.30001515 + caniuse-lite: 1.0.30001543 lodash.memoize: 4.1.2 lodash.uniq: 4.5.0 dev: true - /caniuse-lite@1.0.30001374: - resolution: {integrity: sha512-mWvzatRx3w+j5wx/mpFN5v5twlPrabG8NqX2c6e45LCpymdoGqNvRkRutFUqpRTXKFQFNQJasvK0YT7suW6/Hw==} - dev: true - - /caniuse-lite@1.0.30001515: - resolution: {integrity: sha512-eEFDwUOZbE24sb+Ecsx3+OvNETqjWIdabMy52oOkIgcUtAsQifjUG9q4U9dgTHJM2mfk4uEPxc0+xuFdJ629QA==} + /caniuse-lite@1.0.30001543: + resolution: {integrity: sha512-qxdO8KPWPQ+Zk6bvNpPeQIOH47qZSYdFZd6dXQzb2KzhnSXju4Kd7H1PkSJx6NICSMgo/IhRZRhhfPTHYpJUCA==} dev: true /chai@4.3.6: @@ -3138,7 +3134,7 @@ packages: normalize-path: 3.0.0 readdirp: 3.6.0 optionalDependencies: - fsevents: 2.3.2 + fsevents: 2.3.3 dev: true /ci-info@3.3.2: @@ -4390,8 +4386,8 @@ packages: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} dev: true - /fsevents@2.3.2: - resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + /fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] requiresBuild: true @@ -6890,7 +6886,7 @@ packages: engines: {node: '>=10.0.0'} hasBin: true optionalDependencies: - fsevents: 2.3.2 + fsevents: 2.3.3 dev: true /run-parallel@1.2.0: @@ -7652,7 +7648,7 @@ packages: resolve: 1.22.1 rollup: 2.77.2 optionalDependencies: - fsevents: 2.3.2 + fsevents: 2.3.3 dev: true /void-elements@2.0.1: