1
0
Fork 0
mirror of https://github.com/mozilla/pdf.js.git synced 2025-04-22 16:18:08 +02:00

JS -- Add listener for sandbox events only if there are some actions

* When no actions then set it to null instead of empty object
* Even if a field has no actions, it needs to listen to events from the sandbox in order to be updated if an action changes something in it.
This commit is contained in:
Calixte Denizet 2020-10-28 19:16:56 +01:00
parent 55f55f5859
commit a5279897a7
13 changed files with 170 additions and 28 deletions

View file

@ -1020,6 +1020,21 @@ class PDFDocument {
);
}
get hasJSActions() {
return shadow(
this,
"hasJSActions",
this.fieldObjects.then(fieldObjects => {
return (
fieldObjects !== null &&
Object.values(fieldObjects).some(fieldObject =>
fieldObject.some(object => object.actions !== null)
)
);
})
);
}
get calculationOrderIds() {
const acroForm = this.catalog.acroForm;
if (!acroForm || !acroForm.has("CO")) {

View file

@ -525,6 +525,10 @@ class WorkerMessageHandler {
return pdfManager.ensureDoc("fieldObjects");
});
handler.on("HasJSActions", function (data) {
return pdfManager.ensureDoc("hasJSActions");
});
handler.on("GetCalculationOrderIds", function (data) {
return pdfManager.ensureDoc("calculationOrderIds");
});

View file

@ -43,6 +43,8 @@ import { AnnotationStorage } from "./annotation_storage.js";
* for annotation icons. Include trailing slash.
* @property {boolean} renderInteractiveForms
* @property {Object} svgFactory
* @property {boolean} [enableScripting]
* @property {boolean} [hasJSActions]
*/
class AnnotationElementFactory {
@ -142,6 +144,8 @@ class AnnotationElement {
this.renderInteractiveForms = parameters.renderInteractiveForms;
this.svgFactory = parameters.svgFactory;
this.annotationStorage = parameters.annotationStorage;
this.enableScripting = parameters.enableScripting;
this.hasJSActions = parameters.hasJSActions;
if (isRenderable) {
this.container = this._createContainer(ignoreBorder);
@ -507,7 +511,7 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
event.target.setSelectionRange(0, 0);
});
if (this.data.actions) {
if (this.enableScripting && this.hasJSActions) {
element.addEventListener("updateFromSandbox", function (event) {
const data = event.detail;
if ("value" in data) {
@ -517,21 +521,23 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
}
});
for (const eventType of Object.keys(this.data.actions)) {
switch (eventType) {
case "Format":
element.addEventListener("blur", function (event) {
window.dispatchEvent(
new CustomEvent("dispatchEventInSandbox", {
detail: {
id,
name: "Format",
value: event.target.value,
},
})
);
});
break;
if (this.data.actions !== null) {
for (const eventType of Object.keys(this.data.actions)) {
switch (eventType) {
case "Format":
element.addEventListener("blur", function (event) {
window.dispatchEvent(
new CustomEvent("dispatchEventInSandbox", {
detail: {
id,
name: "Format",
value: event.target.value,
},
})
);
});
break;
}
}
}
}
@ -1562,6 +1568,9 @@ class FileAttachmentAnnotationElement extends AnnotationElement {
* @property {string} [imageResourcesPath] - Path for image resources, mainly
* for annotation icons. Include trailing slash.
* @property {boolean} renderInteractiveForms
* @property {boolean} [enableScripting] - Enable embedded script execution.
* @property {boolean} [hasJSActions] - Some fields have JS actions.
* The default value is `false`.
*/
class AnnotationLayer {
@ -1608,6 +1617,8 @@ class AnnotationLayer {
svgFactory: new DOMSVGFactory(),
annotationStorage:
parameters.annotationStorage || new AnnotationStorage(),
enableScripting: parameters.enableScripting,
hasJSActions: parameters.hasJSActions,
});
if (element.isRenderable) {
const rendered = element.render();

View file

@ -903,6 +903,14 @@ class PDFDocumentProxy {
return this._transport.getFieldObjects();
}
/**
* @returns {Promise<boolean>} A promise that is resolved with `true`
* if some /AcroForm fields have JavaScript actions.
*/
hasJSActions() {
return this._transport.hasJSActions();
}
/**
* @returns {Promise<Array<string> | null>} A promise that is resolved with an
* {Array<string>} containing IDs of annotations that have a calculation
@ -2568,6 +2576,10 @@ class WorkerTransport {
return this.messageHandler.sendWithPromise("GetFieldObjects", null);
}
hasJSActions() {
return this.messageHandler.sendWithPromise("HasJSActions", null);
}
getCalculationOrderIds() {
return this.messageHandler.sendWithPromise("GetCalculationOrderIds", null);
}

View file

@ -73,12 +73,14 @@ class Field extends PDFObject {
// Private
this._actions = Object.create(null);
const doc = (this._document = data.doc);
for (const [eventType, actions] of Object.entries(data.actions)) {
// This code is running in a sandbox so it's safe to use Function
this._actions[eventType] = actions.map(action =>
// eslint-disable-next-line no-new-func
Function("event", `with (this) {${action}}`).bind(doc)
);
if (data.actions !== null) {
for (const [eventType, actions] of Object.entries(data.actions)) {
// This code is running in a sandbox so it's safe to use Function
this._actions[eventType] = actions.map(action =>
// eslint-disable-next-line no-new-func
Function("event", `with (this) {${action}}`).bind(doc)
);
}
}
}