Skip to content

UVE: Unable to edit page when document.write re-executes inline scripts and throws 'already declared'  #36141

Description

@rjvelazco

Problem Statement

In the Universal Visual Editor (UVE), traditional (VTL) pages are rendered into the editor iframe via document.open() / document.write() / document.close(). The component writes the page content more than once per render:

  • the reactive effect ($isTraditionalPageEffect) and the iframe (load) handler both call insertPageContent, and
  • doc.close() itself re-fires the iframe load event, which routes straight back into insertPageContent.

Each re-write re-executes all of the page's inline <script> blocks in the same global scope. For customer pages whose inline scripts declare top-level const/let (e.g. let resizeTimer, const urlParams), the second/third write throws:

Uncaught SyntaxError: Identifier 'resizeTimer' has already been declared
Failed to execute 'write' on 'Document': Identifier 'urlParams' has already been declared

These declarations are perfectly valid and work fine on the live published page — they only collide in the editor because we write the same document repeatedly into a scope that already has them defined. The thrown error aborts the script run that the inline editor (TinyMCE) setup depends on, so inline editing never initializes and the page is not editable (window.dotUVE is defined, but tinymce.editors is empty and there are no contenteditable elements).

Impact: Customers with valid top-level const/let in VTL inline scripts cannot use inline editing in UVE. Discovered on a customer instance.

Browser & OS: Chromium-based browsers (reproduces wherever document.write re-entrancy occurs).

Steps to Reproduce

  1. On a traditional (VTL) page, add an inline <script> that declares a top-level let or const, e.g. let resizeTimer; (no IIFE / module wrapping).
  2. Open the page in the Universal Visual Editor in Edit mode.
  3. Open the browser console.
  4. Observe Uncaught SyntaxError: Identifier '…' has already been declared errors thrown from insertPageContent.
  5. Try to edit content or doing inline editing.

Acceptance Criteria

  • insertPageContent writes the iframe document once per unique render — re-entrant load events and the synthetic load fired by doc.close() do not trigger a destructive re-write of identical content.
  • Genuine content changes (real-time canvas) still re-render correctly.
  • Navigating to a different page (src changes) still re-renders, even if the rendered HTML is identical.
  • Inline editing initializes correctly on VTL pages whose inline scripts declare valid top-level const/let.
  • No "Identifier '…' has already been declared" errors appear in the console when editing such pages.
  • Existing UVE iframe behavior (SEO data, inline-edit toggle, click/navigation handling) is unchanged, covered by unit tests.

dotCMS Version

Latest from main branch.

Links

Metadata

Metadata

Assignees

Type

Projects

Status
Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions