From 689ff4fe6deebcfc0213cea332b589eeb3584f7f Mon Sep 17 00:00:00 2001 From: GrinZero <774933704@qq.com> Date: Fri, 28 Jun 2024 09:12:45 +0800 Subject: [PATCH] feat: save code --- .../src/Entrypoint/Imports.ts | 2 + .../ReactiveScopes/CodegenReactiveFunction.ts | 226 +++++++++++++----- 2 files changed, 170 insertions(+), 58 deletions(-) diff --git a/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Imports.ts b/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Imports.ts index 7fc42b8d73780..6d7c21e053d39 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Imports.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Imports.ts @@ -17,6 +17,8 @@ export function addImportsToProgram( ): void { const identifiers: Set = new Set(); const sortedImports: Map> = new Map(); + + console.log('importList',importList) for (const { importSpecifierName, source } of importList) { /* * Codegen currently does not rename import specifiers, so we do additional diff --git a/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/CodegenReactiveFunction.ts b/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/CodegenReactiveFunction.ts index 809f773ebda37..0060c42aff769 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/CodegenReactiveFunction.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/CodegenReactiveFunction.ts @@ -156,65 +156,86 @@ export function codegenFunction( // HMR detection is enabled, emit code to reset the memo cache on source changes const index = cx.synthesizeName("$i"); preface.push( - t.ifStatement( - t.binaryExpression( - "!==", - t.memberExpression( - t.identifier(cx.synthesizeName("$")), - t.numericLiteral(fastRefreshState.cacheIndex), - true - ), - t.stringLiteral(fastRefreshState.hash) - ), - t.blockStatement([ - t.forStatement( - t.variableDeclaration("let", [ - t.variableDeclarator(t.identifier(index), t.numericLiteral(0)), + t.variableDeclaration("const", [ + t.variableDeclarator( + t.identifier(index), + t.logicalExpression( + "||", + t.callExpression(t.identifier("u"), [ + t.identifier(cx.synthesizeName("$")), + t.arrayExpression([]), + t.arrayExpression([]), + t.arrayExpression([]), ]), - t.binaryExpression( - "<", - t.identifier(index), - t.numericLiteral(cacheCount) - ), - t.assignmentExpression( - "+=", - t.identifier(index), - t.numericLiteral(1) - ), - t.blockStatement([ - t.expressionStatement( - t.assignmentExpression( - "=", - t.memberExpression( - t.identifier(cx.synthesizeName("$")), - t.identifier(index), - true - ), - t.callExpression( - t.memberExpression( - t.identifier("Symbol"), - t.identifier("for") - ), - [t.stringLiteral(MEMO_CACHE_SENTINEL)] - ) - ) - ), - ]) - ), - t.expressionStatement( - t.assignmentExpression( - "=", - t.memberExpression( - t.identifier(cx.synthesizeName("$")), - t.numericLiteral(fastRefreshState.cacheIndex), - true - ), - t.stringLiteral(fastRefreshState.hash) + t.memberExpression( + t.identifier(cx.synthesizeName("$")), + t.numericLiteral(fastRefreshState.cacheIndex), + true ) - ), - ]) - ) + ) + ), + ]) ); + // preface.push( + // t.ifStatement( + // t.binaryExpression( + // "!==", + // t.memberExpression( + // t.identifier(cx.synthesizeName("$")), + // t.numericLiteral(fastRefreshState.cacheIndex), + // true + // ), + // t.stringLiteral(fastRefreshState.hash) + // ), + // t.blockStatement([ + // t.forStatement( + // t.variableDeclaration("let", [ + // t.variableDeclarator(t.identifier(index), t.numericLiteral(0)), + // ]), + // t.binaryExpression( + // "<", + // t.identifier(index), + // t.numericLiteral(cacheCount) + // ), + // t.assignmentExpression( + // "+=", + // t.identifier(index), + // t.numericLiteral(1) + // ), + // t.blockStatement([ + // t.expressionStatement( + // t.assignmentExpression( + // "=", + // t.memberExpression( + // t.identifier(cx.synthesizeName("$")), + // t.identifier(index), + // true + // ), + // t.callExpression( + // t.memberExpression( + // t.identifier("Symbol"), + // t.identifier("for") + // ), + // [t.stringLiteral(MEMO_CACHE_SENTINEL)] + // ) + // ) + // ), + // ]) + // ), + // t.expressionStatement( + // t.assignmentExpression( + // "=", + // t.memberExpression( + // t.identifier(cx.synthesizeName("$")), + // t.numericLiteral(fastRefreshState.cacheIndex), + // true + // ), + // t.stringLiteral(fastRefreshState.hash) + // ) + // ), + // ]) + // ) + // ); } compiled.body.body.unshift(...preface); } @@ -274,7 +295,7 @@ function codegenReactiveFunction( } const params = fn.params.map((param) => convertParameter(param)); - const body: t.BlockStatement = codegenBlock(cx, fn.body); + const body: t.BlockStatement = codegenBlock(cx, fn.body); // 生成块 body.directives = fn.directives.map((d) => t.directive(t.directiveLiteral(d)) ); @@ -291,6 +312,7 @@ function codegenReactiveFunction( } const countMemoBlockVisitor = new CountMemoBlockVisitor(fn.env); + visitReactiveFunction(fn, countMemoBlockVisitor, undefined); return Ok({ @@ -400,6 +422,7 @@ class Context { function codegenBlock(cx: Context, block: ReactiveBlock): t.BlockStatement { const temp = new Map(cx.temp); const result = codegenBlockNoReset(cx, block); + /* * Check that the block only added new temporaries and did not update the * value of any existing temporary @@ -431,9 +454,11 @@ function codegenBlockNoReset( block: ReactiveBlock ): t.BlockStatement { const statements: Array = []; + //TODO: hack to generate for (const item of block) { switch (item.kind) { case "instruction": { + // like a = b + c const statement = codegenInstructionNullable(cx, item.instruction); if (statement !== null) { statements.push(statement); @@ -446,12 +471,14 @@ function codegenBlockNoReset( break; } case "scope": { + // like if, for, while const temp = new Map(cx.temp); codegenReactiveScope(cx, statements, item.scope, item.instructions); cx.temp = temp; break; } case "terminal": { + // like break, continue, return const statement = codegenTerminal(cx, item.terminal); if (statement === null) { break; @@ -498,6 +525,7 @@ function wrapCacheDep(cx: Context, value: t.Expression): t.Expression { } } +const count: 0 | 1 = 1; function codegenReactiveScope( cx: Context, statements: Array, @@ -514,6 +542,77 @@ function codegenReactiveScope( const changeExpressions: Array = []; const changeExpressionComments: Array = []; const outputComments: Array = []; + + // #region taking + + if (count === 1) { + const indices: t.NumericLiteral[] = []; + const newValues: t.Expression[] = []; + const todo: (t.Expression | null | undefined)[] = []; + + for (const dep of scope.dependencies) { + const index = cx.nextCacheIndex; + indices.push(t.numericLiteral(index)); + newValues.push(codegenDependency(cx, dep)); + + todo.push(codegenDependency(cx, dep)); + } + + const arr: t.Identifier[] = []; + const index = cx.nextCacheIndex; + for (const [, { identifier }] of scope.declarations) { + const name = convertIdentifier(identifier); + arr.push(name); + cacheLoads.push({ name, index, value: wrapCacheDep(cx, name) }); + } + for (const reassignment of scope.reassignments) { + const index = cx.nextCacheIndex; + const name = convertIdentifier(reassignment); + cacheLoads.push({ name, index, value: wrapCacheDep(cx, name) }); + } + // qucik + let computationBlock = codegenBlock(cx, block); + + const [variableDeclaration] = computationBlock.body; + if ("declarations" in variableDeclaration) { + todo.push(...variableDeclaration.declarations.map((item) => item.init)); + } + + const back: t.MemberExpression[] = []; + for (const { index, value } of cacheLoads) { + todo.push(value); + back.push( + t.memberExpression( + t.identifier(cx.synthesizeName("$")), + t.numericLiteral(index), + true + ) + ); + } + + const elements = t.variableDeclaration("const", [ + t.variableDeclarator( + t.arrayPattern(arr), + t.logicalExpression( + "||", + t.callExpression(t.identifier("u"), [ + t.identifier(cx.synthesizeName("$")), + t.arrayExpression(indices), + t.arrayExpression(newValues), + t.arrayExpression( + todo.slice(0, -1).filter(Boolean) as t.Expression[] + ), + ]), + t.arrayExpression(back) + ) + ), + ]); + + statements.push(elements); + return; + } + // #endregion + for (const dep of scope.dependencies) { const index = cx.nextCacheIndex; changeExpressionComments.push(printDependencyComment(dep)); @@ -556,6 +655,7 @@ function codegenReactiveScope( ) ); } + let firstOutputIndex: number | null = null; for (const [, { identifier }] of scope.declarations) { const index = cx.nextCacheIndex; @@ -574,6 +674,7 @@ function codegenReactiveScope( const name = convertIdentifier(identifier); outputComments.push(name.name); + // !!! const t4 if (!cx.hasDeclared(identifier)) { statements.push( t.variableDeclaration("let", [t.variableDeclarator(name)]) @@ -637,8 +738,8 @@ function codegenReactiveScope( t.booleanLiteral(true) ); } - let computationBlock = codegenBlock(cx, block); + let computationBlock = codegenBlock(cx, block); let memoStatement; if ( cx.env.config.enableChangeDetectionForDebugging != null && @@ -749,6 +850,7 @@ function codegenReactiveScope( ); } computationBlock.body.push(...cacheStoreStatements); + memoStatement = t.ifStatement( testCondition, computationBlock, @@ -820,6 +922,11 @@ function codegenReactiveScope( ); const name: ValidIdentifierName = earlyReturnValue.value.name.value; statements.push( + /** + * if (name !== Symbol.for("EARLY_RETURN_SENTINEL")) { + * return name; + * } + */ t.ifStatement( t.binaryExpression( "!==", @@ -1119,6 +1226,7 @@ function codegenInstructionNullable( cx: Context, instr: ReactiveInstruction ): t.Statement | null { + // TODO: know if ( instr.value.kind === "StoreLocal" || instr.value.kind === "StoreContext" || @@ -1176,6 +1284,7 @@ function codegenInstructionNullable( } value = codegenPlaceToExpression(cx, instr.value.value); } + switch (kind) { case InstructionKind.Const: { CompilerError.invariant(instr.lvalue === null, { @@ -1294,6 +1403,7 @@ function codegenForInit( instruction, })) ).body; + const declarators: Array = []; let kind: "let" | "const" = "const"; body.forEach((instr) => {