Skip to content
Draft
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 6 additions & 8 deletions core/src/main/java/lucee/transformer/bytecode/PageImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -550,9 +550,10 @@ else if (functions.length <= 10) {
if (functions.length == 0) {
}
else if (functions.length == 1) {
bc.visitLine(functions[0].getStart());
// Don't emit function wrapper lines - the body statements have their own line numbers.
// Emitting start/end here causes bytecode position conflicts since no instructions
// are generated between the function start and the first body statement.
functions[0].getBody().writeOut(bc);
bc.visitLine(functions[0].getEnd());
}
else writeOutUdfCallInner(bc, functions, 0, functions.length);
adapter.visitInsn(Opcodes.ACONST_NULL);
Expand Down Expand Up @@ -1233,11 +1234,10 @@ public void _writeOut(BytecodeContext bc) {
adapter.loadArg(0);
adapter.invokeVirtual(Types.COMPONENT_IMPL, BEFORE_CALL);
adapter.storeLocal(oldData);
bc.visitLine(component.getStart());
// Don't emit component wrapper lines - the body statements have their own line numbers.

funcs = writeOutCallBody(bc, component.getBody(), IFunction.PAGE_TYPE_COMPONENT, false);

bc.visitLine(component.getEnd());
int t = tcf.visitTryEndCatchBeging(bc);
// BodyContentUtil.flushAndPop(pc,bc);
adapter.loadArg(0);
Expand All @@ -1255,9 +1255,8 @@ public void _writeOut(BytecodeContext bc) {
adapter.invokeStatic(Types.BODY_CONTENT_UTIL, CLEAR_AND_POP);
}
else {
bc.visitLine(component.getStart());
// Don't emit component wrapper lines - the body statements have their own line numbers.
funcs = writeOutCallBody(bc, component.getBody(), IFunction.PAGE_TYPE_COMPONENT, false);
bc.visitLine(component.getEnd());
}

adapter.visitLabel(afterIf); // Move this label after the main logic
Expand All @@ -1279,9 +1278,8 @@ private List<IFunction> writeOutInitInterface(ConstrBytecodeContext constr, Map<
adapter.visitLocalVariable("this", "L" + name + ";", null, methodBegin, methodEnd, 0);
adapter.visitLabel(methodBegin);

bc.visitLine(interf.getStart());
// Don't emit interface wrapper lines - the body statements have their own line numbers.
List<IFunction> funcs = writeOutCallBody(bc, interf.getBody(), IFunction.PAGE_TYPE_INTERFACE, false);
bc.visitLine(interf.getEnd());

adapter.returnValue();
adapter.visitLabel(methodEnd);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ public void _writeOut(BytecodeContext bc) throws TransformerException {
cv.visitWhenAfterExprBeforeBody(bc);
pair.body.writeOut(bc);
cv.visitWhenAfterBody(bc);
if (pair.end != null) bc.visitLine(pair.end);
// Don't emit end line - it causes bytecode position conflicts with the next elseif/else start
}
// else
if (_else != null && _else.body != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ public final class DoWhile extends StatementBaseNoFinal implements FlowControlBr
* @param label
*/
public DoWhile(Expression expr, Body body, Position start, Position end, String label) {
super(expr.getFactory(), start, end);
// Pass null for start to prevent emitting wrapper line - the body statements have their own lines.
// The 'do' keyword doesn't generate bytecode itself, it's just a loop entry point.
super(expr.getFactory(), null, end);
this.expr = expr.getFactory().toExprBoolean(expr);
this.body = body;
body.setParent(this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,10 @@ public void _writeOut(BytecodeContext bc) throws TransformerException {
while (it.hasNext()) {
c = it.next();
adapter.visitLabel(c.label);
bc.visitLine(c.startPos);
// Don't emit case wrapper lines - the body statements have their own line numbers.
// Emitting start/end here causes bytecode position conflicts since no instructions
// are generated between the case label and the first body statement.
c.body.writeOut(bc);
bc.visitLine(c.endPos);
if (c.doBreak) {
adapter.goTo(end);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,9 @@ public final void writeOut(Context c) throws TransformerException {
BytecodeContext bc = (BytecodeContext) c;
bc.visitLine(start);
_writeOut(bc);
bc.visitLine(end);

// Skip emitting end line - it causes bytecode position conflicts when the next statement's
// start line is emitted before any bytecode is generated. The start position is sufficient
// for debugging and breakpoints. The end position (closing brace) isn't executable anyway.
}

/**
Expand Down Expand Up @@ -133,26 +134,22 @@ public void setHasFlowController(boolean hasReturnChild) {

@Override
public void dump(Struct sct) {
// start
if (start != null) {
// start - use getter to allow subclasses to override
Position s = getStart();
if (s != null) {
Struct sctStart = new StructImpl(StructImpl.TYPE_LINKED_NOT_SYNC, 8);
sctStart.setEL(KeyConstants._line, start.line);
sctStart.setEL(KeyConstants._column, start.displayColumn());
sctStart.setEL(KeyConstants._offset, start.displayPosition());
// sctStart.setEL("_pos", start.pos);
// sctStart.setEL("_col", start.column);
// sctStart.setEL("_off", start.offset);
sctStart.setEL(KeyConstants._line, s.line);
sctStart.setEL(KeyConstants._column, s.displayColumn());
sctStart.setEL(KeyConstants._offset, s.displayPosition());
sct.setEL(KeyConstants._start, sctStart);
}
// end
if (end != null) {
// end - use getter to allow subclasses to override
Position e = getEnd();
if (e != null) {
Struct sctEnd = new StructImpl(StructImpl.TYPE_LINKED_NOT_SYNC, 8);
sctEnd.setEL(KeyConstants._line, end.line);
sctEnd.setEL(KeyConstants._column, end.displayColumn());
sctEnd.setEL(KeyConstants._offset, end.displayPosition());
// sctEnd.setEL("_pos", end.pos);
// sctEnd.setEL("_col", end.column);
// sctEnd.setEL("_off", end.offset);
sctEnd.setEL(KeyConstants._line, e.line);
sctEnd.setEL(KeyConstants._column, e.displayColumn());
sctEnd.setEL(KeyConstants._offset, e.displayPosition());
sct.setEL(KeyConstants._end, sctEnd);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,40 @@

public final class TagScript extends TagBaseNoFinal {

// Store positions for AST, but don't pass to super (prevents bytecode line emission)
private Position astStart;
private Position astEnd;

/**
* Constructor stores positions for AST but passes null to super to prevent line number emissions.
* The cfscript tag itself is not executable - it's just a container for script content. Emitting
* line numbers for it causes conflicts when functions are extracted and written before the body,
* resulting in the same bytecode position having multiple line numbers.
*/
public TagScript(Factory f, Position start, Position end) {
super(f, start, end);
super(f, null, null);
this.astStart = start;
this.astEnd = end;
}

@Override
public Position getStart() {
return astStart;
}

@Override
public void setStart(Position start) {
this.astStart = start;
}

@Override
public Position getEnd() {
return astEnd;
}

@Override
public void setEnd(Position end) {
this.astEnd = end;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,9 @@ public final void writeOut(Context context, int type) throws TransformerExceptio
// register(bc.getPage());
bc.visitLine(getStart());
_writeOut(bc, type);
bc.visitLine(getEnd());
// Skip emitting end line - it causes bytecode position conflicts when multiple functions are
// registered consecutively (function1 end collides with function2 start at same bytecode label).
// The start position is sufficient for debugging and breakpoints.
}

@Override
Expand Down
2 changes: 1 addition & 1 deletion test/tickets/LDEV6078.cfc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
component extends="org.lucee.cfml.test.LuceeTestCase" skip=true {
component extends="org.lucee.cfml.test.LuceeTestCase" {

function beforeAll() {
variables.uri = createURI( "LDEV6078" );
Expand Down