{"record":{"id":"e74d1b153afee905","repo":"mozilla/pdf.js","slug":"doc-mousex-is-read-only","errorCode":null,"errorMessage":"doc.mouseX is read-only","messagePattern":"doc\\.mouseX is read-only","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/scripting_api/doc.js","lineNumber":494,"sourceCode":"\n  set metadata(metadata) {\n    this._metadata = metadata;\n  }\n\n  get modDate() {\n    return this._modDate;\n  }\n\n  set modDate(_) {\n    throw new Error(\"doc.modDate is read-only\");\n  }\n\n  get mouseX() {\n    return 0;\n  }\n\n  set mouseX(_) {\n    throw new Error(\"doc.mouseX is read-only\");\n  }\n\n  get mouseY() {\n    return 0;\n  }\n\n  set mouseY(_) {\n    throw new Error(\"doc.mouseY is read-only\");\n  }\n\n  get noautocomplete() {\n    return this._noautocomplete;\n  }\n\n  set noautocomplete(noautocomplete) {\n    this._noautocomplete = noautocomplete;\n  }\n","sourceCodeStart":476,"sourceCodeEnd":512,"githubUrl":"https://github.com/mozilla/pdf.js/blob/5903d58d58e4dd9ce6ffa3834aea8480f06b4ada/src/scripting_api/doc.js#L476-L512","documentation":"PDF.js implements the Acrobat JavaScript `Doc` object inside its scripting sandbox. `Doc.mouseX` is a read-only getter returning the cursor's X coordinate (in points) relative to the page's top-left corner; PDF.js always returns 0 because it does not feed live cursor position into the scripting context. The setter throws `doc.mouseX is read-only` because the Acrobat JavaScript Scripting Reference marks mouseX as a read-only property, so PDF.js installs a throwing setter to mirror the spec rather than silently accepting writes.","triggerScenarios":"A PDF form/document script executes an assignment to `this.mouseX` or `doc.mouseX` (e.g. `doc.mouseX = event.x;` inside a MouseUp/Calculate action). The throwing setter is invoked immediately and aborts the running script action.","commonSituations":"Porting an AcroJS/XFA script written for desktop Acrobat that tried to reposition or echo the cursor; copy-pasted sample code from an Acrobat SDK tutorial; an obfuscated or generated script that blindly assigns to every `Doc` property.","solutions":["Remove the assignment to `doc.mouseX` — read it instead (`var x = doc.mouseX;`).","If you need the event mouse coordinate, read the `event` object (`event.x`, `event.targetX`, `event.rc`) in the action handler where the click occurred.","Wrap third-party/legacy script execution in a try/catch at the host integration layer so a read-only write logs and continues instead of killing the whole form script."],"exampleFix":"// before\ndoc.mouseX = 100;\n\n// after\nvar x = doc.mouseX; // read-only; returns 0 in PDF.js","handlingStrategy":"try-catch","validationCode":"// Read-only by spec; validate intent before running a script that may write it.\nconst READ_ONLY_DOC_PROPS = new Set(['mouseX','mouseY' /* ...other read-only Doc props */]);\nfunction assertsNoReadOnlyWrite(scriptSrc) {\n  for (const p of READ_ONLY_DOC_PROPS) {\n    if (new RegExp(`\\\\bdoc\\\\.${p}\\\\s*=`).test(scriptSrc)) {\n      throw new Error(`Script writes read-only property doc.${p}`);\n    }\n  }\n}\nassertsNoReadOnlyWrite(myScript);","typeGuard":"// PDF.js Doc getters are writable===false; detect at runtime in the sandbox.\nfunction isReadOnlyDocProp(doc, prop) {\n  const desc = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(doc), prop)\n    || Object.getOwnPropertyDescriptor(doc, prop);\n  return !!desc && desc.get && !desc.set;\n}\nisReadOnlyDocProp(doc, 'mouseX'); // true","tryCatchPattern":"try {\n  doc.mouseX = 100; // legacy/3rd-party script line\n} catch (e) {\n  if (/mouseX is read-only/.test(e.message)) {\n    console.warn('Ignored read-only write:', e.message);\n  } else { throw e; }\n}","preventionTips":["Treat all Acrobat-JS `Doc` geometry/mouse properties as read-only unless the Acrobat Scripting Reference explicitly lists a setter.","Lint scripts against a known set of read-only Doc properties before dispatching them to the sandbox.","Wrap third-party or legacy form-script execution in a try/catch boundary so one read-only write does not abort the whole form."],"tags":["scripting","acrobat-js-api","doc-object","read-only","mouse"],"backgroundTag":null,"analyzedSha":"5903d58d58e4dd9ce6ffa3834aea8480f06b4ada","analyzedAt":"2026-08-13T02:28:27.364Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}