@samitouri / QOS-React-1 / commits / d2983888f4

[sprout] Initial draft of sprout 🌱 test runner

--- ## Sprout 🌱 Overview **(Overview copied from [sprout/README.md](https://github.com/facebook/react-forget/blob/0468ddf8bbee54a9394317a667ea4ed96bb3bef3/forget/packages/sprout/README.md))** React Forget test framework that executes compiler fixtures. Currently, Sprout runs each fixture with a known set of inputs and annotations. We hope to add fuzzing capabilities to Sprout, synthesizing sets of program inputs based on type and/or effect annotations. Sprout is currently WIP and only executes files listed in `src/SproutOnlyFilterTodoRemove.ts`. ### Milestones: - [✅] Render fixtures with React runtime / `testing-library/react`. - [ ] Make Sprout CLI -runnable and report results in process exit code. After this point: - Sprout can be enabled by default and added to the Github Actions pipeline. - `SproutOnlyFilterTodoRemove` can be renamed to `SproutSkipFilter`. - All new tests should provide a `FIXTURE_ENTRYPOINT`. - [ ] Annotate `FIXTURE_ENTRYPOINT` (fn entrypoint and params) for rest of fixtures. - [ ] Edit rest of fixtures to use shared functions or define their own helpers. - [ ] *(optional)* Store Sprout output as snapshot files. i.e. each fixture could have a `fixture.js`, `fixture.snap.md`, and `fixture.sprout.md`. ### Constraints Each fixture test executed by Sprout needs to export a `FIXTURE_ENTRYPOINT`, a single function and parameter set with the following type signature. ```js type FIXTURE_ENTRYPOINT<T> = { // function to be invoked fn: ((...params: Array<T>) => any), // params to pass to fn params: Array<T>, // true if fn should be rendered as a React Component // i.e. returns jsx or primitives isComponent?: boolean, } ``` Example: ```js // test.js function MyComponent(props) { return <div>{props.a + props.b}</div>; } export const FIXTURE_ENTRYPOINT = { fn: MyComponent, params: [{a: "hello ", b: "world"}], isComponent: true, }; ``` --- ## Implementation Details - jest-worker test orchestrator (similar to Snap 🫰). I chose to write a test runner instead of directly using Jest for flexibility and speed. - Sprout 🌱 currently runs much more code per fixture (2 babel transform pipelines + 2 `exec(...)` than snap, so all scaling concerns apply. - Sprout may need more customization in the future (e.g. fuzzing component inputs, caching artifacts) - We probably want to add snapshot files for Sprout, which is much easier with a custom runner. This is also one of the main reasons we wrote Snap. Jest consolidates all external snapshots (i.e. non-inline snapshots) from a test into [a single file](https://github.com/facebook/react-forget/blob/d0a006ffa9842ee9db6b23ada94622af901eb07f/forget/src/__tests__/__snapshots__/compiler-test.ts.snap). This was painful mainly for rebasing changes, but also for small papercuts (e.g. needing to run `yarn test -u` twice when deleting a fixture) - Currently does not save output to snapshot file, but we can easily add this later (i.e. each test would have a `.snap.md` and `.sprout.md` file) - Supports filter mode (same testfilter.txt file as snap) - Currently does not support watch mode. I expect that sprout's primary use will be catching bugs in the PR / Github Actions phase. Can be changed if we need to iterate on sprout output while developing. - All tests are run with `react-test-renderer` to access the React Runtime, which is needed for calls to `useMemoCache` (and other potential hooks). - react-test-renderer required a mocked DOM, so I ~~used js-dom~~ did a terrible js-dom hack to add document, window, and other browser globals to the jest-worker globals, then exec the test code in the jest worker global. I can clean this up later by bundling library code (e.g. react, react-test-renderer) to not use `require(...)`, then calling `exec` on all "test client code" in the js-dom mock global (instead of the real jest worker one) - Tests marked `isComponent` need to return valid jsx or primitives. Values returned by all other tests are converted to a string primitive via JSON.stringify. ```sh # install new dependencies to node_modules $ yarn $ cd forget/packages/babel-plugin-react-forget $ yarn sprout:build && yarn sprout PASS alias-nested-member-path PASS assignment-variations-complex-lvalue PASS assignment-variations PASS chained-assignment-expressions PASS computed-call-evaluation-order PASS const-propagation-into-function-expression-primitive PASS constant-propagation-for PASS constant-propagation-while PASS constant-propagation ... ✨ Done in 3.91s. ```

Mofei Zhang committed Aug 14, 2023 at 19:26 UTC d2983888f436308353b6559fd96c4df7a494db8b
12 files changed +844 -70
compiler/forget/packages/babel-plugin-react-forget/package.json
+2
@@ -12,7 +12,9 @@
12 "test": "yarn jest && yarn snap:build && yarn snap",
13 "jest": "tsc && ts-node \"$(yarn --silent which jest)\"",
14 "snap": "node ../snap/dist/main.js",
15 + "sprout": "node ../sprout/dist/main.js",
16 "snap:build": "yarn workspace snap run build",
17 + "sprout:build": "yarn workspace sprout run build",
18 "ts:analyze-trace": "scripts/ts-analyze-trace.sh",
19 "test262": "yarn run --silent test262-harness --preprocessor=scripts/test262-preprocessor.js",
20 "test262:all": "yarn run --silent test262 '../../test262/test/**/*.js'",
compiler/forget/packages/babel-plugin-react-forget/src/Babel/RunReactForgetBabelPlugin.ts
+3 -1
@@ -24,7 +24,8 @@ export function runReactForgetBabelPlugin(
24 text: string,
25 file: string,
26 language: "flow" | "typescript",
27 - options: PluginOptions | null
27 + options: PluginOptions | null,
28 + includeAst: boolean = false
29 ): ReactForgetBabelPluginResult {
30 let ast;
31 if (language === "flow") {
@@ -43,6 +44,7 @@ export function runReactForgetBabelPlugin(
44 });
45 }
46 const result = transformFromAstSync(ast, text, {
47 + ast: includeAst,
48 filename: file,
49 highlightCode: false,
50 retainLines: true,
compiler/forget/packages/fixture-test-utils/src/compiler-utils.ts
+39 -33
@@ -85,38 +85,44 @@ export function transformFixtureInput(
85 language = "flow";
86 }
87
88 - return pluginFn(input, basename, language, {
89 - environment: {
90 - customHooks: new Map([
91 - [
92 - "useFreeze",
93 - {
94 - valueKind: "frozen" as ValueKind,
95 - effectKind: "freeze" as Effect,
96 - },
97 - ],
98 - ]),
99 - enableAssumeHooksFollowRulesOfReact,
100 - enableFunctionCallSignatureOptimizations: true,
101 - disableAllMemoization,
102 - enableTreatHooksAsFunctions,
103 - inlineUseMemo: true,
104 - memoizeJsxElements,
105 - validateHooksUsage: true,
106 - validateRefAccessDuringRender,
107 - validateFrozenLambdas: true,
108 - validateNoSetStateInRender,
109 - enableEmitFreeze,
110 - enableOptimizeFunctionExpressions,
111 - assertValidMutableRanges: true,
88 + return pluginFn(
89 + input,
90 + basename,
91 + language,
92 + {
93 + environment: {
94 + customHooks: new Map([
95 + [
96 + "useFreeze",
97 + {
98 + valueKind: "frozen" as ValueKind,
99 + effectKind: "freeze" as Effect,
100 + },
101 + ],
102 + ]),
103 + enableAssumeHooksFollowRulesOfReact,
104 + enableFunctionCallSignatureOptimizations: true,
105 + disableAllMemoization,
106 + enableTreatHooksAsFunctions,
107 + inlineUseMemo: true,
108 + memoizeJsxElements,
109 + validateHooksUsage: true,
110 + validateRefAccessDuringRender,
111 + validateFrozenLambdas: true,
112 + validateNoSetStateInRender,
113 + enableEmitFreeze,
114 + enableOptimizeFunctionExpressions,
115 + assertValidMutableRanges: true,
116 + },
117 + enableOnlyOnUseForgetDirective,
118 + enableOnlyOnReactScript,
119 + logger: null,
120 + gating,
121 + instrumentForget,
122 + panicOnBailout,
123 + isDev: true,
124 + noEmit: false,
125 },
113 - enableOnlyOnUseForgetDirective,
114 - enableOnlyOnReactScript,
115 - logger: null,
116 - gating,
117 - instrumentForget,
118 - panicOnBailout,
119 - isDev: true,
120 - noEmit: false,
121 - });
126 + includeAst
127 + );
128 }
compiler/forget/packages/sprout/README.md new
+46
@@ -0,0 +1,46 @@
1 +## Sprout
2 +React Forget test framework that executes compiler fixtures.
3 +
4 +Currently, Sprout runs each fixture with a known set of inputs and annotations. We hope to add fuzzing capabilities to Sprout, synthesizing sets of program inputs based on type and/or effect annotations.
5 +
6 +Sprout is currently WIP and only executes files listed in `src/SproutOnlyFilterTodoRemove.ts`.
7 +
8 +### Milestones:
9 +- [✅] Render fixtures with React runtime / `testing-library/react`.
10 +- [ ] Make Sprout CLI -runnable and report results in process exit code.
11 + After this point:
12 + - Sprout can be enabled by default and added to the Github Actions pipeline.
13 + - `SproutOnlyFilterTodoRemove` can be renamed to `SproutSkipFilter`.
14 + - All new tests should provide a `FIXTURE_ENTRYPOINT`.
15 +- [ ] Annotate `FIXTURE_ENTRYPOINT` (fn entrypoint and params) for rest of fixtures.
16 +- [ ] Edit rest of fixtures to use shared functions or define their own helpers.
17 +- [ ] *(optional)* Store Sprout output as snapshot files. i.e. each fixture could have a `fixture.js`, `fixture.snap.md`, and `fixture.sprout.md`.
18 +
19 +### Constraints
20 +Each fixture test executed by Sprout needs to export a `FIXTURE_ENTRYPOINT`, a single function and parameter set with the following type signature.
21 +
22 +```js
23 +type FIXTURE_ENTRYPOINT<T> = {
24 + // function to be invoked
25 + fn: ((...params: Array<T>) => any),
26 + // params to pass to fn
27 + params: Array<T>,
28 + // true if fn should be rendered as a React Component
29 + // i.e. returns jsx or primitives
30 + isComponent?: boolean,
31 +}
32 +```
33 +
34 +Example:
35 +```js
36 +// test.js
37 +function MyComponent(props) {
38 + return <div>{props.a + props.b}</div>;
39 +}
40 +export const FIXTURE_ENTRYPOINT = {
41 + fn: MyComponent,
42 + params: [{a: "hello ", b: "world"}],
43 + isComponent: true,
44 +};
45 +```
46 +
compiler/forget/packages/sprout/package.json new
+53
@@ -0,0 +1,53 @@
1 +{
2 + "name": "sprout",
3 + "version": "0.0.1",
4 + "public": false,
5 + "main": "dist/main.js",
6 + "license": "MIT",
7 + "files": [
8 + "src"
9 + ],
10 + "scripts": {
11 + "build": "yarn workspace babel-plugin-react-forget run build && yarn workspace fixture-test-utils run build && rimraf dist && tsc",
12 + "prettier": "prettier --write src",
13 + "test": "echo 'no tests'"
14 + },
15 + "repository": {
16 + "type": "git",
17 + "url": "git+https://github.com/facebook/react-forget.git"
18 + },
19 + "dependencies": {
20 + "@babel/generator": "7.2.0",
21 + "@babel/plugin-syntax-jsx": "^7.18.6",
22 + "@babel/types": "^7.19.0",
23 + "@parcel/watcher": "^2.1.0",
24 + "@testing-library/react": "^13.4.0",
25 + "chalk": "4",
26 + "fixture-test-utils": "*",
27 + "jsdom": "^22.1.0",
28 + "react": "^0.0.0-experimental-493f72b0a-20230727",
29 + "react-dom": "^0.0.0-experimental-493f72b0a-20230727",
30 + "readline": "^1.3.0",
31 + "typescript": "^5.1.0",
32 + "yargs": "^17.7.1"
33 + },
34 + "devDependencies": {
35 + "@babel/core": "^7.19.1",
36 + "@babel/parser": "^7.19.1",
37 + "@babel/plugin-syntax-typescript": "^7.18.6",
38 + "@babel/plugin-transform-modules-commonjs": "^7.18.6",
39 + "@babel/preset-react": "^7.18.6",
40 + "@babel/traverse": "^7.19.1",
41 + "@types/node": "^18.7.18",
42 + "@typescript-eslint/eslint-plugin": "^5.51.0",
43 + "@typescript-eslint/parser": "^5.51.0",
44 + "prettier": "2.8.8",
45 + "rimraf": "^3.0.2"
46 + },
47 + "resolutions": {
48 + "./**/@babel/parser": "7.7.4",
49 + "./**/@babel/types": "7.7.4",
50 + "@babel/core": "7.2.0",
51 + "@babel/traverse": "7.1.6"
52 + }
53 +}
compiler/forget/packages/sprout/src/SproutOnlyFilterTodoRemove.ts new
+55
@@ -0,0 +1,55 @@
1 +const onlyFilter = new Set([
2 + "alias-nested-member-path",
3 + // // TODO: fix invalid .set call
4 + // // "assignment-variations-complex-lvalue-array",
5 + "assignment-variations-complex-lvalue",
6 + "assignment-variations",
7 + "chained-assignment-expressions",
8 + "computed-call-evaluation-order",
9 + "const-propagation-into-function-expression-primitive",
10 + "constant-propagation-for",
11 + "constant-propagation-while",
12 + "constant-propagation",
13 + "do-while-continue",
14 + "do-while-simple",
15 + "expression-with-assignment",
16 + "for-of-break",
17 + "for-of-conditional-break",
18 + "for-of-continue",
19 + "for-of-destructure",
20 + "for-of-simple",
21 + "function-declaration-reassign",
22 + "function-declaration-redeclare",
23 + "lambda-reassign-primitive",
24 + "lambda-reassign-shadowed-primitive",
25 + "property-call-evaluation-order",
26 + "reactive-scope-grouping",
27 + "sequentially-constant-progagatable-if-test-conditions",
28 + "simple-function-1",
29 + // TODO: uses jsx (requires React)
30 + // "sketchy-code-rules-of-hooks",
31 + "ssa-complex-multiple-if",
32 + "ssa-complex-single-if",
33 + // TODO: fix infinite loop
34 + // "ssa-for-trivial-update",
35 + "ssa-for",
36 + "ssa-if-else",
37 + "ssa-objectexpression-phi",
38 + "ssa-property-call",
39 + "ssa-property",
40 + "ssa-return",
41 + "ssa-simple-phi",
42 + "ssa-simple",
43 + "ssa-single-if",
44 + "ssa-switch",
45 + "ssa-throw",
46 + // TODO: fix infinite loop
47 + // "ssa-while-no-reassign",
48 + "ssa-while",
49 + "type-field-load",
50 + "type-test-field-store",
51 + "type-test-primitive",
52 + "update-expression-constant-propagation",
53 +]);
54 +
55 +export default onlyFilter;
compiler/forget/packages/sprout/src/main.ts new
+53
@@ -0,0 +1,53 @@
1 +require("./runner.js");
2 +// /**
3 +// * Copyright (c) Meta Platforms, Inc. and affiliates.
4 +// *
5 +// * This source code is licensed under the MIT license found in the
6 +// * LICENSE file in the root directory of this source tree.
7 +// */
8 +
9 +// import { fork } from "child_process";
10 +// import invariant from "invariant";
11 +// import process from "process";
12 +// import * as readline from "readline";
13 +// import { hideBin } from "yargs/helpers";
14 +
15 +// readline.emitKeypressEvents(process.stdin);
16 +
17 +// if (process.stdin.isTTY) {
18 +// process.stdin.setRawMode(true);
19 +// }
20 +
21 +// process.stdin.on("keypress", function (_, key) {
22 +// if (key && key.name === "c" && key.ctrl) {
23 +// // handle sigint
24 +// if (childProc) {
25 +// console.log("Interrupted!!");
26 +// childProc.kill("SIGINT");
27 +// childProc.unref();
28 +// process.exit(-1);
29 +// }
30 +// }
31 +// });
32 +
33 +// const childProc = fork(require.resolve("./runner.js"), hideBin(process.argv), {
34 +// // for some reason, keypress events aren't sent to handlers in both processes
35 +// // when we `inherit` stdin.
36 +// // pipe stdout and stderr so we can silence child process after parent exits
37 +// stdio: ["pipe", "pipe", "pipe", "ipc"],
38 +// // forward existing env variables, like `NODE_OPTIONS` which VSCode uses to attach
39 +// // its debugger
40 +// env: { ...process.env, FORCE_COLOR: "true" },
41 +// });
42 +
43 +// invariant(
44 +// childProc.stdin && childProc.stdout && childProc.stderr,
45 +// "Expected forked process to have piped stdio"
46 +// );
47 +// process.stdin.pipe(childProc.stdin);
48 +// childProc.stdout.pipe(process.stdout);
49 +// childProc.stderr.pipe(process.stderr);
50 +
51 +// childProc.on("exit", (code) => {
52 +// process.exit(code ?? -1);
53 +// });
compiler/forget/packages/sprout/src/runner-evaluator.ts new
+119
@@ -0,0 +1,119 @@
1 +// tslint:disable:no-unused-variable */
2 +import { JSDOM } from "jsdom";
3 +const React = require("react");
4 +const render = require("@testing-library/react").render;
5 +
6 +const { window: testWindow } = new JSDOM(undefined);
7 +
8 +(globalThis as any).document = testWindow.document;
9 +(globalThis as any).window = testWindow.window;
10 +(globalThis as any).navigator = testWindow.navigator;
11 +(globalThis as any).React = React;
12 +(globalThis as any).render = render;
13 +
14 +export type EvaluatorResult = {
15 + kind: "ok" | "exception" | "UnexpectedError";
16 + value: string;
17 + logs: Array<string>;
18 +};
19 +
20 +const PLACEHOLDER_VALUE = Symbol();
21 +(globalThis as any).placeholderFn = function (..._args: Array<any>) {
22 + throw PLACEHOLDER_VALUE;
23 +};
24 +(globalThis as any).WrapperTestComponent = function (props: {
25 + fn: any;
26 + params: Array<any>;
27 +}) {
28 + const result = props.fn(...props.params);
29 + const seen = new Map();
30 +
31 + return JSON.stringify(result, (_key, val) => {
32 + if (typeof val === "object") {
33 + let id = seen.get(val);
34 + if (id != null) {
35 + return `[[ cyclic ref *${id} ]]`;
36 + }
37 + seen.set(val, seen.size);
38 + }
39 + return val;
40 + });
41 +};
42 +
43 +export function doEval(source: string): EvaluatorResult {
44 + "use strict";
45 +
46 + const originalConsoleLog = console.log.bind(console);
47 + const logs: Array<string> = [];
48 + global.console.log = (...args: Array<any>) => {
49 + logs.push(`${args}`);
50 + };
51 +
52 + // source needs to be evaluated in the same scope as invoke
53 + const evalResult: any = eval(`
54 + (() => {
55 + // Exports should be overwritten by source
56 + let exports = {
57 + FIXTURE_ENTRYPOINT: {
58 + fn: globalThis.placeholderFn,
59 + args: [],
60 + isComponent: false,
61 + },
62 + };
63 + let reachedInvoke = false;
64 + try {
65 + ${source}
66 + reachedInvoke = true;
67 +
68 + if (exports.FIXTURE_ENTRYPOINT.isComponent) {
69 + // try to run fixture as a react component
70 + const result = render(
71 + React.createElement(
72 + exports.FIXTURE_ENTRYPOINT.fn,
73 + exports.FIXTURE_ENTRYPOINT.params)
74 + ).asFragment().textContent;
75 +
76 + return {
77 + kind: "ok",
78 + value: result ?? 'null',
79 + };
80 + } else {
81 + const result = render(
82 + React.createElement(
83 + WrapperTestComponent,
84 + exports.FIXTURE_ENTRYPOINT
85 + )
86 + ).asFragment().textContent;
87 +
88 + return {
89 + kind: "ok",
90 + value: result ?? 'null',
91 + };
92 + }
93 + } catch (e) {
94 + if (!reachedInvoke) {
95 + return {
96 + kind: "UnexpectedError",
97 + value: e.toString(),
98 + };
99 + } else if (e === PLACEHOLDER_VALUE) {
100 + return {
101 + kind: "UnexpectedError",
102 + value: 'FIXTURE_ENTRYPOINT not defined!',
103 + };
104 + } else {
105 + return {
106 + kind: "exception",
107 + value: e.stack,
108 + };
109 + }
110 + }
111 + })()`);
112 +
113 + globalThis.console.log = originalConsoleLog;
114 + const result = {
115 + ...evalResult,
116 + logs,
117 + };
118 + return result;
119 +}
compiler/forget/packages/sprout/src/runner-worker.ts new
+173
@@ -0,0 +1,173 @@
1 +import type { runReactForgetBabelPlugin as RunReactForgetBabelPlugin } from "babel-plugin-react-forget/src/Babel/RunReactForgetBabelPlugin";
2 +import {
3 + COMPILER_PATH,
4 + parseLanguage,
5 + TestFixture,
6 + transformFixtureInput,
7 +} from "fixture-test-utils";
8 +import { transformFromAstSync } from "@babel/core";
9 +import fs from "fs/promises";
10 +import * as parser from "@babel/parser";
11 +import { doEval, EvaluatorResult } from "./runner-evaluator";
12 +
13 +const { runReactForgetBabelPlugin } = require(COMPILER_PATH) as {
14 + runReactForgetBabelPlugin: typeof RunReactForgetBabelPlugin;
15 +};
16 +
17 +// TODO: save output in .sprout.md files
18 +export type TestResult =
19 + | {
20 + nonForgetResult: EvaluatorResult;
21 + forgetResult: EvaluatorResult;
22 + unexpectedError: null;
23 + }
24 + | {
25 + nonForgetResult: null;
26 + forgetResult: null;
27 + unexpectedError: string;
28 + };
29 +
30 +type TransformResult =
31 + | {
32 + type: "Ok";
33 + value: string;
34 + }
35 + | {
36 + type: "UnexpectedError";
37 + value: string;
38 + };
39 +
40 +function transformFixtureForget(
41 + input: string,
42 + basename: string
43 +): TransformResult {
44 + try {
45 + const forgetResult = transformFixtureInput(
46 + input,
47 + basename,
48 + runReactForgetBabelPlugin,
49 + true
50 + );
51 +
52 + if (forgetResult.ast == null) {
53 + return {
54 + type: "UnexpectedError",
55 + value: "Unexpected - no babel ast",
56 + };
57 + }
58 +
59 + // missing more transforms
60 + const transformResult = transformFromAstSync(
61 + forgetResult.ast,
62 + forgetResult.code,
63 + {
64 + presets: [
65 + ["@babel/preset-react", { throwIfNamespace: false }],
66 + {
67 + plugins: ["@babel/plugin-transform-modules-commonjs"],
68 + },
69 + ],
70 + }
71 + );
72 +
73 + const code = transformResult?.code;
74 + if (code == null) {
75 + return {
76 + type: "UnexpectedError",
77 + value: `Expected custom transform to codegen successfully, got: ${transformResult}`,
78 + };
79 + }
80 + return {
81 + type: "Ok",
82 + value: code,
83 + };
84 + } catch (e) {
85 + return {
86 + type: "UnexpectedError",
87 + value: e.message,
88 + };
89 + }
90 +}
91 +
92 +function transformFixtureNoForget(
93 + input: string,
94 + basename: string
95 +): TransformResult {
96 + try {
97 + const language = parseLanguage(input.split("\n", 1)[0]);
98 + const ast = parser.parse(input, {
99 + sourceFilename: basename,
100 + plugins: ["jsx", language],
101 + sourceType: "module",
102 + });
103 +
104 + const transformResult = transformFromAstSync(ast, input, {
105 + presets: [
106 + {
107 + plugins: ["@babel/plugin-syntax-jsx"],
108 + },
109 + ["@babel/preset-react", { throwIfNamespace: false }],
110 + {
111 + plugins: ["@babel/plugin-transform-modules-commonjs"],
112 + },
113 + ],
114 + });
115 +
116 + const code = transformResult?.code;
117 + if (code == null) {
118 + return {
119 + type: "UnexpectedError",
120 + value: `Expected custom transform to codegen successfully, got: ${transformResult}`,
121 + };
122 + }
123 + return {
124 + type: "Ok",
125 + value: code,
126 + };
127 + } catch (e) {
128 + return {
129 + type: "UnexpectedError",
130 + value: e.message,
131 + };
132 + }
133 +}
134 +
135 +export async function run(fixture: TestFixture): Promise<TestResult> {
136 + const seenConsoleErrors: Array<string> = [];
137 + console.error = (...messages: Array<string>) => {
138 + seenConsoleErrors.push(...messages);
139 + };
140 + const { inputPath, inputExists, basename } = fixture;
141 +
142 + if (!inputExists) {
143 + return {
144 + nonForgetResult: null,
145 + forgetResult: null,
146 + unexpectedError: "file did not exist!",
147 + };
148 + }
149 + const inputRaw = await fs.readFile(inputPath, "utf8");
150 + const forgetCode = transformFixtureForget(inputRaw, basename);
151 + const noForgetCode = transformFixtureNoForget(inputRaw, basename);
152 + if (forgetCode.type === "UnexpectedError") {
153 + return {
154 + nonForgetResult: null,
155 + forgetResult: null,
156 + unexpectedError: forgetCode.value,
157 + };
158 + }
159 + if (noForgetCode.type === "UnexpectedError") {
160 + return {
161 + nonForgetResult: null,
162 + forgetResult: null,
163 + unexpectedError: noForgetCode.value,
164 + };
165 + }
166 + const nonForgetResult = doEval(noForgetCode.value);
167 + const forgetResult = doEval(forgetCode.value);
168 + return {
169 + nonForgetResult,
170 + forgetResult,
171 + unexpectedError: null,
172 + };
173 +}
compiler/forget/packages/sprout/src/runner.ts new
+127
@@ -0,0 +1,127 @@
1 +/**
2 + * Copyright (c) Meta Platforms, Inc. and affiliates.
3 + *
4 + * This source code is licensed under the MIT license found in the
5 + * LICENSE file in the root directory of this source tree.
6 + */
7 +
8 +import { TestFixture } from "fixture-test-utils";
9 +import { getFixtures, readTestFilter } from "fixture-test-utils";
10 +import { Worker } from "jest-worker";
11 +import process from "process";
12 +import * as readline from "readline";
13 +import * as RunnerWorker from "./runner-worker";
14 +import SproutOnlyFilterTodoRemove from "./SproutOnlyFilterTodoRemove";
15 +
16 +const WORKER_PATH = require.resolve("./runner-worker");
17 +readline.emitKeypressEvents(process.stdin);
18 +
19 +process.stdin.on("keypress", function (_, key) {
20 + if (key && key.name === "c" && key.ctrl) {
21 + process.exit(1);
22 + }
23 +});
24 +process.on("SIGINT", function () {
25 + // Parent process may send SIGINT
26 + process.exit(1);
27 +});
28 +
29 +process.on("SIGTERM", function () {
30 + process.exit(1);
31 +});
32 +
33 +type RunnerOptions = {
34 + useFilter: boolean;
35 + sync: boolean;
36 + useTodoFilter: boolean;
37 +};
38 +
39 +function logsEqual(a: Array<string>, b: Array<string>) {
40 + if (a.length !== b.length) {
41 + return false;
42 + }
43 + return a.every((val, idx) => val === b[idx]);
44 +}
45 +
46 +function reportResults(results: Array<[string, RunnerWorker.TestResult]>) {
47 + for (const [fixtureName, result] of results) {
48 + if (result.unexpectedError !== null) {
49 + console.log(`ERROR ${fixtureName}: ${result.unexpectedError}`);
50 + continue;
51 + }
52 + const { forgetResult, nonForgetResult } = result;
53 + if (forgetResult.kind === "UnexpectedError") {
54 + console.log(`ERROR ${fixtureName}: ${forgetResult.value}`);
55 + } else if (nonForgetResult.kind === "UnexpectedError") {
56 + console.log(`ERROR ${fixtureName}: ${nonForgetResult.value}`);
57 + } else if (
58 + forgetResult.kind !== nonForgetResult.kind ||
59 + forgetResult.value !== nonForgetResult.value ||
60 + !logsEqual(forgetResult.logs, nonForgetResult.logs)
61 + ) {
62 + console.log(
63 + `FAIL ${fixtureName}: Difference in forget and non-forget results. \nExpected result: ${JSON.stringify(
64 + forgetResult,
65 + undefined,
66 + 2
67 + )}\nFound: ${JSON.stringify(nonForgetResult, undefined, 2)}`
68 + );
69 + } else {
70 + console.log(`PASS ${fixtureName}`);
71 + }
72 + }
73 +}
74 +
75 +/**
76 + * Runs the compiler in watch or single-execution mode
77 + */
78 +export async function main(opts: RunnerOptions): Promise<void> {
79 + const worker: Worker & typeof RunnerWorker = new Worker(WORKER_PATH, {
80 + enableWorkerThreads: true,
81 + }) as any;
82 + worker.getStderr().pipe(process.stderr);
83 + worker.getStdout().pipe(process.stdout);
84 +
85 + const testFilter = opts.useFilter ? await readTestFilter() : null;
86 + let allFixtures: Map<string, TestFixture> = getFixtures(testFilter);
87 +
88 + if (opts.useTodoFilter) {
89 + allFixtures = new Map(
90 + Array.from(allFixtures.entries()).filter(([filename, _]) =>
91 + SproutOnlyFilterTodoRemove.has(filename)
92 + )
93 + );
94 + }
95 +
96 + const validFixtures = new Map();
97 + for (const [name, fixture] of allFixtures) {
98 + if (fixture.basename.startsWith("error.")) {
99 + // skip
100 + continue;
101 + }
102 + validFixtures.set(name, fixture);
103 + }
104 +
105 + const results: Array<[string, RunnerWorker.TestResult]> = [];
106 + if (!opts.sync) {
107 + const work: Array<Promise<[string, RunnerWorker.TestResult]>> = [];
108 + for (const [fixtureName, fixture] of validFixtures) {
109 + work.push(worker.run(fixture).then((result) => [fixtureName, result]));
110 + }
111 + results.push(...(await Promise.all(work)));
112 + } else {
113 + for (const [fixtureName, fixture] of validFixtures) {
114 + const result: [string, RunnerWorker.TestResult] = await RunnerWorker.run(
115 + fixture
116 + ).then((result) => [fixtureName, result]);
117 + results.push(result);
118 + }
119 + }
120 +
121 + reportResults(results);
122 + process.exit(0);
123 +}
124 +
125 +main({ useFilter: false, sync: true, useTodoFilter: true }).catch((error) =>
126 + console.error(error)
127 +);
compiler/forget/packages/sprout/tsconfig.json new
+24
@@ -0,0 +1,24 @@
1 +{
2 + "extends": "@tsconfig/node16-strictest/tsconfig.json",
3 + "compilerOptions": {
4 + "declaration": true,
5 + "outDir": "dist",
6 + "jsx": "react-jsxdev",
7 +
8 + // weaken strictness from preset
9 + "importsNotUsedAsValues": "remove",
10 + "noUncheckedIndexedAccess": false,
11 + "noUnusedParameters": false,
12 + "useUnknownInCatchVariables": false,
13 + "target": "ES2015",
14 + // ideally turn off only during dev, or on a per-file basis
15 + "noUnusedLocals": false,
16 + "sourceMap": true,
17 + "baseUrl": ".",
18 + "paths": {
19 + "fixture-test-utils": ["../packages/fixture-test-utils"]
20 + }
21 + },
22 + "exclude": ["node_modules"],
23 + "include": ["src/**/*.ts"]
24 +}
compiler/forget/yarn.lock
+150 -36
@@ -75,20 +75,20 @@
75 source-map "^0.5.0"
76
77 "@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.19.1":
78 - version "7.22.9"
79 - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.22.9.tgz#bd96492c68822198f33e8a256061da3cf391f58f"
80 - integrity sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w==
78 + version "7.22.10"
79 + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.22.10.tgz#aad442c7bcd1582252cb4576747ace35bc122f35"
80 + integrity sha512-fTmqbbUBAwCcre6zPzNngvsI0aNrPZe77AeqvDxWM9Nm+04RrJ3CAmGHA9f7lJQY6ZMhRztNemy4uslDxTX4Qw==
81 dependencies:
82 "@ampproject/remapping" "^2.2.0"
83 - "@babel/code-frame" "^7.22.5"
84 - "@babel/generator" "^7.22.9"
85 - "@babel/helper-compilation-targets" "^7.22.9"
83 + "@babel/code-frame" "^7.22.10"
84 + "@babel/generator" "^7.22.10"
85 + "@babel/helper-compilation-targets" "^7.22.10"
86 "@babel/helper-module-transforms" "^7.22.9"
87 - "@babel/helpers" "^7.22.6"
88 - "@babel/parser" "^7.22.7"
87 + "@babel/helpers" "^7.22.10"
88 + "@babel/parser" "^7.22.10"
89 "@babel/template" "^7.22.5"
90 - "@babel/traverse" "^7.22.8"
91 - "@babel/types" "^7.22.5"
90 + "@babel/traverse" "^7.22.10"
91 + "@babel/types" "^7.22.10"
92 convert-source-map "^1.7.0"
93 debug "^4.1.0"
94 gensync "^1.0.0-beta.2"
@@ -136,7 +136,7 @@
136 source-map "^0.5.0"
137 trim-right "^1.0.1"
138
139 -"@babel/generator@^7.1.3", "@babel/generator@^7.22.7", "@babel/generator@^7.22.9":
139 +"@babel/generator@^7.1.3":
140 version "7.22.9"
141 resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.9.tgz#572ecfa7a31002fa1de2a9d91621fd895da8493d"
142 integrity sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw==
@@ -638,8 +638,8 @@
638 integrity sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==
639 dependencies:
640 "@babel/template" "^7.22.5"
641 - "@babel/traverse" "^7.22.6"
642 - "@babel/types" "^7.22.5"
641 + "@babel/traverse" "^7.22.10"
642 + "@babel/types" "^7.22.10"
643
644 "@babel/highlight@^7.18.6":
645 version "7.18.6"
@@ -678,7 +678,7 @@
678 resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.19.1.tgz#6f6d6c2e621aad19a92544cc217ed13f1aac5b4c"
679 integrity sha512-h7RCSorm1DdTVGJf3P2Mhj3kdnkmF/EiysUkzS2TdgAYqyjFdMQJbVuXOBej2SBJaXan/lIVtT6KkGbyyq753A==
680
681 -"@babel/parser@^7.1.3", "@babel/parser@^7.22.5", "@babel/parser@^7.22.7":
681 +"@babel/parser@^7.1.3", "@babel/parser@^7.22.5":
682 version "7.22.7"
683 resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.7.tgz#df8cf085ce92ddbdbf668a7f186ce848c9036cae"
684 integrity sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==
@@ -1598,19 +1598,19 @@
1598 globals "^11.1.0"
1599 lodash "^4.17.10"
1600
1601 -"@babel/traverse@^7.19.0", "@babel/traverse@^7.19.1", "@babel/traverse@^7.20.5", "@babel/traverse@^7.21.2", "@babel/traverse@^7.22.1", "@babel/traverse@^7.22.6", "@babel/traverse@^7.22.8", "@babel/traverse@^7.7.2":
1602 - version "7.22.8"
1603 - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.8.tgz#4d4451d31bc34efeae01eac222b514a77aa4000e"
1604 - integrity sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==
1601 +"@babel/traverse@^7.19.0", "@babel/traverse@^7.19.1", "@babel/traverse@^7.20.5", "@babel/traverse@^7.21.2", "@babel/traverse@^7.22.1", "@babel/traverse@^7.22.10", "@babel/traverse@^7.7.2":
1602 + version "7.22.10"
1603 + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.10.tgz#20252acb240e746d27c2e82b4484f199cf8141aa"
1604 + integrity sha512-Q/urqV4pRByiNNpb/f5OSv28ZlGJiFiiTh+GAHktbIrkPhPbl90+uW6SmpoLyZqutrg9AEaEf3Q/ZBRHBXgxig==
1605 dependencies:
1606 - "@babel/code-frame" "^7.22.5"
1607 - "@babel/generator" "^7.22.7"
1606 + "@babel/code-frame" "^7.22.10"
1607 + "@babel/generator" "^7.22.10"
1608 "@babel/helper-environment-visitor" "^7.22.5"
1609 "@babel/helper-function-name" "^7.22.5"
1610 "@babel/helper-hoist-variables" "^7.22.5"
1611 "@babel/helper-split-export-declaration" "^7.22.6"
1612 - "@babel/parser" "^7.22.7"
1613 - "@babel/types" "^7.22.5"
1612 + "@babel/parser" "^7.22.10"
1613 + "@babel/types" "^7.22.10"
1614 debug "^4.1.0"
1615 globals "^11.1.0"
1616
@@ -4213,13 +4213,13 @@ browserslist@^4.14.5, browserslist@^4.21.3, browserslist@^4.21.5:
4213 update-browserslist-db "^1.0.11"
4214
4215 browserslist@^4.21.9:
4216 - version "4.21.9"
4217 - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.9.tgz#e11bdd3c313d7e2a9e87e8b4b0c7872b13897635"
4218 - integrity sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==
4216 + version "4.21.10"
4217 + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.10.tgz#dbbac576628c13d3b2231332cb2ec5a46e015bb0"
4218 + integrity sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==
4219 dependencies:
4220 - caniuse-lite "^1.0.30001503"
4221 - electron-to-chromium "^1.4.431"
4222 - node-releases "^2.0.12"
4220 + caniuse-lite "^1.0.30001517"
4221 + electron-to-chromium "^1.4.477"
4222 + node-releases "^2.0.13"
4223 update-browserslist-db "^1.0.11"
4224
4225 bs-logger@0.x:
@@ -4312,10 +4312,10 @@ caniuse-lite@^1.0.30001406, caniuse-lite@^1.0.30001464, caniuse-lite@^1.0.300014
4312 resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001492.tgz#4a06861788a52b4c81fd3344573b68cc87fe062b"
4313 integrity sha512-2efF8SAZwgAX1FJr87KWhvuJxnGJKOnctQa8xLOskAXNXq8oiuqgl6u1kk3fFpsp3GgvzlRjiK1sl63hNtFADw==
4314
4315 -caniuse-lite@^1.0.30001503:
4316 - version "1.0.30001518"
4317 - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001518.tgz#b3ca93904cb4699c01218246c4d77a71dbe97150"
4318 - integrity sha512-rup09/e3I0BKjncL+FesTayKtPrdwKhUufQFd3riFw1hHg8JmIFoInYfB102cFcY/pPgGmdyl/iy+jgiDi2vdA==
4315 +caniuse-lite@^1.0.30001517:
4316 + version "1.0.30001519"
4317 + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001519.tgz#3e7b8b8a7077e78b0eb054d69e6edf5c7df35601"
4318 + integrity sha512-0QHgqR+Jv4bxHMp8kZ1Kn8CH55OikjKJ6JmKkZYP1F3D7w+lnFXF70nG5eNfsZS89jadi5Ywy5UCSKLAglIRkg==
4319
4320 caseless@~0.12.0:
4321 version "0.12.0"
@@ -4761,6 +4761,13 @@ cssstyle@^2.3.0:
4761 dependencies:
4762 cssom "~0.3.6"
4763
4764 +cssstyle@^3.0.0:
4765 + version "3.0.0"
4766 + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-3.0.0.tgz#17ca9c87d26eac764bb8cfd00583cff21ce0277a"
4767 + integrity sha512-N4u2ABATi3Qplzf0hWbVCdjenim8F3ojEXpBDF5hBpjzW182MjNGLqfmQ0SkSPeQ+V86ZXgeH8aXj6kayd4jgg==
4768 + dependencies:
4769 + rrweb-cssom "^0.6.0"
4770 +
4771 csstype@^3.0.2:
4772 version "3.1.1"
4773 resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9"
@@ -4787,6 +4794,15 @@ data-urls@^3.0.2:
4794 whatwg-mimetype "^3.0.0"
4795 whatwg-url "^11.0.0"
4796
4797 +data-urls@^4.0.0:
4798 + version "4.0.0"
4799 + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-4.0.0.tgz#333a454eca6f9a5b7b0f1013ff89074c3f522dd4"
4800 + integrity sha512-/mMTei/JXPqvFqQtfyTowxmJVwr2PVAeCcDxyFf6LhoOu/09TX2OX3kb2wzi4DMXcfj4OItwDOnhl5oziPnT6g==
4801 + dependencies:
4802 + abab "^2.0.6"
4803 + whatwg-mimetype "^3.0.0"
4804 + whatwg-url "^12.0.0"
4805 +
4806 date-fns@^2.29.1:
4807 version "2.30.0"
4808 resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.30.0.tgz#f367e644839ff57894ec6ac480de40cae4b0f4d0"
@@ -4839,6 +4855,11 @@ decimal.js@^10.3.1:
4855 resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.1.tgz#be75eeac4a2281aace80c1a8753587c27ef053e7"
4856 integrity sha512-F29o+vci4DodHYT9UrR5IEbfBw9pE5eSapIJdTqXK5+6hq+t8VRxwQyKlW2i+KDKFkkJQRvFyI/QXD83h8LyQw==
4857
4858 +decimal.js@^10.4.3:
4859 + version "10.4.3"
4860 + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23"
4861 + integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==
4862 +
4863 decompress-response@^4.2.0:
4864 version "4.2.1"
4865 resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-4.2.1.tgz#414023cc7a302da25ce2ec82d0d5238ccafd8986"
@@ -5083,10 +5104,10 @@ electron-to-chromium@^1.4.411:
5104 resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.418.tgz#9092aca12db25acf02a2ddf9de59f0e4363c9928"
5105 integrity sha512-1KnpDTS9onwAfMzW50LcpNtyOkMyjd/OLoD2Kx/DDITZqgNYixY71XNszPHNxyQQ/Brh+FDcUnf4BaM041sdWg==
5106
5086 -electron-to-chromium@^1.4.431:
5087 - version "1.4.479"
5088 - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.479.tgz#ec9f676f23d3a0b0e429bc454d25e0b3253d2118"
5089 - integrity sha512-ABv1nHMIR8I5n3O3Een0gr6i0mfM+YcTZqjHy3pAYaOjgFG+BMquuKrSyfYf5CbEkLr9uM05RA3pOk4udNB/aQ==
5107 +electron-to-chromium@^1.4.477:
5108 + version "1.4.490"
5109 + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.490.tgz#d99286f6e915667fa18ea4554def1aa60eb4d5f1"
5110 + integrity sha512-6s7NVJz+sATdYnIwhdshx/N/9O6rvMxmhVoDSDFdj6iA45gHR8EQje70+RYsF4GeB+k0IeNSBnP7yG9ZXJFr7A==
5111
5112 elliptic@^6.5.3:
5113 version "6.5.4"
@@ -8327,6 +8348,35 @@ jsdom@^20.0.0:
8348 ws "^8.8.0"
8349 xml-name-validator "^4.0.0"
8350
8351 +jsdom@^22.1.0:
8352 + version "22.1.0"
8353 + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-22.1.0.tgz#0fca6d1a37fbeb7f4aac93d1090d782c56b611c8"
8354 + integrity sha512-/9AVW7xNbsBv6GfWho4TTNjEo9fe6Zhf9O7s0Fhhr3u+awPwAJMKwAMXnkk5vBxflqLW9hTHX/0cs+P3gW+cQw==
8355 + dependencies:
8356 + abab "^2.0.6"
8357 + cssstyle "^3.0.0"
8358 + data-urls "^4.0.0"
8359 + decimal.js "^10.4.3"
8360 + domexception "^4.0.0"
8361 + form-data "^4.0.0"
8362 + html-encoding-sniffer "^3.0.0"
8363 + http-proxy-agent "^5.0.0"
8364 + https-proxy-agent "^5.0.1"
8365 + is-potential-custom-element-name "^1.0.1"
8366 + nwsapi "^2.2.4"
8367 + parse5 "^7.1.2"
8368 + rrweb-cssom "^0.6.0"
8369 + saxes "^6.0.0"
8370 + symbol-tree "^3.2.4"
8371 + tough-cookie "^4.1.2"
8372 + w3c-xmlserializer "^4.0.0"
8373 + webidl-conversions "^7.0.0"
8374 + whatwg-encoding "^2.0.0"
8375 + whatwg-mimetype "^3.0.0"
8376 + whatwg-url "^12.0.1"
8377 + ws "^8.13.0"
8378 + xml-name-validator "^4.0.0"
8379 +
8380 jsesc@^2.5.1:
8381 version "2.5.2"
8382 resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
@@ -9038,6 +9088,11 @@ node-releases@^2.0.12:
9088 resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.12.tgz#35627cc224a23bfb06fb3380f2b3afaaa7eb1039"
9089 integrity sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==
9090
9091 +node-releases@^2.0.13:
9092 + version "2.0.13"
9093 + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.13.tgz#d5ed1627c23e3461e819b02e57b75e4899b1c81d"
9094 + integrity sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==
9095 +
9096 noop-logger@^0.1.1:
9097 version "0.1.1"
9098 resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2"
@@ -9125,6 +9180,11 @@ nwsapi@^2.2.0:
9180 resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.2.tgz#e5418863e7905df67d51ec95938d67bf801f0bb0"
9181 integrity sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==
9182
9183 +nwsapi@^2.2.4:
9184 + version "2.2.7"
9185 + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.7.tgz#738e0707d3128cb750dddcfe90e4610482df0f30"
9186 + integrity sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==
9187 +
9188 oauth-sign@~0.9.0:
9189 version "0.9.0"
9190 resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
@@ -9361,6 +9421,13 @@ parse5@^7.0.0:
9421 dependencies:
9422 entities "^4.4.0"
9423
9424 +parse5@^7.1.2:
9425 + version "7.1.2"
9426 + resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.1.2.tgz#0736bebbfd77793823240a23b7fc5e010b7f8e32"
9427 + integrity sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==
9428 + dependencies:
9429 + entities "^4.4.0"
9430 +
9431 parseqs@0.0.6:
9432 version "0.0.6"
9433 resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.6.tgz#8e4bb5a19d1cdc844a08ac974d34e273afa670d5"
@@ -9757,6 +9824,11 @@ punycode@^2.1.0, punycode@^2.1.1:
9824 resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
9825 integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
9826
9827 +punycode@^2.3.0:
9828 + version "2.3.0"
9829 + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f"
9830 + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==
9831 +
9832 pure-rand@^6.0.0:
9833 version "6.0.2"
9834 resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.0.2.tgz#a9c2ddcae9b68d736a8163036f088a2781c8b306"
@@ -10161,6 +10233,11 @@ ripemd160@^2.0.0, ripemd160@^2.0.1:
10233 hash-base "^3.0.0"
10234 inherits "^2.0.1"
10235
10236 +rrweb-cssom@^0.6.0:
10237 + version "0.6.0"
10238 + resolved "https://registry.yarnpkg.com/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz#ed298055b97cbddcdeb278f904857629dec5e0e1"
10239 + integrity sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==
10240 +
10241 run-applescript@^5.0.0:
10242 version "5.0.0"
10243 resolved "https://registry.yarnpkg.com/run-applescript/-/run-applescript-5.0.0.tgz#e11e1c932e055d5c6b40d98374e0268d9b11899c"
@@ -11089,6 +11166,16 @@ tough-cookie@^4.0.0:
11166 universalify "^0.2.0"
11167 url-parse "^1.5.3"
11168
11169 +tough-cookie@^4.1.2:
11170 + version "4.1.3"
11171 + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf"
11172 + integrity sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==
11173 + dependencies:
11174 + psl "^1.1.33"
11175 + punycode "^2.1.1"
11176 + universalify "^0.2.0"
11177 + url-parse "^1.5.3"
11178 +
11179 tough-cookie@~2.5.0:
11180 version "2.5.0"
11181 resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
@@ -11104,6 +11191,13 @@ tr46@^3.0.0:
11191 dependencies:
11192 punycode "^2.1.1"
11193
11194 +tr46@^4.1.1:
11195 + version "4.1.1"
11196 + resolved "https://registry.yarnpkg.com/tr46/-/tr46-4.1.1.tgz#281a758dcc82aeb4fe38c7dfe4d11a395aac8469"
11197 + integrity sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==
11198 + dependencies:
11199 + punycode "^2.3.0"
11200 +
11201 tree-kill@^1.2.2:
11202 version "1.2.2"
11203 resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc"
@@ -11459,6 +11553,13 @@ w3c-xmlserializer@^3.0.0:
11553 dependencies:
11554 xml-name-validator "^4.0.0"
11555
11556 +w3c-xmlserializer@^4.0.0:
11557 + version "4.0.0"
11558 + resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz#aebdc84920d806222936e3cdce408e32488a3073"
11559 + integrity sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==
11560 + dependencies:
11561 + xml-name-validator "^4.0.0"
11562 +
11563 walker@^1.0.8:
11564 version "1.0.8"
11565 resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f"
@@ -11560,6 +11661,14 @@ whatwg-url@^11.0.0:
11661 tr46 "^3.0.0"
11662 webidl-conversions "^7.0.0"
11663
11664 +whatwg-url@^12.0.0, whatwg-url@^12.0.1:
11665 + version "12.0.1"
11666 + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-12.0.1.tgz#fd7bcc71192e7c3a2a97b9a8d6b094853ed8773c"
11667 + integrity sha512-Ed/LrqB8EPlGxjS+TrsXcpUond1mhccS3pchLhzSgPCnTimUCKj3IZE75pAs5m6heB2U2TMerKFUXheyHY+VDQ==
11668 + dependencies:
11669 + tr46 "^4.1.1"
11670 + webidl-conversions "^7.0.0"
11671 +
11672 which-boxed-primitive@^1.0.2:
11673 version "1.0.2"
11674 resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"
@@ -11700,6 +11809,11 @@ ws@>=8.7.0:
11809 resolved "https://registry.yarnpkg.com/ws/-/ws-8.11.0.tgz#6a0d36b8edfd9f96d8b25683db2f8d7de6e8e143"
11810 integrity sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==
11811
11812 +ws@^8.13.0:
11813 + version "8.13.0"
11814 + resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0"
11815 + integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==
11816 +
11817 ws@^8.8.0:
11818 version "8.9.0"
11819 resolved "https://registry.yarnpkg.com/ws/-/ws-8.9.0.tgz#2a994bb67144be1b53fe2d23c53c028adeb7f45e"