diff --git a/.prettierrc.js b/.prettierrc.js index 6342f131a0..43f9b6671c 100644 --- a/.prettierrc.js +++ b/.prettierrc.js @@ -14,6 +14,12 @@ module.exports = { parser: 'flow', arrowParens: 'avoid', overrides: [ + { + files: ['*.code-workspace'], + options: { + parser: 'json-stringify', + }, + }, { files: esNextPaths, options: { diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts index 826b720300..e5a067018d 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts @@ -1668,6 +1668,15 @@ function lowerExpression( const left = lowerExpressionToTemporary(builder, leftPath); const right = lowerExpressionToTemporary(builder, expr.get("right")); const operator = expr.node.operator; + if (operator === "|>") { + builder.errors.push({ + reason: `(BuildHIR::lowerExpression) Pipe operator not supported`, + severity: ErrorSeverity.Todo, + loc: leftPath.node.loc ?? null, + suggestions: null, + }); + return { kind: "UnsupportedNode", node: exprNode, loc: exprLoc }; + } return { kind: "BinaryExpression", operator, @@ -1893,7 +1902,9 @@ function lowerExpression( ); } - const operators: { [key: string]: t.BinaryExpression["operator"] } = { + const operators: { + [key: string]: Exclude">; + } = { "+=": "+", "-=": "-", "/=": "/", @@ -2307,6 +2318,20 @@ function lowerExpression( }); return { kind: "UnsupportedNode", node: expr.node, loc: exprLoc }; } + } else if (expr.node.operator === "throw") { + builder.errors.push({ + reason: `Throw expressions are not supported`, + severity: ErrorSeverity.InvalidJS, + loc: expr.node.loc ?? null, + suggestions: [ + { + description: "Remove this line", + range: [expr.node.start!, expr.node.end!], + op: CompilerSuggestionOperation.Remove, + }, + ], + }); + return { kind: "UnsupportedNode", node: expr.node, loc: exprLoc }; } else { return { kind: "UnaryExpression", diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts index d544269869..2294335034 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts @@ -866,7 +866,7 @@ export type InstructionValue = | JSXText | { kind: "BinaryExpression"; - operator: t.BinaryExpression["operator"]; + operator: Exclude">; left: Place; right: Place; loc: SourceLocation; @@ -881,7 +881,7 @@ export type InstructionValue = | MethodCall | { kind: "UnaryExpression"; - operator: t.UnaryExpression["operator"]; + operator: Exclude; value: Place; loc: SourceLocation; } diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/visitors.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/visitors.ts index 632e665723..beda6e4a20 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/visitors.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/visitors.ts @@ -856,7 +856,7 @@ export function mapTerminalSuccessors( const block = fn(terminal.block); const fallthrough = fn(terminal.fallthrough); return { - kind: "scope", + kind: terminal.kind, scope: terminal.scope, block, fallthrough, diff --git a/compiler/packages/babel-plugin-react-compiler/src/Inference/InferReferenceEffects.ts b/compiler/packages/babel-plugin-react-compiler/src/Inference/InferReferenceEffects.ts index 619d1d90ff..ee2ad1a7de 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Inference/InferReferenceEffects.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Inference/InferReferenceEffects.ts @@ -201,7 +201,7 @@ export default function inferReferenceEffects( let queuedState = queuedStates.get(blockId); if (queuedState != null) { // merge the queued states for this block - state = queuedState.merge(state) ?? state; + state = queuedState.merge(state) ?? queuedState; queuedStates.set(blockId, state); } else { /* @@ -765,7 +765,7 @@ class InferenceState { result.values[id] = { kind, value: printMixedHIR(value) }; } for (const [variable, values] of this.#variables) { - result.variables[variable] = [...values].map(identify); + result.variables[`$${variable}`] = [...values].map(identify); } return result; } diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/phi-reference-effects.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/phi-reference-effects.expect.md new file mode 100644 index 0000000000..bef1d7b836 --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/phi-reference-effects.expect.md @@ -0,0 +1,61 @@ + +## Input + +```javascript +import { arrayPush } from "shared-runtime"; + +function Foo(cond) { + let x = null; + if (cond) { + x = []; + } else { + } + // Here, x = phi(x$null, x$[]) should receive a ValueKind of Mutable + arrayPush(x, 2); + + return x; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Foo, + params: [{ cond: true }], + sequentialRenders: [{ cond: true }, { cond: true }], +}; + +``` + +## Code + +```javascript +import { c as _c } from "react/compiler-runtime"; +import { arrayPush } from "shared-runtime"; + +function Foo(cond) { + const $ = _c(2); + let x; + if ($[0] !== cond) { + x = null; + if (cond) { + x = []; + } + + arrayPush(x, 2); + $[0] = cond; + $[1] = x; + } else { + x = $[1]; + } + return x; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Foo, + params: [{ cond: true }], + sequentialRenders: [{ cond: true }, { cond: true }], +}; + +``` + +### Eval output +(kind: ok) [2] +[2] \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/phi-reference-effects.ts b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/phi-reference-effects.ts new file mode 100644 index 0000000000..092791d586 --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/phi-reference-effects.ts @@ -0,0 +1,19 @@ +import { arrayPush } from "shared-runtime"; + +function Foo(cond) { + let x = null; + if (cond) { + x = []; + } else { + } + // Here, x = phi(x$null, x$[]) should receive a ValueKind of Mutable + arrayPush(x, 2); + + return x; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Foo, + params: [{ cond: true }], + sequentialRenders: [{ cond: true }, { cond: true }], +}; diff --git a/fixtures/flight-esm/yarn.lock b/fixtures/flight-esm/yarn.lock index a00d5c244d..8d336e5194 100644 --- a/fixtures/flight-esm/yarn.lock +++ b/fixtures/flight-esm/yarn.lock @@ -79,11 +79,11 @@ brace-expansion@^1.1.7: concat-map "0.0.1" braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== dependencies: - fill-range "^7.0.1" + fill-range "^7.1.1" browserslist@^4.18.1: version "4.21.7" @@ -265,10 +265,10 @@ escalade@^3.1.1: resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== dependencies: to-regex-range "^5.0.1" diff --git a/packages/react-devtools-core/src/standalone.js b/packages/react-devtools-core/src/standalone.js index e4e4ada1c3..541efa0d37 100644 --- a/packages/react-devtools-core/src/standalone.js +++ b/packages/react-devtools-core/src/standalone.js @@ -280,6 +280,7 @@ function initialize(socket: WebSocket) { store = new Store(bridge, { checkBridgeProtocolCompatibility: true, supportsTraceUpdates: true, + supportsClickToInspect: true, }); log('Connected'); diff --git a/packages/react-devtools-extensions/src/main/index.js b/packages/react-devtools-extensions/src/main/index.js index e1db3d5055..5422567db7 100644 --- a/packages/react-devtools-extensions/src/main/index.js +++ b/packages/react-devtools-extensions/src/main/index.js @@ -97,7 +97,8 @@ function createBridgeAndStore() { // At this time, the timeline can only parse Chrome performance profiles. supportsTimeline: __IS_CHROME__, supportsTraceUpdates: true, - supportsNativeInspection: true, + supportsInspectMatchingDOMElement: true, + supportsClickToInspect: true, }); if (!isProfiling) { diff --git a/packages/react-devtools-fusebox/src/frontend.js b/packages/react-devtools-fusebox/src/frontend.js index 976b8693d3..d55241fec7 100644 --- a/packages/react-devtools-fusebox/src/frontend.js +++ b/packages/react-devtools-fusebox/src/frontend.js @@ -37,6 +37,7 @@ export function createStore(bridge: FrontendBridge, config?: Config): Store { return new Store(bridge, { checkBridgeProtocolCompatibility: true, supportsTraceUpdates: true, + supportsClickToInspect: true, ...config, }); } diff --git a/packages/react-devtools-shared/src/devtools/store.js b/packages/react-devtools-shared/src/devtools/store.js index 408151dcdb..ef6f720346 100644 --- a/packages/react-devtools-shared/src/devtools/store.js +++ b/packages/react-devtools-shared/src/devtools/store.js @@ -71,7 +71,8 @@ type ErrorAndWarningTuples = Array<{id: number, index: number}>; export type Config = { checkBridgeProtocolCompatibility?: boolean, isProfiling?: boolean, - supportsNativeInspection?: boolean, + supportsInspectMatchingDOMElement?: boolean, + supportsClickToInspect?: boolean, supportsReloadAndProfile?: boolean, supportsTimeline?: boolean, supportsTraceUpdates?: boolean, @@ -172,7 +173,8 @@ export default class Store extends EventEmitter<{ _rootIDToRendererID: Map = new Map(); // These options may be initially set by a configuration option when constructing the Store. - _supportsNativeInspection: boolean = false; + _supportsInspectMatchingDOMElement: boolean = false; + _supportsClickToInspect: boolean = false; _supportsReloadAndProfile: boolean = false; _supportsTimeline: boolean = false; _supportsTraceUpdates: boolean = false; @@ -211,13 +213,17 @@ export default class Store extends EventEmitter<{ isProfiling = config.isProfiling === true; const { - supportsNativeInspection, + supportsInspectMatchingDOMElement, + supportsClickToInspect, supportsReloadAndProfile, supportsTimeline, supportsTraceUpdates, } = config; - if (supportsNativeInspection) { - this._supportsNativeInspection = true; + if (supportsInspectMatchingDOMElement) { + this._supportsInspectMatchingDOMElement = true; + } + if (supportsClickToInspect) { + this._supportsClickToInspect = true; } if (supportsReloadAndProfile) { this._supportsReloadAndProfile = true; @@ -437,8 +443,12 @@ export default class Store extends EventEmitter<{ return this._rootSupportsTimelineProfiling; } - get supportsNativeInspection(): boolean { - return this._supportsNativeInspection; + get supportsInspectMatchingDOMElement(): boolean { + return this._supportsInspectMatchingDOMElement; + } + + get supportsClickToInspect(): boolean { + return this._supportsClickToInspect; } get supportsNativeStyleEditor(): boolean { diff --git a/packages/react-devtools-shared/src/devtools/views/Components/InspectedElement.js b/packages/react-devtools-shared/src/devtools/views/Components/InspectedElement.js index 8688b132cb..1f1f538b6b 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/InspectedElement.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/InspectedElement.js @@ -296,7 +296,7 @@ export default function InspectedElementWrapper(_: Props): React.Node { )} - {store.supportsNativeInspection && ( + {store.supportsInspectMatchingDOMElement && (