1
-/**
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- */
7
-
8
-import {
9
- BasicBlock,
10
- BlockId,
11
- BuiltinTag,
12
- DeclarationId,
13
- Effect,
14
- forkTemporaryIdentifier,
15
- GotoTerminal,
16
- GotoVariant,
17
- HIRFunction,
18
- Identifier,
19
- IfTerminal,
20
- Instruction,
21
- InstructionKind,
22
- JsxAttribute,
23
- makeInstructionId,
24
- makePropertyLiteral,
25
- ObjectProperty,
26
- Phi,
27
- Place,
28
- promoteTemporary,
29
- SpreadPattern,
30
-} from '../HIR';
31
-import {
32
- createTemporaryPlace,
33
- fixScopeAndIdentifierRanges,
34
- markInstructionIds,
35
- markPredecessors,
36
- reversePostorderBlocks,
37
-} from '../HIR/HIRBuilder';
38
-import {CompilerError, EnvironmentConfig} from '..';
39
-import {
40
- mapInstructionLValues,
41
- mapInstructionOperands,
42
- mapInstructionValueOperands,
43
- mapTerminalOperands,
44
-} from '../HIR/visitors';
45
-import {ErrorCategory} from '../CompilerError';
46
-
47
-type InlinedJsxDeclarationMap = Map<
48
- DeclarationId,
49
- {identifier: Identifier; blockIdsToIgnore: Set<BlockId>}
50
->;
51
-
52
-/**
53
- * A prod-only, RN optimization to replace JSX with inlined ReactElement object literals
54
- *
55
- * Example:
56
- * <>foo</>
57
- * _______________
58
- * let t1;
59
- * if (__DEV__) {
60
- * t1 = <>foo</>
61
- * } else {
62
- * t1 = {...}
63
- * }
64
- *
65
- */
66
-export function inlineJsxTransform(
67
- fn: HIRFunction,
68
- inlineJsxTransformConfig: NonNullable<
69
- EnvironmentConfig['inlineJsxTransform']
70
- >,
71
-): void {
72
- const inlinedJsxDeclarations: InlinedJsxDeclarationMap = new Map();
73
- /**
74
- * Step 1: Codegen the conditional and ReactElement object literal
75
- */
76
- for (const [_, currentBlock] of [...fn.body.blocks]) {
77
- let fallthroughBlockInstructions: Array<Instruction> | null = null;
78
- const instructionCount = currentBlock.instructions.length;
79
- for (let i = 0; i < instructionCount; i++) {
80
- const instr = currentBlock.instructions[i]!;
81
- // TODO: Support value blocks
82
- if (currentBlock.kind === 'value') {
83
- fn.env.logger?.logEvent(fn.env.filename, {
84
- kind: 'CompileDiagnostic',
85
- fnLoc: null,
86
- detail: {
87
- category: ErrorCategory.Todo,
88
- reason: 'JSX Inlining is not supported on value blocks',
89
- loc: instr.loc,
90
- },
91
- });
92
- continue;
93
- }
94
- switch (instr.value.kind) {
95
- case 'JsxExpression':
96
- case 'JsxFragment': {
97
- /**
98
- * Split into blocks for new IfTerminal:
99
- * current, then, else, fallthrough
100
- */
101
- const currentBlockInstructions = currentBlock.instructions.slice(
102
- 0,
103
- i,
104
- );
105
- const thenBlockInstructions = currentBlock.instructions.slice(
106
- i,
107
- i + 1,
108
- );
109
- const elseBlockInstructions: Array<Instruction> = [];
110
- fallthroughBlockInstructions ??= currentBlock.instructions.slice(
111
- i + 1,
112
- );
113
-
114
- const fallthroughBlockId = fn.env.nextBlockId;
115
- const fallthroughBlock: BasicBlock = {
116
- kind: currentBlock.kind,
117
- id: fallthroughBlockId,
118
- instructions: fallthroughBlockInstructions,
119
- terminal: currentBlock.terminal,
120
- preds: new Set(),
121
- phis: new Set(),
122
- };
123
-
124
- /**
125
- * Complete current block
126
- * - Add instruction for variable declaration
127
- * - Add instruction for LoadGlobal used by conditional
128
- * - End block with a new IfTerminal
129
- */
130
- const varPlace = createTemporaryPlace(fn.env, instr.value.loc);
131
- promoteTemporary(varPlace.identifier);
132
- const varLValuePlace = createTemporaryPlace(fn.env, instr.value.loc);
133
- const thenVarPlace = {
134
- ...varPlace,
135
- identifier: forkTemporaryIdentifier(
136
- fn.env.nextIdentifierId,
137
- varPlace.identifier,
138
- ),
139
- };
140
- const elseVarPlace = {
141
- ...varPlace,
142
- identifier: forkTemporaryIdentifier(
143
- fn.env.nextIdentifierId,
144
- varPlace.identifier,
145
- ),
146
- };
147
- const varInstruction: Instruction = {
148
- id: makeInstructionId(0),
149
- lvalue: {...varLValuePlace},
150
- value: {
151
- kind: 'DeclareLocal',
152
- lvalue: {place: {...varPlace}, kind: InstructionKind.Let},
153
- type: null,
154
- loc: instr.value.loc,
155
- },
156
- effects: null,
157
- loc: instr.loc,
158
- };
159
- currentBlockInstructions.push(varInstruction);
160
-
161
- const devGlobalPlace = createTemporaryPlace(fn.env, instr.value.loc);
162
- const devGlobalInstruction: Instruction = {
163
- id: makeInstructionId(0),
164
- lvalue: {...devGlobalPlace, effect: Effect.Mutate},
165
- value: {
166
- kind: 'LoadGlobal',
167
- binding: {
168
- kind: 'Global',
169
- name: inlineJsxTransformConfig.globalDevVar,
170
- },
171
- loc: instr.value.loc,
172
- },
173
- effects: null,
174
- loc: instr.loc,
175
- };
176
- currentBlockInstructions.push(devGlobalInstruction);
177
- const thenBlockId = fn.env.nextBlockId;
178
- const elseBlockId = fn.env.nextBlockId;
179
- const ifTerminal: IfTerminal = {
180
- kind: 'if',
181
- test: {...devGlobalPlace, effect: Effect.Read},
182
- consequent: thenBlockId,
183
- alternate: elseBlockId,
184
- fallthrough: fallthroughBlockId,
185
- loc: instr.loc,
186
- id: makeInstructionId(0),
187
- };
188
- currentBlock.instructions = currentBlockInstructions;
189
- currentBlock.terminal = ifTerminal;
190
-
191
- /**
192
- * Set up then block where we put the original JSX return
193
- */
194
- const thenBlock: BasicBlock = {
195
- id: thenBlockId,
196
- instructions: thenBlockInstructions,
197
- kind: 'block',
198
- phis: new Set(),
199
- preds: new Set(),
200
- terminal: {
201
- kind: 'goto',
202
- block: fallthroughBlockId,
203
- variant: GotoVariant.Break,
204
- id: makeInstructionId(0),
205
- loc: instr.loc,
206
- },
207
- };
208
- fn.body.blocks.set(thenBlockId, thenBlock);
209
-
210
- const resassignElsePlace = createTemporaryPlace(
211
- fn.env,
212
- instr.value.loc,
213
- );
214
- const reassignElseInstruction: Instruction = {
215
- id: makeInstructionId(0),
216
- lvalue: {...resassignElsePlace},
217
- value: {
218
- kind: 'StoreLocal',
219
- lvalue: {
220
- place: elseVarPlace,
221
- kind: InstructionKind.Reassign,
222
- },
223
- value: {...instr.lvalue},
224
- type: null,
225
- loc: instr.value.loc,
226
- },
227
- effects: null,
228
- loc: instr.loc,
229
- };
230
- thenBlockInstructions.push(reassignElseInstruction);
231
-
232
- /**
233
- * Set up else block where we add new codegen
234
- */
235
- const elseBlockTerminal: GotoTerminal = {
236
- kind: 'goto',
237
- block: fallthroughBlockId,
238
- variant: GotoVariant.Break,
239
- id: makeInstructionId(0),
240
- loc: instr.loc,
241
- };
242
- const elseBlock: BasicBlock = {
243
- id: elseBlockId,
244
- instructions: elseBlockInstructions,
245
- kind: 'block',
246
- phis: new Set(),
247
- preds: new Set(),
248
- terminal: elseBlockTerminal,
249
- };
250
- fn.body.blocks.set(elseBlockId, elseBlock);
251
-
252
- /**
253
- * ReactElement object literal codegen
254
- */
255
- const {refProperty, keyProperty, propsProperty} =
256
- createPropsProperties(
257
- fn,
258
- instr,
259
- elseBlockInstructions,
260
- instr.value.kind === 'JsxExpression' ? instr.value.props : [],
261
- instr.value.children,
262
- );
263
- const reactElementInstructionPlace = createTemporaryPlace(
264
- fn.env,
265
- instr.value.loc,
266
- );
267
- const reactElementInstruction: Instruction = {
268
- id: makeInstructionId(0),
269
- lvalue: {...reactElementInstructionPlace, effect: Effect.Store},
270
- value: {
271
- kind: 'ObjectExpression',
272
- properties: [
273
- createSymbolProperty(
274
- fn,
275
- instr,
276
- elseBlockInstructions,
277
- '$$typeof',
278
- inlineJsxTransformConfig.elementSymbol,
279
- ),
280
- instr.value.kind === 'JsxExpression'
281
- ? createTagProperty(
282
- fn,
283
- instr,
284
- elseBlockInstructions,
285
- instr.value.tag,
286
- )
287
- : createSymbolProperty(
288
- fn,
289
- instr,
290
- elseBlockInstructions,
291
- 'type',
292
- 'react.fragment',
293
- ),
294
- refProperty,
295
- keyProperty,
296
- propsProperty,
297
- ],
298
- loc: instr.value.loc,
299
- },
300
- effects: null,
301
- loc: instr.loc,
302
- };
303
- elseBlockInstructions.push(reactElementInstruction);
304
-
305
- const reassignConditionalInstruction: Instruction = {
306
- id: makeInstructionId(0),
307
- lvalue: {...createTemporaryPlace(fn.env, instr.value.loc)},
308
- value: {
309
- kind: 'StoreLocal',
310
- lvalue: {
311
- place: {...elseVarPlace},
312
- kind: InstructionKind.Reassign,
313
- },
314
- value: {...reactElementInstruction.lvalue},
315
- type: null,
316
- loc: instr.value.loc,
317
- },
318
- effects: null,
319
- loc: instr.loc,
320
- };
321
- elseBlockInstructions.push(reassignConditionalInstruction);
322
-
323
- /**
324
- * Create phis to reassign the var
325
- */
326
- const operands: Map<BlockId, Place> = new Map();
327
- operands.set(thenBlockId, {
328
- ...elseVarPlace,
329
- });
330
- operands.set(elseBlockId, {
331
- ...thenVarPlace,
332
- });
333
-
334
- const phiIdentifier = forkTemporaryIdentifier(
335
- fn.env.nextIdentifierId,
336
- varPlace.identifier,
337
- );
338
- const phiPlace = {
339
- ...createTemporaryPlace(fn.env, instr.value.loc),
340
- identifier: phiIdentifier,
341
- };
342
- const phis: Set<Phi> = new Set([
343
- {
344
- kind: 'Phi',
345
- operands,
346
- place: phiPlace,
347
- },
348
- ]);
349
- fallthroughBlock.phis = phis;
350
- fn.body.blocks.set(fallthroughBlockId, fallthroughBlock);
351
-
352
- /**
353
- * Track this JSX instruction so we can replace references in step 2
354
- */
355
- inlinedJsxDeclarations.set(instr.lvalue.identifier.declarationId, {
356
- identifier: phiIdentifier,
357
- blockIdsToIgnore: new Set([thenBlockId, elseBlockId]),
358
- });
359
- break;
360
- }
361
- case 'FunctionExpression':
362
- case 'ObjectMethod': {
363
- inlineJsxTransform(
364
- instr.value.loweredFunc.func,
365
- inlineJsxTransformConfig,
366
- );
367
- break;
368
- }
369
- }
370
- }
371
- }
372
-
373
- /**
374
- * Step 2: Replace declarations with new phi values
375
- */
376
- for (const [blockId, block] of fn.body.blocks) {
377
- for (const instr of block.instructions) {
378
- mapInstructionOperands(instr, place =>
379
- handlePlace(place, blockId, inlinedJsxDeclarations),
380
- );
381
-
382
- mapInstructionLValues(instr, lvalue =>
383
- handlelValue(lvalue, blockId, inlinedJsxDeclarations),
384
- );
385
-
386
- mapInstructionValueOperands(instr.value, place =>
387
- handlePlace(place, blockId, inlinedJsxDeclarations),
388
- );
389
- }
390
-
391
- mapTerminalOperands(block.terminal, place =>
392
- handlePlace(place, blockId, inlinedJsxDeclarations),
393
- );
394
-
395
- if (block.terminal.kind === 'scope') {
396
- const scope = block.terminal.scope;
397
- for (const dep of scope.dependencies) {
398
- dep.identifier = handleIdentifier(
399
- dep.identifier,
400
- inlinedJsxDeclarations,
401
- );
402
- }
403
-
404
- for (const [origId, decl] of [...scope.declarations]) {
405
- const newDecl = handleIdentifier(
406
- decl.identifier,
407
- inlinedJsxDeclarations,
408
- );
409
- if (newDecl.id !== origId) {
410
- scope.declarations.delete(origId);
411
- scope.declarations.set(decl.identifier.id, {
412
- identifier: newDecl,
413
- scope: decl.scope,
414
- });
415
- }
416
- }
417
- }
418
- }
419
-
420
- /**
421
- * Step 3: Fixup the HIR
422
- * Restore RPO, ensure correct predecessors, renumber instructions, fix scope and ranges.
423
- */
424
- reversePostorderBlocks(fn.body);
425
- markPredecessors(fn.body);
426
- markInstructionIds(fn.body);
427
- fixScopeAndIdentifierRanges(fn.body);
428
-}
429
-
430
-function createSymbolProperty(
431
- fn: HIRFunction,
432
- instr: Instruction,
433
- nextInstructions: Array<Instruction>,
434
- propertyName: string,
435
- symbolName: string,
436
-): ObjectProperty {
437
- const symbolPlace = createTemporaryPlace(fn.env, instr.value.loc);
438
- const symbolInstruction: Instruction = {
439
- id: makeInstructionId(0),
440
- lvalue: {...symbolPlace, effect: Effect.Mutate},
441
- value: {
442
- kind: 'LoadGlobal',
443
- binding: {kind: 'Global', name: 'Symbol'},
444
- loc: instr.value.loc,
445
- },
446
- effects: null,
447
- loc: instr.loc,
448
- };
449
- nextInstructions.push(symbolInstruction);
450
-
451
- const symbolForPlace = createTemporaryPlace(fn.env, instr.value.loc);
452
- const symbolForInstruction: Instruction = {
453
- id: makeInstructionId(0),
454
- lvalue: {...symbolForPlace, effect: Effect.Read},
455
- value: {
456
- kind: 'PropertyLoad',
457
- object: {...symbolInstruction.lvalue},
458
- property: makePropertyLiteral('for'),
459
- loc: instr.value.loc,
460
- },
461
- effects: null,
462
- loc: instr.loc,
463
- };
464
- nextInstructions.push(symbolForInstruction);
465
-
466
- const symbolValuePlace = createTemporaryPlace(fn.env, instr.value.loc);
467
- const symbolValueInstruction: Instruction = {
468
- id: makeInstructionId(0),
469
- lvalue: {...symbolValuePlace, effect: Effect.Mutate},
470
- value: {
471
- kind: 'Primitive',
472
- value: symbolName,
473
- loc: instr.value.loc,
474
- },
475
- effects: null,
476
- loc: instr.loc,
477
- };
478
- nextInstructions.push(symbolValueInstruction);
479
-
480
- const $$typeofPlace = createTemporaryPlace(fn.env, instr.value.loc);
481
- const $$typeofInstruction: Instruction = {
482
- id: makeInstructionId(0),
483
- lvalue: {...$$typeofPlace, effect: Effect.Mutate},
484
- value: {
485
- kind: 'MethodCall',
486
- receiver: symbolInstruction.lvalue,
487
- property: symbolForInstruction.lvalue,
488
- args: [symbolValueInstruction.lvalue],
489
- loc: instr.value.loc,
490
- },
491
- effects: null,
492
- loc: instr.loc,
493
- };
494
- const $$typeofProperty: ObjectProperty = {
495
- kind: 'ObjectProperty',
496
- key: {name: propertyName, kind: 'string'},
497
- type: 'property',
498
- place: {...$$typeofPlace, effect: Effect.Capture},
499
- };
500
- nextInstructions.push($$typeofInstruction);
501
- return $$typeofProperty;
502
-}
503
-
504
-function createTagProperty(
505
- fn: HIRFunction,
506
- instr: Instruction,
507
- nextInstructions: Array<Instruction>,
508
- componentTag: BuiltinTag | Place,
509
-): ObjectProperty {
510
- let tagProperty: ObjectProperty;
511
- switch (componentTag.kind) {
512
- case 'BuiltinTag': {
513
- const tagPropertyPlace = createTemporaryPlace(fn.env, instr.value.loc);
514
- const tagInstruction: Instruction = {
515
- id: makeInstructionId(0),
516
- lvalue: {...tagPropertyPlace, effect: Effect.Mutate},
517
- value: {
518
- kind: 'Primitive',
519
- value: componentTag.name,
520
- loc: instr.value.loc,
521
- },
522
- effects: null,
523
- loc: instr.loc,
524
- };
525
- tagProperty = {
526
- kind: 'ObjectProperty',
527
- key: {name: 'type', kind: 'string'},
528
- type: 'property',
529
- place: {...tagPropertyPlace, effect: Effect.Capture},
530
- };
531
- nextInstructions.push(tagInstruction);
532
- break;
533
- }
534
- case 'Identifier': {
535
- tagProperty = {
536
- kind: 'ObjectProperty',
537
- key: {name: 'type', kind: 'string'},
538
- type: 'property',
539
- place: {...componentTag, effect: Effect.Capture},
540
- };
541
- break;
542
- }
543
- }
544
-
545
- return tagProperty;
546
-}
547
-
548
-function createPropsProperties(
549
- fn: HIRFunction,
550
- instr: Instruction,
551
- nextInstructions: Array<Instruction>,
552
- propAttributes: Array<JsxAttribute>,
553
- children: Array<Place> | null,
554
-): {
555
- refProperty: ObjectProperty;
556
- keyProperty: ObjectProperty;
557
- propsProperty: ObjectProperty;
558
-} {
559
- let refProperty: ObjectProperty | undefined;
560
- let keyProperty: ObjectProperty | undefined;
561
- const props: Array<ObjectProperty | SpreadPattern> = [];
562
- const jsxAttributesWithoutKey = propAttributes.filter(
563
- p => p.kind === 'JsxAttribute' && p.name !== 'key',
564
- );
565
- const jsxSpreadAttributes = propAttributes.filter(
566
- p => p.kind === 'JsxSpreadAttribute',
567
- );
568
- const spreadPropsOnly =
569
- jsxAttributesWithoutKey.length === 0 && jsxSpreadAttributes.length === 1;
570
- propAttributes.forEach(prop => {
571
- switch (prop.kind) {
572
- case 'JsxAttribute': {
573
- switch (prop.name) {
574
- case 'key': {
575
- keyProperty = {
576
- kind: 'ObjectProperty',
577
- key: {name: 'key', kind: 'string'},
578
- type: 'property',
579
- place: {...prop.place},
580
- };
581
- break;
582
- }
583
- case 'ref': {
584
- /**
585
- * In the current JSX implementation, ref is both
586
- * a property on the element and a property on props.
587
- */
588
- refProperty = {
589
- kind: 'ObjectProperty',
590
- key: {name: 'ref', kind: 'string'},
591
- type: 'property',
592
- place: {...prop.place},
593
- };
594
- const refPropProperty: ObjectProperty = {
595
- kind: 'ObjectProperty',
596
- key: {name: 'ref', kind: 'string'},
597
- type: 'property',
598
- place: {...prop.place},
599
- };
600
- props.push(refPropProperty);
601
- break;
602
- }
603
- default: {
604
- const attributeProperty: ObjectProperty = {
605
- kind: 'ObjectProperty',
606
- key: {name: prop.name, kind: 'string'},
607
- type: 'property',
608
- place: {...prop.place},
609
- };
610
- props.push(attributeProperty);
611
- }
612
- }
613
- break;
614
- }
615
- case 'JsxSpreadAttribute': {
616
- props.push({
617
- kind: 'Spread',
618
- place: {...prop.argument},
619
- });
620
- break;
621
- }
622
- }
623
- });
624
-
625
- const propsPropertyPlace = createTemporaryPlace(fn.env, instr.value.loc);
626
- if (children) {
627
- let childrenPropProperty: ObjectProperty;
628
- if (children.length === 1) {
629
- childrenPropProperty = {
630
- kind: 'ObjectProperty',
631
- key: {name: 'children', kind: 'string'},
632
- type: 'property',
633
- place: {...children[0], effect: Effect.Capture},
634
- };
635
- } else {
636
- const childrenPropPropertyPlace = createTemporaryPlace(
637
- fn.env,
638
- instr.value.loc,
639
- );
640
-
641
- const childrenPropInstruction: Instruction = {
642
- id: makeInstructionId(0),
643
- lvalue: {...childrenPropPropertyPlace, effect: Effect.Mutate},
644
- value: {
645
- kind: 'ArrayExpression',
646
- elements: [...children],
647
- loc: instr.value.loc,
648
- },
649
- effects: null,
650
- loc: instr.loc,
651
- };
652
- nextInstructions.push(childrenPropInstruction);
653
- childrenPropProperty = {
654
- kind: 'ObjectProperty',
655
- key: {name: 'children', kind: 'string'},
656
- type: 'property',
657
- place: {...childrenPropPropertyPlace, effect: Effect.Capture},
658
- };
659
- }
660
- props.push(childrenPropProperty);
661
- }
662
-
663
- if (refProperty == null) {
664
- const refPropertyPlace = createTemporaryPlace(fn.env, instr.value.loc);
665
- const refInstruction: Instruction = {
666
- id: makeInstructionId(0),
667
- lvalue: {...refPropertyPlace, effect: Effect.Mutate},
668
- value: {
669
- kind: 'Primitive',
670
- value: null,
671
- loc: instr.value.loc,
672
- },
673
- effects: null,
674
- loc: instr.loc,
675
- };
676
- refProperty = {
677
- kind: 'ObjectProperty',
678
- key: {name: 'ref', kind: 'string'},
679
- type: 'property',
680
- place: {...refPropertyPlace, effect: Effect.Capture},
681
- };
682
- nextInstructions.push(refInstruction);
683
- }
684
-
685
- if (keyProperty == null) {
686
- const keyPropertyPlace = createTemporaryPlace(fn.env, instr.value.loc);
687
- const keyInstruction: Instruction = {
688
- id: makeInstructionId(0),
689
- lvalue: {...keyPropertyPlace, effect: Effect.Mutate},
690
- value: {
691
- kind: 'Primitive',
692
- value: null,
693
- loc: instr.value.loc,
694
- },
695
- effects: null,
696
- loc: instr.loc,
697
- };
698
- keyProperty = {
699
- kind: 'ObjectProperty',
700
- key: {name: 'key', kind: 'string'},
701
- type: 'property',
702
- place: {...keyPropertyPlace, effect: Effect.Capture},
703
- };
704
- nextInstructions.push(keyInstruction);
705
- }
706
-
707
- let propsProperty: ObjectProperty;
708
- if (spreadPropsOnly) {
709
- const spreadProp = jsxSpreadAttributes[0];
710
- CompilerError.invariant(spreadProp.kind === 'JsxSpreadAttribute', {
711
- reason: 'Spread prop attribute must be of kind JSXSpreadAttribute',
712
- loc: instr.loc,
713
- });
714
- propsProperty = {
715
- kind: 'ObjectProperty',
716
- key: {name: 'props', kind: 'string'},
717
- type: 'property',
718
- place: {...spreadProp.argument, effect: Effect.Mutate},
719
- };
720
- } else {
721
- const propsInstruction: Instruction = {
722
- id: makeInstructionId(0),
723
- lvalue: {...propsPropertyPlace, effect: Effect.Mutate},
724
- value: {
725
- kind: 'ObjectExpression',
726
- properties: props,
727
- loc: instr.value.loc,
728
- },
729
- effects: null,
730
- loc: instr.loc,
731
- };
732
- propsProperty = {
733
- kind: 'ObjectProperty',
734
- key: {name: 'props', kind: 'string'},
735
- type: 'property',
736
- place: {...propsPropertyPlace, effect: Effect.Capture},
737
- };
738
- nextInstructions.push(propsInstruction);
739
- }
740
-
741
- return {refProperty, keyProperty, propsProperty};
742
-}
743
-
744
-function handlePlace(
745
- place: Place,
746
- blockId: BlockId,
747
- inlinedJsxDeclarations: InlinedJsxDeclarationMap,
748
-): Place {
749
- const inlinedJsxDeclaration = inlinedJsxDeclarations.get(
750
- place.identifier.declarationId,
751
- );
752
- if (
753
- inlinedJsxDeclaration == null ||
754
- inlinedJsxDeclaration.blockIdsToIgnore.has(blockId)
755
- ) {
756
- return place;
757
- }
758
-
759
- return {...place, identifier: inlinedJsxDeclaration.identifier};
760
-}
761
-
762
-function handlelValue(
763
- lvalue: Place,
764
- blockId: BlockId,
765
- inlinedJsxDeclarations: InlinedJsxDeclarationMap,
766
-): Place {
767
- const inlinedJsxDeclaration = inlinedJsxDeclarations.get(
768
- lvalue.identifier.declarationId,
769
- );
770
- if (
771
- inlinedJsxDeclaration == null ||
772
- inlinedJsxDeclaration.blockIdsToIgnore.has(blockId)
773
- ) {
774
- return lvalue;
775
- }
776
-
777
- return {...lvalue, identifier: inlinedJsxDeclaration.identifier};
778
-}
779
-
780
-function handleIdentifier(
781
- identifier: Identifier,
782
- inlinedJsxDeclarations: InlinedJsxDeclarationMap,
783
-): Identifier {
784
- const inlinedJsxDeclaration = inlinedJsxDeclarations.get(
785
- identifier.declarationId,
786
- );
787
- return inlinedJsxDeclaration == null
788
- ? identifier
789
- : inlinedJsxDeclaration.identifier;
790
-}