Environment
- jsPDF version: 3.0.3
- nodejs: 20.19.0
- OS: Linux ubuntu 24
Description
When restoring a RenderTarget (e.g., after creating a FormObject), the internal reference API.internal.pages is not updated to reflect the restored pages array.
This results in a desynchronization between the internal rendering context and the public API (doc.internal.pages), which causes incorrect behavior in plugins or custom rendering logic that relies on the internal API.
Minimal code example
const doc = new jsPDF();
const pages1 = doc.internal.pages;
doc.beginFormObject( 0, 0, doc.internal.pageSize.width, context.internal.pageSize.height, context.Matrix( 1, 0, 0, 1, 0, 0 ) );
doc.endFormObject("myFormObject");
doc.addPage( "a4", "landscape" );
const pages2 = doc.internal.pages );
console.log( pages1, pages2, pages1 === pages2 );
Expected behavior
After restoring the previous render target,
API.internal.pages should be updated to reference the restored pages array,
so that the public and internal contexts stay in sync.
Actual behavior
API.internal.pages continues pointing to the old pages array created before beginFormObject().
This leads to inconsistencies when interacting with doc.internal.pages or plugins that use it.
Suspected cause
In RenderTarget.prototype.restore() (see snippet below),
the pages variable is reassigned,
but the internal API references (API.internal.pages) is not updated:
|
RenderTarget.prototype.restore = function() { |
|
page = this.page; |
|
currentPage = this.currentPage; |
|
pagesContext = this.pagesContext; |
|
pages = this.pages; |
|
pageX = this.x; |
|
pageY = this.y; |
|
pageMatrix = this.matrix; |
|
setPageWidthWithoutScaling(currentPage, this.width); |
|
setPageHeightWithoutScaling(currentPage, this.height); |
|
outputDestination = this.outputDestination; |
|
}; |
Suggested fix
Rebind API.internal.pages after restoring the render target:
RenderTarget.prototype.restore = function() {
page = this.page;
currentPage = this.currentPage;
pagesContext = this.pagesContext;
API.internal.pages = pages = this.pages;
pageX = this.x;
pageY = this.y;
pageMatrix = this.matrix;
setPageWidthWithoutScaling(currentPage, this.width);
setPageHeightWithoutScaling(currentPage, this.height);
outputDestination = this.outputDestination;
};
Why this matters
- Keeps the internal and public state consistent.
- Prevents plugins and internal tools that use
API.internal.pages from breaking after a render target restore.
- Maintains predictable document behavior when working with FormObjects or custom render targets.
PS: Generated by chatgpt and edited by a Human
Environment
Description
When restoring a
RenderTarget(e.g., after creating a FormObject), the internal referenceAPI.internal.pagesis not updated to reflect the restoredpagesarray.This results in a desynchronization between the internal rendering context and the public API (
doc.internal.pages), which causes incorrect behavior in plugins or custom rendering logic that relies on the internal API.Minimal code example
Expected behavior
After restoring the previous render target,
API.internal.pagesshould be updated to reference the restoredpagesarray,so that the public and internal contexts stay in sync.
Actual behavior
API.internal.pagescontinues pointing to the oldpagesarray created beforebeginFormObject().This leads to inconsistencies when interacting with
doc.internal.pagesor plugins that use it.Suspected cause
In
RenderTarget.prototype.restore()(see snippet below),the
pagesvariable is reassigned,but the internal API references (
API.internal.pages) is not updated:jsPDF/src/jspdf.js
Lines 5722 to 5733 in 463b199
Suggested fix
Rebind
API.internal.pagesafter restoring the render target:Why this matters
API.internal.pagesfrom breaking after a render target restore.PS: Generated by chatgpt and edited by a Human