diff --git a/external/quickjs/quickjs-eval.js b/external/quickjs/quickjs-eval.js index 4dd04f00f15499..ed62964423c33a 100644 --- a/external/quickjs/quickjs-eval.js +++ b/external/quickjs/quickjs-eval.js @@ -1,7 +1,7 @@ var Module = (function() { var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined; - + return ( function(Module) { Module = Module || {}; @@ -25,7 +25,7 @@ f=(f&15)<<4|g>>2;var m=(g&3)<<6|k;c+=String.fromCharCode(e);64!==g&&(c+=String.f var Ca={b:function(a,c,b,e){w("Assertion failed: "+G(a)+", at: "+[c?G(c):"unknown filename",b,e?G(e):"unknown function"])},c:function(){w()},q:ra,o:sa,f:ta,n:function(a){let c;try{const b=new window.URL(G(a));c=window.JSON.stringify({cScheme:b.protocol,cUser:b.username,cPassword:b.password,cHost:b.hostname,cPort:b.port,cPath:b.pathname,cParameters:b.search,cFragments:b.F})}catch(b){c=b.message}return T(c)},m:function(a,c){a=G(a);let b;try{b=window.JSON.parse(a)}catch(e){b=a}0!==c?window.alert(a): window.console.log("DEBUGME",b)},k:function(a,c,b){E.copyWithin(a,c,c+b)},l:function(){w("OOM")},e:function(a,c,b,e){for(var f=0,g=0;g>2],m=J[c+(8*g+4)>>2],z=0;z>2]=f;return 0},d:function(a){var c=Date.now();J[a>>2]=c/1E3|0;J[a+4>>2]=c%1E3*1E3|0;return 0},i:function(a,c){va();a=new Date(1E3*J[a>>2]);J[c>>2]=a.getSeconds();J[c+4>>2]=a.getMinutes();J[c+8>>2]=a.getHours();J[c+12>> 2]=a.getDate();J[c+16>>2]=a.getMonth();J[c+20>>2]=a.getFullYear()-1900;J[c+24>>2]=a.getDay();var b=new Date(a.getFullYear(),0,1);J[c+28>>2]=(a.getTime()-b.getTime())/864E5|0;J[c+36>>2]=-(60*a.getTimezoneOffset());var e=(new Date(a.getFullYear(),6,1)).getTimezoneOffset();b=b.getTimezoneOffset();a=(e!=b&&a.getTimezoneOffset()==Math.min(b,e))|0;J[c+32>>2]=a;a=J[U()+(a?4:0)>>2];J[c+40>>2]=a;return c},j:function(a){a=G(a);window.console.log(a)},a:x,r:function(a,c,b,e){a=G(a);c=G(c);b=G(b);b=`Quickjs -- ${a}: ${c}\n${b}`; -0!==e?window.alert(b):window.console.error(b)},h:function(a){a=G(a);try{const b=window.JSON.parse(a);if(void 0!==b&&null!==b){var c=new window.CustomEvent("updateFromSandbox",{detail:b});window.dispatchEvent(c)}}catch(b){}},p:za,g:Aa}; +0!==e?window.alert(b):window.console.error(b)},h:function(a){a=G(a);try{const b=window.JSON.parse(a);if(void 0!==b&&null!==b){var c=new window.CustomEvent("updatefromsandbox",{detail:b});window.dispatchEvent(c)}}catch(b){}},p:za,g:Aa}; (function(){function a(f){d.asm=f.exports;M=d.asm.s;N--;d.monitorRunDependencies&&d.monitorRunDependencies(N);0==N&&(null!==O&&(clearInterval(O),O=null),P&&(f=P,P=null,f()))}function c(f){a(f.instance)}function b(f){return qa().then(function(g){return WebAssembly.instantiate(g,e)}).then(f,function(g){u("failed to asynchronously prepare wasm: "+g);w(g)})}var e={a:Ca};N++;d.monitorRunDependencies&&d.monitorRunDependencies(N);if(d.instantiateWasm)try{return d.instantiateWasm(e,a)}catch(f){return u("Module.instantiateWasm callback failed with error: "+ f),!1}(function(){return v||"function"!==typeof WebAssembly.instantiateStreaming||Q(R)||"function"!==typeof fetch?b(c):fetch(R,{credentials:"same-origin"}).then(function(f){return WebAssembly.instantiateStreaming(f,e).then(c,function(g){u("wasm streaming compile failed: "+g);u("falling back to ArrayBuffer instantiation");return b(c)})})})().catch(n);return{}})(); var Ba=d.___wasm_call_ctors=function(){return(Ba=d.___wasm_call_ctors=d.asm.t).apply(null,arguments)},V=d._evalInSandbox=function(){return(V=d._evalInSandbox=d.asm.u).apply(null,arguments)};d._nukeSandbox=function(){return(d._nukeSandbox=d.asm.v).apply(null,arguments)};d._dumpMemoryUse=function(){return(d._dumpMemoryUse=d.asm.w).apply(null,arguments)}; @@ -39,4 +39,4 @@ if(d.preInit)for("function"==typeof d.preInit&&(d.preInit=[d.preInit]);0 { - window.dispatchEvent( - new CustomEvent("dispatchEventInSandbox", { - detail: { - id: data.id, - name, - }, - }) - ); + this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { + source: this, + detail: { + id: data.id, + name, + }, + }); return false; }; } @@ -551,30 +550,28 @@ class WidgetAnnotationElement extends AnnotationElement { if (baseName.includes("mouse")) { // Mouse events element.addEventListener(baseName, event => { - window.dispatchEvent( - new CustomEvent("dispatchEventInSandbox", { - detail: { - id: this.data.id, - name: eventName, - value: valueGetter(event), - shift: event.shiftKey, - modifier: this._getKeyModifier(event), - }, - }) - ); + this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { + source: this, + detail: { + id: this.data.id, + name: eventName, + value: valueGetter(event), + shift: event.shiftKey, + modifier: this._getKeyModifier(event), + }, + }); }); } else { // Non mouse event element.addEventListener(baseName, event => { - window.dispatchEvent( - new CustomEvent("dispatchEventInSandbox", { - detail: { - id: this.data.id, - name: eventName, - value: event.target.checked, - }, - }) - ); + this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { + source: this, + detail: { + id: this.data.id, + name: eventName, + value: event.target.checked, + }, + }); }); } } @@ -650,7 +647,7 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement { } }); - element.addEventListener("updateFromSandbox", function (event) { + element.addEventListener("updatefromsandbox", function (event) { const { detail } = event; const actions = { value() { @@ -721,39 +718,37 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement { } // Save the entered value elementData.userValue = event.target.value; - window.dispatchEvent( - new CustomEvent("dispatchEventInSandbox", { + this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { + source: this, + detail: { + id, + name: "Keystroke", + value: event.target.value, + willCommit: true, + commitKey, + selStart: event.target.selectionStart, + selEnd: event.target.selectionEnd, + }, + }); + }); + const _blurListener = blurListener; + blurListener = null; + element.addEventListener("blur", event => { + if (this._mouseState?.isDown) { + // Focus out using the mouse: data are committed + elementData.userValue = event.target.value; + this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { + source: this, detail: { id, name: "Keystroke", value: event.target.value, willCommit: true, - commitKey, + commitKey: 1, selStart: event.target.selectionStart, selEnd: event.target.selectionEnd, }, - }) - ); - }); - const _blurListener = blurListener; - blurListener = null; - element.addEventListener("blur", event => { - if (this._mouseState?.isDown) { - // Focus out using the mouse: data are committed - elementData.userValue = event.target.value; - window.dispatchEvent( - new CustomEvent("dispatchEventInSandbox", { - detail: { - id, - name: "Keystroke", - value: event.target.value, - willCommit: true, - commitKey: 1, - selStart: event.target.selectionStart, - selEnd: event.target.selectionEnd, - }, - }) - ); + }); } _blurListener(event); }); @@ -783,19 +778,18 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement { if (elementData.beforeInputSelectionRange) { [selStart, selEnd] = elementData.beforeInputSelectionRange; } - window.dispatchEvent( - new CustomEvent("dispatchEventInSandbox", { - detail: { - id, - name: "Keystroke", - value: elementData.beforeInputValue, - change: event.data, - willCommit: false, - selStart, - selEnd, - }, - }) - ); + this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { + source: this, + detail: { + id, + name: "Keystroke", + value: elementData.beforeInputValue, + change: event.data, + willCommit: false, + selStart, + selEnd, + }, + }); }); } @@ -929,7 +923,7 @@ class CheckboxWidgetAnnotationElement extends WidgetAnnotationElement { }); if (this.enableScripting && this.hasJSActions) { - element.addEventListener("updateFromSandbox", event => { + element.addEventListener("updatefromsandbox", event => { const { detail } = event; const actions = { value() { @@ -1010,7 +1004,7 @@ class RadioButtonWidgetAnnotationElement extends WidgetAnnotationElement { }); if (this.enableScripting && this.hasJSActions) { - element.addEventListener("updateFromSandbox", event => { + element.addEventListener("updatefromsandbox", event => { const { detail } = event; const actions = { value() { @@ -1132,7 +1126,7 @@ class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement { } if (this.enableScripting && this.hasJSActions) { - selectElement.addEventListener("updateFromSandbox", event => { + selectElement.addEventListener("updatefromsandbox", event => { const { detail } = event; const actions = { value() { @@ -1162,22 +1156,21 @@ class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement { .forEach(name => actions[name]()); }); - selectElement.addEventListener("input", function (event) { + selectElement.addEventListener("input", event => { const value = getValue(event); storage.setValue(id, { value }); - window.dispatchEvent( - new CustomEvent("dispatchEventInSandbox", { - detail: { - id, - name: "Keystroke", - changeEx: value, - willCommit: true, - commitKey: 1, - keyDown: false, - }, - }) - ); + this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { + source: this, + detail: { + id, + name: "Keystroke", + changeEx: value, + willCommit: true, + commitKey: 1, + keyDown: false, + }, + }); }); this._setEventListeners( @@ -1852,14 +1845,12 @@ class FileAttachmentAnnotationElement extends AnnotationElement { this.filename = getFilenameFromUrl(filename); this.content = content; - if (this.linkService.eventBus) { - this.linkService.eventBus.dispatch("fileattachmentannotation", { - source: this, - id: stringToPDFString(filename), - filename, - content, - }); - } + this.linkService.eventBus?.dispatch("fileattachmentannotation", { + source: this, + id: stringToPDFString(filename), + filename, + content, + }); } render() { diff --git a/web/app.js b/web/app.js index dd4f777351d749..42d52fb94f1218 100644 --- a/web/app.js +++ b/web/app.js @@ -785,15 +785,20 @@ const PDFViewerApplication = { if (!this._scriptingInstance) { return; } - const { scripting, events } = this._scriptingInstance; + const { scripting, eventBusEvents, domEvents } = this._scriptingInstance; try { await scripting.destroySandbox(); } catch (ex) {} - for (const [name, listener] of events) { + for (const [name, listener] of eventBusEvents) { + this.eventBus._off(name, listener); + } + eventBusEvents.clear(); + + for (const [name, listener] of domEvents) { window.removeEventListener(name, listener); } - events.clear(); + domEvents.clear(); delete this._mouseState.isDown; this._scriptingInstance = null; @@ -1454,15 +1459,19 @@ const PDFViewerApplication = { pdfDocument.getCalculationOrderIds(), ]); - if (!objects || pdfDocument !== this.pdfDocument) { - // No FieldObjects were found in the document, - // or the document was closed while the data resolved. + if (!objects) { + // No FieldObjects were found in the document. return; } + if (pdfDocument !== this.pdfDocument) { + return; // The document was closed while the data resolved. + } const scripting = this.externalServices.createScripting(); // Store a reference to the current scripting-instance, to allow destruction // of the sandbox and removal of the event listeners at document closing. - this._scriptingInstance = { scripting, events: new Map() }; + const eventBusEvents = new Map(), + domEvents = new Map(); + this._scriptingInstance = { scripting, eventBusEvents, domEvents }; if (!this.documentInfo) { // It should be *extremely* rare for metadata to not have been resolved @@ -1479,8 +1488,7 @@ const PDFViewerApplication = { } } - const updateFromSandbox = event => { - const { detail } = event; + const updateFromSandbox = ({ detail }) => { const { id, command, value } = detail; if (!id) { switch (command) { @@ -1519,7 +1527,7 @@ const PDFViewerApplication = { const element = document.getElementById(id); if (element) { - element.dispatchEvent(new CustomEvent("updateFromSandbox", { detail })); + element.dispatchEvent(new CustomEvent("updatefromsandbox", { detail })); } else { if (value !== undefined && value !== null) { // The element hasn't been rendered yet, use the AnnotationStorage. @@ -1527,30 +1535,30 @@ const PDFViewerApplication = { } } }; - window.addEventListener("updateFromSandbox", updateFromSandbox); + this.eventBus._on("updatefromsandbox", updateFromSandbox); // Ensure that the event listener can be removed at document closing. - this._scriptingInstance.events.set("updateFromSandbox", updateFromSandbox); + eventBusEvents.set("updatefromsandbox", updateFromSandbox); - const dispatchEventInSandbox = event => { - scripting.dispatchEventInSandbox(event.detail); + const dispatchEventInSandbox = ({ detail }) => { + scripting.dispatchEventInSandbox(detail); }; - window.addEventListener("dispatchEventInSandbox", dispatchEventInSandbox); + this.eventBus._on("dispatcheventinsandbox", dispatchEventInSandbox); // Ensure that the event listener can be removed at document closing. - this._scriptingInstance.events.set( - "dispatchEventInSandbox", - dispatchEventInSandbox - ); + eventBusEvents.set("dispatcheventinsandbox", dispatchEventInSandbox); const mouseDown = event => { this._mouseState.isDown = true; }; + window.addEventListener("mousedown", mouseDown); + // Ensure that the event listener can be removed at document closing. + domEvents.set("mousedown", mouseDown); + const mouseUp = event => { this._mouseState.isDown = false; }; - window.addEventListener("mousedown", mouseDown); - this._scriptingInstance.events.set("mousedown", mouseDown); window.addEventListener("mouseup", mouseUp); - this._scriptingInstance.events.set("mouseup", mouseUp); + // Ensure that the event listener can be removed at document closing. + domEvents.set("mouseup", mouseUp); const dispatchEventName = generateRandomStringForSandbox(objects); @@ -2084,6 +2092,12 @@ const PDFViewerApplication = { _boundEvents.windowAfterPrint = () => { eventBus.dispatch("afterprint", { source: window }); }; + _boundEvents.windowUpdateFromSandbox = event => { + eventBus.dispatch("updatefromsandbox", { + source: window, + detail: event.detail, + }); + }; window.addEventListener("visibilitychange", webViewerVisibilityChange); window.addEventListener("wheel", webViewerWheel, { passive: false }); @@ -2097,6 +2111,10 @@ const PDFViewerApplication = { window.addEventListener("hashchange", _boundEvents.windowHashChange); window.addEventListener("beforeprint", _boundEvents.windowBeforePrint); window.addEventListener("afterprint", _boundEvents.windowAfterPrint); + window.addEventListener( + "updatefromsandbox", + _boundEvents.windowUpdateFromSandbox + ); }, unbindEvents() { @@ -2171,11 +2189,16 @@ const PDFViewerApplication = { window.removeEventListener("hashchange", _boundEvents.windowHashChange); window.removeEventListener("beforeprint", _boundEvents.windowBeforePrint); window.removeEventListener("afterprint", _boundEvents.windowAfterPrint); + window.removeEventListener( + "updatefromsandbox", + _boundEvents.windowUpdateFromSandbox + ); _boundEvents.windowResize = null; _boundEvents.windowHashChange = null; _boundEvents.windowBeforePrint = null; _boundEvents.windowAfterPrint = null; + _boundEvents.windowUpdateFromSandbox = null; }, accumulateWheelTicks(ticks) {