From 674722a9734ae2ee5d750e4bd4f6c769470a7a52 Mon Sep 17 00:00:00 2001 From: GrinZero <774933704@qq.com> Date: Mon, 1 Jul 2024 20:46:08 +0800 Subject: [PATCH] feat: use coditionHelper --- .../src/Entrypoint/Imports.ts | 34 ++++++++++++------ .../src/Entrypoint/Pipeline.ts | 6 +++- .../src/Entrypoint/Program.ts | 5 ++- .../src/HIR/Environment.ts | 5 ++- .../ReactiveScopes/CodegenReactiveFunction.ts | 33 +++++++++-------- .../react-compiler-runtime/src/index.ts | 35 +++++++++++++++++++ 6 files changed, 91 insertions(+), 27 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..09208a00d6c6f 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Imports.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Imports.ts @@ -100,7 +100,8 @@ function hasExistingNonNamespacedImportOfModule( function addMemoCacheFunctionSpecifierToExistingImport( program: NodePath, moduleName: string, - identifierName: string + identifierName: string, + reactiveFnHelperIdentifierName: string ): boolean { let didInsertUseMemoCache = false; program.traverse({ @@ -109,10 +110,13 @@ function addMemoCacheFunctionSpecifierToExistingImport( !didInsertUseMemoCache && isNonNamespacedImport(importDeclPath, moduleName) ) { - importDeclPath.pushContainer( - "specifiers", - t.importSpecifier(t.identifier(identifierName), t.identifier("c")) - ); + importDeclPath.pushContainer("specifiers", [ + t.importSpecifier(t.identifier(identifierName), t.identifier("c")), + t.importSpecifier( + t.identifier(reactiveFnHelperIdentifierName), + t.identifier("u") + ), + ]); didInsertUseMemoCache = true; } }, @@ -123,7 +127,8 @@ function addMemoCacheFunctionSpecifierToExistingImport( export function updateMemoCacheFunctionImport( program: NodePath, moduleName: string, - useMemoCacheIdentifier: string + useMemoCacheIdentifier: string, + reactiveFnHelperIdentifier: string ): void { /* * If there isn't already an import of * as React, insert it so useMemoCache doesn't @@ -138,7 +143,8 @@ export function updateMemoCacheFunctionImport( const didUpdateImport = addMemoCacheFunctionSpecifierToExistingImport( program, moduleName, - useMemoCacheIdentifier + useMemoCacheIdentifier, + reactiveFnHelperIdentifier ); if (!didUpdateImport) { throw new Error( @@ -149,7 +155,8 @@ export function updateMemoCacheFunctionImport( addMemoCacheFunctionImportDeclaration( program, moduleName, - useMemoCacheIdentifier + useMemoCacheIdentifier, + reactiveFnHelperIdentifier ); } } @@ -157,12 +164,19 @@ export function updateMemoCacheFunctionImport( function addMemoCacheFunctionImportDeclaration( program: NodePath, moduleName: string, - localName: string + localName: string, + reactiveFnHelperIdentifierName: string ): void { program.unshiftContainer( "body", t.importDeclaration( - [t.importSpecifier(t.identifier(localName), t.identifier("c"))], + [ + t.importSpecifier(t.identifier(localName), t.identifier("c")), + t.importSpecifier( + t.identifier(reactiveFnHelperIdentifierName), + t.identifier("u") + ), + ], t.stringLiteral(moduleName) ) ); diff --git a/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Pipeline.ts b/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Pipeline.ts index 762f1a4112ab0..f4da51dfa6a69 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Pipeline.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Pipeline.ts @@ -111,6 +111,7 @@ export function* run( config: EnvironmentConfig, fnType: ReactFunctionType, useMemoCacheIdentifier: string, + reactiveFnHelperIdentifier: string, logger: Logger | null, filename: string | null, code: string | null @@ -123,7 +124,8 @@ export function* run( logger, filename, code, - useMemoCacheIdentifier + useMemoCacheIdentifier, + reactiveFnHelperIdentifier ); yield { kind: "debug", @@ -499,6 +501,7 @@ export function compileFn( config: EnvironmentConfig, fnType: ReactFunctionType, useMemoCacheIdentifier: string, + reactiveFnHelperIdentifier: string, logger: Logger | null, filename: string | null, code: string | null @@ -508,6 +511,7 @@ export function compileFn( config, fnType, useMemoCacheIdentifier, + reactiveFnHelperIdentifier, logger, filename, code diff --git a/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Program.ts b/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Program.ts index adee97238b2b7..f630465f10144 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Program.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Program.ts @@ -248,6 +248,7 @@ export function compileProgram( const environment = parseEnvironmentConfig(pass.opts.environment ?? {}); const useMemoCacheIdentifier = program.scope.generateUidIdentifier("c"); + const reactiveFnHelperIdentifier = program.scope.generateUidIdentifier("u"); const moduleName = pass.opts.runtimeModule ?? "react/compiler-runtime"; if (hasMemoCacheFunctionImport(program, moduleName)) { return; @@ -318,6 +319,7 @@ export function compileProgram( config, fnType, useMemoCacheIdentifier.name, + reactiveFnHelperIdentifier.name, pass.opts.logger, pass.filename, pass.code @@ -463,7 +465,8 @@ export function compileProgram( updateMemoCacheFunctionImport( program, moduleName, - useMemoCacheIdentifier.name + useMemoCacheIdentifier.name, + reactiveFnHelperIdentifier.name ); } addImportsToProgram(program, externalFunctions); diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts index 277921d5e25ee..0a0cd7ea5041a 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts @@ -510,6 +510,7 @@ export class Environment { config: EnvironmentConfig; fnType: ReactFunctionType; useMemoCacheIdentifier: string; + reactiveFnHelperIdentifier: string; #contextIdentifiers: Set; #hoistedIdentifiers: Set; @@ -521,7 +522,8 @@ export class Environment { logger: Logger | null, filename: string | null, code: string | null, - useMemoCacheIdentifier: string + useMemoCacheIdentifier: string, + reactiveFnHelperIdentifier: string ) { this.fnType = fnType; this.config = config; @@ -529,6 +531,7 @@ export class Environment { this.code = code; this.logger = logger; this.useMemoCacheIdentifier = useMemoCacheIdentifier; + this.reactiveFnHelperIdentifier = reactiveFnHelperIdentifier; this.#shapes = new Map(DEFAULT_SHAPES); this.#globals = new Map(DEFAULT_GLOBALS); 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 e4fe710b256d4..53f4abc1ef24c 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/CodegenReactiveFunction.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/CodegenReactiveFunction.ts @@ -161,12 +161,15 @@ export function codegenFunction( t.identifier(index), t.logicalExpression( "||", - t.callExpression(t.identifier("u"), [ - t.identifier(cx.synthesizeName("$")), - t.arrayExpression([]), - t.arrayExpression([]), - t.arrayExpression([]), - ]), + t.callExpression( + t.identifier(fn.env.reactiveFnHelperIdentifier), + [ + t.identifier(cx.synthesizeName("$")), + t.arrayExpression([]), + t.arrayExpression([]), + t.arrayExpression([]), + ] + ), t.memberExpression( t.identifier(cx.synthesizeName("$")), t.numericLiteral(fastRefreshState.cacheIndex), @@ -486,15 +489,15 @@ function codegenReactiveScope( // #region taking if (count === 1) { - const indices: t.NumericLiteral[] = []; - const newValues: t.Expression[] = []; + const conditionIndexs: t.NumericLiteral[] = []; + const conditionTargets: t.Expression[] = []; const updateIndexs: t.NumericLiteral[] = []; const source: (t.Expression | null | undefined)[] = []; for (const dep of scope.dependencies) { const index = cx.nextCacheIndex; - indices.push(t.numericLiteral(index)); - newValues.push(codegenDependency(cx, dep)); + conditionIndexs.push(t.numericLiteral(index)); + conditionTargets.push(codegenDependency(cx, dep)); const comparison = t.binaryExpression( "!==", t.memberExpression( @@ -510,8 +513,8 @@ function codegenReactiveScope( } const arr: t.Identifier[] = []; - const index = cx.nextCacheIndex; for (const [, { identifier }] of scope.declarations) { + const index = cx.nextCacheIndex; const name = convertIdentifier(identifier); arr.push(name); cacheLoads.push({ name, index, value: wrapCacheDep(cx, name) }); @@ -596,14 +599,16 @@ function codegenReactiveScope( t.arrayPattern(arr), t.logicalExpression( "||", - t.callExpression(t.identifier("u"), [ + t.callExpression(t.identifier(cx.env.reactiveFnHelperIdentifier), [ t.identifier(cx.synthesizeName("$")), t.arrowFunctionExpression( [], t.arrayExpression(bd as t.Expression[]) ), - t.arrayExpression(indices), - testCondition ? t.arrayExpression(newValues) : t.nullLiteral(), + t.arrayExpression(conditionIndexs), + testCondition + ? t.arrayExpression(conditionTargets) + : t.nullLiteral(), t.arrayExpression(updateIndexs), t.arrowFunctionExpression( [], diff --git a/compiler/packages/react-compiler-runtime/src/index.ts b/compiler/packages/react-compiler-runtime/src/index.ts index 6975c19411557..75a41c65bcf33 100644 --- a/compiler/packages/react-compiler-runtime/src/index.ts +++ b/compiler/packages/react-compiler-runtime/src/index.ts @@ -44,6 +44,41 @@ export function $read(memoCache: MemoCache, index: number) { return value; } +export function u( + cache: any[], + getSource: () => any[], + conditionIndexs: number[], + conditionTargets: any[] | null, + updateIndexs: number[], + updateTargets: () => any[] +) { + const test = + conditionTargets === null + ? (i: number) => cache[conditionIndexs[i]] === $empty + : (i: number) => cache[conditionIndexs[i]] !== conditionTargets[i]; + const condition = (() => { + for (let i = 0; i < conditionIndexs.length; i++) { + if (test(i)) { + return true; + } + } + return false; + })(); + + if (!condition) { + return null; + } + + const source = getSource(); + const updateList = [...updateTargets(), ...source]; + for (let i = 0; i < updateIndexs.length; i++) { + cache[updateIndexs[i]] = updateList[updateIndexs[i]]; + } + + return source; +} + + const LazyGuardDispatcher: { [key: string]: (...args: Array) => any } = {}; [ "readContext",