tinymce / tinymce/tinymce-svelte

Bug: `TypeError: Cannot read properties of null (reading 'style')` when component unmounts before script loads

Open
#100 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

status: escalated
Dominant language
TypeScript
Stars
31
Forks
8
PR merge metrics
No merged PRs in 30d

Description

(disclaimer: issue description and reproducible test case produced by Claude Open 4.7, but verified by a human for accuracy)

Summary

If an Editor instance unmounts before tinymce.min.js finishes loading, the script's onload later runs an orphaned init() callback and throws TypeError: Cannot read properties of null (reading 'style') at Editor.svelte line 182 (element!.style.visibility = '').

Minimal reproduction

  1. Throttle the network in DevTools to "Slow 3G" (or anything that makes the TinyMCE script take >100ms).
  2. Mount the component below — it unmounts itself after 50ms.
  3. Observe the uncaught TypeError when the script eventually loads.
<script lang="ts">
  import Editor from '@tinymce/tinymce-svelte';

  let mounted = $state(true);

  // Unmount before the TinyMCE script can finish loading.
  // Any value smaller than the script's load time will reproduce.
  $effect(() => {
    const id = setTimeout(() => { mounted = false; }, 50);
    return () => clearTimeout(id);
  });
</script>

{#if mounted}
  <Editor
    apiKey="no-api-key"
    channel="8"
  />
{/if}

<!--
  Expected: clean unmount, no console errors.
  Actual: when the TinyMCE script finishes loading, an uncaught
          TypeError: Cannot read properties of null (reading 'style')
          is thrown from the orphan init() callback.
-->

In a real app, the trigger is more organic: a user navigates to a page containing a <Editor>, then navigates away before the network has finished delivering tinymce.min.js. We observed this in production from users on slower devices/connections.

Suggested fix

Set a destroyed flag in onDestroy and short-circuit the queued init callback if set. Ideally also splice the listener out of state.listeners to avoid unbounded growth in long-lived SPAs.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in Editor.svelte around line 182 and trace how the queued init callback is registered and invoked after tinymce.min.js loads. Reproduce with Slow 3G and the self-unmounting Svelte example, then verify that unmounting before load produces no error and that the state.listeners entry does not accumulate unnecessarily.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
frontend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.