perf: improve VNode creation performance with compiler hints (#3334)

This commit is contained in:
HcySunYang
2021-06-23 07:15:20 +08:00
committed by Evan You
parent 31abdc8ada
commit ceff89905b
42 changed files with 1130 additions and 685 deletions

View File

@@ -5,13 +5,12 @@ import {
CREATE_SLOTS,
RENDER_LIST,
OPEN_BLOCK,
CREATE_BLOCK,
FRAGMENT,
CREATE_VNODE,
WITH_DIRECTIVES
} from './runtimeHelpers'
import { PropsExpression } from './transforms/transformElement'
import { ImportItem, TransformContext } from './transform'
import { getVNodeBlockHelper, getVNodeHelper } from './utils'
// Vue template is a platform-agnostic superset of HTML (syntax only).
// More namespaces like SVG and MathML are declared by platform specific
@@ -293,6 +292,7 @@ export interface VNodeCall extends Node {
directives: DirectiveArguments | undefined
isBlock: boolean
disableTracking: boolean
isComponent: boolean
}
// JS Node Types ---------------------------------------------------------------
@@ -560,14 +560,15 @@ export function createVNodeCall(
directives?: VNodeCall['directives'],
isBlock: VNodeCall['isBlock'] = false,
disableTracking: VNodeCall['disableTracking'] = false,
isComponent: VNodeCall['isComponent'] = false,
loc = locStub
): VNodeCall {
if (context) {
if (isBlock) {
context.helper(OPEN_BLOCK)
context.helper(CREATE_BLOCK)
context.helper(getVNodeBlockHelper(context.inSSR, isComponent))
} else {
context.helper(CREATE_VNODE)
context.helper(getVNodeHelper(context.inSSR, isComponent))
}
if (directives) {
context.helper(WITH_DIRECTIVES)
@@ -584,6 +585,7 @@ export function createVNodeCall(
directives,
isBlock,
disableTracking,
isComponent,
loc
}
}

View File

@@ -30,6 +30,8 @@ import { SourceMapGenerator, RawSourceMap } from 'source-map'
import {
advancePositionWithMutation,
assert,
getVNodeBlockHelper,
getVNodeHelper,
isSimpleIdentifier,
toValidAssetId
} from './utils'
@@ -47,7 +49,7 @@ import {
POP_SCOPE_ID,
WITH_SCOPE_ID,
WITH_DIRECTIVES,
CREATE_BLOCK,
CREATE_ELEMENT_VNODE,
OPEN_BLOCK,
CREATE_STATIC,
WITH_CTX,
@@ -96,7 +98,8 @@ function createCodegenContext(
runtimeGlobalName = `Vue`,
runtimeModuleName = `vue`,
ssr = false,
isTS = false
isTS = false,
inSSR = false
}: CodegenOptions
): CodegenContext {
const context: CodegenContext = {
@@ -110,6 +113,7 @@ function createCodegenContext(
runtimeModuleName,
ssr,
isTS,
inSSR,
source: ast.loc.source,
code: ``,
column: 1,
@@ -218,7 +222,6 @@ export function generate(
} else {
genFunctionPreamble(ast, preambleContext)
}
// enter render function
const functionName = ssr ? `ssrRender` : `render`
const args = ssr ? ['_ctx', '_push', '_parent', '_attrs'] : ['_ctx', '_cache']
@@ -355,6 +358,7 @@ function genFunctionPreamble(ast: RootNode, context: CodegenContext) {
if (ast.hoists.length) {
const staticHelpers = [
CREATE_VNODE,
CREATE_ELEMENT_VNODE,
CREATE_COMMENT,
CREATE_TEXT,
CREATE_STATIC
@@ -754,7 +758,8 @@ function genVNodeCall(node: VNodeCall, context: CodegenContext) {
dynamicProps,
directives,
isBlock,
disableTracking
disableTracking,
isComponent
} = node
if (directives) {
push(helper(WITH_DIRECTIVES) + `(`)
@@ -765,7 +770,10 @@ function genVNodeCall(node: VNodeCall, context: CodegenContext) {
if (pure) {
push(PURE_ANNOTATION)
}
push(helper(isBlock ? CREATE_BLOCK : CREATE_VNODE) + `(`, node)
const callHelper: symbol = isBlock
? getVNodeBlockHelper(context.inSSR, isComponent)
: getVNodeHelper(context.inSSR, isComponent)
push(helper(callHelper) + `(`, node)
genNodeList(
genNullableArgs([tag, props, children, patchFlag, dynamicProps]),
context

View File

@@ -122,11 +122,25 @@ interface SharedTransformCodegenOptions {
*/
prefixIdentifiers?: boolean
/**
* Generate SSR-optimized render functions instead.
* Control whether generate SSR-optimized render functions instead.
* The resulting function must be attached to the component via the
* `ssrRender` option instead of `render`.
*
* When compiler generates code for SSR's fallback branch, we need to set it to false:
* - context.ssr = false
*
* see `subTransform` in `ssrTransformCompoent.ts`
*/
ssr?: boolean
/**
* Indicates whether the compiler generates code for SSR,
* it is always true when generating code for SSR,
* regardless of whether we are generating code for SSR's fallback branch,
* this means that when the compiler generates code for SSR's fallback branch:
* - context.ssr = false
* - context.inSSR = true
*/
inSSR?: boolean
/**
* Optional binding metadata analyzed from script - used to optimize
* binding access when `prefixIdentifiers` is enabled.

View File

@@ -5,7 +5,9 @@ export const KEEP_ALIVE = Symbol(__DEV__ ? `KeepAlive` : ``)
export const BASE_TRANSITION = Symbol(__DEV__ ? `BaseTransition` : ``)
export const OPEN_BLOCK = Symbol(__DEV__ ? `openBlock` : ``)
export const CREATE_BLOCK = Symbol(__DEV__ ? `createBlock` : ``)
export const CREATE_ELEMENT_BLOCK = Symbol(__DEV__ ? `createElementBlock` : ``)
export const CREATE_VNODE = Symbol(__DEV__ ? `createVNode` : ``)
export const CREATE_ELEMENT_VNODE = Symbol(__DEV__ ? `createElementVNode` : ``)
export const CREATE_COMMENT = Symbol(__DEV__ ? `createCommentVNode` : ``)
export const CREATE_TEXT = Symbol(__DEV__ ? `createTextVNode` : ``)
export const CREATE_STATIC = Symbol(__DEV__ ? `createStaticVNode` : ``)
@@ -21,6 +23,10 @@ export const RENDER_SLOT = Symbol(__DEV__ ? `renderSlot` : ``)
export const CREATE_SLOTS = Symbol(__DEV__ ? `createSlots` : ``)
export const TO_DISPLAY_STRING = Symbol(__DEV__ ? `toDisplayString` : ``)
export const MERGE_PROPS = Symbol(__DEV__ ? `mergeProps` : ``)
export const NORMALIZE_CLASS = Symbol(__DEV__ ? `normalizeClass` : ``)
export const NORMALIZE_STYLE = Symbol(__DEV__ ? `normalizeStyle` : ``)
export const NORMALIZE_PROPS = Symbol(__DEV__ ? `normalizeProps` : ``)
export const GUARD_REACTIVE_PROPS = Symbol(__DEV__ ? `guardReactiveProps` : ``)
export const TO_HANDLERS = Symbol(__DEV__ ? `toHandlers` : ``)
export const CAMELIZE = Symbol(__DEV__ ? `camelize` : ``)
export const CAPITALIZE = Symbol(__DEV__ ? `capitalize` : ``)
@@ -44,7 +50,9 @@ export const helperNameMap: any = {
[BASE_TRANSITION]: `BaseTransition`,
[OPEN_BLOCK]: `openBlock`,
[CREATE_BLOCK]: `createBlock`,
[CREATE_ELEMENT_BLOCK]: `createElementBlock`,
[CREATE_VNODE]: `createVNode`,
[CREATE_ELEMENT_VNODE]: `createElementVNode`,
[CREATE_COMMENT]: `createCommentVNode`,
[CREATE_TEXT]: `createTextVNode`,
[CREATE_STATIC]: `createStaticVNode`,
@@ -58,6 +66,10 @@ export const helperNameMap: any = {
[CREATE_SLOTS]: `createSlots`,
[TO_DISPLAY_STRING]: `toDisplayString`,
[MERGE_PROPS]: `mergeProps`,
[NORMALIZE_CLASS]: `normalizeClass`,
[NORMALIZE_STYLE]: `normalizeStyle`,
[NORMALIZE_PROPS]: `normalizeProps`,
[GUARD_REACTIVE_PROPS]: `guardReactiveProps`,
[TO_HANDLERS]: `toHandlers`,
[CAMELIZE]: `camelize`,
[CAPITALIZE]: `capitalize`,

View File

@@ -33,12 +33,10 @@ import {
TO_DISPLAY_STRING,
FRAGMENT,
helperNameMap,
CREATE_BLOCK,
CREATE_COMMENT,
OPEN_BLOCK,
CREATE_VNODE
OPEN_BLOCK
} from './runtimeHelpers'
import { isVSlot } from './utils'
import { getVNodeBlockHelper, getVNodeHelper, isVSlot } from './utils'
import { hoistStatic, isSingleElementRoot } from './transforms/hoistStatic'
import { CompilerCompatOptions } from './compat/compatConfig'
@@ -139,6 +137,7 @@ export function createTransformContext(
scopeId = null,
slotted = true,
ssr = false,
inSSR = false,
ssrCssVars = ``,
bindingMetadata = EMPTY_OBJ,
inline = false,
@@ -164,6 +163,7 @@ export function createTransformContext(
scopeId,
slotted,
ssr,
inSSR,
ssrCssVars,
bindingMetadata,
inline,
@@ -346,10 +346,10 @@ function createRootCodegen(root: RootNode, context: TransformContext) {
const codegenNode = child.codegenNode
if (codegenNode.type === NodeTypes.VNODE_CALL) {
if (!codegenNode.isBlock) {
removeHelper(CREATE_VNODE)
codegenNode.isBlock = true
removeHelper(getVNodeHelper(context.inSSR, codegenNode.isComponent))
helper(OPEN_BLOCK)
helper(CREATE_BLOCK)
helper(getVNodeBlockHelper(context.inSSR, codegenNode.isComponent))
}
}
root.codegenNode = codegenNode
@@ -380,7 +380,9 @@ function createRootCodegen(root: RootNode, context: TransformContext) {
patchFlag + (__DEV__ ? ` /* ${patchFlagText} */` : ``),
undefined,
undefined,
true
true,
undefined,
false /* isComponent */
)
} else {
// no children = noop. codegen will return null.

View File

@@ -9,12 +9,20 @@ import {
ComponentNode,
TemplateNode,
VNodeCall,
ParentNode
ParentNode,
JSChildNode,
CallExpression
} from '../ast'
import { TransformContext } from '../transform'
import { PatchFlags, isString, isSymbol } from '@vue/shared'
import { isSlotOutlet } from '../utils'
import { CREATE_BLOCK, CREATE_VNODE, OPEN_BLOCK } from '../runtimeHelpers'
import { getVNodeBlockHelper, getVNodeHelper, isSlotOutlet } from '../utils'
import {
OPEN_BLOCK,
GUARD_REACTIVE_PROPS,
NORMALIZE_CLASS,
NORMALIZE_PROPS,
NORMALIZE_STYLE
} from '../runtimeHelpers'
export function hoistStatic(root: RootNode, context: TransformContext) {
walk(
@@ -213,9 +221,11 @@ export function getConstantType(
// nested updates.
if (codegenNode.isBlock) {
context.removeHelper(OPEN_BLOCK)
context.removeHelper(CREATE_BLOCK)
context.removeHelper(
getVNodeBlockHelper(context.inSSR, codegenNode.isComponent)
)
codegenNode.isBlock = false
context.helper(CREATE_VNODE)
context.helper(getVNodeHelper(context.inSSR, codegenNode.isComponent))
}
constantCache.set(node, returnType)
@@ -260,6 +270,33 @@ export function getConstantType(
}
}
const allowHoistedHelperSet = new Set([
NORMALIZE_CLASS,
NORMALIZE_STYLE,
NORMALIZE_PROPS,
GUARD_REACTIVE_PROPS
])
function getConstantTypeOfHelperCall(
value: CallExpression,
context: TransformContext
): ConstantTypes {
if (
value.type === NodeTypes.JS_CALL_EXPRESSION &&
!isString(value.callee) &&
allowHoistedHelperSet.has(value.callee)
) {
const arg = value.arguments[0] as JSChildNode
if (arg.type === NodeTypes.SIMPLE_EXPRESSION) {
return getConstantType(arg, context)
} else if (arg.type === NodeTypes.JS_CALL_EXPRESSION) {
// in the case of nested helper call, e.g. `normalizeProps(guardReactiveProps(exp))`
return getConstantTypeOfHelperCall(arg, context)
}
}
return ConstantTypes.NOT_CONSTANT
}
function getGeneratedPropsConstantType(
node: PlainElementNode,
context: TransformContext
@@ -278,6 +315,12 @@ function getGeneratedPropsConstantType(
returnType = keyType
}
if (value.type !== NodeTypes.SIMPLE_EXPRESSION) {
// some helper calls can be hoisted,
// such as the `normalizeProps` generated by the compiler for pre-normalize class,
// in this case we need to respect the ConstanType of the helper's argments
if (value.type === NodeTypes.JS_CALL_EXPRESSION) {
return getConstantTypeOfHelperCall(value, context)
}
return ConstantTypes.NOT_CONSTANT
}
const valueType = getConstantType(value, context)

View File

@@ -37,11 +37,15 @@ import {
RESOLVE_COMPONENT,
RESOLVE_DYNAMIC_COMPONENT,
MERGE_PROPS,
NORMALIZE_CLASS,
NORMALIZE_STYLE,
NORMALIZE_PROPS,
TO_HANDLERS,
TELEPORT,
KEEP_ALIVE,
SUSPENSE,
UNREF
UNREF,
GUARD_REACTIVE_PROPS
} from '../runtimeHelpers'
import {
getInnerRange,
@@ -226,6 +230,7 @@ export const transformElement: NodeTransform = (node, context) => {
vnodeDirectives,
!!shouldUseBlock,
false /* disableTracking */,
isComponent,
node.loc
)
}
@@ -418,15 +423,25 @@ export function buildProps(
// skip if the prop is a cached handler or has constant value
return
}
if (name === 'ref') {
hasRef = true
} else if (name === 'class' && !isComponent) {
} else if (name === 'class') {
hasClassBinding = true
} else if (name === 'style' && !isComponent) {
} else if (name === 'style') {
hasStyleBinding = true
} else if (name !== 'key' && !dynamicPropNames.includes(name)) {
dynamicPropNames.push(name)
}
// treat the dynamic class and style binding of the component as dynamic props
if (
isComponent &&
(name === 'class' || name === 'style') &&
!dynamicPropNames.includes(name)
) {
dynamicPropNames.push(name)
}
} else {
hasDynamicKeys = true
}
@@ -657,10 +672,10 @@ export function buildProps(
if (hasDynamicKeys) {
patchFlag |= PatchFlags.FULL_PROPS
} else {
if (hasClassBinding) {
if (hasClassBinding && !isComponent) {
patchFlag |= PatchFlags.CLASS
}
if (hasStyleBinding) {
if (hasStyleBinding && !isComponent) {
patchFlag |= PatchFlags.STYLE
}
if (dynamicPropNames.length) {
@@ -677,6 +692,72 @@ export function buildProps(
patchFlag |= PatchFlags.NEED_PATCH
}
// pre-normalize props, SSR is skipped for now
if (!context.inSSR && propsExpression) {
switch (propsExpression.type) {
case NodeTypes.JS_OBJECT_EXPRESSION:
// means that there is no v-bind,
// but still need to deal with dynamic key binding
let classKeyIndex = -1
let styleKeyIndex = -1
let dynamicKeyIndex = -1
for (let i = 0; i < propsExpression.properties.length; i++) {
const p = propsExpression.properties[i]
if (p.key.type !== NodeTypes.SIMPLE_EXPRESSION) continue
if (!isStaticExp(p.key)) dynamicKeyIndex = i
if (isStaticExp(p.key) && p.key.content === 'class') classKeyIndex = i
if (isStaticExp(p.key) && p.key.content === 'style') styleKeyIndex = i
}
const classProp = propsExpression.properties[classKeyIndex]
const styleProp = propsExpression.properties[styleKeyIndex]
// no dynamic key
if (dynamicKeyIndex === -1) {
if (classProp && !isStaticExp(classProp.value)) {
classProp.value = createCallExpression(
context.helper(NORMALIZE_CLASS),
[classProp.value]
)
}
if (
styleProp &&
!isStaticExp(styleProp.value) &&
// the static style is compiled into an object,
// so use `hasStyleBinding` to ensure that it is a dynamic style binding
hasStyleBinding
) {
styleProp.value = createCallExpression(
context.helper(NORMALIZE_STYLE),
[styleProp.value]
)
}
} else {
// dynamic key binding, wrap with `normalizeProps`
propsExpression = createCallExpression(
context.helper(NORMALIZE_PROPS),
[propsExpression]
)
}
break
case NodeTypes.JS_CALL_EXPRESSION:
// mergeProps call, do nothing
break
default:
// single v-bind
propsExpression = createCallExpression(
context.helper(NORMALIZE_PROPS),
[
createCallExpression(context.helper(GUARD_REACTIVE_PROPS), [
propsExpression
])
]
)
break
}
}
return {
props: propsExpression,
directives: runtimeDirectives,

View File

@@ -32,15 +32,11 @@ import {
findProp,
isTemplateNode,
isSlotOutlet,
injectProp
injectProp,
getVNodeBlockHelper,
getVNodeHelper
} from '../utils'
import {
RENDER_LIST,
OPEN_BLOCK,
CREATE_BLOCK,
FRAGMENT,
CREATE_VNODE
} from '../runtimeHelpers'
import { RENDER_LIST, OPEN_BLOCK, FRAGMENT } from '../runtimeHelpers'
import { processExpression } from './transformExpression'
import { validateBrowserExpression } from '../validateExpression'
import { PatchFlags, PatchFlagNames } from '@vue/shared'
@@ -85,6 +81,7 @@ export const transformFor = createStructuralDirectiveTransform(
: keyProp
? PatchFlags.KEYED_FRAGMENT
: PatchFlags.UNKEYED_FRAGMENT
forNode.codegenNode = createVNodeCall(
context,
helper(FRAGMENT),
@@ -96,6 +93,7 @@ export const transformFor = createStructuralDirectiveTransform(
undefined,
true /* isBlock */,
!isStableFragment /* disableTracking */,
false /* isComponent */,
node.loc
) as ForCodegenNode
@@ -156,7 +154,9 @@ export const transformFor = createStructuralDirectiveTransform(
: ``),
undefined,
undefined,
true
true,
undefined,
false /* isComponent */
)
} else {
// Normal element v-for. Directly use the child's codegenNode
@@ -170,18 +170,22 @@ export const transformFor = createStructuralDirectiveTransform(
if (childBlock.isBlock) {
// switch from block to vnode
removeHelper(OPEN_BLOCK)
removeHelper(CREATE_BLOCK)
removeHelper(
getVNodeBlockHelper(context.inSSR, childBlock.isComponent)
)
} else {
// switch from vnode to block
removeHelper(CREATE_VNODE)
removeHelper(
getVNodeHelper(context.inSSR, childBlock.isComponent)
)
}
}
childBlock.isBlock = !isStableFragment
if (childBlock.isBlock) {
helper(OPEN_BLOCK)
helper(CREATE_BLOCK)
helper(getVNodeBlockHelper(context.inSSR, childBlock.isComponent))
} else {
helper(CREATE_VNODE)
helper(getVNodeHelper(context.inSSR, childBlock.isComponent))
}
}

View File

@@ -27,14 +27,15 @@ import {
import { createCompilerError, ErrorCodes } from '../errors'
import { processExpression } from './transformExpression'
import { validateBrowserExpression } from '../validateExpression'
import { FRAGMENT, CREATE_COMMENT, OPEN_BLOCK } from '../runtimeHelpers'
import {
CREATE_BLOCK,
FRAGMENT,
CREATE_COMMENT,
OPEN_BLOCK,
CREATE_VNODE
} from '../runtimeHelpers'
import { injectProp, findDir, findProp, isBuiltInType } from '../utils'
injectProp,
findDir,
findProp,
isBuiltInType,
getVNodeHelper,
getVNodeBlockHelper
} from '../utils'
import { PatchFlags, PatchFlagNames } from '@vue/shared'
export const transformIf = createStructuralDirectiveTransform(
@@ -278,6 +279,7 @@ function createChildrenCodegenNode(
undefined,
true,
false,
false /* isComponent */,
branch.loc
)
}
@@ -286,10 +288,10 @@ function createChildrenCodegenNode(
.codegenNode as BlockCodegenNode
// Change createVNode to createBlock.
if (vnodeCall.type === NodeTypes.VNODE_CALL && !vnodeCall.isBlock) {
removeHelper(CREATE_VNODE)
removeHelper(getVNodeHelper(context.inSSR, vnodeCall.isComponent))
vnodeCall.isBlock = true
helper(OPEN_BLOCK)
helper(CREATE_BLOCK)
helper(getVNodeBlockHelper(context.inSSR, vnodeCall.isComponent))
}
// inject branch key
injectProp(vnodeCall, keyProperty, context)

View File

@@ -30,9 +30,16 @@ import {
SUSPENSE,
KEEP_ALIVE,
BASE_TRANSITION,
TO_HANDLERS
TO_HANDLERS,
NORMALIZE_PROPS,
GUARD_REACTIVE_PROPS,
CREATE_BLOCK,
CREATE_ELEMENT_BLOCK,
CREATE_VNODE,
CREATE_ELEMENT_VNODE
} from './runtimeHelpers'
import { isString, isObject, hyphenate, extend } from '@vue/shared'
import { PropsExpression } from './transforms/transformElement'
export const isStaticExp = (p: JSChildNode): p is SimpleExpressionNode =>
p.type === NodeTypes.SIMPLE_EXPRESSION && p.isStatic
@@ -291,14 +298,66 @@ export function isSlotOutlet(
return node.type === NodeTypes.ELEMENT && node.tagType === ElementTypes.SLOT
}
export function getVNodeHelper(ssr: boolean, isComponent: boolean) {
return ssr || isComponent ? CREATE_VNODE : CREATE_ELEMENT_VNODE
}
export function getVNodeBlockHelper(ssr: boolean, isComponent: boolean) {
return ssr || isComponent ? CREATE_BLOCK : CREATE_ELEMENT_BLOCK
}
const propsHelperSet = new Set([NORMALIZE_PROPS, GUARD_REACTIVE_PROPS])
function getUnnormalizedProps(
props: PropsExpression | '{}',
callPath: CallExpression[] = []
): [PropsExpression | '{}', CallExpression[]] {
if (
props &&
!isString(props) &&
props.type === NodeTypes.JS_CALL_EXPRESSION
) {
const callee = props.callee
if (!isString(callee) && propsHelperSet.has(callee)) {
return getUnnormalizedProps(
props.arguments[0] as PropsExpression,
callPath.concat(props)
)
}
}
return [props, callPath]
}
export function injectProp(
node: VNodeCall | RenderSlotCall,
prop: Property,
context: TransformContext
) {
let propsWithInjection: ObjectExpression | CallExpression | undefined
const props =
const originalProps =
node.type === NodeTypes.VNODE_CALL ? node.props : node.arguments[2]
/**
* 1. mergeProps(...)
* 2. toHandlers(...)
* 3. normalizeProps(...)
* 4. normalizeProps(guardReactiveProps(...))
*
* we need to get the real props before normalization
*/
let props = originalProps
let callPath: CallExpression[] = []
let parentCall: CallExpression | undefined
if (
props &&
!isString(props) &&
props.type === NodeTypes.JS_CALL_EXPRESSION
) {
const ret = getUnnormalizedProps(props)
props = ret[0]
callPath = ret[1]
parentCall = callPath[callPath.length - 1]
}
if (props == null || isString(props)) {
propsWithInjection = createObjectExpression([prop])
} else if (props.type === NodeTypes.JS_CALL_EXPRESSION) {
@@ -341,11 +400,25 @@ export function injectProp(
createObjectExpression([prop]),
props
])
// in the case of nested helper call, e.g. `normalizeProps(guardReactiveProps(props))`,
// it will be rewritten as `normalizeProps(mergeProps({ key: 0 }, props))`,
// the `guardReactiveProps` will no longer be needed
if (parentCall && parentCall.callee === GUARD_REACTIVE_PROPS) {
parentCall = callPath[callPath.length - 2]
}
}
if (node.type === NodeTypes.VNODE_CALL) {
node.props = propsWithInjection
if (parentCall) {
parentCall.arguments[0] = propsWithInjection
} else {
node.props = propsWithInjection
}
} else {
node.arguments[2] = propsWithInjection
if (parentCall) {
parentCall.arguments[0] = propsWithInjection
} else {
node.arguments[2] = propsWithInjection
}
}
}