mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Distinguish regular/value blocks
This commit is contained in:
@@ -122,7 +122,7 @@ function lowerStatement(
|
||||
value,
|
||||
id: makeInstructionId(0),
|
||||
};
|
||||
builder.terminate(terminal);
|
||||
builder.terminate("block", terminal);
|
||||
return;
|
||||
}
|
||||
case "ReturnStatement": {
|
||||
@@ -138,7 +138,7 @@ function lowerStatement(
|
||||
value,
|
||||
id: makeInstructionId(0),
|
||||
};
|
||||
builder.terminateWithContinuation(terminal, fallthrough);
|
||||
builder.terminateWithContinuation("block", terminal, fallthrough);
|
||||
return;
|
||||
}
|
||||
case "IfStatement": {
|
||||
@@ -146,7 +146,7 @@ function lowerStatement(
|
||||
// Block for code following the if
|
||||
const continuationBlock = builder.reserve();
|
||||
// Block for the consequent (if the test is truthy)
|
||||
const consequentBlock = builder.enter((blockId) => {
|
||||
const consequentBlock = builder.enter("block", (blockId) => {
|
||||
lowerStatement(builder, stmt.get("consequent"));
|
||||
return {
|
||||
kind: "goto",
|
||||
@@ -159,7 +159,7 @@ function lowerStatement(
|
||||
let alternateBlock = null;
|
||||
const alternate = stmt.get("alternate");
|
||||
if (alternate.hasNode()) {
|
||||
alternateBlock = builder.enter((blockId) => {
|
||||
alternateBlock = builder.enter("block", (blockId) => {
|
||||
lowerStatement(builder, alternate);
|
||||
return {
|
||||
kind: "goto",
|
||||
@@ -181,7 +181,7 @@ function lowerStatement(
|
||||
fallthrough: continuationBlock.id,
|
||||
id: makeInstructionId(0),
|
||||
};
|
||||
builder.terminateWithContinuation(terminal, continuationBlock);
|
||||
builder.terminateWithContinuation("block", terminal, continuationBlock);
|
||||
return;
|
||||
}
|
||||
case "BlockStatement": {
|
||||
@@ -192,7 +192,7 @@ function lowerStatement(
|
||||
case "BreakStatement": {
|
||||
const stmt = stmtPath as NodePath<t.BreakStatement>;
|
||||
const block = builder.lookupBreak(stmt.node.label?.name ?? null);
|
||||
builder.terminate({
|
||||
builder.terminate("block", {
|
||||
kind: "goto",
|
||||
block,
|
||||
variant: GotoVariant.Break,
|
||||
@@ -203,7 +203,7 @@ function lowerStatement(
|
||||
case "ContinueStatement": {
|
||||
const stmt = stmtPath as NodePath<t.ContinueStatement>;
|
||||
const block = builder.lookupContinue(stmt.node.label?.name ?? null);
|
||||
builder.terminate({
|
||||
builder.terminate("block", {
|
||||
kind: "goto",
|
||||
block,
|
||||
variant: GotoVariant.Continue,
|
||||
@@ -217,7 +217,7 @@ function lowerStatement(
|
||||
const conditionalBlock = builder.reserve();
|
||||
// Block for code following the loop
|
||||
const continuationBlock = builder.reserve();
|
||||
const loopBlock = builder.enter((blockId) => {
|
||||
const loopBlock = builder.enter("block", (blockId) => {
|
||||
return builder.loop(
|
||||
label,
|
||||
conditionalBlock.id,
|
||||
@@ -235,6 +235,7 @@ function lowerStatement(
|
||||
});
|
||||
// End the block leading up to the loop and jump to the conditional block
|
||||
builder.terminateWithContinuation(
|
||||
"block",
|
||||
{
|
||||
kind: "goto",
|
||||
block: conditionalBlock.id,
|
||||
@@ -257,7 +258,7 @@ function lowerStatement(
|
||||
fallthrough: continuationBlock.id,
|
||||
id: makeInstructionId(0),
|
||||
};
|
||||
builder.terminateWithContinuation(terminal, continuationBlock);
|
||||
builder.terminateWithContinuation("block", terminal, continuationBlock);
|
||||
return;
|
||||
}
|
||||
case "ForOfStatement": {
|
||||
@@ -270,7 +271,7 @@ function lowerStatement(
|
||||
* Build the loop body, each iteration loops back to the conditional block
|
||||
* to check whether to continue or exit
|
||||
*/
|
||||
const loopBlock = builder.enter((blockId) => {
|
||||
const loopBlock = builder.enter("block", (blockId) => {
|
||||
return builder.loop(
|
||||
label,
|
||||
conditionalBlock.id,
|
||||
@@ -288,6 +289,7 @@ function lowerStatement(
|
||||
});
|
||||
// End the block leading up to the loop and jump to the conditional block
|
||||
builder.terminateWithContinuation(
|
||||
"block",
|
||||
{
|
||||
kind: "goto",
|
||||
block: conditionalBlock.id,
|
||||
@@ -310,7 +312,7 @@ function lowerStatement(
|
||||
fallthrough: continuationBlock.id,
|
||||
id: makeInstructionId(0),
|
||||
};
|
||||
builder.terminateWithContinuation(terminal, continuationBlock);
|
||||
builder.terminateWithContinuation("block", terminal, continuationBlock);
|
||||
return;
|
||||
}
|
||||
case "ForStatement": {
|
||||
@@ -320,7 +322,7 @@ function lowerStatement(
|
||||
// Block for code following the loop
|
||||
const continuationBlock = builder.reserve();
|
||||
|
||||
const initBlock = builder.enter((blockId) => {
|
||||
const initBlock = builder.enter("value", (blockId) => {
|
||||
const init = stmt.get("init") as NodePath<t.VariableDeclaration>;
|
||||
todoInvariant(
|
||||
t.isVariableDeclaration(init.node),
|
||||
@@ -335,7 +337,7 @@ function lowerStatement(
|
||||
};
|
||||
});
|
||||
|
||||
const updateBlock = builder.enter((blockId) => {
|
||||
const updateBlock = builder.enter("value", (blockId) => {
|
||||
const update = stmt.get("update");
|
||||
todoInvariant(update.hasNode(), "Handle empty for updater");
|
||||
if (update.hasNode()) {
|
||||
@@ -349,7 +351,7 @@ function lowerStatement(
|
||||
};
|
||||
});
|
||||
|
||||
const bodyBlock = builder.enter((blockId) => {
|
||||
const bodyBlock = builder.enter("block", (blockId) => {
|
||||
return builder.loop(label, updateBlock, continuationBlock.id, () => {
|
||||
lowerStatement(builder, stmt.get("body"));
|
||||
return {
|
||||
@@ -362,6 +364,7 @@ function lowerStatement(
|
||||
});
|
||||
|
||||
builder.terminateWithContinuation(
|
||||
"block",
|
||||
{
|
||||
kind: "for",
|
||||
init: initBlock,
|
||||
@@ -377,6 +380,7 @@ function lowerStatement(
|
||||
const test = stmt.get("test");
|
||||
todoInvariant(test.hasNode(), "ForStatement without test");
|
||||
builder.terminateWithContinuation(
|
||||
"value",
|
||||
{
|
||||
kind: "if",
|
||||
test: lowerExpressionToPlace(builder, test),
|
||||
@@ -394,7 +398,7 @@ function lowerStatement(
|
||||
// Block for code following the loop
|
||||
const continuationBlock = builder.reserve();
|
||||
// Loop body
|
||||
const loopBlock = builder.enter((loopBlock) => {
|
||||
const loopBlock = builder.enter("block", (loopBlock) => {
|
||||
return builder.loop(label, loopBlock, continuationBlock.id, () => {
|
||||
lowerStatement(builder, stmt.get("body"));
|
||||
/**
|
||||
@@ -415,6 +419,7 @@ function lowerStatement(
|
||||
});
|
||||
// do-while unconditionally enters the loop
|
||||
builder.terminateWithContinuation(
|
||||
"block",
|
||||
{
|
||||
kind: "goto",
|
||||
block: loopBlock,
|
||||
@@ -432,7 +437,7 @@ function lowerStatement(
|
||||
// Block for code following the loop
|
||||
const continuationBlock = builder.reserve();
|
||||
// Loop body
|
||||
const loopBlock = builder.enter((blockId) => {
|
||||
const loopBlock = builder.enter("block", (blockId) => {
|
||||
return builder.loop(
|
||||
label,
|
||||
conditionalBlock.id,
|
||||
@@ -455,6 +460,7 @@ function lowerStatement(
|
||||
const loc = stmt.node.loc;
|
||||
invariant(loc, "while statement must have a location");
|
||||
builder.terminateWithContinuation(
|
||||
"block",
|
||||
{
|
||||
kind: "while",
|
||||
loc,
|
||||
@@ -479,7 +485,7 @@ function lowerStatement(
|
||||
id: makeInstructionId(0),
|
||||
};
|
||||
// Complete the conditional and continue with code after the loop
|
||||
builder.terminateWithContinuation(terminal, continuationBlock);
|
||||
builder.terminateWithContinuation("value", terminal, continuationBlock);
|
||||
return;
|
||||
}
|
||||
case "LabeledStatement": {
|
||||
@@ -505,6 +511,7 @@ function lowerStatement(
|
||||
lowerStatement(builder, stmt.get("body"));
|
||||
});
|
||||
builder.terminateWithContinuation(
|
||||
"block",
|
||||
{
|
||||
kind: "goto",
|
||||
block: continuationBlock.id,
|
||||
@@ -543,7 +550,7 @@ function lowerStatement(
|
||||
);
|
||||
hasDefault = true;
|
||||
}
|
||||
const block = builder.enter((_blockId) => {
|
||||
const block = builder.enter("block", (_blockId) => {
|
||||
return builder.switch(label, continuationBlock.id, () => {
|
||||
case_
|
||||
.get("consequent")
|
||||
@@ -581,6 +588,7 @@ function lowerStatement(
|
||||
|
||||
const test = lowerExpressionToPlace(builder, stmt.get("discriminant"));
|
||||
builder.terminateWithContinuation(
|
||||
"block",
|
||||
{
|
||||
kind: "switch",
|
||||
test,
|
||||
@@ -1192,7 +1200,7 @@ function lowerConditional(
|
||||
// Block for code following the if
|
||||
const continuationBlock = builder.reserve();
|
||||
// Block for the consequent (if the test is truthy)
|
||||
const consequentBlock = builder.enter((blockId) => {
|
||||
const consequentBlock = builder.enter("value", (blockId) => {
|
||||
let value = consequent();
|
||||
builder.push({
|
||||
id: makeInstructionId(0),
|
||||
@@ -1208,7 +1216,7 @@ function lowerConditional(
|
||||
};
|
||||
});
|
||||
// Block for the alternate (if the test is not truthy)
|
||||
const alternateBlock = builder.enter((blockId) => {
|
||||
const alternateBlock = builder.enter("value", (blockId) => {
|
||||
let value = alternate();
|
||||
builder.push({
|
||||
id: makeInstructionId(0),
|
||||
@@ -1231,7 +1239,7 @@ function lowerConditional(
|
||||
fallthrough: continuationBlock.id,
|
||||
id: makeInstructionId(0),
|
||||
};
|
||||
builder.terminateWithContinuation(terminal, continuationBlock);
|
||||
builder.terminateWithContinuation("value", terminal, continuationBlock);
|
||||
return place;
|
||||
}
|
||||
|
||||
|
||||
@@ -141,7 +141,9 @@ export type HIR = {
|
||||
* an exception occurs, therefore the block model only represents explicit throw
|
||||
* statements and not implicit exceptions which may occur.
|
||||
*/
|
||||
export type BlockKind = "block" | "value";
|
||||
export type BasicBlock = {
|
||||
kind: BlockKind;
|
||||
id: BlockId;
|
||||
instructions: Array<Instruction>;
|
||||
terminal: Terminal;
|
||||
@@ -162,6 +164,11 @@ export type Terminal =
|
||||
| ForTerminal
|
||||
| WhileTerminal;
|
||||
|
||||
/**
|
||||
* Terminal nodes allowed for a value block
|
||||
*/
|
||||
export type ValueTerminal = IfTerminal | GotoTerminal;
|
||||
|
||||
export type ThrowTerminal = { kind: "throw"; value: Place; id: InstructionId };
|
||||
|
||||
export type ReturnTerminal = {
|
||||
|
||||
@@ -12,6 +12,7 @@ import { assertExhaustive } from "../Utils/utils";
|
||||
import {
|
||||
BasicBlock,
|
||||
BlockId,
|
||||
BlockKind,
|
||||
GeneratedSource,
|
||||
GotoVariant,
|
||||
HIR,
|
||||
@@ -146,6 +147,7 @@ export default class HIRBuilder {
|
||||
build(): HIR {
|
||||
const { id: blockId, instructions } = this.#current;
|
||||
this.#completed.set(blockId, {
|
||||
kind: "block",
|
||||
id: blockId,
|
||||
instructions,
|
||||
terminal: {
|
||||
@@ -177,9 +179,10 @@ export default class HIRBuilder {
|
||||
/**
|
||||
* Terminate the current block w the given terminal, and start a new block
|
||||
*/
|
||||
terminate(terminal: Terminal) {
|
||||
terminate(kind: BlockKind, terminal: Terminal) {
|
||||
const { id: blockId, instructions } = this.#current;
|
||||
this.#completed.set(blockId, {
|
||||
kind,
|
||||
id: blockId,
|
||||
instructions,
|
||||
terminal,
|
||||
@@ -194,12 +197,17 @@ export default class HIRBuilder {
|
||||
* Terminate the current block w the given terminal, and set the previously
|
||||
* reserved block as the new current block
|
||||
*/
|
||||
terminateWithContinuation(terminal: Terminal, continuation: WipBlock) {
|
||||
terminateWithContinuation(
|
||||
kind: BlockKind,
|
||||
terminal: Terminal,
|
||||
continuation: WipBlock
|
||||
) {
|
||||
const { id: blockId, instructions } = this.#current;
|
||||
this.#completed.set(blockId, {
|
||||
kind: kind,
|
||||
id: blockId,
|
||||
instructions,
|
||||
terminal,
|
||||
terminal: terminal,
|
||||
preds: new Set(),
|
||||
phis: new Set(),
|
||||
});
|
||||
@@ -218,9 +226,10 @@ export default class HIRBuilder {
|
||||
/**
|
||||
* Save a previously reserved block as completed
|
||||
*/
|
||||
complete(block: WipBlock, terminal: Terminal) {
|
||||
complete(kind: BlockKind, block: WipBlock, terminal: Terminal) {
|
||||
const { id: blockId, instructions } = block;
|
||||
this.#completed.set(blockId, {
|
||||
kind,
|
||||
id: blockId,
|
||||
instructions,
|
||||
terminal,
|
||||
@@ -235,13 +244,14 @@ export default class HIRBuilder {
|
||||
* The lambda must return a terminal node, which is used to terminate the
|
||||
* newly constructed block.
|
||||
*/
|
||||
enter(fn: (blockId: BlockId) => Terminal): BlockId {
|
||||
enter(kind: BlockKind, fn: (blockId: BlockId) => Terminal): BlockId {
|
||||
const current = this.#current;
|
||||
const nextId = makeBlockId(this.#nextId++);
|
||||
this.#current = newBlock(nextId);
|
||||
const terminal = fn(nextId);
|
||||
const { id: blockId, instructions } = this.#current;
|
||||
this.#completed.set(blockId, {
|
||||
kind,
|
||||
id: blockId,
|
||||
instructions,
|
||||
terminal,
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
*/
|
||||
|
||||
import { invariant } from "../Utils/CompilerError";
|
||||
import { assertExhaustive } from "../Utils/utils";
|
||||
import {
|
||||
BlockId,
|
||||
Effect,
|
||||
@@ -30,40 +29,10 @@ import {
|
||||
*/
|
||||
export function mergeConsecutiveBlocks(fn: HIRFunction): void {
|
||||
const merged = new MergedBlocks();
|
||||
const valueBlocks = new Set<BlockId>();
|
||||
for (const [, block] of fn.body.blocks) {
|
||||
// Before evaluating the block itself, determine which other blocks
|
||||
// are value blocks. See above TODO which would allow us to bypass this.
|
||||
const terminal = block.terminal;
|
||||
switch (terminal.kind) {
|
||||
case "while": {
|
||||
valueBlocks.add(terminal.test);
|
||||
break;
|
||||
}
|
||||
case "for": {
|
||||
valueBlocks.add(terminal.init);
|
||||
valueBlocks.add(terminal.test);
|
||||
valueBlocks.add(terminal.update);
|
||||
break;
|
||||
}
|
||||
case "if":
|
||||
case "goto":
|
||||
case "return":
|
||||
case "throw":
|
||||
case "switch": {
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
assertExhaustive(
|
||||
terminal,
|
||||
`Unexpected terminal kind '${(terminal as any).kind}'`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Can only merge blocks with a single predecessor, can't merge
|
||||
// value blocks
|
||||
if (block.preds.size !== 1 || valueBlocks.has(block.id)) {
|
||||
if (block.kind === "value" || block.preds.size !== 1) {
|
||||
continue;
|
||||
}
|
||||
const originalPredecessorId = Array.from(block.preds)[0]!;
|
||||
|
||||
@@ -47,7 +47,7 @@ export default function printHIR(
|
||||
output.push(`${indent}${text}`);
|
||||
};
|
||||
for (const [blockId, block] of ir.blocks) {
|
||||
output.push(`bb${blockId}:`);
|
||||
output.push(`bb${blockId} (${block.kind}):`);
|
||||
if (block.preds.size > 0) {
|
||||
const preds = ["predecessor blocks:"];
|
||||
for (const pred of block.preds) {
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
*/
|
||||
|
||||
import {
|
||||
BlockId,
|
||||
GotoVariant,
|
||||
HIRFunction,
|
||||
IdentifierId,
|
||||
@@ -72,9 +71,6 @@ export function constantPropagation(fn: HIRFunction): void {
|
||||
function applyConstantPropagation(fn: HIRFunction): boolean {
|
||||
let hasChanges = false;
|
||||
|
||||
// A set of blocks whose terminals can't (yet) be safely rewritten
|
||||
const valueBlocks = new Set<BlockId>();
|
||||
|
||||
const constants: Constants = new Map();
|
||||
for (const [, block] of fn.body.blocks) {
|
||||
// Initialize phi values if all operands have the same known constant value.
|
||||
@@ -108,7 +104,7 @@ function applyConstantPropagation(fn: HIRFunction): boolean {
|
||||
}
|
||||
}
|
||||
|
||||
if (valueBlocks.has(block.id)) {
|
||||
if (block.kind === "value") {
|
||||
// can't rewrite terminals in value blocks yet
|
||||
continue;
|
||||
}
|
||||
@@ -130,16 +126,6 @@ function applyConstantPropagation(fn: HIRFunction): boolean {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "while": {
|
||||
valueBlocks.add(terminal.test);
|
||||
break;
|
||||
}
|
||||
case "for": {
|
||||
valueBlocks.add(terminal.init);
|
||||
valueBlocks.add(terminal.test);
|
||||
valueBlocks.add(terminal.update);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// no-op
|
||||
}
|
||||
|
||||
+19
-19
@@ -83,12 +83,12 @@
|
||||
"@jridgewell/gen-mapping" "^0.3.2"
|
||||
jsesc "^2.5.1"
|
||||
|
||||
"@babel/generator@^7.20.5":
|
||||
version "7.20.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.20.5.tgz#cb25abee3178adf58d6814b68517c62bdbfdda95"
|
||||
integrity sha512-jl7JY2Ykn9S0yj4DQP82sYvPU+T3g0HFcWTqDLqiuA9tGRNIj9VfbtXGAYTTkyNEnQk1jkMGOdYka8aG/lulCA==
|
||||
"@babel/generator@^7.20.7":
|
||||
version "7.20.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.20.7.tgz#f8ef57c8242665c5929fe2e8d82ba75460187b4a"
|
||||
integrity sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw==
|
||||
dependencies:
|
||||
"@babel/types" "^7.20.5"
|
||||
"@babel/types" "^7.20.7"
|
||||
"@jridgewell/gen-mapping" "^0.3.2"
|
||||
jsesc "^2.5.1"
|
||||
|
||||
@@ -260,10 +260,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.19.3.tgz#8dd36d17c53ff347f9e55c328710321b49479a9a"
|
||||
integrity sha512-pJ9xOlNWHiy9+FuFP09DEAFbAn4JskgRsVcc169w2xRBC3FRGuQEwjeIMMND9L2zc0iEhO/tGv4Zq+km+hxNpQ==
|
||||
|
||||
"@babel/parser@^7.20.5":
|
||||
version "7.20.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.5.tgz#7f3c7335fe417665d929f34ae5dceae4c04015e8"
|
||||
integrity sha512-r27t/cy/m9uKLXQNWWebeCUHgnAZq0CpG1OwKRxzJMP1vpSU4bSIK2hq+/cp0bQxetkXx38n09rNu8jVkcK/zA==
|
||||
"@babel/parser@^7.20.7":
|
||||
version "7.20.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.7.tgz#66fe23b3c8569220817d5feb8b9dcdc95bb4f71b"
|
||||
integrity sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg==
|
||||
|
||||
"@babel/plugin-syntax-async-generators@^7.8.4":
|
||||
version "7.8.4"
|
||||
@@ -484,18 +484,18 @@
|
||||
lodash "^4.17.10"
|
||||
|
||||
"@babel/traverse@^7.19.1":
|
||||
version "7.20.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.20.5.tgz#78eb244bea8270fdda1ef9af22a5d5e5b7e57133"
|
||||
integrity sha512-WM5ZNN3JITQIq9tFZaw1ojLU3WgWdtkxnhM1AegMS+PvHjkM5IXjmYEGY7yukz5XS4sJyEf2VzWjI8uAavhxBQ==
|
||||
version "7.20.12"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.20.12.tgz#7f0f787b3a67ca4475adef1f56cb94f6abd4a4b5"
|
||||
integrity sha512-MsIbFN0u+raeja38qboyF8TIT7K0BFzz/Yd/77ta4MsUsmP2RAnidIlwq7d5HFQrH/OZJecGV6B71C4zAgpoSQ==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.18.6"
|
||||
"@babel/generator" "^7.20.5"
|
||||
"@babel/generator" "^7.20.7"
|
||||
"@babel/helper-environment-visitor" "^7.18.9"
|
||||
"@babel/helper-function-name" "^7.19.0"
|
||||
"@babel/helper-hoist-variables" "^7.18.6"
|
||||
"@babel/helper-split-export-declaration" "^7.18.6"
|
||||
"@babel/parser" "^7.20.5"
|
||||
"@babel/types" "^7.20.5"
|
||||
"@babel/parser" "^7.20.7"
|
||||
"@babel/types" "^7.20.7"
|
||||
debug "^4.1.0"
|
||||
globals "^11.1.0"
|
||||
|
||||
@@ -534,10 +534,10 @@
|
||||
"@babel/helper-validator-identifier" "^7.19.1"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@babel/types@^7.20.5":
|
||||
version "7.20.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.20.5.tgz#e206ae370b5393d94dfd1d04cd687cace53efa84"
|
||||
integrity sha512-c9fst/h2/dcF7H+MJKZ2T0KjEQ8hY/BNnDk/H3XY8C4Aw/eWQXWn/lWntHF9ooUBnGmEvbfGrTgLWc+um0YDUg==
|
||||
"@babel/types@^7.20.7":
|
||||
version "7.20.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.20.7.tgz#54ec75e252318423fc07fb644dc6a58a64c09b7f"
|
||||
integrity sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==
|
||||
dependencies:
|
||||
"@babel/helper-string-parser" "^7.19.4"
|
||||
"@babel/helper-validator-identifier" "^7.19.1"
|
||||
|
||||
Reference in New Issue
Block a user