Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
validateNoRefAccessInRender,
validateNoSetStateInRender,
validatePreservedManualMemoization,
validateSourceLocations,
validateUseMemo,
} from '../Validation';
import {validateLocalsNotReassignedAfterRender} from '../Validation/ValidateLocalsNotReassignedAfterRender';
Expand Down Expand Up @@ -554,6 +555,26 @@
log({kind: 'ast', name: 'Codegen (outlined)', value: outlined.fn});
}

// console.debug(ast.body.body.map((n, i) => `${i}: ${n.type}`))

Check failure on line 558 in compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Pipeline.ts

View workflow job for this annotation

GitHub Actions / Lint babel-plugin-react-compiler

Expected a block comment instead of consecutive line comments
// // const thing = ast.body.body[17]
// // if (thing.type === 'IfStatement' && thing.consequent.type === 'BlockStatement') {
// // const thing2 = thing.consequent.body[0]
// // if (thing2.type === 'ExpressionStatement') {
// // const thing3 = thing2.expression
// // if (thing3.type === 'AssignmentExpression' && thing3.right.type === 'ArrowFunctionExpression') {
// // console.debug(thing3.right)
// // }
// // }
// // }
// const thing = ast.body.body[15]
// if (thing.type == 'ExpressionStatement') {
// console.log(thing)
// }

if (env.config.validateSourceLocations) {
validateSourceLocations(func, ast).unwrap();
}

/**
* This flag should be only set for unit / fixture tests to check
* that Forget correctly handles unexpected errors (e.g. exceptions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -971,7 +971,18 @@
case 'ExpressionStatement': {
const stmt = stmtPath as NodePath<t.ExpressionStatement>;
const expression = stmt.get('expression');
lowerExpressionToTemporary(builder, expression);
const value = lowerExpression(builder, expression);
// Preserve the original source location of the expression statement

Check failure on line 975 in compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts

View workflow job for this annotation

GitHub Actions / Lint babel-plugin-react-compiler

Expected a block comment instead of consecutive line comments
// instead of using the value's location
const stmtLoc = stmt.node.loc ?? GeneratedSource;
const place = buildTemporaryPlace(builder, value.loc);
builder.push({
id: makeInstructionId(0),
lvalue: {...place},
value: value,
effects: null,
loc: stmtLoc,
});
return;
}
case 'DoWhileStatement': {
Expand Down Expand Up @@ -4040,6 +4051,7 @@
pattern: {
kind: 'ArrayPattern',
items,
loc: lvalue.node.loc ?? GeneratedSource,
},
},
value,
Expand Down Expand Up @@ -4217,6 +4229,7 @@
pattern: {
kind: 'ObjectPattern',
properties,
loc: lvalue.node.loc ?? GeneratedSource,
},
},
value,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,13 @@ export const EnvironmentConfigSchema = z.object({
*/
validateNoFreezingKnownMutableFunctions: z.boolean().default(false),

/**
* Validates that all AST nodes generated during codegen have proper source locations.
* This is useful for debugging issues with source maps and Istanbul coverage.
* When enabled, the compiler will error if any AST node is missing a location.
*/
validateSourceLocations: z.boolean().default(false),

/*
* When enabled, the compiler assumes that hooks follow the Rules of React:
* - Hooks may memoize computation based on any of their parameters, thus
Expand Down
2 changes: 2 additions & 0 deletions compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -694,11 +694,13 @@ export type SpreadPattern = {
export type ArrayPattern = {
kind: 'ArrayPattern';
items: Array<Place | SpreadPattern | Hole>;
loc: SourceLocation;
};

export type ObjectPattern = {
kind: 'ObjectPattern';
properties: Array<ObjectProperty | SpreadPattern>;
loc: SourceLocation;
};

export type ObjectPropertyKey =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,7 @@ function emitDestructureProps(
pattern: {
kind: 'ObjectPattern',
properties,
loc: GeneratedSource,
},
kind: InstructionKind.Let,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1120,7 +1120,7 @@ function codegenTerminal(
* This needs to be updated when we handle non-trivial ForOf inits
*/
createVariableDeclaration(iterableItem.value.loc, varDeclKind, [
t.variableDeclarator(lval, null),
createVariableDeclarator(lval, null),
]),
codegenInstructionValueToExpression(cx, iterableCollection.value),
codegenBlock(cx, terminal.loop),
Expand Down Expand Up @@ -1238,7 +1238,7 @@ function codegenTerminal(
* This needs to be updated when we handle non-trivial ForOf inits
*/
createVariableDeclaration(iterableItem.value.loc, varDeclKind, [
t.variableDeclarator(lval, null),
createVariableDeclarator(lval, null),
]),
codegenInstructionValueToExpression(cx, iterableCollection),
codegenBlock(cx, terminal.loop),
Expand All @@ -1260,9 +1260,9 @@ function codegenTerminal(
const value = codegenPlaceToExpression(cx, terminal.value);
if (value.type === 'Identifier' && value.name === 'undefined') {
// Use implicit undefined
return t.returnStatement();
return createReturnStatement(terminal.loc);
}
return t.returnStatement(value);
return createReturnStatement(terminal.loc, value);
}
case 'switch': {
return createSwitchStatement(
Expand Down Expand Up @@ -1406,7 +1406,7 @@ function codegenInstructionNullable(
suggestions: null,
});
return createVariableDeclaration(instr.loc, 'const', [
t.variableDeclarator(codegenLValue(cx, lvalue), value),
createVariableDeclarator(codegenLValue(cx, lvalue), value),
]);
}
case InstructionKind.Function: {
Expand Down Expand Up @@ -1470,7 +1470,7 @@ function codegenInstructionNullable(
suggestions: null,
});
return createVariableDeclaration(instr.loc, 'let', [
t.variableDeclarator(codegenLValue(cx, lvalue), value),
createVariableDeclarator(codegenLValue(cx, lvalue), value),
]);
}
case InstructionKind.Reassign: {
Expand Down Expand Up @@ -1710,11 +1710,15 @@ function withLoc<T extends (...args: Array<any>) => t.Node>(
};
}

const createIdentifier = withLoc(t.identifier);
const createArrayPattern = withLoc(t.arrayPattern);
const createObjectPattern = withLoc(t.objectPattern);
const createBinaryExpression = withLoc(t.binaryExpression);
const createExpressionStatement = withLoc(t.expressionStatement);
const _createLabelledStatement = withLoc(t.labeledStatement);
const createVariableDeclaration = withLoc(t.variableDeclaration);
const createFunctionDeclaration = withLoc(t.functionDeclaration);
const createReturnStatement = withLoc(t.returnStatement);
const createWhileStatement = withLoc(t.whileStatement);
const createDoWhileStatement = withLoc(t.doWhileStatement);
const createSwitchStatement = withLoc(t.switchStatement);
Expand All @@ -1741,6 +1745,24 @@ const createTryStatement = withLoc(t.tryStatement);
const createBreakStatement = withLoc(t.breakStatement);
const createContinueStatement = withLoc(t.continueStatement);

function createVariableDeclarator(
id: t.LVal,
init?: t.Expression | null,
): t.VariableDeclarator {
const node = t.variableDeclarator(id, init);

if (id.loc && init?.loc) {
node.loc = {
start: id.loc.start,
end: init.loc.end,
filename: id.loc.filename,
identifierName: undefined,
};
}

return node;
}

function createHookGuard(
guard: ExternalFunction,
context: ProgramContext,
Expand Down Expand Up @@ -1829,7 +1851,7 @@ function codegenInstruction(
return value;
}
if (instr.lvalue === null) {
return t.expressionStatement(convertValueToExpression(value));
return createExpressionStatement(instr.loc, convertValueToExpression(value));
}
if (instr.lvalue.identifier.name === null) {
// temporary
Expand All @@ -1848,7 +1870,7 @@ function codegenInstruction(
);
} else {
return createVariableDeclaration(instr.loc, 'const', [
t.variableDeclarator(
createVariableDeclarator(
convertIdentifier(instr.lvalue.identifier),
expressionValue,
),
Expand Down Expand Up @@ -2775,7 +2797,7 @@ function codegenArrayPattern(
): t.ArrayPattern {
const hasHoles = !pattern.items.every(e => e.kind !== 'Hole');
if (hasHoles) {
const result = t.arrayPattern([]);
const result = createArrayPattern(pattern.loc, []);
/*
* Older versions of babel have a validation bug fixed by
* https://github.com/babel/babel/pull/10917
Expand All @@ -2796,7 +2818,7 @@ function codegenArrayPattern(
}
return result;
} else {
return t.arrayPattern(
return createArrayPattern(pattern.loc,
pattern.items.map(item => {
if (item.kind === 'Hole') {
return null;
Expand All @@ -2816,7 +2838,8 @@ function codegenLValue(
return codegenArrayPattern(cx, pattern);
}
case 'ObjectPattern': {
return t.objectPattern(
return createObjectPattern(
pattern.loc,
pattern.properties.map(property => {
if (property.kind === 'ObjectProperty') {
const key = codegenObjectPropertyKey(cx, property.key);
Expand Down Expand Up @@ -2935,7 +2958,7 @@ function convertIdentifier(identifier: Identifier): t.Identifier {
suggestions: null,
},
);
return t.identifier(identifier.name.value);
return createIdentifier(identifier.loc, identifier.name.value);
}

function compareScopeDependency(
Expand Down
Loading
Loading