diff --git a/compiler/packages/babel-plugin-react-forget/src/HIR/BuildHIR.ts b/compiler/packages/babel-plugin-react-forget/src/HIR/BuildHIR.ts index fb2dc78d5f..1ec3d31a5a 100644 --- a/compiler/packages/babel-plugin-react-forget/src/HIR/BuildHIR.ts +++ b/compiler/packages/babel-plugin-react-forget/src/HIR/BuildHIR.ts @@ -1277,6 +1277,23 @@ function lowerStatement( } } +function lowerObjectMethod( + builder: HIRBuilder, + property: NodePath +): InstructionValue { + const loc = property.node.loc ?? GeneratedSource; + const loweredFunc = lowerFunction(builder, property); + if (!loweredFunc) { + return { kind: "UnsupportedNode", node: property.node, loc: loc }; + } + + return { + kind: "ObjectMethod", + loc, + loweredFunc, + }; +} + function lowerObjectPropertyKey( builder: HIRBuilder, key: t.PrivateName | t.Expression @@ -1379,6 +1396,22 @@ function lowerExpression( kind: "Spread", place, }); + } else if (propertyPath.isObjectMethod()) { + const method = lowerObjectMethod(builder, propertyPath); + const place = lowerValueToTemporary(builder, method); + const loweredKey = lowerObjectPropertyKey( + builder, + propertyPath.node.key + ); + if (!loweredKey) { + continue; + } + properties.push({ + kind: "ObjectProperty", + type: "method", + place, + key: loweredKey, + }); } else { builder.errors.push({ reason: `(BuildHIR::lowerExpression) Handle ${propertyPath.type} properties in ObjectExpression`, diff --git a/compiler/packages/babel-plugin-react-forget/src/HIR/FindContextIdentifiers.ts b/compiler/packages/babel-plugin-react-forget/src/HIR/FindContextIdentifiers.ts index 6496c02579..cd3304f40c 100644 --- a/compiler/packages/babel-plugin-react-forget/src/HIR/FindContextIdentifiers.ts +++ b/compiler/packages/babel-plugin-react-forget/src/HIR/FindContextIdentifiers.ts @@ -9,6 +9,7 @@ type FindContextIdentifierState = { | NodePath | NodePath | NodePath + | NodePath >; reassigned: Set; referenced: Set; @@ -75,6 +76,12 @@ export function findContextIdentifiers( const left = path.get("left"); handleAssignment(state.reassigned, left); }, + ObjectMethod( + fn: NodePath, + state: FindContextIdentifierState + ): void { + state.currentLambda.push(fn); + }, Identifier( path: NodePath, state: FindContextIdentifierState @@ -93,7 +100,8 @@ function handleIdentifier( currentLambda: | NodePath | NodePath - | NodePath, + | NodePath + | NodePath, referenced: Set, path: NodePath ): void { diff --git a/compiler/packages/babel-plugin-react-forget/src/HIR/HIR.ts b/compiler/packages/babel-plugin-react-forget/src/HIR/HIR.ts index 5821cf1f4d..6f824624fc 100644 --- a/compiler/packages/babel-plugin-react-forget/src/HIR/HIR.ts +++ b/compiler/packages/babel-plugin-react-forget/src/HIR/HIR.ts @@ -732,6 +732,7 @@ export type InstructionValue = properties: Array; loc: SourceLocation; } + | ObjectMethod | ArrayExpression | { kind: "JsxFragment"; children: Array; loc: SourceLocation } | { diff --git a/compiler/packages/babel-plugin-react-forget/src/HIR/MergeConsecutiveBlocks.ts b/compiler/packages/babel-plugin-react-forget/src/HIR/MergeConsecutiveBlocks.ts index 2c1f955e74..666346c289 100644 --- a/compiler/packages/babel-plugin-react-forget/src/HIR/MergeConsecutiveBlocks.ts +++ b/compiler/packages/babel-plugin-react-forget/src/HIR/MergeConsecutiveBlocks.ts @@ -32,7 +32,10 @@ export function mergeConsecutiveBlocks(fn: HIRFunction): void { const merged = new MergedBlocks(); for (const [, block] of fn.body.blocks) { for (const instr of block.instructions) { - if (instr.value.kind === "FunctionExpression") { + if ( + instr.value.kind === "FunctionExpression" || + instr.value.kind === "ObjectMethod" + ) { mergeConsecutiveBlocks(instr.value.loweredFunc.func); } } diff --git a/compiler/packages/babel-plugin-react-forget/src/HIR/PrintHIR.ts b/compiler/packages/babel-plugin-react-forget/src/HIR/PrintHIR.ts index dbd494ec75..08e9ebbb73 100644 --- a/compiler/packages/babel-plugin-react-forget/src/HIR/PrintHIR.ts +++ b/compiler/packages/babel-plugin-react-forget/src/HIR/PrintHIR.ts @@ -462,6 +462,7 @@ export function printInstructionValue(instrValue: ReactiveValue): string { )}]`; break; } + case "ObjectMethod": case "FunctionExpression": { const fn = printFunction(instrValue.loweredFunc.func) .split("\n") diff --git a/compiler/packages/babel-plugin-react-forget/src/HIR/visitors.ts b/compiler/packages/babel-plugin-react-forget/src/HIR/visitors.ts index 3b29f62d82..92a0a1b083 100644 --- a/compiler/packages/babel-plugin-react-forget/src/HIR/visitors.ts +++ b/compiler/packages/babel-plugin-react-forget/src/HIR/visitors.ts @@ -169,6 +169,7 @@ export function* eachInstructionValueOperand( } break; } + case "ObjectMethod": case "FunctionExpression": { yield* instrValue.loweredFunc.dependencies; break; @@ -456,6 +457,7 @@ export function mapInstructionOperands( instrValue.children = instrValue.children.map((e) => fn(e)); break; } + case "ObjectMethod": case "FunctionExpression": { instrValue.loweredFunc.dependencies = instrValue.loweredFunc.dependencies.map((d) => fn(d)); diff --git a/compiler/packages/babel-plugin-react-forget/src/Inference/AnalyseFunctions.ts b/compiler/packages/babel-plugin-react-forget/src/Inference/AnalyseFunctions.ts index 0c232a135a..44bf51bcb0 100644 --- a/compiler/packages/babel-plugin-react-forget/src/Inference/AnalyseFunctions.ts +++ b/compiler/packages/babel-plugin-react-forget/src/Inference/AnalyseFunctions.ts @@ -8,12 +8,12 @@ import { CompilerError } from "../CompilerError"; import { Effect, - FunctionExpression, HIRFunction, Identifier, isRefValueType, isSetStateType, isUseRefType, + LoweredFunction, Place, ReactiveScopeDependency, } from "../HIR"; @@ -70,9 +70,10 @@ export default function analyseFunctions(func: HIRFunction): void { for (const [_, block] of func.body.blocks) { for (const instr of block.instructions) { switch (instr.value.kind) { + case "ObjectMethod": case "FunctionExpression": { lower(instr.value.loweredFunc.func); - infer(instr.value, state, func.context); + infer(instr.value.loweredFunc, state, func.context); break; } case "PropertyLoad": { @@ -113,12 +114,12 @@ function lower(func: HIRFunction): void { } function infer( - value: FunctionExpression, + loweredFunc: LoweredFunction, state: IdentifierState, context: Place[] ): void { const mutations = new Map(); - for (const operand of value.loweredFunc.func.context) { + for (const operand of loweredFunc.func.context) { if ( isMutatedOrReassigned(operand.identifier) && operand.identifier.name !== null @@ -128,7 +129,7 @@ function infer( operand.identifier.mutableRange.end = operand.identifier.mutableRange.start; } - for (const dep of value.loweredFunc.dependencies) { + for (const dep of loweredFunc.dependencies) { let name: string | null = null; if (state.properties.has(dep.identifier)) { @@ -174,7 +175,7 @@ function infer( const effect = mutations.get(place.identifier.name); if (effect !== undefined) { place.effect = effect === Effect.Unknown ? Effect.Capture : effect; - value.loweredFunc.dependencies.push(place); + loweredFunc.dependencies.push(place); } } } diff --git a/compiler/packages/babel-plugin-react-forget/src/Inference/InferReferenceEffects.ts b/compiler/packages/babel-plugin-react-forget/src/Inference/InferReferenceEffects.ts index 3d1cafae50..57d2b0808d 100644 --- a/compiler/packages/babel-plugin-react-forget/src/Inference/InferReferenceEffects.ts +++ b/compiler/packages/babel-plugin-react-forget/src/Inference/InferReferenceEffects.ts @@ -714,6 +714,7 @@ function inferBlock( valueKind = ValueKind.Immutable; break; } + case "ObjectMethod": case "FunctionExpression": { let hasMutableOperand = false; for (const operand of eachInstructionOperand(instr)) { diff --git a/compiler/packages/babel-plugin-react-forget/src/Optimization/ConstantPropagation.ts b/compiler/packages/babel-plugin-react-forget/src/Optimization/ConstantPropagation.ts index c692e8633e..378e3a2824 100644 --- a/compiler/packages/babel-plugin-react-forget/src/Optimization/ConstantPropagation.ts +++ b/compiler/packages/babel-plugin-react-forget/src/Optimization/ConstantPropagation.ts @@ -106,7 +106,10 @@ function applyConstantPropagation( const functionDependencies = new Set(); for (const [, block] of fn.body.blocks) { for (const instr of block.instructions) { - if (instr.value.kind === "FunctionExpression") { + if ( + instr.value.kind === "FunctionExpression" || + instr.value.kind === "ObjectMethod" + ) { for (const operand of instr.value.loweredFunc.dependencies) { functionDependencies.add(operand.identifier.id); } diff --git a/compiler/packages/babel-plugin-react-forget/src/Optimization/DeadCodeElimination.ts b/compiler/packages/babel-plugin-react-forget/src/Optimization/DeadCodeElimination.ts index 8931ca4250..af6ad7d2c5 100644 --- a/compiler/packages/babel-plugin-react-forget/src/Optimization/DeadCodeElimination.ts +++ b/compiler/packages/babel-plugin-react-forget/src/Optimization/DeadCodeElimination.ts @@ -234,6 +234,7 @@ function pruneableValue(value: InstructionValue, state: State): boolean { case "ArrayExpression": case "BinaryExpression": case "ComputedLoad": + case "ObjectMethod": case "FunctionExpression": case "LoadLocal": case "JsxExpression": diff --git a/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/CodegenReactiveFunction.ts b/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/CodegenReactiveFunction.ts index f4338ad1a8..a9cac6ae46 100644 --- a/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/CodegenReactiveFunction.ts +++ b/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/CodegenReactiveFunction.ts @@ -16,6 +16,7 @@ import { IdentifierId, InstructionKind, JsxAttribute, + ObjectMethod, ObjectPropertyKey, Pattern, Place, @@ -118,6 +119,8 @@ class Context { #declarations: Set = new Set(); temp: Temporaries = new Map(); errors: CompilerError = new CompilerError(); + objectMethods: Map = new Map(); + constructor(env: Environment, fnName: string) { this.env = env; this.fnName = fnName; @@ -707,6 +710,14 @@ function codegenInstructionNullable( } } else if (instr.value.kind === "Debugger") { return t.debuggerStatement(); + } else if (instr.value.kind === "ObjectMethod") { + CompilerError.invariant(instr.lvalue, { + reason: "Expected object methods to have a temp lvalue", + loc: null, + suggestions: null, + }); + cx.objectMethods.set(instr.lvalue.identifier.id, instr.value); + return null; } else { const value = codegenInstructionValue(cx, instr.value); const statement = codegenInstruction(cx, instr, value); @@ -969,15 +980,54 @@ function codegenInstructionValue( for (const property of instrValue.properties) { if (property.kind === "ObjectProperty") { const key = codegenObjectPropertyKey(property.key); - const value = codegenPlace(cx, property.place); - properties.push( - t.objectProperty( - key, - value, - false, - value.type === "Identifier" && value.name === property.key.name - ) - ); + + switch (property.type) { + case "property": { + const value = codegenPlace(cx, property.place); + properties.push( + t.objectProperty( + key, + value, + false, + value.type === "Identifier" && + value.name === property.key.name + ) + ); + break; + } + case "method": { + const method = cx.objectMethods.get(property.place.identifier.id); + CompilerError.invariant(method, { + reason: "Expected ObjectMethod instruction", + loc: null, + suggestions: null, + }); + const loweredFunc = method.loweredFunc; + const reactiveFunction = buildReactiveFunction(loweredFunc.func); + pruneUnusedLabels(reactiveFunction); + pruneUnusedLValues(reactiveFunction); + renameVariables(reactiveFunction); + const fn = codegenReactiveFunction(reactiveFunction).unwrap(); + + properties.push( + t.objectMethod( + "method", + key, + fn.params, + fn.body, + false, + fn.generator, + fn.async + ) + ); + break; + } + default: + assertExhaustive( + property.type, + `Unexpected property type: ${property.type}` + ); + } } else { properties.push(t.spreadElement(codegenPlace(cx, property.place))); } @@ -1296,6 +1346,7 @@ function codegenInstructionValue( case "DeclareContext": case "Destructure": case "StoreLocal": + case "ObjectMethod": case "StoreContext": { CompilerError.invariant(false, { reason: `Unexpected ${instrValue.kind} in codegenInstructionValue`, diff --git a/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/InferReactiveScopeVariables.ts b/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/InferReactiveScopeVariables.ts index 88914bfc94..317d4d151a 100644 --- a/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/InferReactiveScopeVariables.ts +++ b/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/InferReactiveScopeVariables.ts @@ -264,6 +264,7 @@ function mayAllocate(env: Environment, instruction: Instruction): boolean { case "NewExpression": case "ObjectExpression": case "UnsupportedNode": + case "ObjectMethod": case "FunctionExpression": case "TaggedTemplateExpression": { return true; diff --git a/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/PruneNonEscapingScopes.ts b/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/PruneNonEscapingScopes.ts index 76ab5f9e79..3242489ad6 100644 --- a/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/PruneNonEscapingScopes.ts +++ b/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/PruneNonEscapingScopes.ts @@ -661,6 +661,7 @@ function computeMemoizationInputs( }; } case "RegExpLiteral": + case "ObjectMethod": case "FunctionExpression": case "TaggedTemplateExpression": case "ArrayExpression": diff --git a/compiler/packages/babel-plugin-react-forget/src/SSA/EliminateRedundantPhi.ts b/compiler/packages/babel-plugin-react-forget/src/SSA/EliminateRedundantPhi.ts index b6ccc436a1..77c434e0b2 100644 --- a/compiler/packages/babel-plugin-react-forget/src/SSA/EliminateRedundantPhi.ts +++ b/compiler/packages/babel-plugin-react-forget/src/SSA/EliminateRedundantPhi.ts @@ -106,7 +106,10 @@ export function eliminateRedundantPhi( rewritePlace(place, rewrites); } - if (instr.value.kind === "FunctionExpression") { + if ( + instr.value.kind === "FunctionExpression" || + instr.value.kind === "ObjectMethod" + ) { const { context } = instr.value.loweredFunc.func; for (const place of context) { rewritePlace(place, rewrites); diff --git a/compiler/packages/babel-plugin-react-forget/src/SSA/EnterSSA.ts b/compiler/packages/babel-plugin-react-forget/src/SSA/EnterSSA.ts index 918d1faa36..c53f0c081c 100644 --- a/compiler/packages/babel-plugin-react-forget/src/SSA/EnterSSA.ts +++ b/compiler/packages/babel-plugin-react-forget/src/SSA/EnterSSA.ts @@ -275,7 +275,10 @@ function enterSSAImpl( mapInstructionOperands(instr, (place) => builder.getPlace(place)); mapInstructionLValues(instr, (lvalue) => builder.definePlace(lvalue)); - if (instr.value.kind === "FunctionExpression") { + if ( + instr.value.kind === "FunctionExpression" || + instr.value.kind === "ObjectMethod" + ) { const loweredFunc = instr.value.loweredFunc.func; const entry = loweredFunc.body.blocks.get(loweredFunc.body.entry)!; CompilerError.invariant(entry.preds.size === 0, { diff --git a/compiler/packages/babel-plugin-react-forget/src/TypeInference/InferTypes.ts b/compiler/packages/babel-plugin-react-forget/src/TypeInference/InferTypes.ts index 33233b5c5f..4970819b0e 100644 --- a/compiler/packages/babel-plugin-react-forget/src/TypeInference/InferTypes.ts +++ b/compiler/packages/babel-plugin-react-forget/src/TypeInference/InferTypes.ts @@ -255,6 +255,7 @@ function* generateInstructionTypes( break; } + case "ObjectMethod": case "FunctionExpression": { yield* generate(value.loweredFunc.func); break; diff --git a/compiler/packages/babel-plugin-react-forget/src/Validation/ValidateFrozenLambdas.ts b/compiler/packages/babel-plugin-react-forget/src/Validation/ValidateFrozenLambdas.ts index 86fb89f9f3..9b23caaa5b 100644 --- a/compiler/packages/babel-plugin-react-forget/src/Validation/ValidateFrozenLambdas.ts +++ b/compiler/packages/babel-plugin-react-forget/src/Validation/ValidateFrozenLambdas.ts @@ -15,6 +15,7 @@ import { FunctionExpression, HIRFunction, IdentifierId, + ObjectMethod, Place, isRefValueType, isUseRefType, @@ -66,6 +67,7 @@ export function validateFrozenLambdas(fn: HIRFunction): void { } for (const instr of block.instructions) { switch (instr.value.kind) { + case "ObjectMethod": case "FunctionExpression": { if ( instr.value.loweredFunc.dependencies.some( @@ -119,7 +121,7 @@ export function validateFrozenLambdas(fn: HIRFunction): void { } class State { - lambdas: Map = new Map(); + lambdas: Map = new Map(); temporaries: Map = new Map(); } @@ -132,9 +134,13 @@ function validateOperand( state.temporaries.get(operand.identifier.id) ?? operand.identifier.id; const lambda = state.lambdas.get(operandId); if (lambda !== undefined) { - // TODO: these seem to always be null, we should try to preserve original names from source + // TODO: these seem to always be null, we should try to preserve original + // names from source + // TODO: figure out how to print object methods as they don't have names const description = - lambda.name !== null && operand.identifier.name !== null + lambda.kind === "FunctionExpression" && + lambda.name !== null && + operand.identifier.name !== null ? `\`${lambda.name}\` is a function that may mutate \`${operand.identifier.name}\`. If you must mutate \`${operand.identifier.name}\` try using a React API like useState and use its setter function instead` : null; return new CompilerErrorDetail({ diff --git a/compiler/packages/babel-plugin-react-forget/src/Validation/ValidateNoRefAccesInRender.ts b/compiler/packages/babel-plugin-react-forget/src/Validation/ValidateNoRefAccesInRender.ts index 7bcdebb9f2..2603fa4157 100644 --- a/compiler/packages/babel-plugin-react-forget/src/Validation/ValidateNoRefAccesInRender.ts +++ b/compiler/packages/babel-plugin-react-forget/src/Validation/ValidateNoRefAccesInRender.ts @@ -59,6 +59,7 @@ export function validateNoRefAccessInRender(fn: HIRFunction): void { } break; } + case "ObjectMethod": case "FunctionExpression": { // functions are allowed to capture refs, so long as the function is not called // during render. see AnalyzeFunctions for how we ensure that functions which diff --git a/compiler/packages/babel-plugin-react-forget/src/Validation/ValidateNoSetStateInRender.ts b/compiler/packages/babel-plugin-react-forget/src/Validation/ValidateNoSetStateInRender.ts index 945250af72..f1d648b9fe 100644 --- a/compiler/packages/babel-plugin-react-forget/src/Validation/ValidateNoSetStateInRender.ts +++ b/compiler/packages/babel-plugin-react-forget/src/Validation/ValidateNoSetStateInRender.ts @@ -36,6 +36,7 @@ export function validateNoSetStateInRender( if (unconditionalBlocks.has(block.id)) { for (const instr of block.instructions) { switch (instr.value.kind) { + case "ObjectMethod": case "FunctionExpression": { /** * TODO: setState's return value is considered Frozen, so the lambda's mutable range diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-kitchensink.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-kitchensink.expect.md index 6397a4f9e1..97a579e90b 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-kitchensink.expect.md +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-kitchensink.expect.md @@ -83,8 +83,6 @@ let moduleLocal = false; [ReactForget] Todo: (BuildHIR::lowerStatement) Handle ClassDeclaration statements (5:10) -[ReactForget] Todo: (BuildHIR::lowerExpression) Handle ObjectMethod properties in ObjectExpression (12:12) - [ReactForget] Todo: (BuildHIR::lowerStatement) Handle non-variable initialization in ForStatement (20:22) [ReactForget] Todo: (BuildHIR::lowerStatement) Handle non-variable initialization in ForStatement (23:25) diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/object-shorthand-method-1.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/object-shorthand-method-1.expect.md new file mode 100644 index 0000000000..6f1ecd5ea7 --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/object-shorthand-method-1.expect.md @@ -0,0 +1,74 @@ + +## Input + +```javascript +function Component({ a, b }) { + return { + x: function () { + return [a]; + }, + y() { + return [b]; + }, + }; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ x: 1 }, { a: 2 }, { b: 2 }], +}; + +``` + +## Code + +```javascript +import { unstable_useMemoCache as useMemoCache } from "react"; +function Component(t16) { + const $ = useMemoCache(7); + const { a, b } = t16; + const c_0 = $[0] !== a; + let t0; + if (c_0) { + t0 = function () { + return [a]; + }; + $[0] = a; + $[1] = t0; + } else { + t0 = $[1]; + } + const c_2 = $[2] !== b; + let t1; + if (c_2) { + $[2] = b; + $[3] = t1; + } else { + t1 = $[3]; + } + const c_4 = $[4] !== t0; + const c_5 = $[5] !== t1; + let t2; + if (c_4 || c_5) { + t2 = { + x: t0, + y() { + return [b]; + }, + }; + $[4] = t0; + $[5] = t1; + $[6] = t2; + } else { + t2 = $[6]; + } + return t2; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ x: 1 }, { a: 2 }, { b: 2 }], +}; + +``` + \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/object-shorthand-method-1.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/object-shorthand-method-1.js new file mode 100644 index 0000000000..b43d5e1cb5 --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/object-shorthand-method-1.js @@ -0,0 +1,15 @@ +function Component({ a, b }) { + return { + x: function () { + return [a]; + }, + y() { + return [b]; + }, + }; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ x: 1 }, { a: 2 }, { b: 2 }], +}; diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/object-shorthand-method-2.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/object-shorthand-method-2.expect.md new file mode 100644 index 0000000000..359aa634c9 --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/object-shorthand-method-2.expect.md @@ -0,0 +1,83 @@ + +## Input + +```javascript +function Component({ a, b, c }) { + return { + x: [a], + y() { + return [b]; + }, + z: { c }, + }; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ x: 1 }, { a: 2 }, { b: 2 }], +}; + +``` + +## Code + +```javascript +import { unstable_useMemoCache as useMemoCache } from "react"; +function Component(t16) { + const $ = useMemoCache(10); + const { a, b, c } = t16; + const c_0 = $[0] !== a; + let t0; + if (c_0) { + t0 = [a]; + $[0] = a; + $[1] = t0; + } else { + t0 = $[1]; + } + const c_2 = $[2] !== b; + let t1; + if (c_2) { + $[2] = b; + $[3] = t1; + } else { + t1 = $[3]; + } + const c_4 = $[4] !== c; + let t2; + if (c_4) { + t2 = { c }; + $[4] = c; + $[5] = t2; + } else { + t2 = $[5]; + } + const c_6 = $[6] !== t0; + const c_7 = $[7] !== t1; + const c_8 = $[8] !== t2; + let t3; + if (c_6 || c_7 || c_8) { + t3 = { + x: t0, + y() { + return [b]; + }, + z: t2, + }; + $[6] = t0; + $[7] = t1; + $[8] = t2; + $[9] = t3; + } else { + t3 = $[9]; + } + return t3; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ x: 1 }, { a: 2 }, { b: 2 }], +}; + +``` + \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/object-shorthand-method-2.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/object-shorthand-method-2.js new file mode 100644 index 0000000000..cda1368f71 --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/object-shorthand-method-2.js @@ -0,0 +1,14 @@ +function Component({ a, b, c }) { + return { + x: [a], + y() { + return [b]; + }, + z: { c }, + }; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ x: 1 }, { a: 2 }, { b: 2 }], +};